]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 01:24:11 +0000 (18:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 01:24:11 +0000 (18:24 -0700)
* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (44 commits)
  debugfs: Silence DEBUG_STRICT_USER_COPY_CHECKS=y warning
  sysfs: remove "last sysfs file:" line from the oops messages
  drivers/base/memory.c: fix warning due to "memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION"
  memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION
  SYSFS: Fix erroneous comments for sysfs_update_group().
  driver core: remove the driver-model structures from the documentation
  driver core: Add the device driver-model structures to kerneldoc
  Translated Documentation/email-clients.txt
  RAW driver: Remove call to kobject_put().
  reboot: disable usermodehelper to prevent fs access
  efivars: prevent oops on unload when efi is not enabled
  Allow setting of number of raw devices as a module parameter
  Introduce CONFIG_GOOGLE_FIRMWARE
  driver: Google Memory Console
  driver: Google EFI SMI
  x86: Better comments for get_bios_ebda()
  x86: get_bios_ebda_length()
  misc: fix ti-st build issues
  params.c: Use new strtobool function to process boolean inputs
  debugfs: move to new strtobool
  ...

Fix up trivial conflicts in fs/debugfs/file.c due to the same patch
being applied twice, and an unrelated cleanup nearby.

1450 files changed:
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/ABI/testing/sysfs-power
Documentation/DocBook/genericirq.tmpl
Documentation/DocBook/media-entities.tmpl
Documentation/DocBook/v4l/media-ioc-setup-link.xml
Documentation/DocBook/v4l/pixfmt-y12.xml [new file with mode: 0644]
Documentation/DocBook/v4l/pixfmt.xml
Documentation/DocBook/v4l/subdev-formats.xml
Documentation/RCU/00-INDEX
Documentation/RCU/stallwarn.txt
Documentation/RCU/trace.txt
Documentation/cgroups/memory.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/flexible-arrays.txt
Documentation/hwmon/adm1021
Documentation/hwmon/lm90
Documentation/hwmon/max16064 [new file with mode: 0644]
Documentation/hwmon/max34440 [new file with mode: 0644]
Documentation/hwmon/max8688 [new file with mode: 0644]
Documentation/hwmon/pmbus
Documentation/hwmon/smm665
Documentation/hwmon/submitting-patches [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/md.txt
Documentation/power/devices.txt
Documentation/power/notifiers.txt
Documentation/sound/alsa/SB-Live-mixer.txt
Documentation/trace/kprobetrace.txt
Documentation/video4linux/sh_mobile_ceu_camera.txt
Documentation/virtual/00-INDEX [new file with mode: 0644]
Documentation/virtual/kvm/api.txt [moved from Documentation/kvm/api.txt with 100% similarity]
Documentation/virtual/kvm/cpuid.txt [moved from Documentation/kvm/cpuid.txt with 100% similarity]
Documentation/virtual/kvm/locking.txt [moved from Documentation/kvm/locking.txt with 100% similarity]
Documentation/virtual/kvm/mmu.txt [moved from Documentation/kvm/mmu.txt with 100% similarity]
Documentation/virtual/kvm/msr.txt [moved from Documentation/kvm/msr.txt with 100% similarity]
Documentation/virtual/kvm/ppc-pv.txt [moved from Documentation/kvm/ppc-pv.txt with 100% similarity]
Documentation/virtual/kvm/review-checklist.txt [moved from Documentation/kvm/review-checklist.txt with 95% similarity]
Documentation/virtual/kvm/timekeeping.txt [moved from Documentation/kvm/timekeeping.txt with 100% similarity]
Documentation/virtual/lguest/.gitignore [moved from Documentation/lguest/.gitignore with 100% similarity]
Documentation/virtual/lguest/Makefile [moved from Documentation/lguest/Makefile with 100% similarity]
Documentation/virtual/lguest/extract [moved from Documentation/lguest/extract with 100% similarity]
Documentation/virtual/lguest/lguest.c [moved from Documentation/lguest/lguest.c with 100% similarity]
Documentation/virtual/lguest/lguest.txt [moved from Documentation/lguest/lguest.txt with 97% similarity]
Documentation/virtual/uml/UserModeLinux-HOWTO.txt [moved from Documentation/uml/UserModeLinux-HOWTO.txt with 100% similarity]
Documentation/workqueue.txt
Documentation/x86/x86_64/boot-options.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/unistd.h
arch/alpha/kernel/smp.c
arch/alpha/kernel/systbls.S
arch/alpha/kernel/time.c
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/vmlinux.lds.in
arch/arm/common/vic.c
arch/arm/configs/at91x40_defconfig [new file with mode: 0644]
arch/arm/include/asm/cputype.h
arch/arm/include/asm/i8253.h [new file with mode: 0644]
arch/arm/include/asm/kprobes.h
arch/arm/include/asm/mach/time.h
arch/arm/include/asm/system.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/kprobes-decode.c
arch/arm/kernel/kprobes.c
arch/arm/kernel/leds.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/signal.c
arch/arm/kernel/smp.c
arch/arm/kernel/sys_oabi-compat.c
arch/arm/kernel/time.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/board-eb01.c
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/cpufreq.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/include/mach/debug-macro.S
arch/arm/mach-davinci/include/mach/serial.h
arch/arm/mach-exynos4/pm.c
arch/arm/mach-footbridge/Kconfig
arch/arm/mach-footbridge/isa-timer.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-mx3/mach-vpr200.c
arch/arm/mach-mx5/board-mx53_loco.c
arch/arm/mach-mxs/clock-mx28.c
arch/arm/mach-omap1/pm_bus.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/cm2xxx_3xxx.c
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_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_l3_smx.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm_bus.c [deleted file]
arch/arm/mach-omap2/voltage.c
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/clock-pxa2xx.c
arch/arm/mach-pxa/clock-pxa3xx.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/cm-x270.c
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/colibri-evalboard.c
arch/arm/mach-pxa/colibri-pxa270-income.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mfp-pxa2xx.c
arch/arm/mach-pxa/mfp-pxa3xx.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa95x.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/smemc.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-realview/include/mach/barriers.h
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2412/irq.c
arch/arm/mach-s3c2412/mach-jive.c
arch/arm/mach-s3c2412/pm.c
arch/arm/mach-s3c2412/s3c2412.c
arch/arm/mach-s3c2416/irq.c
arch/arm/mach-s3c2416/pm.c
arch/arm/mach-s3c2416/s3c2416.c
arch/arm/mach-s3c2440/mach-gta02.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2440/s3c244x-irq.c
arch/arm/mach-s3c2440/s3c244x.c
arch/arm/mach-s3c64xx/irq-pm.c
arch/arm/mach-s5pv210/pm.c
arch/arm/mach-sa1100/irq.c
arch/arm/mach-shmobile/pm_runtime.c
arch/arm/mach-tegra/include/mach/barriers.h
arch/arm/mach-ux500/board-mop500.c
arch/arm/mm/init.c
arch/arm/mm/proc-xscale.S
arch/arm/plat-mxc/gpio.c
arch/arm/plat-mxc/ssi-fiq.S
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-pxa/gpio.c
arch/arm/plat-pxa/mfp.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/irq-pm.c
arch/arm/plat-s5p/irq-pm.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/vfp/vfpmodule.c
arch/avr32/mach-at32ap/intc.c
arch/blackfin/kernel/nmi.c
arch/blackfin/kernel/time-ts.c
arch/blackfin/mach-common/dpmc.c
arch/blackfin/mach-common/smp.c
arch/cris/arch-v32/kernel/smp.c
arch/ia64/kernel/cpufreq/acpi-cpufreq.c
arch/ia64/kernel/cyclone.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/time.c
arch/ia64/sn/kernel/sn2/timer.c
arch/ia64/xen/irq_xen.c
arch/m32r/kernel/smp.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/stdma.c
arch/m68k/include/asm/atarikb.h
arch/m68k/include/asm/bitops_mm.h
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/Makefile_mm
arch/m68k/kernel/entry_mm.S
arch/m68k/kernel/syscalltable.S
arch/m68k/mm/motorola.c
arch/microblaze/kernel/timer.c
arch/mips/Kbuild.platforms
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/alchemy/common/dbdma.c
arch/mips/alchemy/common/dma.c
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/common/setup.c
arch/mips/alchemy/common/time.c
arch/mips/alchemy/devboards/db1200/setup.c
arch/mips/alchemy/devboards/db1x00/board_setup.c
arch/mips/alchemy/devboards/pb1000/board_setup.c
arch/mips/alchemy/devboards/pb1500/board_setup.c
arch/mips/alchemy/devboards/prom.c
arch/mips/alchemy/gpr/board_setup.c
arch/mips/alchemy/gpr/init.c
arch/mips/alchemy/mtx-1/board_setup.c
arch/mips/alchemy/mtx-1/init.c
arch/mips/alchemy/mtx-1/platform.c
arch/mips/alchemy/xxs1500/board_setup.c
arch/mips/alchemy/xxs1500/init.c
arch/mips/ar7/gpio.c
arch/mips/bcm47xx/nvram.c
arch/mips/bcm47xx/setup.c
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
arch/mips/boot/compressed/uart-alchemy.c
arch/mips/cavium-octeon/Kconfig
arch/mips/cavium-octeon/csrc-octeon.c
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/configs/nlm_xlr_defconfig [new file with mode: 0644]
arch/mips/include/asm/cache.h
arch/mips/include/asm/cevt-r4k.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/dma-mapping.h
arch/mips/include/asm/hugetlb.h
arch/mips/include/asm/i8253.h
arch/mips/include/asm/jump_label.h
arch/mips/include/asm/mach-au1x00/au1000.h
arch/mips/include/asm/mach-au1x00/au1000_dma.h
arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
arch/mips/include/asm/mach-au1x00/gpio-au1000.h
arch/mips/include/asm/mach-bcm47xx/nvram.h
arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
arch/mips/include/asm/mach-lantiq/lantiq.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/lantiq_platform.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/war.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/xway/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h [new file with mode: 0644]
arch/mips/include/asm/mach-lantiq/xway/xway_dma.h [new file with mode: 0644]
arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h [new file with mode: 0644]
arch/mips/include/asm/mach-netlogic/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-netlogic/war.h [new file with mode: 0644]
arch/mips/include/asm/module.h
arch/mips/include/asm/netlogic/interrupt.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/mips-extns.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/psb-bootinfo.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/xlr/gpio.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/xlr/iomap.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/xlr/pic.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/xlr/xlr.h [new file with mode: 0644]
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/time.h
arch/mips/jazz/jazzdma.c
arch/mips/jz4740/dma.c
arch/mips/jz4740/setup.c
arch/mips/jz4740/time.c
arch/mips/jz4740/timer.c
arch/mips/kernel/Makefile
arch/mips/kernel/cevt-txx9.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/csrc-bcm1480.c
arch/mips/kernel/csrc-ioasic.c
arch/mips/kernel/csrc-powertv.c
arch/mips/kernel/csrc-r4k.c
arch/mips/kernel/csrc-sb1250.c
arch/mips/kernel/entry.S
arch/mips/kernel/ftrace.c
arch/mips/kernel/i8253.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smtc.c
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/lantiq/Kconfig [new file with mode: 0644]
arch/mips/lantiq/Makefile [new file with mode: 0644]
arch/mips/lantiq/Platform [new file with mode: 0644]
arch/mips/lantiq/clk.c [new file with mode: 0644]
arch/mips/lantiq/clk.h [new file with mode: 0644]
arch/mips/lantiq/devices.c [new file with mode: 0644]
arch/mips/lantiq/devices.h [new file with mode: 0644]
arch/mips/lantiq/early_printk.c [new file with mode: 0644]
arch/mips/lantiq/irq.c [new file with mode: 0644]
arch/mips/lantiq/machtypes.h [new file with mode: 0644]
arch/mips/lantiq/prom.c [new file with mode: 0644]
arch/mips/lantiq/prom.h [new file with mode: 0644]
arch/mips/lantiq/setup.c [new file with mode: 0644]
arch/mips/lantiq/xway/Kconfig [new file with mode: 0644]
arch/mips/lantiq/xway/Makefile [new file with mode: 0644]
arch/mips/lantiq/xway/clk-ase.c [new file with mode: 0644]
arch/mips/lantiq/xway/clk-xway.c [new file with mode: 0644]
arch/mips/lantiq/xway/devices.c [new file with mode: 0644]
arch/mips/lantiq/xway/devices.h [new file with mode: 0644]
arch/mips/lantiq/xway/dma.c [new file with mode: 0644]
arch/mips/lantiq/xway/ebu.c [new file with mode: 0644]
arch/mips/lantiq/xway/gpio.c [new file with mode: 0644]
arch/mips/lantiq/xway/gpio_ebu.c [new file with mode: 0644]
arch/mips/lantiq/xway/gpio_stp.c [new file with mode: 0644]
arch/mips/lantiq/xway/mach-easy50601.c [new file with mode: 0644]
arch/mips/lantiq/xway/mach-easy50712.c [new file with mode: 0644]
arch/mips/lantiq/xway/pmu.c [new file with mode: 0644]
arch/mips/lantiq/xway/prom-ase.c [new file with mode: 0644]
arch/mips/lantiq/xway/prom-xway.c [new file with mode: 0644]
arch/mips/lantiq/xway/reset.c [new file with mode: 0644]
arch/mips/lantiq/xway/setup-ase.c [new file with mode: 0644]
arch/mips/lantiq/xway/setup-xway.c [new file with mode: 0644]
arch/mips/lib/Makefile
arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
arch/mips/loongson/common/env.c
arch/mips/mm/Makefile
arch/mips/mm/c-r4k.c
arch/mips/mm/mmap.c [new file with mode: 0644]
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/netlogic/Kconfig [new file with mode: 0644]
arch/mips/netlogic/xlr/Makefile [new file with mode: 0644]
arch/mips/netlogic/xlr/irq.c [new file with mode: 0644]
arch/mips/netlogic/xlr/platform.c [new file with mode: 0644]
arch/mips/netlogic/xlr/setup.c [new file with mode: 0644]
arch/mips/netlogic/xlr/smp.c [new file with mode: 0644]
arch/mips/netlogic/xlr/smpboot.S [new file with mode: 0644]
arch/mips/netlogic/xlr/time.c [new file with mode: 0644]
arch/mips/netlogic/xlr/xlr_console.c [new file with mode: 0644]
arch/mips/pci/Makefile
arch/mips/pci/ops-lantiq.c [new file with mode: 0644]
arch/mips/pci/pci-lantiq.c [new file with mode: 0644]
arch/mips/pci/pci-lantiq.h [new file with mode: 0644]
arch/mips/pci/pci-xlr.c [new file with mode: 0644]
arch/mips/pmc-sierra/msp71xx/msp_irq_per.c
arch/mips/pmc-sierra/yosemite/smp.c
arch/mips/power/hibernate.S
arch/mips/rb532/gpio.c
arch/mips/sgi-ip22/ip22-platform.c
arch/mips/sgi-ip22/ip22-time.c
arch/mips/sgi-ip27/ip27-hubio.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-klnuma.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sibyte/bcm1480/smp.c
arch/mips/sibyte/sb1250/smp.c
arch/mips/sni/time.c
arch/mn10300/kernel/smp.c
arch/parisc/kernel/smp.c
arch/parisc/mm/init.c
arch/powerpc/include/asm/8xx_immap.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/uninorth.h
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/smp.c
arch/powerpc/platforms/83xx/suspend.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/mpic.c
arch/s390/Kconfig
arch/s390/crypto/prng.c
arch/s390/include/asm/cacheflush.h
arch/s390/include/asm/diag.h
arch/s390/include/asm/ftrace.h
arch/s390/include/asm/jump_label.h [new file with mode: 0644]
arch/s390/include/asm/mmu_context.h
arch/s390/kernel/Makefile
arch/s390/kernel/diag.c
arch/s390/kernel/dis.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/jump_label.c [new file with mode: 0644]
arch/s390/kernel/smp.c
arch/s390/kvm/sie64a.S
arch/s390/mm/cmm.c
arch/s390/mm/fault.c
arch/s390/mm/pageattr.c
arch/s390/oprofile/hwsampler.c
arch/s390/oprofile/hwsampler.h
arch/s390/oprofile/init.c
arch/sh/Kconfig
arch/sh/configs/apsh4ad0a_defconfig
arch/sh/configs/sdk7786_defconfig
arch/sh/kernel/cpu/shmobile/pm_runtime.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/smp.c
arch/sparc/include/asm/jump_label.h
arch/sparc/include/asm/topology_64.h
arch/sparc/kernel/apc.c
arch/sparc/kernel/pci_sabre.c
arch/sparc/kernel/pci_schizo.c
arch/sparc/kernel/pmc.c
arch/sparc/kernel/smp_32.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/time_32.c
arch/sparc/lib/checksum_32.S
arch/tile/kernel/smp.c
arch/um/Kconfig.um
arch/um/include/asm/thread_info.h
arch/um/kernel/smp.c
arch/um/os-Linux/util.c
arch/um/sys-i386/Makefile
arch/um/sys-i386/atomic64_cx8_32.S [new file with mode: 0644]
arch/unicore32/kernel/irq.c
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Makefile_32.cpu
arch/x86/boot/memory.c
arch/x86/include/asm/acpi.h
arch/x86/include/asm/alternative-asm.h
arch/x86/include/asm/alternative.h
arch/x86/include/asm/amd_iommu_proto.h
arch/x86/include/asm/amd_iommu_types.h
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/apicdef.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/dma.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/ftrace.h
arch/x86/include/asm/gart.h
arch/x86/include/asm/i8253.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/jump_label.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mmzone_32.h
arch/x86/include/asm/mmzone_64.h
arch/x86/include/asm/module.h
arch/x86/include/asm/nops.h
arch/x86/include/asm/numa.h
arch/x86/include/asm/numa_32.h
arch/x86/include/asm/numa_64.h
arch/x86/include/asm/numaq.h
arch/x86/include/asm/olpc_ofw.h
arch/x86/include/asm/percpu.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/probe_roms.h [new file with mode: 0644]
arch/x86/include/asm/processor-flags.h
arch/x86/include/asm/setup.h
arch/x86/include/asm/srat.h [deleted file]
arch/x86/include/asm/stacktrace.h
arch/x86/include/asm/system.h
arch/x86/include/asm/topology.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/include/asm/uv/uv_mmrs.h
arch/x86/include/asm/x86_init.h
arch/x86/include/asm/xen/page.h
arch/x86/include/asm/xen/pci.h
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/alternative.c
arch/x86/kernel/amd_gart_64.c [moved from arch/x86/kernel/pci-gart_64.c with 98% similarity]
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apb_timer.c
arch/x86/kernel/aperture_64.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_noop.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apic/summit_32.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpufreq/Makefile [deleted file]
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/devicetree.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/head32.c
arch/x86/kernel/hpet.c
arch/x86/kernel/i8253.c
arch/x86/kernel/irq.c
arch/x86/kernel/jump_label.c
arch/x86/kernel/kprobes.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/module.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/pci-iommu_table.c
arch/x86/kernel/probe_roms.c [moved from arch/x86/kernel/probe_roms_32.c with 65% similarity]
arch/x86/kernel/process.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/reboot.c
arch/x86/kernel/reboot_32.S
arch/x86/kernel/setup.c
arch/x86/kernel/smp.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/x86_init.c
arch/x86/lguest/boot.c
arch/x86/lib/clear_page_64.S
arch/x86/lib/copy_user_64.S
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S
arch/x86/mm/Makefile
arch/x86/mm/amdtopology.c [moved from arch/x86/mm/amdtopology_64.c with 90% similarity]
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa.c
arch/x86/mm/numa_32.c
arch/x86/mm/numa_64.c
arch/x86/mm/numa_emulation.c
arch/x86/mm/numa_internal.h
arch/x86/mm/srat.c [moved from arch/x86/mm/srat_64.c with 67% similarity]
arch/x86/mm/srat_32.c [deleted file]
arch/x86/oprofile/backtrace.c
arch/x86/pci/xen.c
arch/x86/platform/ce4100/falconfalls.dts
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/mrst/mrst.c
arch/x86/platform/olpc/Makefile
arch/x86/platform/olpc/olpc.c
arch/x86/platform/olpc/olpc_dt.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/platform/uv/uv_time.c
arch/x86/xen/enlighten.c
arch/x86/xen/irq.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/x86/xen/time.c
arch/x86/xen/xen-ops.h
arch/xtensa/kernel/irq.c
block/blk-cgroup.c
block/blk-cgroup.h
block/blk-core.c
block/blk-sysfs.c
block/blk-throttle.c
block/blk.h
block/cfq-iosched.c
block/elevator.c
block/genhd.c
drivers/Kconfig
drivers/acpi/processor_perflib.c
drivers/acpi/processor_throttling.c
drivers/acpi/scan.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_at91.c
drivers/atm/fore200e.c
drivers/base/Kconfig
drivers/base/base.h
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/Makefile
drivers/base/power/clock_ops.c [new file with mode: 0644]
drivers/base/power/generic_ops.c
drivers/base/power/main.c
drivers/base/power/runtime.c
drivers/base/power/sysfs.c
drivers/base/power/wakeup.c
drivers/base/sys.c
drivers/base/syscore.c
drivers/block/DAC960.c
drivers/block/amiflop.c
drivers/block/ataflop.c
drivers/block/floppy.c
drivers/block/paride/pcd.c
drivers/block/paride/pd.c
drivers/block/paride/pf.c
drivers/block/rbd.c
drivers/block/swim.c
drivers/block/swim3.c
drivers/block/ub.c
drivers/block/xsysace.c
drivers/cdrom/cdrom.c
drivers/cdrom/gdrom.c
drivers/cdrom/viocd.c
drivers/char/agp/generic.c
drivers/char/hpet.c
drivers/char/hw_random/n2-drv.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/virtio_console.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/clk/clkdev.c
drivers/clocksource/Kconfig [new file with mode: 0644]
drivers/clocksource/Makefile
drivers/clocksource/cyclone.c
drivers/clocksource/i8253.c [new file with mode: 0644]
drivers/connector/connector.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.x86 [moved from arch/x86/kernel/cpu/cpufreq/Kconfig with 97% similarity]
drivers/cpufreq/Makefile
drivers/cpufreq/acpi-cpufreq.c [moved from arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c with 94% similarity]
drivers/cpufreq/cpufreq-nforce2.c [moved from arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c with 97% similarity]
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_performance.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/e_powersaver.c [moved from arch/x86/kernel/cpu/cpufreq/e_powersaver.c with 100% similarity]
drivers/cpufreq/elanfreq.c [moved from arch/x86/kernel/cpu/cpufreq/elanfreq.c with 100% similarity]
drivers/cpufreq/freq_table.c
drivers/cpufreq/gx-suspmod.c [moved from arch/x86/kernel/cpu/cpufreq/gx-suspmod.c with 95% similarity]
drivers/cpufreq/longhaul.c [moved from arch/x86/kernel/cpu/cpufreq/longhaul.c with 98% similarity]
drivers/cpufreq/longhaul.h [moved from arch/x86/kernel/cpu/cpufreq/longhaul.h with 100% similarity]
drivers/cpufreq/longrun.c [moved from arch/x86/kernel/cpu/cpufreq/longrun.c with 94% similarity]
drivers/cpufreq/mperf.c [moved from arch/x86/kernel/cpu/cpufreq/mperf.c with 100% similarity]
drivers/cpufreq/mperf.h [moved from arch/x86/kernel/cpu/cpufreq/mperf.h with 100% similarity]
drivers/cpufreq/p4-clockmod.c [moved from arch/x86/kernel/cpu/cpufreq/p4-clockmod.c with 96% similarity]
drivers/cpufreq/pcc-cpufreq.c [moved from arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c with 91% similarity]
drivers/cpufreq/powernow-k6.c [moved from arch/x86/kernel/cpu/cpufreq/powernow-k6.c with 100% similarity]
drivers/cpufreq/powernow-k7.c [moved from arch/x86/kernel/cpu/cpufreq/powernow-k7.c with 95% similarity]
drivers/cpufreq/powernow-k7.h [moved from arch/x86/kernel/cpu/cpufreq/powernow-k7.h with 100% similarity]
drivers/cpufreq/powernow-k8.c [moved from arch/x86/kernel/cpu/cpufreq/powernow-k8.c with 93% similarity]
drivers/cpufreq/powernow-k8.h [moved from arch/x86/kernel/cpu/cpufreq/powernow-k8.h with 98% similarity]
drivers/cpufreq/sc520_freq.c [moved from arch/x86/kernel/cpu/cpufreq/sc520_freq.c with 95% similarity]
drivers/cpufreq/speedstep-centrino.c [moved from arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c with 96% similarity]
drivers/cpufreq/speedstep-ich.c [moved from arch/x86/kernel/cpu/cpufreq/speedstep-ich.c with 92% similarity]
drivers/cpufreq/speedstep-lib.c [moved from arch/x86/kernel/cpu/cpufreq/speedstep-lib.c with 90% similarity]
drivers/cpufreq/speedstep-lib.h [moved from arch/x86/kernel/cpu/cpufreq/speedstep-lib.h with 100% similarity]
drivers/cpufreq/speedstep-smi.c [moved from arch/x86/kernel/cpu/cpufreq/speedstep-smi.c with 90% similarity]
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/edac_mc_sysfs.c
drivers/edac/ppc4xx_edac.c
drivers/firewire/ohci.c
drivers/firmware/edd.c
drivers/firmware/iscsi_ibft_find.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_notifier.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv50_instmem.c
drivers/gpu/drm/nouveau/nv50_vm.c
drivers/gpu/drm/nouveau/nvc0_vm.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/gpu/vga/vga_switcheroo.c
drivers/hwmon/Kconfig
drivers/hwmon/lm85.c
drivers/hwmon/lm90.c
drivers/hwmon/pmbus_core.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-pnx.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd_ioctl.c
drivers/ide/ide-gd.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/provider.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_pcie.c
drivers/input/keyboard/atakbd.c
drivers/input/mouse/atarimouse.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/wm831x-ts.c
drivers/leds/leds-lm3530.c
drivers/lguest/Kconfig
drivers/lguest/Makefile
drivers/md/md.c
drivers/md/raid5.c
drivers/media/common/tuners/tda18271-common.c
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/tda18271-maps.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/ngene/ngene-core.c
drivers/media/media-entity.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/saa7706h.c
drivers/media/radio/tef6862.c
drivers/media/rc/imon.c
drivers/media/rc/ite-cir.c
drivers/media/rc/mceusb.c
drivers/media/rc/rc-main.c
drivers/media/video/Kconfig
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx88/cx88-input.c
drivers/media/video/imx074.c
drivers/media/video/m52790.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/isp.h
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/omap3isp/ispqueue.c
drivers/media/video/omap3isp/ispresizer.c
drivers/media/video/omap3isp/ispstat.h
drivers/media/video/omap3isp/ispvideo.c
drivers/media/video/omap3isp/ispvideo.h
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_mobile_csi2.c
drivers/media/video/soc_camera.c
drivers/media/video/tda9840.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/v4l2-subdev.c
drivers/media/video/videobuf-dma-contig.c
drivers/media/video/videobuf2-core.c
drivers/media/video/videobuf2-dma-contig.c
drivers/message/i2o/i2o_block.c
drivers/mfd/asic3.c
drivers/mfd/omap-usb-host.c
drivers/mfd/twl4030-power.c
drivers/mmc/core/bus.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-of-core.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/lantiq-flash.c [new file with mode: 0644]
drivers/mtd/maps/physmap_of.c
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/diskonchip.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/amd8111e.c
drivers/net/arm/etherh.c
drivers/net/atarilance.c
drivers/net/atl1c/atl1c.h
drivers/net/atl1c/atl1c_main.c
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/bna/bfa_ioc.c
drivers/net/bna/bfa_ioc.h
drivers/net/bna/bfa_ioc_ct.c
drivers/net/bna/bfi.h
drivers/net/bna/bnad.c
drivers/net/bnx2.c
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bnx2x/bnx2x_ethtool.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/slcan.c
drivers/net/ehea/ehea_ethtool.c
drivers/net/ehea/ehea_main.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fs_enet/mac-fec.c
drivers/net/fs_enet/mii-fec.c
drivers/net/ftmac100.c
drivers/net/hydra.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/lantiq_etop.c [new file with mode: 0644]
drivers/net/loopback.c
drivers/net/macvlan.c
drivers/net/mii.c
drivers/net/natsemi.c
drivers/net/ne-h8300.c
drivers/net/netconsole.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_main.c
drivers/net/pch_gbe/pch_gbe_main.c
drivers/net/qlcnic/qlcnic.h
drivers/net/qlcnic/qlcnic_main.c
drivers/net/r8169.c
drivers/net/sfc/efx.c
drivers/net/sfc/io.h
drivers/net/sfc/mcdi.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/sfc/nic.h
drivers/net/sfc/selftest.c
drivers/net/sfc/siena.c
drivers/net/sfc/tx.c
drivers/net/sis900.c
drivers/net/slip.c
drivers/net/stmmac/dwmac_lib.c
drivers/net/stmmac/stmmac_main.c
drivers/net/sunhme.c
drivers/net/tg3.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/olympic.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/ipheth.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/regd_common.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/iwlegacy/Kconfig
drivers/net/wireless/iwlegacy/iwl-3945-hw.h
drivers/net/wireless/iwlegacy/iwl-4965-hw.h
drivers/net/wireless/iwlegacy/iwl-4965-tx.c
drivers/net/wireless/iwlegacy/iwl-core.c
drivers/net/wireless/iwlegacy/iwl-dev.h
drivers/net/wireless/iwlegacy/iwl-eeprom.c
drivers/net/wireless/iwlegacy/iwl-led.c
drivers/net/wireless/iwlegacy/iwl3945-base.c
drivers/net/wireless/iwlegacy/iwl4965-base.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/p54/txrx.c
drivers/net/zorro8390.c
drivers/parport/parport_pc.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/intel-iommu.c
drivers/pci/iov.c
drivers/pci/pci.h
drivers/pci/setup-bus.c
drivers/pcmcia/pcmcia_resource.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/rapidio/switches/idt_gen2.c
drivers/rapidio/switches/idtcps.c
drivers/rapidio/switches/tsi57x.c
drivers/rtc/Kconfig
drivers/rtc/class.c
drivers/rtc/rtc-coh901331.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1286.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-max8925.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-msm6242.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcap.c
drivers/rtc/rtc-rp5c01.c
drivers/rtc/rtc-s3c.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/tape_block.c
drivers/s390/cio/qdio_main.c
drivers/s390/kvm/kvm_virtio.c
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/pmcraid.c
drivers/scsi/qlogicpti.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/ssb/pci.c
drivers/ssb/sprom.c
drivers/ssb/ssb_private.h
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
drivers/staging/gma500/Kconfig
drivers/staging/intel_sst/intelmid_v1_control.c
drivers/staging/intel_sst/intelmid_v2_control.c
drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
drivers/staging/rt2860/common/cmm_data_pci.c
drivers/staging/rt2860/common/cmm_data_usb.c
drivers/staging/rts_pstor/debug.h
drivers/staging/rts_pstor/ms.c
drivers/staging/rts_pstor/rtsx_chip.c
drivers/staging/rts_pstor/rtsx_scsi.c
drivers/staging/rts_pstor/sd.c
drivers/staging/rts_pstor/trace.h
drivers/staging/rts_pstor/xd.c
drivers/staging/solo6x10/Kconfig
drivers/staging/spectra/ffsport.c
drivers/staging/tidspbridge/dynload/cload.c
drivers/staging/tty/specialix.c
drivers/staging/usbip/vhci_hcd.c
drivers/staging/usbip/vhci_sysfs.c
drivers/staging/wlan-ng/cfg80211.c
drivers/tty/n_gsm.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/imx.c
drivers/tty/serial/lantiq.c [new file with mode: 0644]
drivers/tty/serial/of_serial.c
drivers/usb/gadget/fsl_qe_udc.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/omap2430.c
drivers/vhost/vhost.c
drivers/video/acornfb.c
drivers/video/atafb.c
drivers/video/fbmem.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/lantiq_wdt.c [new file with mode: 0644]
drivers/watchdog/mpc8xxx_wdt.c
drivers/watchdog/mtx-1_wdt.c
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/events.c
drivers/xen/gntalloc.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/manage.c
drivers/xen/sys-hypervisor.c
fs/block_dev.c
fs/btrfs/acl.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifs_unicode.c
fs/cifs/connect.c
fs/cifs/sess.c
fs/configfs/dir.c
fs/dcache.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c
fs/ecryptfs/super.c
fs/file.c
fs/fuse/dir.c
fs/gfs2/aops.c
fs/gfs2/dir.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/ops_fstype.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/hpfs/Kconfig
fs/hpfs/alloc.c
fs/hpfs/anode.c
fs/hpfs/buffer.c
fs/hpfs/dir.c
fs/hpfs/dnode.c
fs/hpfs/ea.c
fs/hpfs/file.c
fs/hpfs/hpfs.h
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/map.c
fs/hpfs/name.c
fs/hpfs/namei.c
fs/hpfs/super.c
fs/logfs/super.c
fs/namei.c
fs/nfs/namespace.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
fs/nilfs2/alloc.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/file.c
fs/ocfs2/journal.c
fs/ocfs2/ocfs2_fs.h
fs/partitions/efi.c
fs/proc/task_mmu.c
fs/ubifs/log.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/super.c
fs/xattr.c
fs/xfs/linux-2.6/xfs_message.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_trans_ail.c
include/asm-generic/vmlinux.lds.h
include/drm/drm_fb_helper.h
include/drm/drm_mm.h
include/drm/drm_pciids.h
include/drm/radeon_drm.h
include/linux/alarmtimer.h [new file with mode: 0644]
include/linux/bit_spinlock.h
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/bsearch.h [new file with mode: 0644]
include/linux/capability.h
include/linux/clockchips.h
include/linux/clocksource.h
include/linux/cpufreq.h
include/linux/cred.h
include/linux/dcache.h
include/linux/device.h
include/linux/dynamic_debug.h
include/linux/fb.h
include/linux/flex_array.h
include/linux/fs.h
include/linux/ftrace.h
include/linux/ftrace_event.h
include/linux/gfp.h
include/linux/huge_mm.h
include/linux/init.h
include/linux/init_task.h
include/linux/interrupt.h
include/linux/irq.h
include/linux/irqdesc.h
include/linux/jump_label.h
include/linux/jump_label_ref.h [deleted file]
include/linux/kernel.h
include/linux/kmod.h
include/linux/libata.h
include/linux/list.h
include/linux/list_bl.h
include/linux/mfd/wm831x/pdata.h
include/linux/mm.h
include/linux/module.h
include/linux/moduleparam.h
include/linux/mutex.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/of_device.h
include/linux/pci-ats.h [new file with mode: 0644]
include/linux/pci_ids.h
include/linux/percpu.h
include/linux/perf_event.h
include/linux/platform_device.h
include/linux/pm.h
include/linux/pm_runtime.h
include/linux/posix-clock.h
include/linux/posix-timers.h
include/linux/proc_fs.h
include/linux/ptrace.h
include/linux/rbtree.h
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/sched.h
include/linux/security.h
include/linux/seqlock.h
include/linux/signal.h
include/linux/ssb/ssb.h
include/linux/sunrpc/sched.h
include/linux/sysdev.h
include/linux/time.h
include/linux/timerqueue.h
include/linux/tracepoint.h
include/linux/usb/usbnet.h
include/linux/v4l2-mediabus.h
include/linux/videodev2.h
include/media/v4l2-device.h
include/net/inet_ecn.h
include/net/ip_vs.h
include/net/llc_pdu.h
include/net/sctp/sctp.h
include/net/xfrm.h
include/rdma/iw_cm.h
include/rdma/rdma_cm.h
include/rdma/rdma_user_cm.h
include/scsi/scsi_device.h
include/trace/events/gfpflags.h
include/trace/events/irq.h
include/xen/events.h
init/Kconfig
init/main.c
kernel/Makefile
kernel/capability.c
kernel/cgroup.c
kernel/cpuset.c
kernel/cred.c
kernel/events/Makefile [new file with mode: 0644]
kernel/events/core.c [moved from kernel/perf_event.c with 99% similarity]
kernel/events/hw_breakpoint.c [moved from kernel/hw_breakpoint.c with 100% similarity]
kernel/exit.c
kernel/extable.c
kernel/fork.c
kernel/freezer.c
kernel/hrtimer.c
kernel/hung_task.c
kernel/irq/Kconfig
kernel/irq/Makefile
kernel/irq/chip.c
kernel/irq/debug.h
kernel/irq/generic-chip.c [new file with mode: 0644]
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/irq/settings.h
kernel/jump_label.c
kernel/kexec.c
kernel/kmod.c
kernel/lockdep.c
kernel/module.c
kernel/mutex-debug.c
kernel/mutex-debug.h
kernel/mutex.c
kernel/mutex.h
kernel/params.c
kernel/power/Kconfig
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/power.h
kernel/power/snapshot.c
kernel/power/suspend.c
kernel/power/user.c
kernel/ptrace.c
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched.c
kernel/sched_debug.c
kernel/sched_fair.c
kernel/sched_features.h
kernel/sched_idletask.c
kernel/sched_rt.c
kernel/sched_stoptask.c
kernel/softirq.c
kernel/sys.c
kernel/time/Makefile
kernel/time/alarmtimer.c [new file with mode: 0644]
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/posix-clock.c
kernel/time/tick-broadcast.c
kernel/time/timekeeping.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events.c
kernel/trace/trace_functions.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_output.c
kernel/trace/trace_printk.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_selftest.c
kernel/trace/trace_selftest_dynamic.c
kernel/trace/trace_stack.c
kernel/tracepoint.c
kernel/watchdog.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/bsearch.c [new file with mode: 0644]
lib/dma-debug.c
lib/flex_array.c
lib/vsprintf.c
lib/xz/xz_dec_lzma2.c
mm/huge_memory.c
mm/kmemleak.c
mm/memory.c
mm/mlock.c
mm/mmap.c
mm/oom_kill.c
mm/page_alloc.c
mm/page_cgroup.c
mm/shmem.c
mm/slub.c
mm/swap.c
mm/vmscan.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/9p/client.c
net/9p/protocol.c
net/9p/trans_common.c
net/batman-adv/gateway_client.c
net/batman-adv/originator.c
net/batman-adv/soft-interface.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bridge/br_input.c
net/bridge/br_netfilter.c
net/bridge/netfilter/ebtables.c
net/caif/cfdgml.c
net/caif/cfmuxl.c
net/can/bcm.c
net/can/raw.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/drop_monitor.c
net/core/gen_estimator.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/dccp/options.c
net/decnet/dn_dev.c
net/dsa/Kconfig
net/dsa/mv88e6131.c
net/ieee802154/Makefile
net/ipv4/devinet.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/igmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inetpeer.c
net/ipv4/ip_fragment.c
net/ipv4/ip_options.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_cubic.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_state.c
net/ipv6/addrconf.c
net/ipv6/esp6.c
net/ipv6/inet6_connection_sock.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/udp.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_state.c
net/irda/af_irda.c
net/l2tp/l2tp_ip.c
net/llc/llc_input.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/tx.c
net/mac80211/work.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/ip_vs_app.c
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_est.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_extend.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/x_tables.c
net/netfilter/xt_DSCP.c
net/netfilter/xt_conntrack.c
net/netfilter/xt_osf.c
net/netfilter/xt_set.c
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/phonet/pn_dev.c
net/sched/act_api.c
net/sched/act_police.c
net/sctp/associola.c
net/sctp/bind_addr.c
net/sctp/ipv6.c
net/sctp/protocol.c
net/sctp/ulpevent.c
net/socket.c
net/sunrpc/Kconfig
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/unix/af_unix.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_user.c
scripts/Makefile.build
scripts/kconfig/conf.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/module-common.lds
scripts/recordmcount.c
scripts/recordmcount.h
scripts/recordmcount.pl
security/capability.c
security/keys/user_defined.c
security/security.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/avc.h
security/selinux/netif.c
security/selinux/ss/policydb.c
security/smack/smack_lsm.c
sound/aoa/codecs/tas.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/codecs/jz4740.c
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/mid-x86/sst_platform.c
sound/soc/samsung/goni_wm8994.c
sound/soc/samsung/pcm.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
sound/soc/tegra/harmony.c
sound/usb/format.c
sound/usb/quirks.c
tools/perf/Documentation/perf-script-perl.txt
tools/perf/Documentation/perf-script-python.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Makefile
tools/perf/builtin-record.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/config/feature-tests.mak [moved from tools/perf/feature-tests.mak with 86% similarity]
tools/perf/config/utilities.mak [new file with mode: 0644]
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/include/asm/alternative-asm.h [new file with mode: 0644]
tools/perf/util/parse-events.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/trace-event-parse.c
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/hists.c

index c17cd4bb2290895ee209764708efcb372815b8bb..1b777b9604921396c47497e4bf919adb3d51c0f4 100644 (file)
@@ -328,8 +328,6 @@ sysrq.txt
        - info on the magic SysRq key.
 telephony/
        - directory with info on telephony (e.g. voice over IP) support.
-uml/
-       - directory with information about User Mode Linux.
 unicode.txt
        - info on the Unicode character/font mapping used in Linux.
 unshare.txt
index 7564e88bfa431cb588584c72e8d6e1b040016793..e7be75b96e4bcae77caec52d3e00fa3d7d725204 100644 (file)
@@ -183,21 +183,21 @@ Description:      Discover and change clock speed of CPUs
                to learn how to control the knobs.
 
 
-What:      /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X
-Date:      August 2008
+What:          /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
+Date:          August 2008
 KernelVersion: 2.6.27
-Contact:       mark.langsdorf@amd.com
-Description:   These files exist in every cpu's cache index directories.
-               There are currently 2 cache_disable_# files in each
-               directory.  Reading from these files on a supported
-               processor will return that cache disable index value
-               for that processor and node.  Writing to one of these
-               files will cause the specificed cache index to be disabled.
-
-               Currently, only AMD Family 10h Processors support cache index
-               disable, and only for their L3 caches.  See the BIOS and
-               Kernel Developer's Guide at
-               http://support.amd.com/us/Embedded_TechDocs/31116-Public-GH-BKDG_3-28_5-28-09.pdf       
-               for formatting information and other details on the
-               cache index disable.
-Users:    joachim.deguara@amd.com
+Contact:       discuss@x86-64.org
+Description:   Disable L3 cache indices
+
+               These files exist in every CPU's cache/index3 directory. Each
+               cache_disable_{0,1} file corresponds to one disable slot which
+               can be used to disable a cache index. Reading from these files
+               on a processor with this functionality will return the currently
+               disabled index for that node. There is one L3 structure per
+               node, or per internal node on MCM machines. Writing a valid
+               index to one of these files will cause the specificed cache
+               index to be disabled.
+
+               All AMD processors with L3 caches provide this functionality.
+               For details, see BKDGs at
+               http://developer.amd.com/documentation/guides/Pages/default.aspx
index 194ca446ac287692333040ca76235503af8738a9..b464d12761baf81023bb35da2e3aba01049fc81a 100644 (file)
@@ -158,3 +158,17 @@ Description:
                successful, will make the kernel abort a subsequent transition
                to a sleep state if any wakeup events are reported after the
                write has returned.
+
+What:          /sys/power/reserved_size
+Date:          May 2011
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power/reserved_size file allows user space to control
+               the amount of memory reserved for allocations made by device
+               drivers during the "device freeze" stage of hibernation.  It can
+               be written a string representing a non-negative integer that
+               will be used as the amount of memory to reserve for allocations
+               made by device drivers' "freeze" callbacks, in bytes.
+
+               Reading from this file will display the current value, which is
+               set to 1 MB by default.
index fb10fd08c05cd00a49a4276f06842299e092b4a7..b3422341d65c7ae07c14b743c328cae15c529d17 100644 (file)
        <para>
        Whenever an interrupt triggers, the lowlevel arch code calls into
        the generic interrupt code by calling desc->handle_irq().
-       This highlevel IRQ handling function only uses desc->chip primitives
-       referenced by the assigned chip descriptor structure.
+       This highlevel IRQ handling function only uses desc->irq_data.chip
+       primitives referenced by the assigned chip descriptor structure.
        </para>
     </sect1>
     <sect1 id="Highlevel_Driver_API">
          <listitem><para>enable_irq()</para></listitem>
          <listitem><para>disable_irq_nosync() (SMP only)</para></listitem>
          <listitem><para>synchronize_irq() (SMP only)</para></listitem>
-         <listitem><para>set_irq_type()</para></listitem>
-         <listitem><para>set_irq_wake()</para></listitem>
-         <listitem><para>set_irq_data()</para></listitem>
-         <listitem><para>set_irq_chip()</para></listitem>
-         <listitem><para>set_irq_chip_data()</para></listitem>
+         <listitem><para>irq_set_irq_type()</para></listitem>
+         <listitem><para>irq_set_irq_wake()</para></listitem>
+         <listitem><para>irq_set_handler_data()</para></listitem>
+         <listitem><para>irq_set_chip()</para></listitem>
+         <listitem><para>irq_set_chip_data()</para></listitem>
           </itemizedlist>
          See the autogenerated function documentation for details.
        </para>
          <listitem><para>handle_fasteoi_irq</para></listitem>
          <listitem><para>handle_simple_irq</para></listitem>
          <listitem><para>handle_percpu_irq</para></listitem>
+         <listitem><para>handle_edge_eoi_irq</para></listitem>
+         <listitem><para>handle_bad_irq</para></listitem>
          </itemizedlist>
          The interrupt flow handlers (either predefined or architecture
          specific) are assigned to specific interrupts by the architecture
                <programlisting>
 default_enable(struct irq_data *data)
 {
-       desc->chip->irq_unmask(data);
+       desc->irq_data.chip->irq_unmask(data);
 }
 
 default_disable(struct irq_data *data)
 {
        if (!delay_disable(data))
-               desc->chip->irq_mask(data);
+               desc->irq_data.chip->irq_mask(data);
 }
 
 default_ack(struct irq_data *data)
@@ -284,9 +286,9 @@ noop(struct irq_data *data))
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-desc->chip->irq_mask();
-handle_IRQ_event(desc->action);
-desc->chip->irq_unmask();
+desc->irq_data.chip->irq_mask_ack();
+handle_irq_event(desc->action);
+desc->irq_data.chip->irq_unmask();
                </programlisting>
                </para>
            </sect3>
@@ -300,8 +302,8 @@ desc->chip->irq_unmask();
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-handle_IRQ_event(desc->action);
-desc->chip->irq_eoi();
+handle_irq_event(desc->action);
+desc->irq_data.chip->irq_eoi();
                </programlisting>
                </para>
            </sect3>
@@ -315,17 +317,17 @@ desc->chip->irq_eoi();
                The following control flow is implemented (simplified excerpt):
                <programlisting>
 if (desc->status &amp; running) {
-       desc->chip->irq_mask();
+       desc->irq_data.chip->irq_mask_ack();
        desc->status |= pending | masked;
        return;
 }
-desc->chip->irq_ack();
+desc->irq_data.chip->irq_ack();
 desc->status |= running;
 do {
        if (desc->status &amp; masked)
-               desc->chip->irq_unmask();
+               desc->irq_data.chip->irq_unmask();
        desc->status &amp;= ~pending;
-       handle_IRQ_event(desc->action);
+       handle_irq_event(desc->action);
 } while (status &amp; pending);
 desc->status &amp;= ~running;
                </programlisting>
@@ -344,7 +346,7 @@ desc->status &amp;= ~running;
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-handle_IRQ_event(desc->action);
+handle_irq_event(desc->action);
                </programlisting>
                </para>
            </sect3>
@@ -362,12 +364,29 @@ handle_IRQ_event(desc->action);
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-handle_IRQ_event(desc->action);
-if (desc->chip->irq_eoi)
-        desc->chip->irq_eoi();
+if (desc->irq_data.chip->irq_ack)
+       desc->irq_data.chip->irq_ack();
+handle_irq_event(desc->action);
+if (desc->irq_data.chip->irq_eoi)
+        desc->irq_data.chip->irq_eoi();
                </programlisting>
                </para>
            </sect3>
+           <sect3 id="EOI_Edge_IRQ_flow_handler">
+               <title>EOI Edge IRQ flow handler</title>
+               <para>
+               handle_edge_eoi_irq provides an abnomination of the edge
+               handler which is solely used to tame a badly wreckaged
+               irq controller on powerpc/cell.
+               </para>
+           </sect3>
+           <sect3 id="BAD_IRQ_flow_handler">
+               <title>Bad IRQ flow handler</title>
+               <para>
+               handle_bad_irq is used for spurious interrupts which
+               have no real handler assigned..
+               </para>
+           </sect3>
        </sect2>
        <sect2 id="Quirks_and_optimizations">
        <title>Quirks and optimizations</title>
@@ -410,6 +429,7 @@ if (desc->chip->irq_eoi)
          <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
          <listitem><para>irq_mask()</para></listitem>
          <listitem><para>irq_unmask()</para></listitem>
+         <listitem><para>irq_eoi() - Optional, required for eoi flow handlers</para></listitem>
          <listitem><para>irq_retrigger() - Optional</para></listitem>
          <listitem><para>irq_set_type() - Optional</para></listitem>
          <listitem><para>irq_set_wake() - Optional</para></listitem>
@@ -424,32 +444,24 @@ if (desc->chip->irq_eoi)
   <chapter id="doirq">
      <title>__do_IRQ entry point</title>
      <para>
-       The original implementation __do_IRQ() is an alternative entry
-       point for all types of interrupts.
+       The original implementation __do_IRQ() was an alternative entry
+       point for all types of interrupts. It not longer exists.
      </para>
      <para>
        This handler turned out to be not suitable for all
        interrupt hardware and was therefore reimplemented with split
-       functionality for egde/level/simple/percpu interrupts. This is not
+       functionality for edge/level/simple/percpu interrupts. This is not
        only a functional optimization. It also shortens code paths for
        interrupts.
       </para>
-      <para>
-       To make use of the split implementation, replace the call to
-       __do_IRQ by a call to desc->handle_irq() and associate
-        the appropriate handler function to desc->handle_irq().
-       In most cases the generic handler implementations should
-       be sufficient.
-     </para>
   </chapter>
 
   <chapter id="locking">
      <title>Locking on SMP</title>
      <para>
        The locking of chip registers is up to the architecture that
-       defines the chip primitives. There is a chip->lock field that can be used
-       for serialization, but the generic layer does not touch it. The per-irq
-       structure is protected via desc->lock, by the generic layer.
+       defines the chip primitives. The per-irq structure is
+       protected via desc->lock, by the generic layer.
      </para>
   </chapter>
   <chapter id="structs">
index 5d259c632cdfdb8af5627b990271d79201bb0c92..fea63b45471aadce771b99ce3874abb5ef2c9c36 100644 (file)
 <!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
+<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
index 2331e76ded17d652be38fdf24fdb1de848740b7e..cec97af4dab47cb924966439fbe771dbcbdea12a 100644 (file)
@@ -34,7 +34,7 @@
       <varlistentry>
        <term><parameter>request</parameter></term>
        <listitem>
-         <para>MEDIA_IOC_ENUM_LINKS</para>
+         <para>MEDIA_IOC_SETUP_LINK</para>
        </listitem>
       </varlistentry>
       <varlistentry>
diff --git a/Documentation/DocBook/v4l/pixfmt-y12.xml b/Documentation/DocBook/v4l/pixfmt-y12.xml
new file mode 100644 (file)
index 0000000..ff417b8
--- /dev/null
@@ -0,0 +1,79 @@
+<refentry id="V4L2-PIX-FMT-Y12">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y12 ('Y12 ')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y12</constant></refname>
+    <refpurpose>Grey-scale image</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a grey-scale image with a depth of 12 bits per pixel. Pixels
+are stored in 16-bit words with unused high bits padded with 0. The least
+significant byte is stored at lower memory addresses (little-endian).</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y12</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+       <title>Byte Order.</title>
+       <para>Each cell is one byte.
+         <informaltable frame="none">
+           <tgroup cols="9" align="center">
+             <colspec align="left" colwidth="2*" />
+             <tbody valign="top">
+               <row>
+                 <entry>start&nbsp;+&nbsp;0:</entry>
+                 <entry>Y'<subscript>00low</subscript></entry>
+                 <entry>Y'<subscript>00high</subscript></entry>
+                 <entry>Y'<subscript>01low</subscript></entry>
+                 <entry>Y'<subscript>01high</subscript></entry>
+                 <entry>Y'<subscript>02low</subscript></entry>
+                 <entry>Y'<subscript>02high</subscript></entry>
+                 <entry>Y'<subscript>03low</subscript></entry>
+                 <entry>Y'<subscript>03high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;8:</entry>
+                 <entry>Y'<subscript>10low</subscript></entry>
+                 <entry>Y'<subscript>10high</subscript></entry>
+                 <entry>Y'<subscript>11low</subscript></entry>
+                 <entry>Y'<subscript>11high</subscript></entry>
+                 <entry>Y'<subscript>12low</subscript></entry>
+                 <entry>Y'<subscript>12high</subscript></entry>
+                 <entry>Y'<subscript>13low</subscript></entry>
+                 <entry>Y'<subscript>13high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;16:</entry>
+                 <entry>Y'<subscript>20low</subscript></entry>
+                 <entry>Y'<subscript>20high</subscript></entry>
+                 <entry>Y'<subscript>21low</subscript></entry>
+                 <entry>Y'<subscript>21high</subscript></entry>
+                 <entry>Y'<subscript>22low</subscript></entry>
+                 <entry>Y'<subscript>22high</subscript></entry>
+                 <entry>Y'<subscript>23low</subscript></entry>
+                 <entry>Y'<subscript>23high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;24:</entry>
+                 <entry>Y'<subscript>30low</subscript></entry>
+                 <entry>Y'<subscript>30high</subscript></entry>
+                 <entry>Y'<subscript>31low</subscript></entry>
+                 <entry>Y'<subscript>31high</subscript></entry>
+                 <entry>Y'<subscript>32low</subscript></entry>
+                 <entry>Y'<subscript>32high</subscript></entry>
+                 <entry>Y'<subscript>33low</subscript></entry>
+                 <entry>Y'<subscript>33high</subscript></entry>
+               </row>
+             </tbody>
+           </tgroup>
+         </informaltable>
+       </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
index c6fdcbbd1b41dc7adbffc0011ac34a291b503509..40af4beb48b92aa7403e8c6682e1160cbbaa761d 100644 (file)
@@ -696,6 +696,7 @@ information.</para>
     &sub-packed-yuv;
     &sub-grey;
     &sub-y10;
+    &sub-y12;
     &sub-y16;
     &sub-yuyv;
     &sub-uyvy;
index 7041127d6dfcea31b867b0e33a75910396726839..d7ccd25edcc1f454e66e1bf1ae4b40ab52d9abd8 100644 (file)
              <entry>b<subscript>1</subscript></entry>
              <entry>b<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-SGBRG8-1X8">
+             <entry>V4L2_MBUS_FMT_SGBRG8_1X8</entry>
+             <entry>0x3013</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-SGRBG8-1X8">
              <entry>V4L2_MBUS_FMT_SGRBG8_1X8</entry>
              <entry>0x3002</entry>
              <entry>g<subscript>1</subscript></entry>
              <entry>g<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-SRGGB8-1X8">
+             <entry>V4L2_MBUS_FMT_SRGGB8_1X8</entry>
+             <entry>0x3014</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>r<subscript>7</subscript></entry>
+             <entry>r<subscript>6</subscript></entry>
+             <entry>r<subscript>5</subscript></entry>
+             <entry>r<subscript>4</subscript></entry>
+             <entry>r<subscript>3</subscript></entry>
+             <entry>r<subscript>2</subscript></entry>
+             <entry>r<subscript>1</subscript></entry>
+             <entry>r<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
              <entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
              <entry>0x300b</entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-Y12-1X12">
+             <entry>V4L2_MBUS_FMT_Y12_1X12</entry>
+             <entry>0x2013</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-UYVY8-1X16">
              <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry>
              <entry>0x200f</entry>
index 71b6f500ddb9ae3914ba8f31988470c4d8cb8d3c..1d7a885761f51f07a8e46be9199ac67d5939f946 100644 (file)
@@ -21,7 +21,7 @@ rcu.txt
 RTFP.txt
        - List of RCU papers (bibliography) going back to 1980.
 stallwarn.txt
-       - RCU CPU stall warnings (CONFIG_RCU_CPU_STALL_DETECTOR)
+       - RCU CPU stall warnings (module parameter rcu_cpu_stall_suppress)
 torture.txt
        - RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST)
 trace.txt
index 862c08ef1fde4436ddac8010ba4a1aae40328719..4e959208f7363c7a2fb1e5e3e190fac2c0c90887 100644 (file)
@@ -1,22 +1,25 @@
 Using RCU's CPU Stall Detector
 
-The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables
-RCU's CPU stall detector, which detects conditions that unduly delay
-RCU grace periods.  The stall detector's idea of what constitutes
-"unduly delayed" is controlled by a set of C preprocessor macros:
+The rcu_cpu_stall_suppress module parameter enables RCU's CPU stall
+detector, which detects conditions that unduly delay RCU grace periods.
+This module parameter enables CPU stall detection by default, but
+may be overridden via boot-time parameter or at runtime via sysfs.
+The stall detector's idea of what constitutes "unduly delayed" is
+controlled by a set of kernel configuration variables and cpp macros:
 
-RCU_SECONDS_TILL_STALL_CHECK
+CONFIG_RCU_CPU_STALL_TIMEOUT
 
-       This macro defines the period of time that RCU will wait from
-       the beginning of a grace period until it issues an RCU CPU
-       stall warning.  This time period is normally ten seconds.
+       This kernel configuration parameter defines the period of time
+       that RCU will wait from the beginning of a grace period until it
+       issues an RCU CPU stall warning.  This time period is normally
+       ten seconds.
 
 RCU_SECONDS_TILL_STALL_RECHECK
 
        This macro defines the period of time that RCU will wait after
        issuing a stall warning until it issues another stall warning
-       for the same stall.  This time period is normally set to thirty
-       seconds.
+       for the same stall.  This time period is normally set to three
+       times the check interval plus thirty seconds.
 
 RCU_STALL_RAT_DELAY
 
index 6a8c73f55b80ca38601ba96f179565fe8b0b7ea0..c078ad48f7a187aa8d76e9885d1776a46a4255e7 100644 (file)
@@ -10,34 +10,46 @@ for rcutree and next for rcutiny.
 
 CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats
 
-These implementations of RCU provides five debugfs files under the
-top-level directory RCU: rcu/rcudata (which displays fields in struct
-rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of
-rcu/rcudata), rcu/rcugp (which displays grace-period counters),
-rcu/rcuhier (which displays the struct rcu_node hierarchy), and
-rcu/rcu_pending (which displays counts of the reasons that the
-rcu_pending() function decided that there was core RCU work to do).
+These implementations of RCU provides several debugfs files under the
+top-level directory "rcu":
+
+rcu/rcudata:
+       Displays fields in struct rcu_data.
+rcu/rcudata.csv:
+       Comma-separated values spreadsheet version of rcudata.
+rcu/rcugp:
+       Displays grace-period counters.
+rcu/rcuhier:
+       Displays the struct rcu_node hierarchy.
+rcu/rcu_pending:
+       Displays counts of the reasons rcu_pending() decided that RCU had
+       work to do.
+rcu/rcutorture:
+       Displays rcutorture test progress.
+rcu/rcuboost:
+       Displays RCU boosting statistics.  Only present if
+       CONFIG_RCU_BOOST=y.
 
 The output of "cat rcu/rcudata" looks as follows:
 
 rcu_sched:
-  0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1 dn=0 df=1101 of=0 ri=36 ql=0 b=10
-  1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1 dn=0 df=1015 of=0 ri=0 ql=0 b=10
-  2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1 dn=0 df=1839 of=0 ri=0 ql=0 b=10
-  3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1 dn=0 df=1545 of=0 ri=0 ql=0 b=10
-  4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1 dn=0 df=1992 of=0 ri=0 ql=0 b=10
-  5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1 dn=0 df=3331 of=0 ri=4 ql=2 b=10
-  6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1 dn=0 df=3224 of=0 ri=0 ql=0 b=10
-  7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1 dn=0 df=1818 of=0 ri=0 ql=2 b=10
+  0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
+  1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
+  2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
+  3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
+  4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
+  5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
+  6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
+  7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
 rcu_bh:
-  0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1 dn=0 df=0 of=0 ri=0 ql=0 b=10
-  1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1 dn=0 df=13 of=0 ri=0 ql=0 b=10
-  2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
-  3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1 dn=0 df=9 of=0 ri=0 ql=0 b=10
-  4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
-  5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
-  6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
-  7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+  0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
+  1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
+  2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
+  3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
+  4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
+  5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
+  6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
+  7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
 
 The first section lists the rcu_data structures for rcu_sched, the second
 for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -52,17 +64,18 @@ o   The number at the beginning of each line is the CPU number.
        substantially larger than the number of actual CPUs.
 
 o      "c" is the count of grace periods that this CPU believes have
-       completed.  CPUs in dynticks idle mode may lag quite a ways
-       behind, for example, CPU 4 under "rcu_sched" above, which has
-       slept through the past 25 RCU grace periods.  It is not unusual
-       to see CPUs lagging by thousands of grace periods.
+       completed.  Offlined CPUs and CPUs in dynticks idle mode may
+       lag quite a ways behind, for example, CPU 6 under "rcu_sched"
+       above, which has been offline through not quite 40,000 RCU grace
+       periods.  It is not unusual to see CPUs lagging by thousands of
+       grace periods.
 
 o      "g" is the count of grace periods that this CPU believes have
-       started.  Again, CPUs in dynticks idle mode may lag behind.
-       If the "c" and "g" values are equal, this CPU has already
-       reported a quiescent state for the last RCU grace period that
-       it is aware of, otherwise, the CPU believes that it owes RCU a
-       quiescent state.
+       started.  Again, offlined CPUs and CPUs in dynticks idle mode
+       may lag behind.  If the "c" and "g" values are equal, this CPU
+       has already reported a quiescent state for the last RCU grace
+       period that it is aware of, otherwise, the CPU believes that it
+       owes RCU a quiescent state.
 
 o      "pq" indicates that this CPU has passed through a quiescent state
        for the current grace period.  It is possible for "pq" to be
@@ -81,7 +94,8 @@ o     "pqc" indicates which grace period the last-observed quiescent
        the next grace period!
 
 o      "qp" indicates that RCU still expects a quiescent state from
-       this CPU.
+       this CPU.  Offlined CPUs and CPUs in dyntick idle mode might
+       well have qp=1, which is OK: RCU is still ignoring them.
 
 o      "dt" is the current value of the dyntick counter that is incremented
        when entering or leaving dynticks idle state, either by the
@@ -108,7 +122,7 @@ o   "df" is the number of times that some other CPU has forced a
 
 o      "of" is the number of times that some other CPU has forced a
        quiescent state on behalf of this CPU due to this CPU being
-       offline.  In a perfect world, this might neve happen, but it
+       offline.  In a perfect world, this might never happen, but it
        turns out that offlining and onlining a CPU can take several grace
        periods, and so there is likely to be an extended period of time
        when RCU believes that the CPU is online when it really is not.
@@ -125,6 +139,62 @@ o  "ql" is the number of RCU callbacks currently residing on
        of what state they are in (new, waiting for grace period to
        start, waiting for grace period to end, ready to invoke).
 
+o      "qs" gives an indication of the state of the callback queue
+       with four characters:
+
+       "N"     Indicates that there are callbacks queued that are not
+               ready to be handled by the next grace period, and thus
+               will be handled by the grace period following the next
+               one.
+
+       "R"     Indicates that there are callbacks queued that are
+               ready to be handled by the next grace period.
+
+       "W"     Indicates that there are callbacks queued that are
+               waiting on the current grace period.
+
+       "D"     Indicates that there are callbacks queued that have
+               already been handled by a prior grace period, and are
+               thus waiting to be invoked.  Note that callbacks in
+               the process of being invoked are not counted here.
+               Callbacks in the process of being invoked are those
+               that have been removed from the rcu_data structures
+               queues by rcu_do_batch(), but which have not yet been
+               invoked.
+
+       If there are no callbacks in a given one of the above states,
+       the corresponding character is replaced by ".".
+
+o      "kt" is the per-CPU kernel-thread state.  The digit preceding
+       the first slash is zero if there is no work pending and 1
+       otherwise.  The character between the first pair of slashes is
+       as follows:
+
+       "S"     The kernel thread is stopped, in other words, all
+               CPUs corresponding to this rcu_node structure are
+               offline.
+
+       "R"     The kernel thread is running.
+
+       "W"     The kernel thread is waiting because there is no work
+               for it to do.
+
+       "O"     The kernel thread is waiting because it has been
+               forced off of its designated CPU or because its
+               ->cpus_allowed mask permits it to run on other than
+               its designated CPU.
+
+       "Y"     The kernel thread is yielding to avoid hogging CPU.
+
+       "?"     Unknown value, indicates a bug.
+
+       The number after the final slash is the CPU that the kthread
+       is actually running on.
+
+o      "ktl" is the low-order 16 bits (in hexadecimal) of the count of
+       the number of times that this CPU's per-CPU kthread has gone
+       through its loop servicing invoke_rcu_cpu_kthread() requests.
+
 o      "b" is the batch limit for this CPU.  If more than this number
        of RCU callbacks is ready to invoke, then the remainder will
        be deferred.
@@ -174,14 +244,14 @@ o "gpnum" is the number of grace periods that have started.  It is
 The output of "cat rcu/rcuhier" looks as follows, with very long lines:
 
 c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6
-1/1 .>. 0:127 ^0    
-3/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
-3/3f .>. 0:5 ^0    2/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3    
+1/1 ..>. 0:127 ^0
+3/3 ..>. 0:35 ^0    0/0 ..>. 36:71 ^1    0/0 ..>. 72:107 ^2    0/0 ..>. 108:127 ^3
+3/3f ..>. 0:5 ^0    2/3 ..>. 6:11 ^1    0/0 ..>. 12:17 ^2    0/0 ..>. 18:23 ^3    0/0 ..>. 24:29 ^4    0/0 ..>. 30:35 ^5    0/0 ..>. 36:41 ^0    0/0 ..>. 42:47 ^1    0/0 ..>. 48:53 ^2    0/0 ..>. 54:59 ^3    0/0 ..>. 60:65 ^4    0/0 ..>. 66:71 ^5    0/0 ..>. 72:77 ^0    0/0 ..>. 78:83 ^1    0/0 ..>. 84:89 ^2    0/0 ..>. 90:95 ^3    0/0 ..>. 96:101 ^4    0/0 ..>. 102:107 ^5    0/0 ..>. 108:113 ^0    0/0 ..>. 114:119 ^1    0/0 ..>. 120:125 ^2    0/0 ..>. 126:127 ^3
 rcu_bh:
 c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0
-0/1 .>. 0:127 ^0    
-0/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
-0/3f .>. 0:5 ^0    0/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3
+0/1 ..>. 0:127 ^0
+0/3 ..>. 0:35 ^0    0/0 ..>. 36:71 ^1    0/0 ..>. 72:107 ^2    0/0 ..>. 108:127 ^3
+0/3f ..>. 0:5 ^0    0/3 ..>. 6:11 ^1    0/0 ..>. 12:17 ^2    0/0 ..>. 18:23 ^3    0/0 ..>. 24:29 ^4    0/0 ..>. 30:35 ^5    0/0 ..>. 36:41 ^0    0/0 ..>. 42:47 ^1    0/0 ..>. 48:53 ^2    0/0 ..>. 54:59 ^3    0/0 ..>. 60:65 ^4    0/0 ..>. 66:71 ^5    0/0 ..>. 72:77 ^0    0/0 ..>. 78:83 ^1    0/0 ..>. 84:89 ^2    0/0 ..>. 90:95 ^3    0/0 ..>. 96:101 ^4    0/0 ..>. 102:107 ^5    0/0 ..>. 108:113 ^0    0/0 ..>. 114:119 ^1    0/0 ..>. 120:125 ^2    0/0 ..>. 126:127 ^3
 
 This is once again split into "rcu_sched" and "rcu_bh" portions,
 and CONFIG_TREE_PREEMPT_RCU kernels will again have an additional
@@ -240,13 +310,20 @@ o Each element of the form "1/1 0:127 ^0" represents one struct
                current grace period.
 
        o       The characters separated by the ">" indicate the state
-               of the blocked-tasks lists.  A "T" preceding the ">"
+               of the blocked-tasks lists.  A "G" preceding the ">"
                indicates that at least one task blocked in an RCU
                read-side critical section blocks the current grace
-               period, while a "." preceding the ">" indicates otherwise.
-               The character following the ">" indicates similarly for
-               the next grace period.  A "T" should appear in this
-               field only for rcu-preempt.
+               period, while a "E" preceding the ">" indicates that
+               at least one task blocked in an RCU read-side critical
+               section blocks the current expedited grace period.
+               A "T" character following the ">" indicates that at
+               least one task is blocked within an RCU read-side
+               critical section, regardless of whether any current
+               grace period (expedited or normal) is inconvenienced.
+               A "." character appears if the corresponding condition
+               does not hold, so that "..>." indicates that no tasks
+               are blocked.  In contrast, "GE>T" indicates maximal
+               inconvenience from blocked tasks.
 
        o       The numbers separated by the ":" are the range of CPUs
                served by this struct rcu_node.  This can be helpful
@@ -328,6 +405,113 @@ o "nn" is the number of times that this CPU needed nothing.  Alert
        is due to short-circuit evaluation in rcu_pending().
 
 
+The output of "cat rcu/rcutorture" looks as follows:
+
+rcutorture test sequence: 0 (test in progress)
+rcutorture update version number: 615
+
+The first line shows the number of rcutorture tests that have completed
+since boot.  If a test is currently running, the "(test in progress)"
+string will appear as shown above.  The second line shows the number of
+update cycles that the current test has started, or zero if there is
+no test in progress.
+
+
+The output of "cat rcu/rcuboost" looks as follows:
+
+0:5 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f
+     balk: nt=0 egt=989 bt=0 nb=0 ny=0 nos=16
+6:7 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f
+     balk: nt=0 egt=225 bt=0 nb=0 ny=0 nos=6
+
+This information is output only for rcu_preempt.  Each two-line entry
+corresponds to a leaf rcu_node strcuture.  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
+       CPUs zero through five and the second entry covers CPUs 6
+       and 7.
+
+o      "tasks=TNEB" gives the state of the various segments of the
+       rnp->blocked_tasks list:
+
+       "T"     This indicates that there are some tasks that blocked
+               while running on one of the corresponding CPUs while
+               in an RCU read-side critical section.
+
+       "N"     This indicates that some of the blocked tasks are preventing
+               the current normal (non-expedited) grace period from
+               completing.
+
+       "E"     This indicates that some of the blocked tasks are preventing
+               the current expedited grace period from completing.
+
+       "B"     This indicates that some of the blocked tasks are in
+               need of RCU priority boosting.
+
+       Each character is replaced with "." if the corresponding
+       condition does not hold.
+
+o      "kt" is the state of the RCU priority-boosting kernel
+       thread associated with the corresponding rcu_node structure.
+       The state can be one of the following:
+
+       "S"     The kernel thread is stopped, in other words, all
+               CPUs corresponding to this rcu_node structure are
+               offline.
+
+       "R"     The kernel thread is running.
+
+       "W"     The kernel thread is waiting because there is no work
+               for it to do.
+
+       "Y"     The kernel thread is yielding to avoid hogging CPU.
+
+       "?"     Unknown value, indicates a bug.
+
+o      "ntb" is the number of tasks boosted.
+
+o      "neb" is the number of tasks boosted in order to complete an
+       expedited grace period.
+
+o      "nnb" is the number of tasks boosted in order to complete a
+       normal (non-expedited) grace period.  When boosting a task
+       that was blocking both an expedited and a normal grace period,
+       it is counted against the expedited total above.
+
+o      "j" is the low-order 16 bits of the jiffies counter in
+       hexadecimal.
+
+o      "bt" is the low-order 16 bits of the value that the jiffies
+       counter will have when we next start boosting, assuming that
+       the current grace period does not end beforehand.  This is
+       also in hexadecimal.
+
+o      "balk: nt" counts the number of times we didn't boost (in
+       other words, we balked) even though it was time to boost because
+       there were no blocked tasks to boost.  This situation occurs
+       when there is one blocked task on one rcu_node structure and
+       none on some other rcu_node structure.
+
+o      "egt" counts the number of times we balked because although
+       there were blocked tasks, none of them were blocking the
+       current grace period, whether expedited or otherwise.
+
+o      "bt" counts the number of times we balked because boosting
+       had already been initiated for the current grace period.
+
+o      "nb" counts the number of times we balked because there
+       was at least one task blocking the current non-expedited grace
+       period that never had blocked.  If it is already running, it
+       just won't help to boost its priority!
+
+o      "ny" counts the number of times we balked because it was
+       not yet time to start boosting.
+
+o      "nos" counts the number of times we balked for other
+       reasons, e.g., the grace period ended first.
+
+
 CONFIG_TINY_RCU and CONFIG_TINY_PREEMPT_RCU debugfs Files and Formats
 
 These implementations of RCU provides a single debugfs file under the
@@ -394,9 +578,9 @@ o   "neb" is the number of expedited grace periods that have had
 o      "nnb" is the number of normal grace periods that have had
        to resort to RCU priority boosting since boot.
 
-o      "j" is the low-order 12 bits of the jiffies counter in hexadecimal.
+o      "j" is the low-order 16 bits of the jiffies counter in hexadecimal.
 
-o      "bt" is the low-order 12 bits of the value that the jiffies counter
+o      "bt" is the low-order 16 bits of the value that the jiffies counter
        will have at the next time that boosting is scheduled to begin.
 
 o      In the line beginning with "normal balk", the fields are as follows:
index b6ed61c958560d987e40cc28a9eca7f7d12401a1..7c163477fcd8f001fb217cc66e4c67812af907a7 100644 (file)
@@ -52,8 +52,10 @@ Brief summary of control files.
  tasks                          # attach a task(thread) and show list of threads
  cgroup.procs                   # show list of processes
  cgroup.event_control           # an interface for event_fd()
- memory.usage_in_bytes          # show current memory(RSS+Cache) usage.
- memory.memsw.usage_in_bytes    # show current memory+Swap usage
+ memory.usage_in_bytes          # show current res_counter usage for memory
+                                (See 5.5 for details)
+ memory.memsw.usage_in_bytes    # show current res_counter usage for memory+Swap
+                                (See 5.5 for details)
  memory.limit_in_bytes          # set/show limit of memory usage
  memory.memsw.limit_in_bytes    # set/show limit of memory+Swap usage
  memory.failcnt                         # show the number of memory usage hits limits
@@ -453,6 +455,15 @@ memory under it will be reclaimed.
 You can reset failcnt by writing 0 to failcnt file.
 # echo 0 > .../memory.failcnt
 
+5.5 usage_in_bytes
+
+For efficiency, as other kernel components, memory cgroup uses some optimization
+to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
+method and doesn't show 'exact' value of memory(and swap) usage, it's an fuzz
+value for efficient access. (Of course, when necessary, it's synchronized.)
+If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
+value in memory.stat(see 5.2).
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
index 492e81df296835e04ff6195304b3a32931e466c6..f6a24e8aa11ed1491de7d6ea48d1a4010873d566 100644 (file)
@@ -460,14 +460,6 @@ Who:       Thomas Gleixner <tglx@linutronix.de>
 
 ----------------------------
 
-What:  The acpi_sleep=s4_nonvs command line option
-When:  2.6.37
-Files: arch/x86/kernel/acpi/sleep.c
-Why:   superseded by acpi_sleep=nonvs
-Who:   Rafael J. Wysocki <rjw@sisk.pl>
-
-----------------------------
-
 What:  PCI DMA unmap state API
 When:  August 2012
 Why:   PCI DMA unmap state API (include/linux/pci-dma.h) was replaced
index b0b814d75ca138090395820794d5a2749d0052f4..60740e8ecb3779e7bb314dcde47d88f54183788b 100644 (file)
@@ -836,7 +836,6 @@ Provides counts of softirq handlers serviced since boot time, for each cpu.
  TASKLET:          0          0          0        290
    SCHED:      27035      26983      26971      26746
  HRTIMER:          0          0          0          0
-     RCU:       1678       1769       2178       2250
 
 
 1.3 IDE devices in /proc/ide
index cb8a3a00cc92694947cb72840ddbcb340407ce08..df904aec99044f8056ac530b9e9dc6de8f26f73e 100644 (file)
@@ -66,10 +66,10 @@ trick is to ensure that any needed memory allocations are done before
 entering atomic context, using:
 
     int flex_array_prealloc(struct flex_array *array, unsigned int start,
-                           unsigned int end, gfp_t flags);
+                           unsigned int nr_elements, gfp_t flags);
 
 This function will ensure that memory for the elements indexed in the range
-defined by start and end has been allocated.  Thereafter, a
+defined by start and nr_elements has been allocated.  Thereafter, a
 flex_array_put() call on an element in that range is guaranteed not to
 block.
 
index 03d02bfb3df13a8f7f06859f8669de4a905bcc88..02ad96cf9b2b18e5b1307f0e8ad88be4f07d3fce 100644 (file)
@@ -14,10 +14,6 @@ Supported chips:
     Prefix: 'gl523sm'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
     Datasheet:
-  * Intel Xeon Processor
-    Prefix: - any other - may require 'force_adm1021' parameter
-    Addresses scanned: none
-    Datasheet: Publicly available at Intel website
   * Maxim MAX1617
     Prefix: 'max1617'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
@@ -91,21 +87,27 @@ will do no harm, but will return 'old' values. It is possible to make
 ADM1021-clones do faster measurements, but there is really no good reason
 for that.
 
-Xeon support
-------------
 
-Some Xeon processors have real max1617, adm1021, or compatible chips
-within them, with two temperature sensors.
+Netburst-based Xeon support
+---------------------------
 
-Other Xeons have chips with only one sensor.
+Some Xeon processors based on the Netburst (early Pentium 4, from 2001 to
+2003) microarchitecture had real MAX1617, ADM1021, or compatible chips
+within them, with two temperature sensors. Other Xeon processors of this
+era (with 400 MHz FSB) had chips with only one temperature sensor.
 
-If you have a Xeon, and the adm1021 module loads, and both temperatures
-appear valid, then things are good.
+If you have such an old Xeon, and you get two valid temperatures when
+loading the adm1021 module, then things are good.
 
-If the adm1021 module doesn't load, you should try this:
-       modprobe adm1021 force_adm1021=BUS,ADDRESS
-       ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+If nothing happens when loading the adm1021 module, and you are certain
+that your specific Xeon processor model includes compatible sensors, you
+will have to explicitly instantiate the sensor chips from user-space. See
+method 4 in Documentation/i2c/instantiating-devices. Possible slave
+addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that
+only temp2 will be correct and temp1 will have to be ignored.
 
-If you have dual Xeons you may have appear to have two separate
-adm1021-compatible chips, or two single-temperature sensors, at distinct
-addresses.
+Previous generations of the Xeon processor (based on Pentium II/III)
+didn't have these sensors. Next generations of Xeon processors (533 MHz
+FSB and faster) lost them, until the Core-based generation which
+introduced integrated digital thermal sensors. These are supported by
+the coretemp driver.
index fa475c0a48a34330e98b412e896013881dd6c50d..f3efd18e87f402ac3ba346ae15da07119f392fa6 100644 (file)
@@ -32,6 +32,16 @@ Supported chips:
     Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the ON Semiconductor website
                http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
+  * Analog Devices ADT7461A
+    Prefix: 'adt7461a'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A
+  * ON Semiconductor NCT1008
+    Prefix: 'nct1008'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=NCT1008
   * Maxim MAX6646
     Prefix: 'max6646'
     Addresses scanned: I2C 0x4d
@@ -149,7 +159,7 @@ ADM1032:
   * ALERT is triggered by open remote sensor.
   * SMBus PEC support for Write Byte and Receive Byte transactions.
 
-ADT7461:
+ADT7461, ADT7461A, NCT1008:
   * Extended temperature range (breaks compatibility)
   * Lower resolution for remote temperature
 
@@ -195,9 +205,9 @@ are exported, one for each channel, but these values are of course linked.
 Only the local hysteresis can be set from user-space, and the same delta
 applies to the remote hysteresis.
 
-The lm90 driver will not update its values more frequently than every
-other second; reading them more often will do no harm, but will return
-'old' values.
+The lm90 driver will not update its values more frequently than configured with
+the update_interval attribute; reading them more often will do no harm, but will
+return 'old' values.
 
 SMBus Alert Support
 -------------------
@@ -205,11 +215,12 @@ SMBus Alert Support
 This driver has basic support for SMBus alert. When an alert is received,
 the status register is read and the faulty temperature channel is logged.
 
-The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
-alert protocol properly so additional care is needed: the ALERT output is
-disabled when an alert is received, and is re-enabled only when the alarm
-is gone. Otherwise the chip would block alerts from other chips in the bus
-as long as the alarm is active.
+The Analog Devices chips (ADM1032, ADT7461 and ADT7461A) and ON
+Semiconductor chips (NCT1008) do not implement the SMBus alert protocol
+properly so additional care is needed: the ALERT output is disabled when
+an alert is received, and is re-enabled only when the alarm is gone.
+Otherwise the chip would block alerts from other chips in the bus as long
+as the alarm is active.
 
 PEC Support
 -----------
diff --git a/Documentation/hwmon/max16064 b/Documentation/hwmon/max16064
new file mode 100644 (file)
index 0000000..4172899
--- /dev/null
@@ -0,0 +1,62 @@
+Kernel driver max16064
+======================
+
+Supported chips:
+  * Maxim MAX16064
+    Prefix: 'max16064'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX16064 Quad Power-Supply
+Controller with Active-Voltage Output Control and PMBus Interface.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-4]_label          "vout[1-4]"
+in[1-4]_input          Measured voltage. From READ_VOUT register.
+in[1-4]_min            Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-4]_max            Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-4]_lcrit          Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-4]_crit           Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-4]_min_alarm      Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-4]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-4]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-4]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit             Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm                Chip temperature high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+                       status is set.
+temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+                       status is set.
diff --git a/Documentation/hwmon/max34440 b/Documentation/hwmon/max34440
new file mode 100644 (file)
index 0000000..6c525dd
--- /dev/null
@@ -0,0 +1,79 @@
+Kernel driver max34440
+======================
+
+Supported chips:
+  * Maxim MAX34440
+    Prefixes: 'max34440'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
+  * Maxim MAX34441
+    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
+    Prefixes: 'max34441'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
+Power-Supply Manager and MAX34441 PMBus 5-Channel Power-Supply Manager
+and Intelligent Fan Controller.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-6]_label          "vout[1-6]".
+in[1-6]_input          Measured voltage. From READ_VOUT register.
+in[1-6]_min            Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-6]_max            Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-6]_lcrit          Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-6]_crit           Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-6]_min_alarm      Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-6]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-6]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-6]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr[1-6]_label                "iout[1-6]".
+curr[1-6]_input                Measured current. From READ_IOUT register.
+curr[1-6]_max          Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr[1-6]_crit         Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr[1-6]_max_alarm    Current high alarm. From IOUT_OC_WARNING status.
+curr[1-6]_crit_alarm   Current critical high alarm. From IOUT_OC_FAULT status.
+
+                       in6 and curr6 attributes only exist for MAX34440.
+
+temp[1-8]_input                Measured temperatures. From READ_TEMPERATURE_1 register.
+                       temp1 is the chip's internal temperature. temp2..temp5
+                       are remote I2C temperature sensors. For MAX34441, temp6
+                       is a remote thermal-diode sensor. For MAX34440, temp6..8
+                       are remote I2C temperature sensors.
+temp[1-8]_max          Maximum temperature. From OT_WARN_LIMIT register.
+temp[1-8]_crit         Critical high temperature. From OT_FAULT_LIMIT register.
+temp[1-8]_max_alarm    Temperature high alarm.
+temp[1-8]_crit_alarm   Temperature critical high alarm.
+
+                       temp7 and temp8 attributes only exist for MAX34440.
diff --git a/Documentation/hwmon/max8688 b/Documentation/hwmon/max8688
new file mode 100644 (file)
index 0000000..0ddd3a4
--- /dev/null
@@ -0,0 +1,69 @@
+Kernel driver max8688
+=====================
+
+Supported chips:
+  * Maxim MAX8688
+    Prefix: 'max8688'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX8688 Digital Power-Supply
+Controller/Monitor with PMBus Interface.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label              "vout1"
+in1_input              Measured voltage. From READ_VOUT register.
+in1_min                        Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in1_max                        Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in1_lcrit              Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in1_crit               Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in1_min_alarm          Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in1_max_alarm          Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_lcrit_alarm                Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in1_crit_alarm         Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr1_label            "iout1"
+curr1_input            Measured current. From READ_IOUT register.
+curr1_max              Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr1_crit             Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr1_max_alarm                Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_crit_alarm       Current critical high alarm. From IOUT_OC_FAULT status.
+
+temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit             Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm                Chip temperature high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+                       status is set.
+temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+                       status is set.
index dc4933e96344809ea8bf4f65ba607142426d4e69..5e462fc7f99b5f2e0f42c4edb92ebc1ac6c7571f 100644 (file)
@@ -13,26 +13,6 @@ Supported chips:
     Prefix: 'ltc2978'
     Addresses scanned: -
     Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
-  * Maxim MAX16064
-    Quad Power-Supply Controller
-    Prefix: 'max16064'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
-  * Maxim MAX34440
-    PMBus 6-Channel Power-Supply Manager
-    Prefixes: 'max34440'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
-  * Maxim MAX34441
-    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
-    Prefixes: 'max34441'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
-  * Maxim MAX8688
-    Digital Power-Supply Controller/Monitor
-    Prefix: 'max8688'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
@@ -175,11 +155,13 @@ currX_crit                Critical maximum current.
                        From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
 currX_alarm            Current high alarm.
                        From IIN_OC_WARNING or IOUT_OC_WARNING status.
+currX_max_alarm                Current high alarm.
+                       From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT status.
 currX_lcrit_alarm      Output current critical low alarm.
                        From IOUT_UC_FAULT status.
 currX_crit_alarm       Current critical high alarm.
                        From IIN_OC_FAULT or IOUT_OC_FAULT status.
-currX_label            "iin" or "vinY"
+currX_label            "iin" or "ioutY"
 
 powerX_input           Measured power. From READ_PIN or READ_POUT register.
 powerX_cap             Output power cap. From POUT_MAX register.
@@ -193,13 +175,13 @@ powerX_crit_alarm Output power critical high alarm.
                        From POUT_OP_FAULT status.
 powerX_label           "pin" or "poutY"
 
-tempX_input            Measured tempererature.
+tempX_input            Measured temperature.
                        From READ_TEMPERATURE_X register.
-tempX_min              Mimimum tempererature. From UT_WARN_LIMIT register.
-tempX_max              Maximum tempererature. From OT_WARN_LIMIT register.
-tempX_lcrit            Critical low tempererature.
+tempX_min              Mimimum temperature. From UT_WARN_LIMIT register.
+tempX_max              Maximum temperature. From OT_WARN_LIMIT register.
+tempX_lcrit            Critical low temperature.
                        From UT_FAULT_LIMIT register.
-tempX_crit             Critical high tempererature.
+tempX_crit             Critical high temperature.
                        From OT_FAULT_LIMIT register.
 tempX_min_alarm                Chip temperature low alarm. Set by comparing
                        READ_TEMPERATURE_X with UT_WARN_LIMIT if
index 3820fc9ca52d25ae4c3ed9a7e6d7f04fcb092bee..59e316140542017517be09171448fc4e6e16d28e 100644 (file)
@@ -150,8 +150,8 @@ in8_crit_alarm              Channel F critical alarm
 in9_crit_alarm         AIN1 critical alarm
 in10_crit_alarm                AIN2 critical alarm
 
-temp1_input            Chip tempererature
-temp1_min              Mimimum chip tempererature
-temp1_max              Maximum chip tempererature
-temp1_crit             Critical chip tempererature
+temp1_input            Chip temperature
+temp1_min              Mimimum chip temperature
+temp1_max              Maximum chip temperature
+temp1_crit             Critical chip temperature
 temp1_crit_alarm       Temperature critical alarm
diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches
new file mode 100644 (file)
index 0000000..86f42e8
--- /dev/null
@@ -0,0 +1,109 @@
+       How to Get Your Patch Accepted Into the Hwmon Subsystem
+       -------------------------------------------------------
+
+This text is is a collection of suggestions for people writing patches or
+drivers for the hwmon subsystem. Following these suggestions will greatly
+increase the chances of your change being accepted.
+
+
+1. General
+----------
+
+* It should be unnecessary to mention, but please read and follow
+    Documentation/SubmitChecklist
+    Documentation/SubmittingDrivers
+    Documentation/SubmittingPatches
+    Documentation/CodingStyle
+
+* If your patch generates checkpatch warnings, please refrain from explanations
+  such as "I don't like that coding style". Keep in mind that each unnecessary
+  warning helps hiding a real problem. If you don't like the kernel coding
+  style, don't write kernel drivers.
+
+* Please test your patch thoroughly. We are not your test group.
+  Sometimes a patch can not or not completely be tested because of missing
+  hardware. In such cases, you should test-build the code on at least one
+  architecture. If run-time testing was not achieved, it should be written
+  explicitly below the patch header.
+
+* If your patch (or the driver) is affected by configuration options such as
+  CONFIG_SMP or CONFIG_HOTPLUG, make sure it compiles for all configuration
+  variants.
+
+
+2. Adding functionality to existing drivers
+-------------------------------------------
+
+* Make sure the documentation in Documentation/hwmon/<driver_name> is up to
+  date.
+
+* Make sure the information in Kconfig is up to date.
+
+* If the added functionality requires some cleanup or structural changes, split
+  your patch into a cleanup part and the actual addition. This makes it easier
+  to review your changes, and to bisect any resulting problems.
+
+* Never mix bug fixes, cleanup, and functional enhancements in a single patch.
+
+
+3. New drivers
+--------------
+
+* Running your patch or driver file(s) through checkpatch does not mean its
+  formatting is clean. If unsure about formatting in your new driver, run it
+  through Lindent. Lindent is not perfect, and you may have to do some minor
+  cleanup, but it is a good start.
+
+* Consider adding yourself to MAINTAINERS.
+
+* Document the driver in Documentation/hwmon/<driver_name>.
+
+* Add the driver to Kconfig and Makefile in alphabetical order.
+
+* Make sure that all dependencies are listed in Kconfig. For new drivers, it
+  is most likely prudent to add a dependency on EXPERIMENTAL.
+
+* Avoid forward declarations if you can. Rearrange the code if necessary.
+
+* Avoid calculations in macros and macro-generated functions. While such macros
+  may save a line or so in the source, it obfuscates the code and makes code
+  review more difficult. It may also result in code which is more complicated
+  than necessary. Use inline functions or just regular functions instead.
+
+* If the driver has a detect function, make sure it is silent. Debug messages
+  and messages printed after a successful detection are acceptable, but it
+  must not print messages such as "Chip XXX not found/supported".
+
+  Keep in mind that the detect function will run for all drivers supporting an
+  address if a chip is detected on that address. Unnecessary messages will just
+  pollute the kernel log and not provide any value.
+
+* Provide a detect function if and only if a chip can be detected reliably.
+
+* Avoid writing to chip registers in the detect function. If you have to write,
+  only do it after you have already gathered enough data to be certain that the
+  detection is going to be successful.
+
+  Keep in mind that the chip might not be what your driver believes it is, and
+  writing to it might cause a bad misconfiguration.
+
+* Make sure there are no race conditions in the probe function. Specifically,
+  completely initialize your chip first, then create sysfs entries and register
+  with the hwmon subsystem.
+
+* Do not provide support for deprecated sysfs attributes.
+
+* Do not create non-standard attributes unless really needed. If you have to use
+  non-standard attributes, or you believe you do, discuss it on the mailing list
+  first. Either case, provide a detailed explanation why you need the
+  non-standard attribute(s).
+  Standard attributes are specified in Documentation/hwmon/sysfs-interface.
+
+* When deciding which sysfs attributes to support, look at the chip's
+  capabilities. While we do not expect your driver to support everything the
+  chip may offer, it should at least support all limits and alarms.
+
+* Last but not least, please check if a driver for your chip already exists
+  before starting to write a new driver. Especially for temperature sensors,
+  new chips are often variants of previously released chips. In some cases,
+  a presumably new chip may simply have been relabeled.
index cc85a927819070bef71e5802204b0f07cfb76973..c603ef7b056870f043902e60592ee7c780e1a64d 100644 (file)
@@ -245,7 +245,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        acpi_sleep=     [HW,ACPI] Sleep options
                        Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
-                                 old_ordering, s4_nonvs, sci_force_enable }
+                                 old_ordering, nonvs, sci_force_enable }
                        See Documentation/power/video.txt for information on
                        s3_bios and s3_mode.
                        s3_beep is for debugging; it makes the PC's speaker beep
@@ -1664,6 +1664,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        noexec=on: enable non-executable mappings (default)
                        noexec=off: disable non-executable mappings
 
+       nosmep          [X86]
+                       Disable SMEP (Supervisor Mode Execution Protection)
+                       even if it is supported by processor.
+
        noexec32        [X86-64]
                        This affects only 32-bit executables.
                        noexec32=on: enable non-executable mappings (default)
index a81c7b4790f2177afb7ad1911dbc20a5128ad7eb..2366b1c8cf19492f52480669449ecd2b0a0d0f34 100644 (file)
@@ -552,6 +552,16 @@ also have
      within the array where IO will be blocked.  This is currently
      only supported for raid4/5/6.
 
+   sync_min
+   sync_max
+     The two values, given as numbers of sectors, indicate a range
+     withing the array where 'check'/'repair' will operate. Must be
+     a multiple of chunk_size. When it reaches "sync_max" it will
+     pause, rather than complete.
+     You can use 'select' or 'poll' on "sync_completed" to wait for
+     that number to reach sync_max.  Then you can either increase
+     "sync_max", or can write 'idle' to "sync_action".
+
 
 Each active md device may also have attributes specific to the
 personality module that manages it.
index 1971bcf48a602fd5466bd3c1e440b666115f2a8a..88880839ece4e84f8101b4cfd50e3e22b8024515 100644 (file)
@@ -279,11 +279,15 @@ When the system goes into the standby or memory sleep state, the phases are:
        time.)  Unlike the other suspend-related phases, during the prepare
        phase the device tree is traversed top-down.
 
-       The prepare phase uses only a bus callback.  After the callback method
-       returns, no new children may be registered below the device.  The method
-       may also prepare the device or driver in some way for the upcoming
-       system power transition, but it should not put the device into a
-       low-power state.
+       In addition to that, if device drivers need to allocate additional
+       memory to be able to hadle device suspend correctly, that should be
+       done in the prepare phase.
+
+       After the prepare callback method returns, no new children may be
+       registered below the device.  The method may also prepare the device or
+       driver in some way for the upcoming system power transition (for
+       example, by allocating additional memory required for this purpose), but
+       it should not put the device into a low-power state.
 
     2. The suspend methods should quiesce the device to stop it from performing
        I/O.  They also may save the device registers and put it into the
index cf980709122aa25cfaef984e60da0f2f7218e92e..c2a4a346c0d98597d3375c5a9f160c012fded709 100644 (file)
@@ -1,46 +1,41 @@
 Suspend notifiers
-       (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
-
-There are some operations that device drivers may want to carry out in their
-.suspend() routines, but shouldn't, because they can cause the hibernation or
-suspend to fail. For example, a driver may want to allocate a substantial amount
-of memory (like 50 MB) in .suspend(), but that shouldn't be done after the
-swsusp's memory shrinker has run.
-
-Also, there may be some operations, that subsystems want to carry out before a
-hibernation/suspend or after a restore/resume, requiring the system to be fully
-functional, so the drivers' .suspend() and .resume() routines are not suitable
-for this purpose.  For example, device drivers may want to upload firmware to
-their devices after a restore from a hibernation image, but they cannot do it by
-calling request_firmware() from their .resume() routines (user land processes
-are frozen at this point).  The solution may be to load the firmware into
-memory before processes are frozen and upload it from there in the .resume()
-routine.  Of course, a hibernation notifier may be used for this purpose.
-
-The subsystems that have such needs can register suspend notifiers that will be
-called upon the following events by the suspend core:
+       (C) 2007-2011 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+There are some operations that subsystems or drivers may want to carry out
+before hibernation/suspend or after restore/resume, but they require the system
+to be fully functional, so the drivers' and subsystems' .suspend() and .resume()
+or even .prepare() and .complete() callbacks are not suitable for this purpose.
+For example, device drivers may want to upload firmware to their devices after
+resume/restore, but they cannot do it by calling request_firmware() from their
+.resume() or .complete() routines (user land processes are frozen at these
+points).  The solution may be to load the firmware into memory before processes
+are frozen and upload it from there in the .resume() routine.
+A suspend/hibernation notifier may be used for this purpose.
+
+The subsystems or drivers having such needs can register suspend notifiers that
+will be called upon the following events by the PM core:
 
 PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will
                        be frozen immediately.
 
 PM_POST_HIBERNATION    The system memory state has been restored from a
-                       hibernation image or an error occurred during the
-                       hibernation.  Device drivers' .resume() callbacks have
+                       hibernation image or an error occurred during
+                       hibernation.  Device drivers' restore callbacks have
                        been executed and tasks have been thawed.
 
 PM_RESTORE_PREPARE     The system is going to restore a hibernation image.
-                       If all goes well the restored kernel will issue a
+                       If all goes well, the restored kernel will issue a
                        PM_POST_HIBERNATION notification.
 
-PM_POST_RESTORE                An error occurred during the hibernation restore.
-                       Device drivers' .resume() callbacks have been executed
+PM_POST_RESTORE                An error occurred during restore from hibernation.
+                       Device drivers' restore callbacks have been executed
                        and tasks have been thawed.
 
-PM_SUSPEND_PREPARE     The system is preparing for suspend.
+PM_SUSPEND_PREPARE     The system is preparing for suspend.
 
 PM_POST_SUSPEND                The system has just resumed or an error occurred during
-                       the suspend.    Device drivers' .resume() callbacks have
-                       been executed and tasks have been thawed.
+                       suspend.  Device drivers' resume callbacks have been
+                       executed and tasks have been thawed.
 
 It is generally assumed that whatever the notifiers do for
 PM_HIBERNATION_PREPARE, should be undone for PM_POST_HIBERNATION.  Analogously,
index f5639d40521df5a60706d542d5dd93ace9f24c1c..f4b5988f450cf296dc625eb55b4840a557ca4732 100644 (file)
@@ -87,14 +87,14 @@ accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
 The result is forwarded to the ADC capture FIFO (thus to the standard capture
 PCM device).
 
-name='Music Playback Volume',index=0
+name='Synth Playback Volume',index=0
 
 This control is used to attenuate samples for left and right MIDI FX-bus
 accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
 The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
 
-name='Music Capture Volume',index=0
-name='Music Capture Switch',index=0
+name='Synth Capture Volume',index=0
+name='Synth Capture Switch',index=0
 
 These controls are used to attenuate samples for left and right MIDI FX-bus
 accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
index 6d27ab8d6e9fcc5b00c42f5a9bc6eee6f2a36086..c83bd6b4e6e82b7641eb5d411cb69c415b57d24d 100644 (file)
@@ -120,7 +120,6 @@ format:
         field:unsigned char common_flags;       offset:2;       size:1; signed:0;
         field:unsigned char common_preempt_count;       offset:3; size:1;signed:0;
         field:int common_pid;   offset:4;       size:4; signed:1;
-        field:int common_lock_depth;    offset:8;       size:4; signed:1;
 
         field:unsigned long __probe_ip; offset:12;      size:4; signed:0;
         field:int __probe_nargs;        offset:16;      size:4; signed:1;
index cb47e723af7436defbc6db5007bdf2fd3f675414..1e96ce6e2d2f9d39705c8a79e60b95bcc6cc9082 100644 (file)
@@ -37,7 +37,7 @@ Generic scaling / cropping scheme
 -1'-
 
 In the above chart minuses and slashes represent "real" data amounts, points and
-accents represent "useful" data, basically, CEU scaled amd cropped output,
+accents represent "useful" data, basically, CEU scaled and cropped output,
 mapped back onto the client's source plane.
 
 Such a configuration can be produced by user requests:
@@ -65,7 +65,7 @@ Do not touch input rectangle - it is already optimal.
 
 1. Calculate current sensor scales:
 
-       scale_s = ((3') - (3)) / ((2') - (2))
+       scale_s = ((2') - (2)) / ((3') - (3))
 
 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
 current sensor scales onto input window - this is user S_CROP:
@@ -80,7 +80,7 @@ window:
 4. Calculate sensor output window by applying combined scales to real input
 window:
 
-       width_s_out = ((2') - (2)) / scale_comb
+       width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
 
 5. Apply iterative sensor S_FMT for sensor output window.
 
diff --git a/Documentation/virtual/00-INDEX b/Documentation/virtual/00-INDEX
new file mode 100644 (file)
index 0000000..fe0251c
--- /dev/null
@@ -0,0 +1,10 @@
+Virtualization support in the Linux kernel.
+
+00-INDEX
+       - this file.
+kvm/
+       - Kernel Virtual Machine.  See also http://linux-kvm.org
+lguest/
+       - Extremely simple hypervisor for experimental/educational use.
+uml/
+       - User Mode Linux, builds/runs Linux kernel as a userspace program.
similarity index 95%
rename from Documentation/kvm/review-checklist.txt
rename to Documentation/virtual/kvm/review-checklist.txt
index 730475ae1b8dbefed43a47c0c80f8207f19412d9..a850986ed684c7409ab616a55781c1adfddf70b0 100644 (file)
@@ -7,7 +7,7 @@ Review checklist for kvm patches
 2.  Patches should be against kvm.git master branch.
 
 3.  If the patch introduces or modifies a new userspace API:
-    - the API must be documented in Documentation/kvm/api.txt
+    - the API must be documented in Documentation/virtual/kvm/api.txt
     - the API must be discoverable using KVM_CHECK_EXTENSION
 
 4.  New state must include support for save/restore.
similarity index 97%
rename from Documentation/lguest/lguest.txt
rename to Documentation/virtual/lguest/lguest.txt
index dad99978a6a8d5439d80662716bc52519a310293..bff0c554485dbeaba6fe45e18d5a256b77e4a286 100644 (file)
@@ -74,7 +74,8 @@ Running Lguest:
 
 - Run an lguest as root:
 
-      Documentation/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 --block=rootfile root=/dev/vda
+      Documentation/virtual/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 \
+        --block=rootfile root=/dev/vda
 
    Explanation:
     64: the amount of memory to use, in MB.
index 01c513fac40ece66b73a1709f6df496b5aade8d2..a0b577de918f7cd3fcdec46f06b72f7de074d6d8 100644 (file)
@@ -12,6 +12,7 @@ CONTENTS
 4. Application Programming Interface (API)
 5. Example Execution Scenarios
 6. Guidelines
+7. Debugging
 
 
 1. Introduction
@@ -379,3 +380,42 @@ If q1 has WQ_CPU_INTENSIVE set,
 * Unless work items are expected to consume a huge amount of CPU
   cycles, using a bound wq is usually beneficial due to the increased
   level of locality in wq operations and work item execution.
+
+
+7. Debugging
+
+Because the work functions are executed by generic worker threads
+there are a few tricks needed to shed some light on misbehaving
+workqueue users.
+
+Worker threads show up in the process list as:
+
+root      5671  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/0:1]
+root      5672  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/1:2]
+root      5673  0.0  0.0      0     0 ?        S    12:12   0:00 [kworker/0:0]
+root      5674  0.0  0.0      0     0 ?        S    12:13   0:00 [kworker/1:0]
+
+If kworkers are going crazy (using too much cpu), there are two types
+of possible problems:
+
+       1. Something beeing scheduled in rapid succession
+       2. A single work item that consumes lots of cpu cycles
+
+The first one can be tracked using tracing:
+
+       $ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
+       $ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
+       (wait a few secs)
+       ^C
+
+If something is busy looping on work queueing, it would be dominating
+the output and the offender can be determined with the work item
+function.
+
+For the second type of problems it should be possible to just check
+the stack trace of the offending worker thread.
+
+       $ cat /proc/THE_OFFENDING_KWORKER/stack
+
+The work item's function should be trivially visible in the stack
+trace.
index 092e596a1301f184bce14acd04a15f8e97904c48..c54b4f503e2a00e0d45a6ae7ae92533b5d3468af 100644 (file)
@@ -206,7 +206,7 @@ IOMMU (input/output memory management unit)
       (e.g. because you have < 3 GB memory).
       Kernel boot message: "PCI-DMA: Disabling IOMMU"
 
-   2. <arch/x86_64/kernel/pci-gart.c>: AMD GART based hardware IOMMU.
+   2. <arch/x86/kernel/amd_gart_64.c>: AMD GART based hardware IOMMU.
       Kernel boot message: "PCI-DMA: using GART IOMMU"
 
    3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
index ec360030628927de81456717aa541565fdbe7a58..8df8d2dfba284b251e85c2b975b3fa1039bb7e10 100644 (file)
@@ -151,6 +151,7 @@ S:  Maintained
 F:     drivers/net/hamradio/6pack.c
 
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
+M:     Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -404,8 +405,8 @@ S:  Maintained
 F:     sound/oss/aedsp16.c
 
 AFFS FILE SYSTEM
-M:     Roman Zippel <zippel@linux-m68k.org>
-S:     Maintained
+L:     linux-fsdevel@vger.kernel.org
+S:     Orphan
 F:     Documentation/filesystems/affs.txt
 F:     fs/affs/
 
@@ -1031,12 +1032,13 @@ W:      http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/mach-s3c64xx/
 
-ARM/S5P ARM ARCHITECTURES
+ARM/S5P EXYNOS ARM ARCHITECTURES
 M:     Kukjin Kim <kgene.kim@samsung.com>
 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:     arch/arm/mach-s5p*/
+F:     arch/arm/mach-exynos*/
 
 ARM/SAMSUNG MOBILE MACHINE SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -2807,42 +2809,23 @@ GPIO SUBSYSTEM
 M:     Grant Likely <grant.likely@secretlab.ca>
 S:     Maintained
 T:     git git://git.secretlab.ca/git/linux-2.6.git
-F:     Documentation/gpio/gpio.txt
+F:     Documentation/gpio.txt
 F:     drivers/gpio/
 F:     include/linux/gpio*
 
+GRE DEMULTIPLEXER DRIVER
+M:     Dmitry Kozlov <xeb@mail.ru>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/ipv4/gre.c
+F:     include/net/gre.h
+
 GRETH 10/100/1G Ethernet MAC device driver
 M:     Kristoffer Glembo <kristoffer@gaisler.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/greth*
 
-HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
-M:     Frank Seidel <frank@f-seidel.de>
-L:     platform-driver-x86@vger.kernel.org
-W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
-S:     Maintained
-F:     drivers/platform/x86/hdaps.c
-
-HWPOISON MEMORY FAILURE HANDLING
-M:     Andi Kleen <andi@firstfloor.org>
-L:     linux-mm@kvack.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
-S:     Maintained
-F:     mm/memory-failure.c
-F:     mm/hwpoison-inject.c
-
-HYPERVISOR VIRTUAL CONSOLE DRIVER
-L:     linuxppc-dev@lists.ozlabs.org
-S:     Odd Fixes
-F:     drivers/tty/hvc/
-
-iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
-M:     Peter Jones <pjones@redhat.com>
-M:     Konrad Rzeszutek Wilk <konrad@kernel.org>
-S:     Maintained
-F:     drivers/firmware/iscsi_ibft*
-
 GSPCA FINEPIX SUBDRIVER
 M:     Frank Zago <frank@zago.net>
 L:     linux-media@vger.kernel.org
@@ -2893,6 +2876,26 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/gspca/
 
+HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
+M:     Frank Seidel <frank@f-seidel.de>
+L:     platform-driver-x86@vger.kernel.org
+W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
+S:     Maintained
+F:     drivers/platform/x86/hdaps.c
+
+HWPOISON MEMORY FAILURE HANDLING
+M:     Andi Kleen <andi@firstfloor.org>
+L:     linux-mm@kvack.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
+S:     Maintained
+F:     mm/memory-failure.c
+F:     mm/hwpoison-inject.c
+
+HYPERVISOR VIRTUAL CONSOLE DRIVER
+L:     linuxppc-dev@lists.ozlabs.org
+S:     Odd Fixes
+F:     drivers/tty/hvc/
+
 HARDWARE MONITORING
 M:     Jean Delvare <khali@linux-fr.org>
 M:     Guenter Roeck <guenter.roeck@ericsson.com>
@@ -2943,8 +2946,8 @@ F:        drivers/block/cciss*
 F:     include/linux/cciss_ioctl.h
 
 HFS FILESYSTEM
-M:     Roman Zippel <zippel@linux-m68k.org>
-S:     Maintained
+L:     linux-fsdevel@vger.kernel.org
+S:     Orphan
 F:     Documentation/filesystems/hfs.txt
 F:     fs/hfs/
 
@@ -3476,6 +3479,12 @@ F:       Documentation/isapnp.txt
 F:     drivers/pnp/isapnp/
 F:     include/linux/isapnp.h
 
+iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
+M:     Peter Jones <pjones@redhat.com>
+M:     Konrad Rzeszutek Wilk <konrad@kernel.org>
+S:     Maintained
+F:     drivers/firmware/iscsi_ibft*
+
 ISCSI
 M:     Mike Christie <michaelc@cs.wisc.edu>
 L:     open-iscsi@googlegroups.com
@@ -3805,7 +3814,7 @@ M:        Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@lists.ozlabs.org
 W:     http://lguest.ozlabs.org/
 S:     Odd Fixes
-F:     Documentation/lguest/
+F:     Documentation/virtual/lguest/
 F:     arch/x86/lguest/
 F:     drivers/lguest/
 F:     include/linux/lguest*.h
@@ -3992,7 +4001,6 @@ F:        arch/m32r/
 
 M68K ARCHITECTURE
 M:     Geert Uytterhoeven <geert@linux-m68k.org>
-M:     Roman Zippel <zippel@linux-m68k.org>
 L:     linux-m68k@lists.linux-m68k.org
 W:     http://www.linux-m68k.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
@@ -4987,6 +4995,13 @@ F:       Documentation/pps/
 F:     drivers/pps/
 F:     include/linux/pps*.h
 
+PPTP DRIVER
+M:     Dmitry Kozlov <xeb@mail.ru>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/pptp.c
+W:     http://sourceforge.net/projects/accel-pptp
+
 PREEMPTIBLE KERNEL
 M:     Robert Love <rml@tech9.net>
 L:     kpreempt-tech@lists.sourceforge.net
@@ -5395,7 +5410,7 @@ F:        drivers/media/video/*7146*
 F:     include/media/*7146*
 
 SAMSUNG AUDIO (ASoC) DRIVERS
-M:     Jassi Brar <jassi.brar@samsung.com>
+M:     Jassi Brar <jassisinghbrar@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/samsung
@@ -6554,7 +6569,7 @@ S:        Maintained
 F:     drivers/usb/host/uhci*
 
 USB "USBNET" DRIVER FRAMEWORK
-M:     David Brownell <dbrownell@users.sourceforge.net>
+M:     Oliver Neukum <oneukum@suse.de>
 L:     netdev@vger.kernel.org
 W:     http://www.linux-usb.org/usbnet
 S:     Maintained
@@ -6616,7 +6631,7 @@ L:        user-mode-linux-devel@lists.sourceforge.net
 L:     user-mode-linux-user@lists.sourceforge.net
 W:     http://user-mode-linux.sourceforge.net
 S:     Maintained
-F:     Documentation/uml/
+F:     Documentation/virtual/uml/
 F:     arch/um/
 F:     fs/hostfs/
 F:     fs/hppfs/
@@ -6920,6 +6935,18 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.
 S:     Maintained
 F:     drivers/platform/x86
 
+XEN HYPERVISOR INTERFACE
+M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
+L:     virtualization@lists.linux-foundation.org
+S:     Supported
+F:     arch/x86/xen/
+F:     drivers/*/xen-*front.c
+F:     drivers/xen/
+F:     arch/x86/include/asm/xen/
+F:     include/xen/
+
 XEN NETWORK BACKEND DRIVER
 M:     Ian Campbell <ian.campbell@citrix.com>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
@@ -6941,18 +6968,6 @@ S:       Supported
 F:     arch/x86/xen/*swiotlb*
 F:     drivers/xen/*swiotlb*
 
-XEN HYPERVISOR INTERFACE
-M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
-M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
-L:     virtualization@lists.linux-foundation.org
-S:     Supported
-F:     arch/x86/xen/
-F:     drivers/*/xen-*front.c
-F:     drivers/xen/
-F:     arch/x86/include/asm/xen/
-F:     include/xen/
-
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
 M:     Alex Elder <aelder@sgi.com>
@@ -7022,20 +7037,6 @@ M:       "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/tty/serial/zs.*
 
-GRE DEMULTIPLEXER DRIVER
-M:     Dmitry Kozlov <xeb@mail.ru>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     net/ipv4/gre.c
-F:     include/net/gre.h
-
-PPTP DRIVER
-M:     Dmitry Kozlov <xeb@mail.ru>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/pptp.c
-W:     http://sourceforge.net/projects/accel-pptp
-
 THE REST
 M:     Linus Torvalds <torvalds@linux-foundation.org>
 L:     linux-kernel@vger.kernel.org
index b967b967572bb1c3bca2ab1b046add090b0f9248..a0344a81a893b1a6e8d35346c370db7574d656ff 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 39
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
@@ -1268,6 +1268,7 @@ help:
        @echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
        @echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
        @echo  '  make W=1   [targets] Enable extra gcc checks'
+       @echo  '  make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
        @echo  ''
        @echo  'Execute "make" or "make all" to build all targets marked with [*] '
        @echo  'For further info see the ./README file'
index 058937bf5a77718983126f2ab3813a023cb8c1d0..b1834166922dbb8260eb4457cf2c77a8c4616e59 100644 (file)
 #define __NR_fanotify_init             494
 #define __NR_fanotify_mark             495
 #define __NR_prlimit64                 496
+#define __NR_name_to_handle_at         497
+#define __NR_open_by_handle_at         498
+#define __NR_clock_adjtime             499
+#define __NR_syncfs                    500
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS                    497
+#define NR_SYSCALLS                    501
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 42aa078a5e4d3531994144998b6a5c6bfe87ddaf..5a621c6d22ab4e217b489376c82da5f3d5f94894 100644 (file)
@@ -585,8 +585,7 @@ handle_ipi(struct pt_regs *regs)
 
                switch (which) {
                case IPI_RESCHEDULE:
-                       /* Reschedule callback.  Everything to be done
-                          is done by the interrupt return path.  */
+                       scheduler_ipi();
                        break;
 
                case IPI_CALL_FUNC:
index a6a1de9db16fd6e57d96c4e0b1f76db70f27147f..15f999d41c75c820822fffb70a437ab0467d629e 100644 (file)
@@ -498,23 +498,27 @@ sys_call_table:
        .quad sys_ni_syscall                    /* sys_timerfd */
        .quad sys_eventfd
        .quad sys_recvmmsg
-       .quad sys_fallocate                             /* 480 */
+       .quad sys_fallocate                     /* 480 */
        .quad sys_timerfd_create
        .quad sys_timerfd_settime
        .quad sys_timerfd_gettime
        .quad sys_signalfd4
-       .quad sys_eventfd2                              /* 485 */
+       .quad sys_eventfd2                      /* 485 */
        .quad sys_epoll_create1
        .quad sys_dup3
        .quad sys_pipe2
        .quad sys_inotify_init1
-       .quad sys_preadv                                /* 490 */
+       .quad sys_preadv                        /* 490 */
        .quad sys_pwritev
        .quad sys_rt_tgsigqueueinfo
        .quad sys_perf_event_open
        .quad sys_fanotify_init
-       .quad sys_fanotify_mark                         /* 495 */
+       .quad sys_fanotify_mark                 /* 495 */
        .quad sys_prlimit64
+       .quad sys_name_to_handle_at
+       .quad sys_open_by_handle_at
+       .quad sys_clock_adjtime
+       .quad sys_syncfs                        /* 500 */
 
        .size sys_call_table, . - sys_call_table
        .type sys_call_table, @object
index 918e8e0b72ff1e3220845ea410277a83ff326517..818e74ed45dc01bbc0eaef0eb60b2ccbf8c137e9 100644 (file)
@@ -375,8 +375,7 @@ static struct clocksource clocksource_rpcc = {
 
 static inline void register_rpcc_clocksource(long cycle_freq)
 {
-       clocksource_calc_mult_shift(&clocksource_rpcc, cycle_freq, 4);
-       clocksource_register(&clocksource_rpcc);
+       clocksource_register_hz(&clocksource_rpcc, cycle_freq);
 }
 #else /* !CONFIG_SMP */
 static inline void register_rpcc_clocksource(long cycle_freq)
index 8ebbb511c7836383aac94622d0ed00aed5c5f29a..0c6852d93506c0afef2841ea21df84ae72d907d5 100644 (file)
@@ -74,7 +74,7 @@ ZTEXTADDR     := $(CONFIG_ZBOOT_ROM_TEXT)
 ZBSSADDR       := $(CONFIG_ZBOOT_ROM_BSS)
 else
 ZTEXTADDR      := 0
-ZBSSADDR       := ALIGN(4)
+ZBSSADDR       := ALIGN(8)
 endif
 
 SEDFLAGS       = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
index adf583cd0c351196cbfb4efe450b845707c7e36c..49f5b2eaaa87e3f0ff290f666e11a868d19c77df 100644 (file)
@@ -179,15 +179,14 @@ not_angel:
                bl      cache_on
 
 restart:       adr     r0, LC0
-               ldmia   r0, {r1, r2, r3, r5, r6, r9, r11, r12}
-               ldr     sp, [r0, #32]
+               ldmia   r0, {r1, r2, r3, r6, r9, r11, r12}
+               ldr     sp, [r0, #28]
 
                /*
                 * We might be running at a different address.  We need
                 * to fix up various pointers.
                 */
                sub     r0, r0, r1              @ calculate the delta offset
-               add     r5, r5, r0              @ _start
                add     r6, r6, r0              @ _edata
 
 #ifndef CONFIG_ZBOOT_ROM
@@ -206,31 +205,40 @@ restart:  adr     r0, LC0
 /*
  * Check to see if we will overwrite ourselves.
  *   r4  = final kernel address
- *   r5  = start of this image
  *   r9  = size of decompressed image
  *   r10 = end of this image, including  bss/stack/malloc space if non XIP
  * We basically want:
- *   r4 >= r10 -> OK
- *   r4 + image length <= r5 -> OK
+ *   r4 - 16k page directory >= r10 -> OK
+ *   r4 + image length <= current position (pc) -> OK
  */
+               add     r10, r10, #16384
                cmp     r4, r10
                bhs     wont_overwrite
                add     r10, r4, r9
-               cmp     r10, r5
+   ARM(                cmp     r10, pc         )
+ THUMB(                mov     lr, pc          )
+ THUMB(                cmp     r10, lr         )
                bls     wont_overwrite
 
 /*
  * Relocate ourselves past the end of the decompressed kernel.
- *   r5  = start of this image
  *   r6  = _edata
  *   r10 = end of the decompressed kernel
  * Because we always copy ahead, we need to do it from the end and go
  * backward in case the source and destination overlap.
  */
-               /* Round up to next 256-byte boundary. */
-               add     r10, r10, #256
+               /*
+                * Bump to the next 256-byte boundary with the size of
+                * the relocation code added. This avoids overwriting
+                * ourself when the offset is small.
+                */
+               add     r10, r10, #((reloc_code_end - restart + 256) & ~255)
                bic     r10, r10, #255
 
+               /* Get start of code we want to copy and align it down. */
+               adr     r5, restart
+               bic     r5, r5, #31
+
                sub     r9, r6, r5              @ size to copy
                add     r9, r9, #31             @ rounded up to a multiple
                bic     r9, r9, #31             @ ... of 32 bytes
@@ -245,6 +253,11 @@ restart:   adr     r0, LC0
                /* Preserve offset to relocated code. */
                sub     r6, r9, r6
 
+#ifndef CONFIG_ZBOOT_ROM
+               /* cache_clean_flush may use the stack, so relocate it */
+               add     sp, sp, r6
+#endif
+
                bl      cache_clean_flush
 
                adr     r0, BSYM(restart)
@@ -333,7 +346,6 @@ not_relocated:      mov     r0, #0
 LC0:           .word   LC0                     @ r1
                .word   __bss_start             @ r2
                .word   _end                    @ r3
-               .word   _start                  @ r5
                .word   _edata                  @ r6
                .word   _image_size             @ r9
                .word   _got_start              @ r11
@@ -1062,6 +1074,7 @@ memdump:  mov     r12, r0
 #endif
 
                .ltorg
+reloc_code_end:
 
                .align
                .section ".stack", "aw", %nobits
index 5309909d72823592dc7e9f6db0ba1e73574da46d..ea80abe788449444a685339c01a128e04250ceb8 100644 (file)
@@ -54,6 +54,7 @@ SECTIONS
   .bss                 : { *(.bss) }
   _end = .;
 
+  . = ALIGN(8);                /* the stack must be 64-bit aligned */
   .stack               : { *(.stack) }
 
   .stab 0              : { *(.stab) }
index 113085a77123d95b9cad64a882fff297c3f98dfe..7aa4262ada7a1b5f046f8bbe36631e11ce516c74 100644 (file)
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 
 #include <asm/mach/irq.h>
 #include <asm/hardware/vic.h>
 
-#if defined(CONFIG_PM)
+#ifdef CONFIG_PM
 /**
  * struct vic_device - VIC PM device
- * @sysdev: The system device which is registered.
  * @irq: The IRQ number for the base of the VIC.
  * @base: The register base for the VIC.
  * @resume_sources: A bitmask of interrupts for resume.
@@ -43,8 +42,6 @@
  * @protect: Save for VIC_PROTECT.
  */
 struct vic_device {
-       struct sys_device sysdev;
-
        void __iomem    *base;
        int             irq;
        u32             resume_sources;
@@ -59,11 +56,6 @@ struct vic_device {
 static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
 
 static int vic_id;
-
-static inline struct vic_device *to_vic(struct sys_device *sys)
-{
-       return container_of(sys, struct vic_device, sysdev);
-}
 #endif /* CONFIG_PM */
 
 /**
@@ -85,10 +77,9 @@ static void vic_init2(void __iomem *base)
        writel(32, base + VIC_PL190_DEF_VECT_ADDR);
 }
 
-#if defined(CONFIG_PM)
-static int vic_class_resume(struct sys_device *dev)
+#ifdef CONFIG_PM
+static void resume_one_vic(struct vic_device *vic)
 {
-       struct vic_device *vic = to_vic(dev);
        void __iomem *base = vic->base;
 
        printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
@@ -107,13 +98,18 @@ static int vic_class_resume(struct sys_device *dev)
 
        writel(vic->soft_int, base + VIC_INT_SOFT);
        writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
+}
 
-       return 0;
+static void vic_resume(void)
+{
+       int id;
+
+       for (id = vic_id - 1; id >= 0; id--)
+               resume_one_vic(vic_devices + id);
 }
 
-static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
+static void suspend_one_vic(struct vic_device *vic)
 {
-       struct vic_device *vic = to_vic(dev);
        void __iomem *base = vic->base;
 
        printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
@@ -128,14 +124,21 @@ static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
 
        writel(vic->resume_irqs, base + VIC_INT_ENABLE);
        writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
+}
+
+static int vic_suspend(void)
+{
+       int id;
+
+       for (id = 0; id < vic_id; id++)
+               suspend_one_vic(vic_devices + id);
 
        return 0;
 }
 
-struct sysdev_class vic_class = {
-       .name           = "vic",
-       .suspend        = vic_class_suspend,
-       .resume         = vic_class_resume,
+struct syscore_ops vic_syscore_ops = {
+       .suspend        = vic_suspend,
+       .resume         = vic_resume,
 };
 
 /**
@@ -147,30 +150,8 @@ struct sysdev_class vic_class = {
 */
 static int __init vic_pm_init(void)
 {
-       struct vic_device *dev = vic_devices;
-       int err;
-       int id;
-
-       if (vic_id == 0)
-               return 0;
-
-       err = sysdev_class_register(&vic_class);
-       if (err) {
-               printk(KERN_ERR "%s: cannot register class\n", __func__);
-               return err;
-       }
-
-       for (id = 0; id < vic_id; id++, dev++) {
-               dev->sysdev.id = id;
-               dev->sysdev.cls = &vic_class;
-
-               err = sysdev_register(&dev->sysdev);
-               if (err) {
-                       printk(KERN_ERR "%s: failed to register device\n",
-                              __func__);
-                       return err;
-               }
-       }
+       if (vic_id > 0)
+               register_syscore_ops(&vic_syscore_ops);
 
        return 0;
 }
diff --git a/arch/arm/configs/at91x40_defconfig b/arch/arm/configs/at91x40_defconfig
new file mode 100644 (file)
index 0000000..c55e921
--- /dev/null
@@ -0,0 +1,48 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_FUTEX is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91X40=y
+CONFIG_MACH_AT91EB01=y
+CONFIG_AT91_EARLY_USART0=y
+CONFIG_CPU_ARM7TDMI=y
+CONFIG_SET_MEM_PARAM=y
+CONFIG_DRAM_BASE=0x01000000
+CONFIG_DRAM_SIZE=0x00400000
+CONFIG_FLASH_MEM_BASE=0x01400000
+CONFIG_PROCESSOR_ID=0x14000040
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_BINFMT_FLAT=y
+# CONFIG_SUSPEND is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_ENABLE_MUST_CHECK is not set
index ed5bc9e05a4e176e0c86c89762afeb770efc998c..cd4458f64171e5e40720b991e8df5ad72099b0c5 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_ARM_CPUTYPE_H
 
 #include <linux/stringify.h>
+#include <linux/kernel.h>
 
 #define CPUID_ID       0
 #define CPUID_CACHETYPE        1
diff --git a/arch/arm/include/asm/i8253.h b/arch/arm/include/asm/i8253.h
new file mode 100644 (file)
index 0000000..70656b6
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASMARM_I8253_H
+#define __ASMARM_I8253_H
+
+/* i8253A PIT registers */
+#define PIT_MODE       0x43
+#define PIT_CH0                0x40
+
+#define PIT_LATCH      ((PIT_TICK_RATE + HZ / 2) / HZ)
+
+extern raw_spinlock_t i8253_lock;
+
+#define outb_pit       outb_p
+#define inb_pit                inb_p
+
+#endif
index bb8a19bd58225a3ce39bf39443cfd5b74b6409fd..e46bdd0097ebd9125f7382f76048d5fc20bbbb22 100644 (file)
@@ -39,10 +39,13 @@ typedef u32 kprobe_opcode_t;
 struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
 
+typedef unsigned long (kprobe_check_cc)(unsigned long);
+
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
        kprobe_opcode_t         *insn;
        kprobe_insn_handler_t   *insn_handler;
+       kprobe_check_cc         *insn_check_cc;
 };
 
 struct prev_kprobe {
index 883f6be5117a75a529e8a07af892cc80f2974dd6..d5adaae5ee2c0b576aa3d0805591d8796376de06 100644 (file)
@@ -34,7 +34,6 @@
  *   timer interrupt which may be pending.
  */
 struct sys_timer {
-       struct sys_device       dev;
        void                    (*init)(void);
        void                    (*suspend)(void);
        void                    (*resume)(void);
index 885be097769d108d9ff9c5d39dd0cd94af55fbb9..832888d0c20c263a761cc093bb96ae4977ed15bc 100644 (file)
@@ -159,7 +159,7 @@ extern unsigned int user_debug;
 #include <mach/barriers.h>
 #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
 #define mb()           do { dsb(); outer_sync(); } while (0)
-#define rmb()          dmb()
+#define rmb()          dsb()
 #define wmb()          mb()
 #else
 #include <asm/memory.h>
index c891eb76c0e313406847e7b9fbe968bb1b8fa459..87dbe3e21970c224391e4f2e29e08c34157821f7 100644 (file)
 #define __NR_fanotify_init             (__NR_SYSCALL_BASE+367)
 #define __NR_fanotify_mark             (__NR_SYSCALL_BASE+368)
 #define __NR_prlimit64                 (__NR_SYSCALL_BASE+369)
+#define __NR_name_to_handle_at         (__NR_SYSCALL_BASE+370)
+#define __NR_open_by_handle_at         (__NR_SYSCALL_BASE+371)
+#define __NR_clock_adjtime             (__NR_SYSCALL_BASE+372)
+#define __NR_syncfs                    (__NR_SYSCALL_BASE+373)
 
 /*
  * The following SWIs are ARM private.
index 5c26eccef9982665b1e1672416b9bc996f3b2dae..7fbf28c35bb2b438469894bb6bc80797fd8a3cf6 100644 (file)
                CALL(sys_fanotify_init)
                CALL(sys_fanotify_mark)
                CALL(sys_prlimit64)
+/* 370 */      CALL(sys_name_to_handle_at)
+               CALL(sys_open_by_handle_at)
+               CALL(sys_clock_adjtime)
+               CALL(sys_syncfs)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 23891317dc4be73d083f497291525feefaf015c6..15eeff6aea0e8185d9d4b7111da60afad3ea7967 100644 (file)
@@ -34,9 +34,6 @@
  *
  *   *) If the PC is written to by the instruction, the
  *      instruction must be fully simulated in software.
- *      If it is a conditional instruction, the handler
- *      will use insn[0] to copy its condition code to
- *     set r0 to 1 and insn[1] to "mov pc, lr" to return.
  *
  *   *) Otherwise, a modified form of the instruction is
  *      directly executed.  Its handler calls the
 
 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
 
+#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
 #define PSR_fs (PSR_f|PSR_s)
 
 #define KPROBE_RETURN_INSTRUCTION      0xe1a0f00e      /* mov pc, lr */
-#define SET_R0_TRUE_INSTRUCTION                0xe3a00001      /* mov  r0, #1 */
-
-#define        truecc_insn(insn)       (((insn) & 0xf0000000) | \
-                                (SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
 
 typedef long (insn_0arg_fn_t)(void);
 typedef long (insn_1arg_fn_t)(long);
@@ -419,14 +420,10 @@ insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
 
 static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        long iaddr = (long)p->addr;
        int disp  = branch_displacement(insn);
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        if (insn & (1 << 24))
                regs->ARM_lr = iaddr + 4;
 
@@ -446,14 +443,10 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
 
 static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        int rm = insn & 0xf;
        long rmv = regs->uregs[rm];
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        if (insn & (1 << 5))
                regs->ARM_lr = (long)p->addr + 4;
 
@@ -463,9 +456,16 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
                regs->ARM_cpsr |= PSR_T_BIT;
 }
 
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+       kprobe_opcode_t insn = p->opcode;
+       int rd = (insn >> 12) & 0xf;
+       unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+       regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
 static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        int rn = (insn >> 16) & 0xf;
        int lbit = insn & (1 << 20);
@@ -476,9 +476,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
        int reg_bit_vector;
        int reg_count;
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        reg_count = 0;
        reg_bit_vector = insn & 0xffff;
        while (reg_bit_vector) {
@@ -510,11 +507,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
 
 static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        regs->ARM_pc = (long)p->addr + str_pc_offset;
        simulate_ldm1stm1(p, regs);
        regs->ARM_pc = (long)p->addr + 4;
@@ -525,24 +517,16 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
        regs->uregs[12] = regs->uregs[13];
 }
 
-static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rn = (insn >> 16) & 0xf;
-       long rnv = regs->uregs[rn];
-
-       /* Save Rn in case of writeback. */
-       regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
-}
-
 static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
 {
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
        int rd = (insn >> 12) & 0xf;
        int rn = (insn >> 16) & 0xf;
        int rm = insn & 0xf;  /* rm may be invalid, don't care. */
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
 
        /* Not following the C calling convention here, so need asm(). */
        __asm__ __volatile__ (
@@ -554,29 +538,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
                "str    r0, %[rn]       \n\t"   /* in case of writeback */
                "str    r2, %[rd0]      \n\t"
                "str    r3, %[rd1]      \n\t"
-               : [rn]  "+m" (regs->uregs[rn]),
+               : [rn]  "+m" (rnv),
                  [rd0] "=m" (regs->uregs[rd]),
                  [rd1] "=m" (regs->uregs[rd+1])
-               : [rm]   "m" (regs->uregs[rm]),
+               : [rm]   "m" (rmv),
                  [cpsr] "r" (regs->ARM_cpsr),
                  [i_fn] "r" (i_fn)
                : "r0", "r1", "r2", "r3", "lr", "cc"
        );
+       if (is_writeback(insn))
+               regs->uregs[rn] = rnv;
 }
 
 static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
 {
        insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
        int rd = (insn >> 12) & 0xf;
        int rn = (insn >> 16) & 0xf;
        int rm  = insn & 0xf;
-       long rnv = regs->uregs[rn];
-       long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+       /* rm/rmv may be invalid, don't care. */
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rnv_wb;
 
-       regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
+       rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
                                               regs->uregs[rd+1],
                                               regs->ARM_cpsr, i_fn);
+       if (is_writeback(insn))
+               regs->uregs[rn] = rnv_wb;
 }
 
 static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
@@ -630,31 +621,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
                regs->uregs[rn] = rnv_wb;  /* Save Rn in case of writeback. */
 }
 
-static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       union reg_pair fnr;
-       int rd = (insn >> 12) & 0xf;
-       int rn = (insn >> 16) & 0xf;
-
-       fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
-       regs->uregs[rn] = fnr.r0;
-       regs->uregs[rd] = fnr.r1;
-}
-
-static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rd = (insn >> 12) & 0xf;
-       int rn = (insn >> 16) & 0xf;
-       long rnv = regs->uregs[rn];
-       long rdv = regs->uregs[rd];
-
-       insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
-}
-
 static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
 {
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -688,32 +654,32 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
        insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rd = (insn >> 12) & 0xf;
-
-       regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
 {
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
-       int ird = (insn >> 12) & 0xf;
+       int rd = (insn >> 12) & 0xf;
+       long rdv = regs->uregs[rd];
 
-       insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
+       regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+       insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
-       int rn = (insn >> 16) & 0xf;
+       int rd = (insn >> 12) & 0xf;
+       int rn = insn & 0xf;
+       long rdv = regs->uregs[rd];
        long rnv = regs->uregs[rn];
 
-       insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
+       regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
 }
 
 static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
@@ -818,6 +784,17 @@ emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
        regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
 }
 
+static void __kprobes
+emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
+{
+       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+       kprobe_opcode_t insn = p->opcode;
+       int rn = (insn >> 16) & 0xf;
+       long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
+
+       insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
+}
+
 static void __kprobes
 emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
 {
@@ -854,14 +831,34 @@ emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
                insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
 }
 
+static void __kprobes
+emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
+{
+       insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
+       kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
+       int rn = (insn >> 16) & 0xf;
+       int rs = (insn >> 8) & 0xf;     /* rs/rsv may be invalid, don't care. */
+       int rm = insn & 0xf;
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rsv = regs->uregs[rs];
+
+       insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
+}
+
 static enum kprobe_insn __kprobes
 prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       int ibit = (insn & (1 << 26)) ? 25 : 22;
+       int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
+                                        : (~insn & (1 << 22));
+
+       if (is_writeback(insn) && is_r15(insn, 16))
+               return INSN_REJECTED;   /* Writeback to PC */
 
        insn &= 0xfff00fff;
        insn |= 0x00001000;     /* Rn = r0, Rd = r1 */
-       if (insn & (1 << ibit)) {
+       if (not_imm) {
                insn &= ~0xf;
                insn |= 2;      /* Rm = r2 */
        }
@@ -871,20 +868,40 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0fff;     /* Rd = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = emulate_rd12rm0;
+       asi->insn_handler = emulate_rd12_modify;
        return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
+                           struct arch_specific_insn *asi)
 {
-       insn &= 0xffff0fff;     /* Rd = r0 */
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0ff0;     /* Rd = r0 */
+       insn |= 0x00000001;     /* Rn = r1 */
+       asi->insn[0] = insn;
+       asi->insn_handler = emulate_rd12rn0_modify;
+       return INSN_GOOD;
+}
+
+static enum kprobe_insn __kprobes
+prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = emulate_rd12;
+       asi->insn_handler = emulate_rd12rm0;
        return INSN_GOOD;
 }
 
@@ -892,6 +909,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
                                struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
        insn |= 0x00000001;     /* Rm = r1 */
        asi->insn[0] = insn;
@@ -903,6 +923,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
                               struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff0f0f0;     /* Rd = r0, Rs = r0 */
        insn |= 0x00000001;     /* Rm = r1          */
        asi->insn[0] = insn;
@@ -914,6 +937,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
                                   struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff000f0;     /* Rd = r0, Rn = r0 */
        insn |= 0x00000102;     /* Rs = r1, Rm = r2 */
        asi->insn[0] = insn;
@@ -925,6 +951,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
                                       struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16) || is_r15(insn, 12))
+               return INSN_REJECTED;   /* RdHi or RdLo is PC */
+
        insn &= 0xfff000f0;     /* RdHi = r0, RdLo = r1 */
        insn |= 0x00001203;     /* Rs = r2, Rm = r3 */
        asi->insn[0] = insn;
@@ -945,20 +974,13 @@ prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
 static enum kprobe_insn __kprobes
 space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       /* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */
-       /* RFE           : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */
-       /* SRS           : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */
-       if ((insn & 0xfff30020) == 0xf1020000 ||
-           (insn & 0xfe500f00) == 0xf8100a00 ||
-           (insn & 0xfe5f0f00) == 0xf84d0500)
-               return INSN_REJECTED;
-
-       /* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */
-       if ((insn & 0xfd700000) == 0xf4500000) {
-               insn &= 0xfff0ffff;     /* Rn = r0 */
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_rn16;
-               return INSN_GOOD;
+       /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLDI        : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLDW        : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLD         : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
+       if ((insn & 0xfe300000) == 0xf4100000) {
+               asi->insn_handler = emulate_nop;
+               return INSN_GOOD_NO_SLOT;
        }
 
        /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
@@ -967,41 +989,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                return INSN_GOOD_NO_SLOT;
        }
 
-       /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
-       /* CDP2   : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-       if ((insn & 0xffff00f0) == 0xf1010000 ||
-           (insn & 0xff000010) == 0xfe000000) {
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_none;
-               return INSN_GOOD;
-       }
+       /* CPS   : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+       /* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
 
+       /* SRS   : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+       /* RFE   : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+
+       /* Coprocessor instructions... */
        /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
        /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
-       if ((insn & 0xffe00000) == 0xfc400000) {
-               insn &= 0xfff00fff;     /* Rn = r0 */
-               insn |= 0x00001000;     /* Rd = r1 */
-               asi->insn[0] = insn;
-               asi->insn_handler =
-                       (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-               return INSN_GOOD;
-       }
+       /* LDC2  : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+       /* STC2  : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+       /* CDP2  : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+       /* MCR2  : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+       /* MRC2  : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
 
-       /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-       /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-       if ((insn & 0xfe000000) == 0xfc000000) {
-               insn &= 0xfff0ffff;      /* Rn = r0 */
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_ldcstc;
-               return INSN_GOOD;
-       }
-
-       /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-       /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-       insn &= 0xffff0fff;     /* Rd = r0 */
-       asi->insn[0]      = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-       return INSN_GOOD;
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1010,19 +1013,18 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
        if ((insn & 0x0f900010) == 0x01000000) {
 
-               /* BXJ  : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
-               /* MSR  : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
-               if ((insn & 0x0ff000f0) == 0x01200020 ||
-                   (insn & 0x0fb000f0) == 0x01200000)
-                       return INSN_REJECTED;
-
-               /* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */
-               if ((insn & 0x0fb00010) == 0x01000000)
-                       return prep_emulate_rd12(insn, asi);
+               /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+               if ((insn & 0x0ff000f0) == 0x01000000) {
+                       if (is_r15(insn, 12))
+                               return INSN_REJECTED;   /* Rd is PC */
+                       asi->insn_handler = simulate_mrs;
+                       return INSN_GOOD_NO_SLOT;
+               }
 
                /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
                if ((insn & 0x0ff00090) == 0x01400080)
-                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
+                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+                                                                       asi);
 
                /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
                /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
@@ -1031,24 +1033,29 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                        return prep_emulate_rd16rs8rm0_wflags(insn, asi);
 
                /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
-               /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */
-               return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+               /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
+               if ((insn & 0x0ff00090) == 0x01000080 ||
+                   (insn & 0x0ff000b0) == 0x01200080)
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+
+               /* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+               /* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+               /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
 
+               /* Other instruction encodings aren't yet defined */
+               return INSN_REJECTED;
        }
 
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
        else if ((insn & 0x0f900090) == 0x01000010) {
 
-               /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-               if ((insn & 0xfff000f0) == 0xe1200070)
-                       return INSN_REJECTED;
-
                /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
                /* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
                if ((insn & 0x0ff000d0) == 0x01200010) {
-                       asi->insn[0] = truecc_insn(insn);
+                       if ((insn & 0x0ff000ff) == 0x0120003f)
+                               return INSN_REJECTED; /* BLX pc */
                        asi->insn_handler = simulate_blx2bx;
-                       return INSN_GOOD;
+                       return INSN_GOOD_NO_SLOT;
                }
 
                /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
@@ -1059,17 +1066,27 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                /* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
                /* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
                /* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
-               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+               if ((insn & 0x0f9000f0) == 0x01000050)
+                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
+               /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+               /* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+
+               /* Other instruction encodings aren't yet defined */
+               return INSN_REJECTED;
        }
 
        /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
-       else if ((insn & 0x0f000090) == 0x00000090) {
+       else if ((insn & 0x0f0000f0) == 0x00000090) {
 
                /* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
                /* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
                /* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
                /* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
                /* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
+               /* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
+               /* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
+               /* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
                /* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
                /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
                /* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
@@ -1078,13 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
                /* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
                /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
-               if ((insn & 0x0fe000f0) == 0x00000090) {
-                      return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-               } else if  ((insn & 0x0fe000f0) == 0x00200090) {
-                      return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-               } else {
-                      return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
-               }
+               if ((insn & 0x00d00000) == 0x00500000)
+                       return INSN_REJECTED;
+               else if ((insn & 0x00e00000) == 0x00000000)
+                       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+               else if ((insn & 0x00a00000) == 0x00200000)
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+               else
+                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+                                                                       asi);
        }
 
        /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
@@ -1092,23 +1111,45 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
                /* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
                /* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
-               /* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
-               /* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
+               /* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
+               /* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
+               /* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
                /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
                /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
+
+               /* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
+               /* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
                /* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
                /* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
                /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
                /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
-               if ((insn & 0x0fb000f0) == 0x01000090) {
-                       /* SWP/SWPB */
-                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+               if ((insn & 0x0f0000f0) == 0x01000090) {
+                       if ((insn & 0x0fb000f0) == 0x01000090) {
+                               /* SWP/SWPB */
+                               return prep_emulate_rd12rn16rm0_wflags(insn,
+                                                                       asi);
+                       } else {
+                               /* STREX/LDREX variants and unallocaed space */
+                               return INSN_REJECTED;
+                       }
+
                } else if ((insn & 0x0e1000d0) == 0x00000d0) {
                        /* STRD/LDRD */
+                       if ((insn & 0x0000e000) == 0x0000e000)
+                               return INSN_REJECTED;   /* Rd is LR or PC */
+                       if (is_writeback(insn) && is_r15(insn, 16))
+                               return INSN_REJECTED;   /* Writeback to PC */
+
                        insn &= 0xfff00fff;
                        insn |= 0x00002000;     /* Rn = r0, Rd = r2 */
-                       if (insn & (1 << 22)) {
-                               /* I bit */
+                       if (!(insn & (1 << 22))) {
+                               /* Register index */
                                insn &= ~0xf;
                                insn |= 1;      /* Rm = r1 */
                        }
@@ -1118,6 +1159,9 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                        return INSN_GOOD;
                }
 
+               /* LDRH/STRH/LDRSB/LDRSH */
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                return prep_emulate_ldr_str(insn, asi);
        }
 
@@ -1125,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /*
         * ALU op with S bit and Rd == 15 :
-        *      cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
+        *      cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
         */
        if ((insn & 0x0e10f000) == 0x0010f000)
                return INSN_REJECTED;
@@ -1154,22 +1198,61 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                insn |= 0x00000200;     /* Rs = r2 */
        }
        asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+       if ((insn & 0x0f900000) == 0x01100000) {
+               /*
+                * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
+                * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
+                * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
+                * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
+                */
+               asi->insn_handler = emulate_alu_tests;
+       } else {
+               /* ALU ops which write to Rd */
+               asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                                emulate_alu_rwflags : emulate_alu_rflags;
+       }
        return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
 space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       /* MOVW  : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+       /* MOVT  : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+       if ((insn & 0x0fb00000) == 0x03000000)
+               return prep_emulate_rd12_modify(insn, asi);
+
+       /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+       if ((insn & 0x0fff0000) == 0x03200000) {
+               unsigned op2 = insn & 0x000000ff;
+               if (op2 == 0x01 || op2 == 0x04) {
+                       /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+                       /* SEV   : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+                       asi->insn[0] = insn;
+                       asi->insn_handler = emulate_none;
+                       return INSN_GOOD;
+               } else if (op2 <= 0x03) {
+                       /* NOP   : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+                       /* WFE   : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+                       /* WFI   : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+                       /*
+                        * We make WFE and WFI true NOPs to avoid stalls due
+                        * to missing events whilst processing the probe.
+                        */
+                       asi->insn_handler = emulate_nop;
+                       return INSN_GOOD_NO_SLOT;
+               }
+               /* For DBG and unallocated hints it's safest to reject them */
+               return INSN_REJECTED;
+       }
+
        /*
         * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-        * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
         * ALU op with S bit and Rd == 15 :
         *         cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
         */
        if ((insn & 0x0fb00000) == 0x03200000 ||        /* MSR */
-           (insn & 0x0ff00000) == 0x03400000 ||        /* Undef */
            (insn & 0x0e10f000) == 0x0210f000)          /* ALU s-bit, R15  */
                return INSN_REJECTED;
 
@@ -1180,10 +1263,22 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
         * *S (bit 20) updates condition codes
         * ADC/SBC/RSC reads the C flag
         */
-       insn &= 0xffff0fff;     /* Rd = r0 */
+       insn &= 0xfff00fff;     /* Rn = r0 and Rd = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+       if ((insn & 0x0f900000) == 0x03100000) {
+               /*
+                * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
+                * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
+                * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
+                * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
+                */
+               asi->insn_handler = emulate_alu_tests_imm;
+       } else {
+               /* ALU ops which write to Rd */
+               asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                        emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
+       }
        return INSN_GOOD;
 }
 
@@ -1192,6 +1287,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
        /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
        if ((insn & 0x0ff000f0) == 0x068000b0) {
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
                insn |= 0x00000001;     /* Rm = r1 */
                asi->insn[0] = insn;
@@ -1205,6 +1302,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
        if ((insn & 0x0fa00030) == 0x06a00010 ||
            (insn & 0x0fb000f0) == 0x06a00030) {
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
                asi->insn[0] = insn;
                asi->insn_handler = emulate_sat;
@@ -1213,57 +1312,101 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /* REV    : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
        /* REV16  : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+       /* RBIT   : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
        /* REVSH  : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
        if ((insn & 0x0ff00070) == 0x06b00030 ||
-           (insn & 0x0ff000f0) == 0x06f000b0)
+           (insn & 0x0ff00070) == 0x06f00030)
                return prep_emulate_rd12rm0(insn, asi);
 
+       /* ???       : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx :   */
        /* SADD16    : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
        /* SADDSUBX  : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
        /* SSUBADDX  : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
        /* SSUB16    : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
        /* SADD8     : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
+       /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx :   */
        /* SSUB8     : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
        /* QADD16    : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx :   */
        /* QADDSUBX  : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx :   */
        /* QSUBADDX  : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx :   */
        /* QSUB16    : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx :   */
        /* QADD8     : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx :   */
        /* QSUB8     : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx :   */
        /* SHADD16   : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx :   */
        /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx :   */
        /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx :   */
        /* SHSUB16   : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx :   */
        /* SHADD8    : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx :   */
        /* SHSUB8    : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx :   */
+       /* ???       : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx :   */
        /* UADD16    : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
        /* UADDSUBX  : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
        /* USUBADDX  : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
        /* USUB16    : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
        /* UADD8     : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
+       /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx :   */
        /* USUB8     : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
        /* UQADD16   : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx :   */
        /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx :   */
        /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx :   */
        /* UQSUB16   : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx :   */
        /* UQADD8    : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx :   */
        /* UQSUB8    : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx :   */
        /* UHADD16   : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx :   */
        /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx :   */
        /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx :   */
        /* UHSUB16   : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx :   */
        /* UHADD8    : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx :   */
        /* UHSUB8    : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx :   */
+       if ((insn & 0x0f800010) == 0x06000010) {
+               if ((insn & 0x00300000) == 0x00000000 ||
+                   (insn & 0x000000e0) == 0x000000a0 ||
+                   (insn & 0x000000e0) == 0x000000c0)
+                       return INSN_REJECTED;   /* Unallocated space */
+               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       }
+
        /* PKHBT     : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx :   */
        /* PKHTB     : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx :   */
+       if ((insn & 0x0ff00030) == 0x06800010)
+               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
        /* SXTAB16   : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx :   */
-       /* SXTB      : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTB16    : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx :   */
+       /* ???       : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx :   */
        /* SXTAB     : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTB      : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx :   */
        /* SXTAH     : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTH      : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx :   */
        /* UXTAB16   : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx :   */
+       /* UXTB16    : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx :   */
+       /* ???       : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx :   */
        /* UXTAB     : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx :   */
+       /* UXTB      : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx :   */
        /* UXTAH     : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx :   */
-       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       /* UXTH      : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx :   */
+       if ((insn & 0x0f8000f0) == 0x06800070) {
+               if ((insn & 0x00300000) == 0x00100000)
+                       return INSN_REJECTED;   /* Unallocated space */
+
+               if ((insn & 0x000f0000) == 0x000f0000)
+                       return prep_emulate_rd12rm0(insn, asi);
+               else
+                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       }
+
+       /* Other instruction encodings aren't yet defined */
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1273,29 +1416,49 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        if ((insn & 0x0ff000f0) == 0x03f000f0)
                return INSN_REJECTED;
 
-       /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
-       /* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
-       if ((insn & 0x0ff000f0) == 0x07800010)
-                return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
        /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
        /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
        if ((insn & 0x0ff00090) == 0x07400010)
                return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
 
        /* SMLAD  : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
+       /* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
        /* SMLSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
+       /* SMUSD  : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx :  */
        /* SMMLA  : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx :  */
-       /* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+       /* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
+       /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx :  */
+       /* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx :  */
        if ((insn & 0x0ff00090) == 0x07000010 ||
            (insn & 0x0ff000d0) == 0x07500010 ||
-           (insn & 0x0ff000d0) == 0x075000d0)
+           (insn & 0x0ff000f0) == 0x07800010) {
+
+               if ((insn & 0x0000f000) == 0x0000f000)
+                       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+               else
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+       }
+
+       /* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+       if ((insn & 0x0ff000d0) == 0x075000d0)
                return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
 
-       /* SMUSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :  */
-       /* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
-       /* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
-       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+       /* SBFX   : cccc 0111 101x xxxx xxxx xxxx x101 xxxx :  */
+       /* UBFX   : cccc 0111 111x xxxx xxxx xxxx x101 xxxx :  */
+       if ((insn & 0x0fa00070) == 0x07a00050)
+               return prep_emulate_rd12rm0(insn, asi);
+
+       /* BFI    : cccc 0111 110x xxxx xxxx xxxx x001 xxxx :  */
+       /* BFC    : cccc 0111 110x xxxx xxxx xxxx x001 1111 :  */
+       if ((insn & 0x0fe00070) == 0x07c00010) {
+
+               if ((insn & 0x0000000f) == 0x0000000f)
+                       return prep_emulate_rd12_modify(insn, asi);
+               else
+                       return prep_emulate_rd12rn0_modify(insn, asi);
+       }
+
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1309,6 +1472,10 @@ space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* STRB  : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
        /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
        /* STRT  : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+
+       if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
+               return INSN_REJECTED;   /* LDRB into PC */
+
        return prep_emulate_ldr_str(insn, asi);
 }
 
@@ -1323,10 +1490,9 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
        /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
-       asi->insn[0] = truecc_insn(insn);
        asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
                                simulate_stm1_pc : simulate_ldm1stm1;
-       return INSN_GOOD;
+       return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
@@ -1334,58 +1500,117 @@ space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
        /* B  : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
        /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
-       asi->insn[0] = truecc_insn(insn);
        asi->insn_handler = simulate_bbl;
-       return INSN_GOOD;
+       return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
-space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       /* Coprocessor instructions... */
        /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
        /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
-       insn &= 0xfff00fff;
-       insn |= 0x00001000;     /* Rn = r0, Rd = r1 */
-       asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-       return INSN_GOOD;
+       /* LDC  : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+       /* STC  : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+       /* CDP  : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+       /* MCR  : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+       /* MRC  : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+       /* SVC  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+
+       return INSN_REJECTED;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
 {
-       /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-       /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-       insn &= 0xfff0ffff;     /* Rn = r0 */
-       asi->insn[0] = insn;
-       asi->insn_handler = emulate_ldcstc;
-       return INSN_GOOD;
+       return cpsr & PSR_Z_BIT;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
 {
-       /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-       /* SWI  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
-       if ((insn & 0xfff000f0) == 0xe1200070 ||
-           (insn & 0x0f000000) == 0x0f000000)
-               return INSN_REJECTED;
+       return (~cpsr) & PSR_Z_BIT;
+}
 
-       /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-       if ((insn & 0x0f000010) == 0x0e000000) {
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_none;
-               return INSN_GOOD;
-       }
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+       return cpsr & PSR_C_BIT;
+}
 
-       /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-       /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-       insn &= 0xffff0fff;     /* Rd = r0 */
-       asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-       return INSN_GOOD;
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+       return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+       return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+       cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+       return cpsr & PSR_C_BIT;
 }
 
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+       cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+       return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+       cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+       cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+       unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
+       return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+       unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
+       return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+       return true;
+}
+
+static kprobe_check_cc * const condition_checks[16] = {
+       &__check_eq, &__check_ne, &__check_cs, &__check_cc,
+       &__check_mi, &__check_pl, &__check_vs, &__check_vc,
+       &__check_hi, &__check_ls, &__check_ge, &__check_lt,
+       &__check_gt, &__check_le, &__check_al, &__check_al
+};
+
 /* Return:
  *   INSN_REJECTED     If instruction is one not allowed to kprobe,
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
@@ -1401,133 +1626,45 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 enum kprobe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       asi->insn_check_cc = condition_checks[insn>>28];
        asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
 
-       if ((insn & 0xf0000000) == 0xf0000000) {
+       if ((insn & 0xf0000000) == 0xf0000000)
 
                return space_1111(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x00000000) {
+       else if ((insn & 0x0e000000) == 0x00000000)
 
                return space_cccc_000x(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x02000000) {
+       else if ((insn & 0x0e000000) == 0x02000000)
 
                return space_cccc_001x(insn, asi);
 
-       } else if ((insn & 0x0f000010) == 0x06000010) {
+       else if ((insn & 0x0f000010) == 0x06000010)
 
                return space_cccc_0110__1(insn, asi);
 
-       } else if ((insn & 0x0f000010) == 0x07000010) {
+       else if ((insn & 0x0f000010) == 0x07000010)
 
                return space_cccc_0111__1(insn, asi);
 
-       } else if ((insn & 0x0c000000) == 0x04000000) {
+       else if ((insn & 0x0c000000) == 0x04000000)
 
                return space_cccc_01xx(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x08000000) {
+       else if ((insn & 0x0e000000) == 0x08000000)
 
                return space_cccc_100x(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x0a000000) {
+       else if ((insn & 0x0e000000) == 0x0a000000)
 
                return space_cccc_101x(insn, asi);
 
-       } else if ((insn & 0x0fe00000) == 0x0c400000) {
-
-               return space_cccc_1100_010x(insn, asi);
-
-       } else if ((insn & 0x0e000000) == 0x0c000000) {
-
-               return space_cccc_110x(insn, asi);
-
-       }
-
-       return space_cccc_111x(insn, asi);
+       return space_cccc_11xx(insn, asi);
 }
 
 void __init arm_kprobe_decode_init(void)
 {
        find_str_pc_offset();
 }
-
-
-/*
- * All ARM instructions listed below.
- *
- * Instructions and their general purpose registers are given.
- * If a particular register may not use R15, it is prefixed with a "!".
- * If marked with a "*" means the value returned by reading R15
- * is implementation defined.
- *
- * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ
- *     TST: Rd, Rn, Rm, !Rs
- * BX: Rm
- * BLX(2): !Rm
- * BX: Rm (R15 legal, but discouraged)
- * BXJ: !Rm,
- * CLZ: !Rd, !Rm
- * CPY: Rd, Rm
- * LDC/2,STC/2 immediate offset & unindex: Rn
- * LDC/2,STC/2 immediate pre/post-indexed: !Rn
- * LDM(1/3): !Rn, register_list
- * LDM(2): !Rn, !register_list
- * LDR,STR,PLD immediate offset: Rd, Rn
- * LDR,STR,PLD register offset: Rd, Rn, !Rm
- * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm
- * LDR,STR immediate pre/post-indexed: Rd, !Rn
- * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm
- * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm
- * LDRB,STRB immediate offset: !Rd, Rn
- * LDRB,STRB register offset: !Rd, Rn, !Rm
- * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm
- * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn
- * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn
- * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm
- * LDREX: !Rd, !Rn
- * MCR/2: !Rd
- * MCRR/2,MRRC/2: !Rd, !Rn
- * MLA: !Rd, !Rn, !Rm, !Rs
- * MOV: Rd
- * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register)
- * MRS,MSR: !Rd
- * MUL: !Rd, !Rm, !Rs
- * PKH{BT,TB}: !Rd, !Rn, !Rm
- * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn
- * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn
- * REV/16/SH: !Rd, !Rm
- * RFE: !Rn
- * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm
- * SEL: !Rd, !Rn, !Rm
- * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs
- * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs
- * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs
- * SSAT/16: !Rd, !Rm
- * STM(1/2): !Rn, register_list* (R15 in reg list not recommended)
- * STRT immediate pre/post-indexed: Rd*, !Rn
- * STRT register pre/post-indexed: Rd*, !Rn, !Rm
- * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm
- * STREX: !Rd, !Rn, !Rm
- * SWP/B: !Rd, !Rn, !Rm
- * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm
- * {S,U}XT{B,B16,H}: !Rd, !Rm
- * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs
- * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs
- *
- * May transfer control by writing R15 (possible mode changes or alternate
- * mode accesses marked by "*"):
- * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY,
- * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI*
- *
- * Instructions that do not take general registers, nor transfer control:
- * CDP/2, SETEND, SRS*
- */
index 2ba7deb3072e5962c6cd3de55d4a2ed2594c1589..1656c87501c0f5bee77ebaab931e8249d70ce451 100644 (file)
@@ -134,7 +134,8 @@ static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
                                 struct kprobe_ctlblk *kcb)
 {
        regs->ARM_pc += 4;
-       p->ainsn.insn_handler(p, regs);
+       if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
+               p->ainsn.insn_handler(p, regs);
 }
 
 /*
index 31a316c1777b8e80ca362407b008168fc7f2e06b..0f107dcb034790d3be0b7405b7c235034d495868 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/leds.h>
 
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_device *dev,
 
 static SYSDEV_ATTR(event, 0200, NULL, leds_store);
 
-static int leds_suspend(struct sys_device *dev, pm_message_t state)
+static struct sysdev_class leds_sysclass = {
+       .name           = "leds",
+};
+
+static struct sys_device leds_device = {
+       .id             = 0,
+       .cls            = &leds_sysclass,
+};
+
+static int leds_suspend(void)
 {
        leds_event(led_stop);
        return 0;
 }
 
-static int leds_resume(struct sys_device *dev)
+static void leds_resume(void)
 {
        leds_event(led_start);
-       return 0;
 }
 
-static int leds_shutdown(struct sys_device *dev)
+static void leds_shutdown(void)
 {
        leds_event(led_halted);
-       return 0;
 }
 
-static struct sysdev_class leds_sysclass = {
-       .name           = "leds",
+static struct syscore_ops leds_syscore_ops = {
        .shutdown       = leds_shutdown,
        .suspend        = leds_suspend,
        .resume         = leds_resume,
 };
 
-static struct sys_device leds_device = {
-       .id             = 0,
-       .cls            = &leds_sysclass,
-};
-
 static int __init leds_init(void)
 {
        int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void)
                ret = sysdev_register(&leds_device);
        if (ret == 0)
                ret = sysdev_create_file(&leds_device, &attr_event);
+       if (ret == 0)
+               register_syscore_ops(&leds_syscore_ops);
        return ret;
 }
 
index 979da3947f4272c933739064d576f991c412eeac..139e3c8273696198fa0995a761a5368875961b51 100644 (file)
@@ -746,7 +746,8 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 
        tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
-       while (tail && !((unsigned long)tail & 0x3))
+       while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+              tail && !((unsigned long)tail & 0x3))
                tail = user_backtrace(tail, entry);
 }
 
index 2bf27f364d098c210ed7cca9ece5edca613a9f2b..8182f45ca493724f732f59cfe38e69a7c45afe44 100644 (file)
@@ -767,12 +767,20 @@ long arch_ptrace(struct task_struct *child, long request,
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
                case PTRACE_GETHBPREGS:
+                       if (ptrace_get_breakpoints(child) < 0)
+                               return -ESRCH;
+
                        ret = ptrace_gethbpregs(child, addr,
                                                (unsigned long __user *)data);
+                       ptrace_put_breakpoints(child);
                        break;
                case PTRACE_SETHBPREGS:
+                       if (ptrace_get_breakpoints(child) < 0)
+                               return -ESRCH;
+
                        ret = ptrace_sethbpregs(child, addr,
                                                (unsigned long __user *)data);
+                       ptrace_put_breakpoints(child);
                        break;
 #endif
 
index cb83983176447ee04d2492a957e691b459f3f7f4..0340224cf73c5c9db2d16185bd698a6ba6518fb8 100644 (file)
@@ -597,45 +597,19 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
        return err;
 }
 
-static inline void setup_syscall_restart(struct pt_regs *regs)
-{
-       regs->ARM_r0 = regs->ARM_ORIG_r0;
-       regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
-}
-
 /*
  * OK, we're invoking a handler
  */    
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
              siginfo_t *info, sigset_t *oldset,
-             struct pt_regs * regs, int syscall)
+             struct pt_regs * regs)
 {
        struct thread_info *thread = current_thread_info();
        struct task_struct *tsk = current;
        int usig = sig;
        int ret;
 
-       /*
-        * If we were from a system call, check for system call restarting...
-        */
-       if (syscall) {
-               switch (regs->ARM_r0) {
-               case -ERESTART_RESTARTBLOCK:
-               case -ERESTARTNOHAND:
-                       regs->ARM_r0 = -EINTR;
-                       break;
-               case -ERESTARTSYS:
-                       if (!(ka->sa.sa_flags & SA_RESTART)) {
-                               regs->ARM_r0 = -EINTR;
-                               break;
-                       }
-                       /* fallthrough */
-               case -ERESTARTNOINTR:
-                       setup_syscall_restart(regs);
-               }
-       }
-
        /*
         * translate the signal
         */
@@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
  */
 static void do_signal(struct pt_regs *regs, int syscall)
 {
+       unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
        struct k_sigaction ka;
        siginfo_t info;
        int signr;
@@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall)
        if (!user_mode(regs))
                return;
 
+       /*
+        * If we were from a system call, check for system call restarting...
+        */
+       if (syscall) {
+               continue_addr = regs->ARM_pc;
+               restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
+               retval = regs->ARM_r0;
+
+               /*
+                * Prepare for system call restart.  We do this here so that a
+                * debugger will see the already changed PSW.
+                */
+               switch (retval) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
+                       regs->ARM_r0 = regs->ARM_ORIG_r0;
+                       regs->ARM_pc = restart_addr;
+                       break;
+               case -ERESTART_RESTARTBLOCK:
+                       regs->ARM_r0 = -EINTR;
+                       break;
+               }
+       }
+
        if (try_to_freeze())
                goto no_signal;
 
+       /*
+        * Get the signal to deliver.  When running under ptrace, at this
+        * point the debugger may change all our registers ...
+        */
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                sigset_t *oldset;
 
+               /*
+                * Depending on the signal settings we may need to revert the
+                * decision to restart the system call.  But skip this if a
+                * debugger has chosen to restart at a different PC.
+                */
+               if (regs->ARM_pc == restart_addr) {
+                       if (retval == -ERESTARTNOHAND
+                           || (retval == -ERESTARTSYS
+                               && !(ka.sa.sa_flags & SA_RESTART))) {
+                               regs->ARM_r0 = -EINTR;
+                               regs->ARM_pc = continue_addr;
+                       }
+               }
+
                if (test_thread_flag(TIF_RESTORE_SIGMASK))
                        oldset = &current->saved_sigmask;
                else
                        oldset = &current->blocked;
-               if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
                        /*
                         * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
@@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
        }
 
  no_signal:
-       /*
-        * No signal to deliver to the process - restart the syscall.
-        */
        if (syscall) {
-               if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
+               /*
+                * Handle restarting a different system call.  As above,
+                * if a debugger has chosen to restart at a different PC,
+                * ignore the restart.
+                */
+               if (retval == -ERESTART_RESTARTBLOCK
+                   && regs->ARM_pc == continue_addr) {
                        if (thumb_mode(regs)) {
                                regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
                                regs->ARM_pc -= 2;
@@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
 #endif
                        }
                }
-               if (regs->ARM_r0 == -ERESTARTNOHAND ||
-                   regs->ARM_r0 == -ERESTARTSYS ||
-                   regs->ARM_r0 == -ERESTARTNOINTR) {
-                       setup_syscall_restart(regs);
-               }
 
                /* If there's no signal to deliver, we just put the saved sigmask
                 * back.
index 8fe05ad932e4bd0b113c11c19f7e816650ace696..007a0a950e75709424691b135deb918d4ff363fe 100644 (file)
@@ -479,7 +479,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode,
 {
 }
 
-static void broadcast_timer_setup(struct clock_event_device *evt)
+static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
 {
        evt->name       = "dummy_timer";
        evt->features   = CLOCK_EVT_FEAT_ONESHOT |
@@ -560,10 +560,7 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
                break;
 
        case IPI_RESCHEDULE:
-               /*
-                * nothing more to do - eveything is
-                * done on the interrupt return path
-                */
+               scheduler_ipi();
                break;
 
        case IPI_CALL_FUNC:
index 4ad8da15ef2b3972f4412631ceb1a5cf1d63eba2..af0aaebf4de62e16e70fcfcad8ccafece2879217 100644 (file)
@@ -311,7 +311,7 @@ asmlinkage long sys_oabi_semtimedop(int semid,
        long err;
        int i;
 
-       if (nsops < 1)
+       if (nsops < 1 || nsops > SEMOPM)
                return -EINVAL;
        sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
        if (!sops)
index 1ff46cabc7efd4cd65c97ab0447895b3c21cf533..cb634c3e28e95c6aa6f21ece37341c0e42c9d75b 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/profile.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/timer.h>
 #include <linux/irq.h>
 
@@ -115,48 +115,37 @@ void timer_tick(void)
 #endif
 
 #if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
+static int timer_suspend(void)
 {
-       struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
-
-       if (timer->suspend != NULL)
-               timer->suspend();
+       if (system_timer->suspend)
+               system_timer->suspend();
 
        return 0;
 }
 
-static int timer_resume(struct sys_device *dev)
+static void timer_resume(void)
 {
-       struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
-
-       if (timer->resume != NULL)
-               timer->resume();
-
-       return 0;
+       if (system_timer->resume)
+               system_timer->resume();
 }
 #else
 #define timer_suspend NULL
 #define timer_resume NULL
 #endif
 
-static struct sysdev_class timer_sysclass = {
-       .name           = "timer",
+static struct syscore_ops timer_syscore_ops = {
        .suspend        = timer_suspend,
        .resume         = timer_resume,
 };
 
-static int __init timer_init_sysfs(void)
+static int __init timer_init_syscore_ops(void)
 {
-       int ret = sysdev_class_register(&timer_sysclass);
-       if (ret == 0) {
-               system_timer->dev.cls = &timer_sysclass;
-               ret = sysdev_register(&system_timer->dev);
-       }
+       register_syscore_ops(&timer_syscore_ops);
 
-       return ret;
+       return 0;
 }
 
-device_initcall(timer_init_sysfs);
+device_initcall(timer_init_syscore_ops);
 
 void __init time_init(void)
 {
index 19390231a0e98d5e792c64e487269e5f75a2ba23..2d299bf5d72fc05085dacf6ce5bcb20d9c02e1ea 100644 (file)
@@ -83,6 +83,7 @@ config ARCH_AT91CAP9
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
        select HAVE_FB_ATMEL
+       select HAVE_NET_MACB
 
 config ARCH_AT572D940HF
        bool "AT572D940HF"
index 1f9d3cb64c50d66aa7f10f48cdd5fc532eb36a90..d8df59a3426d82a75de3255bf586292659072616 100644 (file)
 #include <mach/board.h>
 #include "generic.h"
 
+static void __init at91eb01_init_irq(void)
+{
+       at91x40_init_interrupts(NULL);
+}
+
 static void __init at91eb01_map_io(void)
 {
        at91x40_initialize(40000000);
@@ -38,7 +43,7 @@ static void __init at91eb01_map_io(void)
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
        /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
        .timer          = &at91x40_timer,
-       .init_irq       = at91x40_init_interrupts,
+       .init_irq       = at91eb01_init_irq,
        .map_io         = at91eb01_map_io,
 MACHINE_END
 
index 3bef931d0b1c915b5de540ee860dcf37cf27cba6..0700f2125305d99fd769f46726fe1e09afaa3dcc 100644 (file)
@@ -27,6 +27,7 @@
 #define ARCH_ID_AT91SAM9G45    0x819b05a0
 #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2      /* aka 9G45-ES2 & non ES lots */
 #define ARCH_ID_AT91SAM9G45ES  0x819b05a1      /* 9G45-ES (Engineering Sample) */
+#define ARCH_ID_AT91SAM9X5     0x819a05a0
 #define ARCH_ID_AT91CAP9       0x039A03A0
 
 #define ARCH_ID_AT91SAM9XE128  0x329973a0
@@ -55,6 +56,12 @@ static inline unsigned long at91_cpu_fully_identify(void)
 #define ARCH_EXID_AT91SAM9G46  0x00000003
 #define ARCH_EXID_AT91SAM9G45  0x00000004
 
+#define ARCH_EXID_AT91SAM9G15  0x00000000
+#define ARCH_EXID_AT91SAM9G35  0x00000001
+#define ARCH_EXID_AT91SAM9X35  0x00000002
+#define ARCH_EXID_AT91SAM9G25  0x00000003
+#define ARCH_EXID_AT91SAM9X25  0x00000004
+
 static inline unsigned long at91_exid_identify(void)
 {
        return at91_sys_read(AT91_DBGU_EXID);
@@ -143,6 +150,27 @@ static inline unsigned long at91cap9_rev_identify(void)
 #define cpu_is_at91sam9m11()   (0)
 #endif
 
+#ifdef CONFIG_ARCH_AT91SAM9X5
+#define cpu_is_at91sam9x5()    (at91_cpu_identify() == ARCH_ID_AT91SAM9X5)
+#define cpu_is_at91sam9g15()   (cpu_is_at91sam9x5() && \
+                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G15))
+#define cpu_is_at91sam9g35()   (cpu_is_at91sam9x5() && \
+                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G35))
+#define cpu_is_at91sam9x35()   (cpu_is_at91sam9x5() && \
+                               (at91_exid_identify() == ARCH_EXID_AT91SAM9X35))
+#define cpu_is_at91sam9g25()   (cpu_is_at91sam9x5() && \
+                               (at91_exid_identify() == ARCH_EXID_AT91SAM9G25))
+#define cpu_is_at91sam9x25()   (cpu_is_at91sam9x5() && \
+                               (at91_exid_identify() == ARCH_EXID_AT91SAM9X25))
+#else
+#define cpu_is_at91sam9x5()    (0)
+#define cpu_is_at91sam9g15()   (0)
+#define cpu_is_at91sam9g35()   (0)
+#define cpu_is_at91sam9x35()   (0)
+#define cpu_is_at91sam9g25()   (0)
+#define cpu_is_at91sam9x25()   (0)
+#endif
+
 #ifdef CONFIG_ARCH_AT91CAP9
 #define cpu_is_at91cap9()      (at91_cpu_identify() == ARCH_ID_AT91CAP9)
 #define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B)
index 32f147998cd9536b7daf47236da1b75e9029087f..c0deacae778d28c3ef8ff50c004ac65f01ef3ce6 100644 (file)
@@ -63,6 +63,7 @@ config MACH_DAVINCI_EVM
        depends on ARCH_DAVINCI_DM644x
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify the whether the board used
          for development is a DM644x EVM
@@ -72,6 +73,7 @@ config MACH_SFFSDR
        depends on ARCH_DAVINCI_DM644x
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the Lyrtech Small Form Factor
          Software Defined Radio (SFFSDR) board.
@@ -105,6 +107,7 @@ config MACH_DAVINCI_DM6467_EVM
        select MACH_DAVINCI_DM6467TEVM
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify the whether the board used
          for development is a DM6467 EVM
@@ -118,6 +121,7 @@ config MACH_DAVINCI_DM365_EVM
        depends on ARCH_DAVINCI_DM365
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify whether the board used
          for development is a DM365 EVM
@@ -129,6 +133,7 @@ config MACH_DAVINCI_DA830_EVM
        select GPIO_PCF857X
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
@@ -205,6 +210,7 @@ config MACH_MITYOMAPL138
        depends on ARCH_DAVINCI_DA850
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
          System on Module.  Information on this SoM may be found at
index 2aa79c54f98e664d5a48701fdf0cec553090c9aa..606a6f27ed6c20e4e38034c180e592a407e68eea 100644 (file)
@@ -29,7 +29,7 @@
 #include <mach/mux.h>
 #include <mach/spi.h>
 
-#define MITYOMAPL138_PHY_ID            "0:03"
+#define MITYOMAPL138_PHY_ID            ""
 
 #define FACTORY_CONFIG_MAGIC   0x012C0138
 #define FACTORY_CONFIG_VERSION 0x00010001
@@ -414,7 +414,7 @@ static struct resource mityomapl138_nandflash_resource[] = {
 
 static struct platform_device mityomapl138_nandflash_device = {
        .name           = "davinci_nand",
-       .id             = 0,
+       .id             = 1,
        .dev            = {
                .platform_data  = &mityomapl138_nandflash_data,
        },
index 0a95be1512bbfd5044cea277bffe9bf4646905f6..41669ecc1f91f14f0d4cade20f2cf502deb8774b 100644 (file)
@@ -94,9 +94,7 @@ static int davinci_target(struct cpufreq_policy *policy,
        if (freqs.old == freqs.new)
                return ret;
 
-       cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER,
-                       dev_driver_string(cpufreq.dev),
-                       "transition: %u --> %u\n", freqs.old, freqs.new);
+       dev_dbg(&cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new);
 
        ret = cpufreq_frequency_table_target(policy, pdata->freq_table,
                                                freqs.new, relation, &idx);
index 625d4b66718ba89bc3062c8b9b7b9189b13cc0c5..58a02dc7b15a5b76f8deb2f540e55f030d484d55 100644 (file)
@@ -39,7 +39,8 @@
 #define DA8XX_GPIO_BASE                        0x01e26000
 #define DA8XX_I2C1_BASE                        0x01e28000
 #define DA8XX_SPI0_BASE                        0x01c41000
-#define DA8XX_SPI1_BASE                        0x01f0e000
+#define DA830_SPI1_BASE                        0x01e12000
+#define DA850_SPI1_BASE                        0x01f0e000
 
 #define DA8XX_EMAC_CTRL_REG_OFFSET     0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET      0x2000
@@ -762,8 +763,8 @@ static struct resource da8xx_spi0_resources[] = {
 
 static struct resource da8xx_spi1_resources[] = {
        [0] = {
-               .start  = DA8XX_SPI1_BASE,
-               .end    = DA8XX_SPI1_BASE + SZ_4K - 1,
+               .start  = DA830_SPI1_BASE,
+               .end    = DA830_SPI1_BASE + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -832,5 +833,10 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info,
 
        da8xx_spi_pdata[instance].num_chipselect = len;
 
+       if (instance == 1 && cpu_is_davinci_da850()) {
+               da8xx_spi1_resources[0].start = DA850_SPI1_BASE;
+               da8xx_spi1_resources[0].end = DA850_SPI1_BASE + SZ_4K - 1;
+       }
+
        return platform_device_register(&da8xx_spi_device[instance]);
 }
index f6801223964157084a7442939364ab255d0c8e39..a3a94e9c93784b10a6d98c3b379a680def7641e2 100644 (file)
@@ -314,7 +314,7 @@ static struct clk timer2_clk = {
        .name = "timer2",
        .parent = &pll1_aux_clk,
        .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't' this be disabled? */
+       .usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk timer3_clk = {
index 5f8a6542418421147e84e31c18a54afc22728380..4c82c2716293a6e750f242c128fb14e66c2ce636 100644 (file)
@@ -274,7 +274,7 @@ static struct clk timer2_clk = {
        .name = "timer2",
        .parent = &pll1_aux_clk,
        .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't' this be disabled? */
+       .usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk_lookup dm644x_clks[] = {
index 9f1befc5ac387d2d0124c080c88458a67dc0b30f..f8b7ea4f6235f6f5dc66aa15d9bfe203523f4486 100644 (file)
@@ -24,6 +24,9 @@
 
 #define UART_SHIFT     2
 
+#define davinci_uart_v2p(x)    ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define davinci_uart_p2v(x)    ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
                .pushsection .data
 davinci_uart_phys:     .word   0
 davinci_uart_virt:     .word   0
@@ -34,7 +37,7 @@ davinci_uart_virt:    .word   0
                /* Use davinci_uart_phys/virt if already configured */
 10:            mrc     p15, 0, \rp, c1, c0
                tst     \rp, #1                 @ MMU enabled?
-               ldreq   \rp, =__virt_to_phys(davinci_uart_phys)
+               ldreq   \rp, =davinci_uart_v2p(davinci_uart_phys)
                ldrne   \rp, =davinci_uart_phys
                add     \rv, \rp, #4            @ davinci_uart_virt
                ldr     \rp, [\rp, #0]
@@ -48,18 +51,18 @@ davinci_uart_virt:  .word   0
                tst     \rp, #1                 @ MMU enabled?
 
                /* Copy uart phys address from decompressor uart info */
-               ldreq   \rv, =__virt_to_phys(davinci_uart_phys)
+               ldreq   \rv, =davinci_uart_v2p(davinci_uart_phys)
                ldrne   \rv, =davinci_uart_phys
                ldreq   \rp, =DAVINCI_UART_INFO
-               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldrne   \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
                ldr     \rp, [\rp, #0]
                str     \rp, [\rv]
 
                /* Copy uart virt address from decompressor uart info */
-               ldreq   \rv, =__virt_to_phys(davinci_uart_virt)
+               ldreq   \rv, =davinci_uart_v2p(davinci_uart_virt)
                ldrne   \rv, =davinci_uart_virt
                ldreq   \rp, =DAVINCI_UART_INFO
-               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldrne   \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
                ldr     \rp, [\rp, #4]
                str     \rp, [\rv]
 
index 8051110b8ac3417cf2817878204f9f1f1e28da42..c9e6ce185a66fa62a6a028613413e582894d6896 100644 (file)
@@ -22,7 +22,7 @@
  *
  * This area sits just below the page tables (see arch/arm/kernel/head.S).
  */
-#define DAVINCI_UART_INFO      (PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO      (PLAT_PHYS_OFFSET + 0x3ff8)
 
 #define DAVINCI_UART0_BASE     (IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE     (IO_PHYS + 0x20400)
index 10d917d9e3ad091d72d9971e9db96e734c5c8fbc..8755ca8dd48d2157df921a7fb5150deceb804ef1 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/suspend.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
@@ -372,7 +373,27 @@ void exynos4_scu_enable(void __iomem *scu_base)
        flush_cache_all();
 }
 
-static int exynos4_pm_resume(struct sys_device *dev)
+static struct sysdev_driver exynos4_pm_driver = {
+       .add            = exynos4_pm_add,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+       unsigned int tmp;
+
+       s3c_pm_init();
+
+       /* All wakeup disable */
+
+       tmp = __raw_readl(S5P_WAKEUP_MASK);
+       tmp |= ((0xFF << 8) | (0x1F << 1));
+       __raw_writel(tmp, S5P_WAKEUP_MASK);
+
+       return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
+
+static void exynos4_pm_resume(void)
 {
        /* For release retention */
 
@@ -394,27 +415,15 @@ static int exynos4_pm_resume(struct sys_device *dev)
        /* enable L2X0*/
        writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
 #endif
-
-       return 0;
 }
 
-static struct sysdev_driver exynos4_pm_driver = {
-       .add            = exynos4_pm_add,
+static struct syscore_ops exynos4_pm_syscore_ops = {
        .resume         = exynos4_pm_resume,
 };
 
-static __init int exynos4_pm_drvinit(void)
+static __init int exynos4_pm_syscore_init(void)
 {
-       unsigned int tmp;
-
-       s3c_pm_init();
-
-       /* All wakeup disable */
-
-       tmp = __raw_readl(S5P_WAKEUP_MASK);
-       tmp |= ((0xFF << 8) | (0x1F << 1));
-       __raw_writel(tmp, S5P_WAKEUP_MASK);
-
-       return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+       register_syscore_ops(&exynos4_pm_syscore_ops);
+       return 0;
 }
-arch_initcall(exynos4_pm_drvinit);
+arch_initcall(exynos4_pm_syscore_init);
index bdd257921cfbe639cd0adfb8c30c4febd79487cc..46adca068f2c585c2d90d47eb6415825911e3708 100644 (file)
@@ -4,6 +4,7 @@ menu "Footbridge Implementations"
 
 config ARCH_CATS
        bool "CATS"
+       select CLKSRC_I8253
        select FOOTBRIDGE_HOST
        select ISA
        select ISA_DMA
@@ -59,6 +60,7 @@ config ARCH_EBSA285_HOST
 
 config ARCH_NETWINDER
        bool "NetWinder"
+       select CLKSRC_I8253
        select FOOTBRIDGE_HOST
        select ISA
        select ISA_DMA
index 441c6ce0d555afe96ff8eaf1ddd7815846b71b33..7020f1a3feca4291a6367e5d2500286362d07395 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
 #include <linux/timex.h>
 
 #include <asm/irq.h>
-
+#include <asm/i8253.h>
 #include <asm/mach/time.h>
 
 #include "common.h"
 
-#define PIT_MODE       0x43
-#define PIT_CH0                0x40
-
-#define PIT_LATCH      ((PIT_TICK_RATE + HZ / 2) / HZ)
-
-static cycle_t pit_read(struct clocksource *cs)
-{
-       unsigned long flags;
-       static int old_count;
-       static u32 old_jifs;
-       int count;
-       u32 jifs;
-
-       raw_local_irq_save(flags);
-
-       jifs = jiffies;
-       outb_p(0x00, PIT_MODE);         /* latch the count */
-       count = inb_p(PIT_CH0);         /* read the latched count */
-       count |= inb_p(PIT_CH0) << 8;
-
-       if (count > old_count && jifs == old_jifs)
-               count = old_count;
-
-       old_count = count;
-       old_jifs = jifs;
-
-       raw_local_irq_restore(flags);
-
-       count = (PIT_LATCH - 1) - count;
-
-       return (cycle_t)(jifs * PIT_LATCH) + count;
-}
-
-static struct clocksource pit_cs = {
-       .name           = "pit",
-       .rating         = 110,
-       .read           = pit_read,
-       .mask           = CLOCKSOURCE_MASK(32),
-};
+DEFINE_RAW_SPINLOCK(i8253_lock);
 
 static void pit_set_mode(enum clock_event_mode mode,
        struct clock_event_device *evt)
@@ -121,7 +84,7 @@ static void __init isa_timer_init(void)
        pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
        pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
 
-       clocksource_register_hz(&pit_cs, PIT_TICK_RATE);
+       clocksource_i8253_init();
 
        setup_irq(pit_ce.irq, &pit_timer_irq);
        clockevents_register_device(&pit_ce);
index 980803ff348ce938bcd72d9abdb7ed45b0af2803..d3e96451529c90e5b478b03fc68c1a16b987a9b8 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/kmi.h>
 #include <linux/clocksource.h>
@@ -180,13 +180,13 @@ static void __init ap_init_irq(void)
 #ifdef CONFIG_PM
 static unsigned long ic_irq_enable;
 
-static int irq_suspend(struct sys_device *dev, pm_message_t state)
+static int irq_suspend(void)
 {
        ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
        return 0;
 }
 
-static int irq_resume(struct sys_device *dev)
+static void irq_resume(void)
 {
        /* disable all irq sources */
        writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
@@ -194,33 +194,25 @@ static int irq_resume(struct sys_device *dev)
        writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 
        writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
-       return 0;
 }
 #else
 #define irq_suspend NULL
 #define irq_resume NULL
 #endif
 
-static struct sysdev_class irq_class = {
-       .name           = "irq",
+static struct syscore_ops irq_syscore_ops = {
        .suspend        = irq_suspend,
        .resume         = irq_resume,
 };
 
-static struct sys_device irq_device = {
-       .id     = 0,
-       .cls    = &irq_class,
-};
-
-static int __init irq_init_sysfs(void)
+static int __init irq_syscore_init(void)
 {
-       int ret = sysdev_class_register(&irq_class);
-       if (ret == 0)
-               ret = sysdev_register(&irq_device);
-       return ret;
+       register_syscore_ops(&irq_syscore_ops);
+
+       return 0;
 }
 
-device_initcall(irq_init_sysfs);
+device_initcall(irq_syscore_init);
 
 /*
  * Flash handling.
index 2cf390fbd9809876a55a2b9dd6687e40cea41d60..47a69cbc31a873dbc19fc9f69d4b231095f3d356 100644 (file)
@@ -257,11 +257,16 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
+static int vpr200_usbh_init(struct platform_device *pdev)
+{
+       return mx35_initialize_usb_hw(pdev->id,
+                       MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY);
+}
+
 /* USB HOST config */
 static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
-       .portsc         = MXC_EHCI_MODE_SERIAL,
-       .flags          = MXC_EHCI_INTERFACE_SINGLE_UNI |
-                         MXC_EHCI_INTERNAL_PHY,
+       .init = vpr200_usbh_init,
+       .portsc = MXC_EHCI_MODE_SERIAL,
 };
 
 static struct platform_device *devices[] __initdata = {
index 10a1bea1054888ecfe0a24689722090a2bc778c0..6206b1191fe8e574efe7c480864fd8201060244c 100644 (file)
@@ -193,7 +193,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
        .wakeup         = wake,                                 \
 }
 
-static const struct gpio_keys_button loco_buttons[] __initconst = {
+static struct gpio_keys_button loco_buttons[] = {
        GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
        GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
        GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
index 1ad97fed1e948ccecf16db4562ad54c80252fadb..5dcc59d5b9ec9feab991fc34302273702388b21e 100644 (file)
@@ -295,11 +295,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)           \
        unsigned long diff, parent_rate, calc_rate;                     \
        int i;                                                          \
                                                                        \
-       parent_rate = clk_get_rate(clk->parent);                        \
        div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;       \
        bm_busy = BM_CLKCTRL_##dr##_BUSY;                               \
                                                                        \
        if (clk->parent == &ref_xtal_clk) {                             \
+               parent_rate = clk_get_rate(clk->parent);                \
                div = DIV_ROUND_UP(parent_rate, rate);                  \
                if (clk == &cpu_clk) {                                  \
                        div_max = BM_CLKCTRL_CPU_DIV_XTAL >>            \
@@ -309,6 +309,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)            \
                if (div == 0 || div > div_max)                          \
                        return -EINVAL;                                 \
        } else {                                                        \
+               /*                                                      \
+                * hack alert: this block modifies clk->parent, too,    \
+                * so the base to use it the grand parent.              \
+                */                                                     \
+               parent_rate = clk_get_rate(clk->parent->parent);        \
                rate >>= PARENT_RATE_SHIFT;                             \
                parent_rate >>= PARENT_RATE_SHIFT;                      \
                diff = parent_rate;                                     \
index 6588c22b8a64116dd11004001e2682aa14fe423e..fe31d933f0edee78106d52d0c82fb95ef70a3a58 100644 (file)
 #ifdef CONFIG_PM_RUNTIME
 static int omap1_pm_runtime_suspend(struct device *dev)
 {
-       struct clk *iclk, *fclk;
-       int ret = 0;
+       int ret;
 
        dev_dbg(dev, "%s\n", __func__);
 
        ret = pm_generic_runtime_suspend(dev);
+       if (ret)
+               return ret;
 
-       fclk = clk_get(dev, "fck");
-       if (!IS_ERR(fclk)) {
-               clk_disable(fclk);
-               clk_put(fclk);
-       }
-
-       iclk = clk_get(dev, "ick");
-       if (!IS_ERR(iclk)) {
-               clk_disable(iclk);
-               clk_put(iclk);
+       ret = pm_runtime_clk_suspend(dev);
+       if (ret) {
+               pm_generic_runtime_resume(dev);
+               return ret;
        }
 
        return 0;
-};
+}
 
 static int omap1_pm_runtime_resume(struct device *dev)
 {
-       struct clk *iclk, *fclk;
-
        dev_dbg(dev, "%s\n", __func__);
 
-       iclk = clk_get(dev, "ick");
-       if (!IS_ERR(iclk)) {
-               clk_enable(iclk);
-               clk_put(iclk);
-       }
+       pm_runtime_clk_resume(dev);
+       return pm_generic_runtime_resume(dev);
+}
 
-       fclk = clk_get(dev, "fck");
-       if (!IS_ERR(fclk)) {
-               clk_enable(fclk);
-               clk_put(fclk);
-       }
+static struct dev_power_domain default_power_domain = {
+       .ops = {
+               .runtime_suspend = omap1_pm_runtime_suspend,
+               .runtime_resume = omap1_pm_runtime_resume,
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
 
-       return pm_generic_runtime_resume(dev);
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pwr_domain = &default_power_domain,
+       .con_ids = { "ick", "fck", NULL, },
 };
 
 static int __init omap1_pm_runtime_init(void)
 {
-       const struct dev_pm_ops *pm;
-       struct dev_pm_ops *omap_pm;
-
        if (!cpu_class_is_omap1())
                return -ENODEV;
 
-       pm = platform_bus_get_pm_ops();
-       if (!pm) {
-               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
-       if (!omap_pm) {
-               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
-                       __func__);
-               return -ENOMEM;
-       }
-
-       omap_pm->runtime_suspend = omap1_pm_runtime_suspend;
-       omap_pm->runtime_resume = omap1_pm_runtime_resume;
-
-       platform_bus_set_pm_ops(omap_pm);
+       pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
 
        return 0;
 }
index a45cd6409686f7eadfd6cc85e24e010c628c6d0d..66dfbccacd25e0cabfdbbbf802f8cb59526d8fc7 100644 (file)
@@ -59,16 +59,16 @@ endif
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o \
-                                          cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o pm_bus.o
+                                          cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o
 obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)  += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
-AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a
+AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
 
 ifeq ($(CONFIG_PM_VERBOSE),y)
 CFLAGS_pm_bus.o                                += -DDEBUG
index e964895b80e8f95bbf8544a840e4598062c96a88..f8ba20a14e625554f95fded51abc2177e7326b96 100644 (file)
@@ -141,14 +141,19 @@ static void __init rx51_init(void)
 static void __init rx51_map_io(void)
 {
        omap2_set_globals_3xxx();
-       rx51_video_mem_init();
        omap34xx_map_common_io();
 }
 
+static void __init rx51_reserve(void)
+{
+       rx51_video_mem_init();
+       omap_reserve();
+}
+
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
        /* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
        .boot_params    = 0x80000100,
-       .reserve        = omap_reserve,
+       .reserve        = rx51_reserve,
        .map_io         = rx51_map_io,
        .init_early     = rx51_init_early,
        .init_irq       = omap_init_irq,
index b2b1e37bb6bba3cefa5961f39d026c1a5f616d53..d6e34dd9e7e75c6dde4de60a004e319dd7f02547 100644 (file)
@@ -115,6 +115,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
                                  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
                                  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
                                  0, 0, 0, 0);
+       clk->rate = rate;
 
        return 0;
 }
index 276992d3b7fba19b8873e2ff3cae068424b441e0..8c965671b4d486aae235439483204ccef4d2fbe7 100644 (file)
@@ -3116,14 +3116,9 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
        CLK("omapdss_dss",      "sys_clk",                      &dss_sys_clk,   CK_443X),
        CLK("omapdss_dss",      "tv_clk",                       &dss_tv_clk,    CK_443X),
-       CLK("omapdss_dss",      "dss_clk",                      &dss_dss_clk,   CK_443X),
        CLK("omapdss_dss",      "video_clk",                    &dss_48mhz_clk, CK_443X),
-       CLK("omapdss_dss",      "fck",                          &dss_fck,       CK_443X),
-       /*
-        * On OMAP4, DSS ick is a dummy clock; this is needed for compatibility
-        * with OMAP2/3.
-        */
-       CLK("omapdss_dss",      "ick",                          &dummy_ck,      CK_443X),
+       CLK("omapdss_dss",      "fck",                          &dss_dss_clk,   CK_443X),
+       CLK("omapdss_dss",      "ick",                          &dss_fck,       CK_443X),
        CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
        CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
        CLK(NULL,       "emif2_fck",                    &emif2_fck,     CK_443X),
index 9d0dec806e9294e721294149550a8746960e4d4f..38830d8d47835d30db060b77c49d4beb385ded4a 100644 (file)
@@ -247,6 +247,7 @@ struct omap3_cm_regs {
        u32 per_cm_clksel;
        u32 emu_cm_clksel;
        u32 emu_cm_clkstctrl;
+       u32 pll_cm_autoidle;
        u32 pll_cm_autoidle2;
        u32 pll_cm_clksel4;
        u32 pll_cm_clksel5;
@@ -319,6 +320,15 @@ void omap3_cm_save_context(void)
                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
        cm_context.emu_cm_clkstctrl =
                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+        * In this case, even though this register has been saved in
+        * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
+        * by ourselves. So, we need to save it anyway.
+        */
+       cm_context.pll_cm_autoidle =
+               omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
        cm_context.pll_cm_autoidle2 =
                omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
        cm_context.pll_cm_clksel4 =
@@ -441,6 +451,13 @@ void omap3_cm_restore_context(void)
                               CM_CLKSEL1);
        omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
                               OMAP2_CM_CLKSTCTRL);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+        * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
+        */
+       omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
+                              CM_AUTOIDLE);
        omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
                               CM_AUTOIDLE2);
        omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
index 695279419020372cf16d2be18465734308d2c5c4..da53ba3917cae5df365b34bcb8f314e4142a2471 100644 (file)
@@ -316,8 +316,14 @@ void omap3_save_scratchpad_contents(void)
                        omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
        prcm_block_contents.cm_clken_pll =
                        omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
+        * Then,  in anycase, clear these bits to avoid extra latencies.
+        */
        prcm_block_contents.cm_autoidle_pll =
-                       omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+                       omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
+                       ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
        prcm_block_contents.cm_clksel1_pll =
                        omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
        prcm_block_contents.cm_clksel2_pll =
index 8eb3ce1bbfbe3b26ab9612fb015ca366ffd6bdb0..c4d0ae87d62a98596475c74853a6ed0503d6df7f 100644 (file)
@@ -1639,6 +1639,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio1_irqs),
        .main_clk       = "gpios_fck",
@@ -1669,6 +1670,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio2_irqs),
        .main_clk       = "gpios_fck",
@@ -1699,6 +1701,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio3_irqs),
        .main_clk       = "gpios_fck",
@@ -1729,6 +1732,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio4_irqs),
        .main_clk       = "gpios_fck",
@@ -1782,7 +1786,7 @@ static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index e6e3810db77f1036c5237d62f27c161dfdf3acdd..9682dd519f8dd9d1dd0e84a788212c778672cf30 100644 (file)
@@ -1742,6 +1742,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio1_irqs),
        .main_clk       = "gpios_fck",
@@ -1772,6 +1773,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio2_irqs),
        .main_clk       = "gpios_fck",
@@ -1802,6 +1804,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio3_irqs),
        .main_clk       = "gpios_fck",
@@ -1832,6 +1835,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio4_irqs),
        .main_clk       = "gpios_fck",
@@ -1862,6 +1866,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio5_hwmod = {
        .name           = "gpio5",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio5_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio5_irqs),
        .main_clk       = "gpio5_fck",
@@ -1915,7 +1920,7 @@ static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index b98e2dfcba28c8b7a57f228472205b9266f4464b..909a84de6682d8673d7f04d1fbe47bc745a77b14 100644 (file)
@@ -2141,6 +2141,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio1_irqs),
        .main_clk       = "gpio1_ick",
@@ -2177,6 +2178,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio2_irqs),
        .main_clk       = "gpio2_ick",
@@ -2213,6 +2215,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio3_irqs),
        .main_clk       = "gpio3_ick",
@@ -2249,6 +2252,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio4_irqs),
        .main_clk       = "gpio4_ick",
@@ -2285,6 +2289,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio5_hwmod = {
        .name           = "gpio5",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio5_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio5_irqs),
        .main_clk       = "gpio5_ick",
@@ -2321,6 +2326,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio6_hwmod = {
        .name           = "gpio6",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio6_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio6_irqs),
        .main_clk       = "gpio6_ick",
@@ -2386,7 +2392,7 @@ static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index 3e88dd3f8ef3f452f814b617d35274a1490a38cb..abc548a0c98dacae4bd6c5fc7d8eb615dde9b4c5 100644 (file)
@@ -885,7 +885,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
 static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
        {
                .pa_start       = 0x4a056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x4a056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index 5f2da7565b68b917dd439c4574ab98402ed1790c..4321e79389291c9695e4695d91132f64b48cc803 100644 (file)
@@ -196,11 +196,11 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
                /* No timeout error for debug sources */
        }
 
-       base = ((l3->rt) + (*(omap3_l3_bases[int_type] + err_source)));
-
        /* identify the error source */
        for (err_source = 0; !(status & (1 << err_source)); err_source++)
                                                                        ;
+
+       base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
        error = omap3_l3_readll(base, L3_ERROR_LOG);
 
        if (error) {
index 30af3351c2d68d4f42df644696dbe478cb2dc8f1..49486f522dca55b05fc55f74523a2053f8df54e0 100644 (file)
@@ -89,6 +89,7 @@ static void omap2_init_processor_devices(void)
        if (cpu_is_omap44xx()) {
                _init_omap_device("l3_main_1", &l3_dev);
                _init_omap_device("dsp", &dsp_dev);
+               _init_omap_device("iva", &iva_dev);
        } else {
                _init_omap_device("l3_main", &l3_dev);
        }
diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c
deleted file mode 100644 (file)
index 5acd2ab..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Runtime PM support code for OMAP
- *
- * Author: Kevin Hilman, Deep Root Systems, LLC
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
-
-#ifdef CONFIG_PM_RUNTIME
-static int omap_pm_runtime_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       int r, ret = 0;
-
-       dev_dbg(dev, "%s\n", __func__);
-
-       ret = pm_generic_runtime_suspend(dev);
-
-       if (!ret && dev->parent == &omap_device_parent) {
-               r = omap_device_idle(pdev);
-               WARN_ON(r);
-       }
-
-       return ret;
-};
-
-static int omap_pm_runtime_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       int r;
-
-       dev_dbg(dev, "%s\n", __func__);
-
-       if (dev->parent == &omap_device_parent) {
-               r = omap_device_enable(pdev);
-               WARN_ON(r);
-       }
-
-       return pm_generic_runtime_resume(dev);
-};
-#else
-#define omap_pm_runtime_suspend NULL
-#define omap_pm_runtime_resume NULL
-#endif /* CONFIG_PM_RUNTIME */
-
-static int __init omap_pm_runtime_init(void)
-{
-       const struct dev_pm_ops *pm;
-       struct dev_pm_ops *omap_pm;
-
-       pm = platform_bus_get_pm_ops();
-       if (!pm) {
-               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
-       if (!omap_pm) {
-               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
-                       __func__);
-               return -ENOMEM;
-       }
-
-       omap_pm->runtime_suspend = omap_pm_runtime_suspend;
-       omap_pm->runtime_resume = omap_pm_runtime_resume;
-
-       platform_bus_set_pm_ops(omap_pm);
-
-       return 0;
-}
-core_initcall(omap_pm_runtime_init);
index 6fb520999b6e770bb12e376042ef0fc15da5b7ed..0c1552d9d99508c3bc0d2a3aaf4ae5038becc089 100644 (file)
@@ -114,7 +114,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
        sys_clk_speed /= 1000;
 
        /* Generic voltage parameters */
-       vdd->curr_volt = 1200000;
        vdd->volt_scale = vp_forceupdate_scale_voltage;
        vdd->vp_enabled = false;
 
index bfbecec6d05fbd5a3f3457185675720e00ab74d1..810a982a66f8246291ffd8f776c5debb08714bc7 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
index 1ce090448493501a23ce9c9da74a4dc81c57182e..1d5859d9a0e3299bfe55d82d21b9fe3ba123b94c 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/pxa2xx-regs.h>
 
@@ -33,32 +33,22 @@ const struct clkops clk_pxa2xx_cken_ops = {
 #ifdef CONFIG_PM
 static uint32_t saved_cken;
 
-static int pxa2xx_clock_suspend(struct sys_device *d, pm_message_t state)
+static int pxa2xx_clock_suspend(void)
 {
        saved_cken = CKEN;
        return 0;
 }
 
-static int pxa2xx_clock_resume(struct sys_device *d)
+static void pxa2xx_clock_resume(void)
 {
        CKEN = saved_cken;
-       return 0;
 }
 #else
 #define pxa2xx_clock_suspend   NULL
 #define pxa2xx_clock_resume    NULL
 #endif
 
-struct sysdev_class pxa2xx_clock_sysclass = {
-       .name           = "pxa2xx-clock",
+struct syscore_ops pxa2xx_clock_syscore_ops = {
        .suspend        = pxa2xx_clock_suspend,
        .resume         = pxa2xx_clock_resume,
 };
-
-static int __init pxa2xx_clock_init(void)
-{
-       if (cpu_is_pxa2xx())
-               return sysdev_class_register(&pxa2xx_clock_sysclass);
-       return 0;
-}
-postcore_initcall(pxa2xx_clock_init);
index 3f864cd0bd2893d786bc0441576a8c648a4435d3..2a37a9a8f62188cafffbe6289130129d1bfc9c9e 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/smemc.h>
 #include <mach/pxa3xx-regs.h>
@@ -182,7 +183,7 @@ const struct clkops clk_pxa3xx_pout_ops = {
 static uint32_t cken[2];
 static uint32_t accr;
 
-static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
+static int pxa3xx_clock_suspend(void)
 {
        cken[0] = CKENA;
        cken[1] = CKENB;
@@ -190,28 +191,18 @@ static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
        return 0;
 }
 
-static int pxa3xx_clock_resume(struct sys_device *d)
+static void pxa3xx_clock_resume(void)
 {
        ACCR = accr;
        CKENA = cken[0];
        CKENB = cken[1];
-       return 0;
 }
 #else
 #define pxa3xx_clock_suspend   NULL
 #define pxa3xx_clock_resume    NULL
 #endif
 
-struct sysdev_class pxa3xx_clock_sysclass = {
-       .name           = "pxa3xx-clock",
+struct syscore_ops pxa3xx_clock_syscore_ops = {
        .suspend        = pxa3xx_clock_suspend,
        .resume         = pxa3xx_clock_resume,
 };
-
-static int __init pxa3xx_clock_init(void)
-{
-       if (cpu_is_pxa3xx() || cpu_is_pxa95x())
-               return sysdev_class_register(&pxa3xx_clock_sysclass);
-       return 0;
-}
-postcore_initcall(pxa3xx_clock_init);
index f9f349a21b54ee7f2d2c1b67f5079efc11b5ad65..1f2fb9c43f062301ab5dc9595203a94ab4bfada4 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/clkdev.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 struct clkops {
        void                    (*enable)(struct clk *);
@@ -54,7 +54,7 @@ extern const struct clkops clk_pxa2xx_cken_ops;
 void clk_pxa2xx_cken_enable(struct clk *clk);
 void clk_pxa2xx_cken_disable(struct clk *clk);
 
-extern struct sysdev_class pxa2xx_clock_sysclass;
+extern struct syscore_ops pxa2xx_clock_syscore_ops;
 
 #if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
 #define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)  \
@@ -74,5 +74,6 @@ extern const struct clkops clk_pxa3xx_smemc_ops;
 extern void clk_pxa3xx_cken_enable(struct clk *);
 extern void clk_pxa3xx_cken_disable(struct clk *);
 
-extern struct sysdev_class pxa3xx_clock_sysclass;
+extern struct syscore_ops pxa3xx_clock_syscore_ops;
+
 #endif
index b88d601a80904baddb4c787dcee19194dab4bdf0..13518a7053994dbfe6c4ce422ee994a88d3e21f4 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
index 8225e2e58c6e9d15ede4d76d705b134534d4ec37..a1099678247630524da6ab789d4719e87d75ce47 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
 
@@ -388,7 +388,7 @@ static inline void cmx2xx_init_display(void) {}
 #ifdef CONFIG_PM
 static unsigned long sleep_save_msc[10];
 
-static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state)
+static int cmx2xx_suspend(void)
 {
        cmx2xx_pci_suspend();
 
@@ -412,7 +412,7 @@ static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int cmx2xx_resume(struct sys_device *dev)
+static void cmx2xx_resume(void)
 {
        cmx2xx_pci_resume();
 
@@ -420,27 +420,18 @@ static int cmx2xx_resume(struct sys_device *dev)
        __raw_writel(sleep_save_msc[0], MSC0);
        __raw_writel(sleep_save_msc[1], MSC1);
        __raw_writel(sleep_save_msc[2], MSC2);
-
-       return 0;
 }
 
-static struct sysdev_class cmx2xx_pm_sysclass = {
-       .name = "pm",
+static struct syscore_ops cmx2xx_pm_syscore_ops = {
        .resume = cmx2xx_resume,
        .suspend = cmx2xx_suspend,
 };
 
-static struct sys_device cmx2xx_pm_device = {
-       .cls = &cmx2xx_pm_sysclass,
-};
-
 static int __init cmx2xx_pm_init(void)
 {
-       int error;
-       error = sysdev_class_register(&cmx2xx_pm_sysclass);
-       if (error == 0)
-               error = sysdev_register(&cmx2xx_pm_device);
-       return error;
+       register_syscore_ops(&cmx2xx_pm_syscore_ops);
+
+       return 0;
 }
 #else
 static int __init cmx2xx_pm_init(void) { return 0; }
index 81c3c433e2d6c8dc35a99b006cad812baf1f53e7..d28e802e2448b9a4c210c778a0faea4f650182fd 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
index 44c1b77ece67a66773e4af8bbd570073bb59dffd..80538b8806ed73627fb83c523a46f2d88b7d5aee 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c/pxa-i2c.h>
-#include <linux/sysdev.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
index 6fc5d328ba7f80b2a40fb1926691fdcfced0d7f8..7545a48ed88bf5e66c28ca8c859dfedddda9e7a4 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
 #include <linux/ucb1400.h>
 
 #include <asm/mach/arch.h>
index a079d8baa45ac93f14d8ee3915f7626cc14529a8..e6c9344a95ae1cb9062fab82415f096f6d96b651 100644 (file)
@@ -61,10 +61,10 @@ extern unsigned pxa3xx_get_clk_frequency_khz(int);
 #define pxa3xx_get_clk_frequency_khz(x)                (0)
 #endif
 
-extern struct sysdev_class pxa_irq_sysclass;
-extern struct sysdev_class pxa_gpio_sysclass;
-extern struct sysdev_class pxa2xx_mfp_sysclass;
-extern struct sysdev_class pxa3xx_mfp_sysclass;
+extern struct syscore_ops pxa_irq_syscore_ops;
+extern struct syscore_ops pxa_gpio_syscore_ops;
+extern struct syscore_ops pxa2xx_mfp_syscore_ops;
+extern struct syscore_ops pxa3xx_mfp_syscore_ops;
 
 void __init pxa_set_ffuart_info(void *info);
 void __init pxa_set_btuart_info(void *info);
index 6de0ad0eea654f7c5ef4148005b69ead76871f7b..9cdcca59792455ede51f2046fcf66df898561779 100644 (file)
@@ -711,7 +711,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = {
 static struct regulator_init_data bq24022_init_data = {
        .constraints = {
                .max_uA         = 500000,
-               .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+               .valid_ops_mask = REGULATOR_CHANGE_CURRENT|REGULATOR_CHANGE_STATUS,
        },
        .num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
        .consumer_supplies      = bq24022_consumers,
index 6251e3f5c62c0399a8c019d71e576de1cab49974..32ed551bf9c5d363f8181a590e79157ed002f0c1 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 
@@ -183,7 +183,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
 static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32];
 static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
 
-static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa_irq_suspend(void)
 {
        int i;
 
@@ -202,7 +202,7 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int pxa_irq_resume(struct sys_device *dev)
+static void pxa_irq_resume(void)
 {
        int i;
 
@@ -218,22 +218,13 @@ static int pxa_irq_resume(struct sys_device *dev)
                        __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
 
        __raw_writel(1, IRQ_BASE + ICCR);
-       return 0;
 }
 #else
 #define pxa_irq_suspend                NULL
 #define pxa_irq_resume         NULL
 #endif
 
-struct sysdev_class pxa_irq_sysclass = {
-       .name           = "irq",
+struct syscore_ops pxa_irq_syscore_ops = {
        .suspend        = pxa_irq_suspend,
        .resume         = pxa_irq_resume,
 };
-
-static int __init pxa_irq_init(void)
-{
-       return sysdev_class_register(&pxa_irq_sysclass);
-}
-
-core_initcall(pxa_irq_init);
index f5de541725b1525024e6a469492934ce4e9c1be5..6cf8180bf5bdd2de3941009ccf1231fa9fa0d8ac 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -159,30 +159,22 @@ static void __init lpd270_init_irq(void)
 
 
 #ifdef CONFIG_PM
-static int lpd270_irq_resume(struct sys_device *dev)
+static void lpd270_irq_resume(void)
 {
        __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
-       return 0;
 }
 
-static struct sysdev_class lpd270_irq_sysclass = {
-       .name = "cpld_irq",
+static struct syscore_ops lpd270_irq_syscore_ops = {
        .resume = lpd270_irq_resume,
 };
 
-static struct sys_device lpd270_irq_device = {
-       .cls = &lpd270_irq_sysclass,
-};
-
 static int __init lpd270_irq_device_init(void)
 {
-       int ret = -ENODEV;
        if (machine_is_logicpd_pxa270()) {
-               ret = sysdev_class_register(&lpd270_irq_sysclass);
-               if (ret == 0)
-                       ret = sysdev_register(&lpd270_irq_device);
+               register_syscore_ops(&lpd270_irq_syscore_ops);
+               return 0;
        }
-       return ret;
+       return -ENODEV;
 }
 
 device_initcall(lpd270_irq_device_init);
index 3ede978c83d9573128ae409723d5387ed66de49b..e10ddb827147940b14d7793942c301e3fe9ea806 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/major.h>
 #include <linux/fb.h>
 #include <linux/interrupt.h>
@@ -176,31 +176,22 @@ static void __init lubbock_init_irq(void)
 
 #ifdef CONFIG_PM
 
-static int lubbock_irq_resume(struct sys_device *dev)
+static void lubbock_irq_resume(void)
 {
        LUB_IRQ_MASK_EN = lubbock_irq_enabled;
-       return 0;
 }
 
-static struct sysdev_class lubbock_irq_sysclass = {
-       .name = "cpld_irq",
+static struct syscore_ops lubbock_irq_syscore_ops = {
        .resume = lubbock_irq_resume,
 };
 
-static struct sys_device lubbock_irq_device = {
-       .cls = &lubbock_irq_sysclass,
-};
-
 static int __init lubbock_irq_device_init(void)
 {
-       int ret = -ENODEV;
-
        if (machine_is_lubbock()) {
-               ret = sysdev_class_register(&lubbock_irq_sysclass);
-               if (ret == 0)
-                       ret = sysdev_register(&lubbock_irq_device);
+               register_syscore_ops(&lubbock_irq_syscore_ops);
+               return 0;
        }
-       return ret;
+       return -ENODEV;
 }
 
 device_initcall(lubbock_irq_device_init);
index a72993dde2b301f301a9c4caab8d98dd2f3e1388..9984ef70bd794ff8e5a97ffff07ebc08eebb0988 100644 (file)
@@ -599,7 +599,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = {
 static struct regulator_init_data bq24022_init_data = {
        .constraints = {
                .max_uA         = 500000,
-               .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+               .valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS,
        },
        .num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
        .consumer_supplies      = bq24022_consumers,
index 95163baca29ec04dcf77d76e0b87b35ef67d5294..3479e2b3b51195ee51c40962604aecfc68a35a35 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -185,31 +185,21 @@ static void __init mainstone_init_irq(void)
 
 #ifdef CONFIG_PM
 
-static int mainstone_irq_resume(struct sys_device *dev)
+static void mainstone_irq_resume(void)
 {
        MST_INTMSKENA = mainstone_irq_enabled;
-       return 0;
 }
 
-static struct sysdev_class mainstone_irq_sysclass = {
-       .name = "cpld_irq",
+static struct syscore_ops mainstone_irq_syscore_ops = {
        .resume = mainstone_irq_resume,
 };
 
-static struct sys_device mainstone_irq_device = {
-       .cls = &mainstone_irq_sysclass,
-};
-
 static int __init mainstone_irq_device_init(void)
 {
-       int ret = -ENODEV;
+       if (machine_is_mainstone())
+               register_syscore_ops(&mainstone_irq_syscore_ops);
 
-       if (machine_is_mainstone()) {
-               ret = sysdev_class_register(&mainstone_irq_sysclass);
-               if (ret == 0)
-                       ret = sysdev_register(&mainstone_irq_device);
-       }
-       return ret;
+       return 0;
 }
 
 device_initcall(mainstone_irq_device_init);
index 1d1419b7345770aacdd28fce8b482055fdd28bf7..87ae3129f4f702353e7348442f9ae29df4379d47 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/gpio.h>
 #include <mach/pxa2xx-regs.h>
@@ -338,7 +338,7 @@ static unsigned long saved_gafr[2][4];
 static unsigned long saved_gpdr[4];
 static unsigned long saved_pgsr[4];
 
-static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+static int pxa2xx_mfp_suspend(void)
 {
        int i;
 
@@ -365,7 +365,7 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
        return 0;
 }
 
-static int pxa2xx_mfp_resume(struct sys_device *d)
+static void pxa2xx_mfp_resume(void)
 {
        int i;
 
@@ -376,15 +376,13 @@ static int pxa2xx_mfp_resume(struct sys_device *d)
                PGSR(i) = saved_pgsr[i];
        }
        PSSR = PSSR_RDH | PSSR_PH;
-       return 0;
 }
 #else
 #define pxa2xx_mfp_suspend     NULL
 #define pxa2xx_mfp_resume      NULL
 #endif
 
-struct sysdev_class pxa2xx_mfp_sysclass = {
-       .name           = "mfp",
+struct syscore_ops pxa2xx_mfp_syscore_ops = {
        .suspend        = pxa2xx_mfp_suspend,
        .resume         = pxa2xx_mfp_resume,
 };
@@ -409,6 +407,6 @@ static int __init pxa2xx_mfp_init(void)
        for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++)
                gpdr_lpm[i] = GPDR(i * 32);
 
-       return sysdev_class_register(&pxa2xx_mfp_sysclass);
+       return 0;
 }
 postcore_initcall(pxa2xx_mfp_init);
index 7a270eecd4808a64f60a7bc1dc97395a47c23b51..89863a01ecd7a438cff6692c8396a6327347851c 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
 #include <mach/mfp-pxa3xx.h>
  * a pull-down mode if they're an active low chip select, and we're
  * just entering standby.
  */
-static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+static int pxa3xx_mfp_suspend(void)
 {
        mfp_config_lpm();
        return 0;
 }
 
-static int pxa3xx_mfp_resume(struct sys_device *d)
+static void pxa3xx_mfp_resume(void)
 {
        mfp_config_run();
 
@@ -47,24 +47,13 @@ static int pxa3xx_mfp_resume(struct sys_device *d)
         * preserve them here in case they will be referenced later
         */
        ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
-       return 0;
 }
 #else
 #define pxa3xx_mfp_suspend     NULL
 #define pxa3xx_mfp_resume      NULL
 #endif
 
-struct sysdev_class pxa3xx_mfp_sysclass = {
-       .name           = "mfp",
+struct syscore_ops pxa3xx_mfp_syscore_ops = {
        .suspend        = pxa3xx_mfp_suspend,
-       .resume         = pxa3xx_mfp_resume,
+       .resume         = pxa3xx_mfp_resume,
 };
-
-static int __init mfp_init_devicefs(void)
-{
-       if (cpu_is_pxa3xx())
-               return sysdev_class_register(&pxa3xx_mfp_sysclass);
-
-       return 0;
-}
-postcore_initcall(mfp_init_devicefs);
index 23925db8ff74fe8dff4b3ea229bae7e178322676..e3470137c93473a3929d5fb53a7eebb0932b1090 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/gpio_keys.h>
@@ -488,7 +488,7 @@ static void install_bootstrap(void)
 }
 
 
-static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state)
+static int mioa701_sys_suspend(void)
 {
        int i = 0, is_bt_on;
        u32 *mem_resume_vector  = phys_to_virt(RESUME_VECTOR_ADDR);
@@ -514,7 +514,7 @@ static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state)
        return 0;
 }
 
-static int mioa701_sys_resume(struct sys_device *sysdev)
+static void mioa701_sys_resume(void)
 {
        int i = 0;
        u32 *mem_resume_vector  = phys_to_virt(RESUME_VECTOR_ADDR);
@@ -527,43 +527,18 @@ static int mioa701_sys_resume(struct sys_device *sysdev)
        *mem_resume_enabler = save_buffer[i++];
        *mem_resume_bt      = save_buffer[i++];
        *mem_resume_unknown = save_buffer[i++];
-
-       return 0;
 }
 
-static struct sysdev_class mioa701_sysclass = {
-       .name = "mioa701",
-};
-
-static struct sys_device sysdev_bootstrap = {
-       .cls            = &mioa701_sysclass,
-};
-
-static struct sysdev_driver driver_bootstrap = {
-       .suspend        = &mioa701_sys_suspend,
-       .resume         = &mioa701_sys_resume,
+static struct syscore_ops mioa701_syscore_ops = {
+       .suspend        = mioa701_sys_suspend,
+       .resume         = mioa701_sys_resume,
 };
 
 static int __init bootstrap_init(void)
 {
-       int rc;
        int save_size = mioa701_bootstrap_lg + (sizeof(u32) * 3);
 
-       rc = sysdev_class_register(&mioa701_sysclass);
-       if (rc) {
-               printk(KERN_ERR "Failed registering mioa701 sys class\n");
-               return -ENODEV;
-       }
-       rc = sysdev_register(&sysdev_bootstrap);
-       if (rc) {
-               printk(KERN_ERR "Failed registering mioa701 sys device\n");
-               return -ENODEV;
-       }
-       rc = sysdev_driver_register(&mioa701_sysclass, &driver_bootstrap);
-       if (rc) {
-               printk(KERN_ERR "Failed registering PMU sys driver\n");
-               return -ENODEV;
-       }
+       register_syscore_ops(&mioa701_syscore_ops);
 
        save_buffer = kmalloc(save_size, GFP_KERNEL);
        if (!save_buffer)
@@ -576,9 +551,7 @@ static int __init bootstrap_init(void)
 static void bootstrap_exit(void)
 {
        kfree(save_buffer);
-       sysdev_driver_unregister(&mioa701_sysclass, &driver_bootstrap);
-       sysdev_unregister(&sysdev_bootstrap);
-       sysdev_class_unregister(&mioa701_sysclass);
+       unregister_syscore_ops(&mioa701_syscore_ops);
 
        printk(KERN_CRIT "Unregistering mioa701 suspend will hang next"
               "resume !!!\n");
index a6f898cbfac91b30b0f82d95a4b9fe5dcb94ea43..4061ecddee70fa02524bede634c451ede4f2d702 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx.h>
 #include <linux/power_supply.h>
-#include <linux/sysdev.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
index 8aadad55fbe49babfca457c0bb11b5bd444527ab..20d1b18b1733ff5ab37b994264ba01b4bdcf9554 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/pwm_backlight.h>
 #include <linux/gpio.h>
 #include <linux/power_supply.h>
-#include <linux/sysdev.h>
 #include <linux/w1-gpio.h>
 
 #include <asm/mach-types.h>
index 3b8a4f37dbbe3e546f7ec0b3aa1d16c7e9caa0c5..65f24f0b77e85673d7908aec8683debc6110249e 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/gpio_keys.h>
@@ -233,9 +233,9 @@ static struct palmz72_resume_info palmz72_resume_info = {
 
 static unsigned long store_ptr;
 
-/* sys_device for Palm Zire 72 PM */
+/* syscore_ops for Palm Zire 72 PM */
 
-static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
+static int palmz72_pm_suspend(void)
 {
        /* setup the resume_info struct for the original bootloader */
        palmz72_resume_info.resume_addr = (u32) cpu_resume;
@@ -249,31 +249,23 @@ static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
        return 0;
 }
 
-static int palmz72_pm_resume(struct sys_device *dev)
+static void palmz72_pm_resume(void)
 {
        *PALMZ72_SAVE_DWORD = store_ptr;
-       return 0;
 }
 
-static struct sysdev_class palmz72_pm_sysclass = {
-       .name = "palmz72_pm",
+static struct syscore_ops palmz72_pm_syscore_ops = {
        .suspend = palmz72_pm_suspend,
        .resume = palmz72_pm_resume,
 };
 
-static struct sys_device palmz72_pm_device = {
-       .cls = &palmz72_pm_sysclass,
-};
-
 static int __init palmz72_pm_init(void)
 {
-       int ret = -ENODEV;
        if (machine_is_palmz72()) {
-               ret = sysdev_class_register(&palmz72_pm_sysclass);
-               if (ret == 0)
-                       ret = sysdev_register(&palmz72_pm_device);
+               register_syscore_ops(&palmz72_pm_syscore_ops);
+               return 0;
        }
-       return ret;
+       return -ENODEV;
 }
 
 device_initcall(palmz72_pm_init);
index a4af8c52d7ee297b49246be5246aa0e055e1c970..fed363cec9c635feb64cdaa70a79a375c92c1a0d 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
@@ -350,21 +350,9 @@ static struct platform_device *pxa25x_devices[] __initdata = {
        &pxa_device_asoc_platform,
 };
 
-static struct sys_device pxa25x_sysdev[] = {
-       {
-               .cls    = &pxa_irq_sysclass,
-       }, {
-               .cls    = &pxa2xx_mfp_sysclass,
-       }, {
-               .cls    = &pxa_gpio_sysclass,
-       }, {
-               .cls    = &pxa2xx_clock_sysclass,
-       }
-};
-
 static int __init pxa25x_init(void)
 {
-       int i, ret = 0;
+       int ret = 0;
 
        if (cpu_is_pxa25x()) {
 
@@ -377,11 +365,10 @@ static int __init pxa25x_init(void)
 
                pxa25x_init_pm();
 
-               for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) {
-                       ret = sysdev_register(&pxa25x_sysdev[i]);
-                       if (ret)
-                               pr_err("failed to register sysdev[%d]\n", i);
-               }
+               register_syscore_ops(&pxa_irq_syscore_ops);
+               register_syscore_ops(&pxa2xx_mfp_syscore_ops);
+               register_syscore_ops(&pxa_gpio_syscore_ops);
+               register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
                ret = platform_add_devices(pxa25x_devices,
                                           ARRAY_SIZE(pxa25x_devices));
index 909756eaf4b72a3b32a36f444517d1748604767a..2fecbec58d8821e720066b0e20583d18b69dc3f7 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/i2c/pxa-i2c.h>
@@ -428,21 +428,9 @@ static struct platform_device *devices[] __initdata = {
        &pxa27x_device_pwm1,
 };
 
-static struct sys_device pxa27x_sysdev[] = {
-       {
-               .cls    = &pxa_irq_sysclass,
-       }, {
-               .cls    = &pxa2xx_mfp_sysclass,
-       }, {
-               .cls    = &pxa_gpio_sysclass,
-       }, {
-               .cls    = &pxa2xx_clock_sysclass,
-       }
-};
-
 static int __init pxa27x_init(void)
 {
-       int i, ret = 0;
+       int ret = 0;
 
        if (cpu_is_pxa27x()) {
 
@@ -455,11 +443,10 @@ static int __init pxa27x_init(void)
 
                pxa27x_init_pm();
 
-               for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) {
-                       ret = sysdev_register(&pxa27x_sysdev[i]);
-                       if (ret)
-                               pr_err("failed to register sysdev[%d]\n", i);
-               }
+               register_syscore_ops(&pxa_irq_syscore_ops);
+               register_syscore_ops(&pxa2xx_mfp_syscore_ops);
+               register_syscore_ops(&pxa_gpio_syscore_ops);
+               register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
                ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        }
index 8dd107391157489a8ea651d7386cd37f1da61638..8521d7d6f1dab39402ef5c36ed3abece4cf17f89 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
@@ -427,21 +427,9 @@ static struct platform_device *devices[] __initdata = {
        &pxa27x_device_pwm1,
 };
 
-static struct sys_device pxa3xx_sysdev[] = {
-       {
-               .cls    = &pxa_irq_sysclass,
-       }, {
-               .cls    = &pxa3xx_mfp_sysclass,
-       }, {
-               .cls    = &pxa_gpio_sysclass,
-       }, {
-               .cls    = &pxa3xx_clock_sysclass,
-       }
-};
-
 static int __init pxa3xx_init(void)
 {
-       int i, ret = 0;
+       int ret = 0;
 
        if (cpu_is_pxa3xx()) {
 
@@ -462,11 +450,10 @@ static int __init pxa3xx_init(void)
 
                pxa3xx_init_pm();
 
-               for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) {
-                       ret = sysdev_register(&pxa3xx_sysdev[i]);
-                       if (ret)
-                               pr_err("failed to register sysdev[%d]\n", i);
-               }
+               register_syscore_ops(&pxa_irq_syscore_ops);
+               register_syscore_ops(&pxa3xx_mfp_syscore_ops);
+               register_syscore_ops(&pxa_gpio_syscore_ops);
+               register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
                ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        }
index 23b229bd06e9a39a66d788b6fb6bea3e5346d038..ecc82a330fad09a6747beca85c9007598ded30f5 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
 #include <mach/gpio.h>
@@ -260,16 +260,6 @@ static struct platform_device *devices[] __initdata = {
        &pxa27x_device_pwm1,
 };
 
-static struct sys_device pxa95x_sysdev[] = {
-       {
-               .cls    = &pxa_irq_sysclass,
-       }, {
-               .cls    = &pxa_gpio_sysclass,
-       }, {
-               .cls    = &pxa3xx_clock_sysclass,
-       }
-};
-
 static int __init pxa95x_init(void)
 {
        int ret = 0, i;
@@ -293,11 +283,9 @@ static int __init pxa95x_init(void)
                if ((ret = pxa_init_dma(IRQ_DMA, 32)))
                        return ret;
 
-               for (i = 0; i < ARRAY_SIZE(pxa95x_sysdev); i++) {
-                       ret = sysdev_register(&pxa95x_sysdev[i]);
-                       if (ret)
-                               pr_err("failed to register sysdev[%d]\n", i);
-               }
+               register_syscore_ops(&pxa_irq_syscore_ops);
+               register_syscore_ops(&pxa_gpio_syscore_ops);
+               register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
                ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        }
index cd1861351f75790258b8b9daee865ab628a0617f..d130f77b6d11c8dfd6317cf793dcdcabd1b354af 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
index 232b7316ec08aa1c1de7e913b01fdef069ad5b84..79923058d10f1352d8fd420180fc86ceca06957c 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
 #include <mach/smemc.h>
@@ -16,7 +16,7 @@ static unsigned long msc[2];
 static unsigned long sxcnfg, memclkcfg;
 static unsigned long csadrcfg[4];
 
-static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa3xx_smemc_suspend(void)
 {
        msc[0] = __raw_readl(MSC0);
        msc[1] = __raw_readl(MSC1);
@@ -30,7 +30,7 @@ static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int pxa3xx_smemc_resume(struct sys_device *dev)
+static void pxa3xx_smemc_resume(void)
 {
        __raw_writel(msc[0], MSC0);
        __raw_writel(msc[1], MSC1);
@@ -40,34 +40,19 @@ static int pxa3xx_smemc_resume(struct sys_device *dev)
        __raw_writel(csadrcfg[1], CSADRCFG1);
        __raw_writel(csadrcfg[2], CSADRCFG2);
        __raw_writel(csadrcfg[3], CSADRCFG3);
-
-       return 0;
 }
 
-static struct sysdev_class smemc_sysclass = {
-       .name           = "smemc",
+static struct syscore_ops smemc_syscore_ops = {
        .suspend        = pxa3xx_smemc_suspend,
        .resume         = pxa3xx_smemc_resume,
 };
 
-static struct sys_device smemc_sysdev = {
-       .id             = 0,
-       .cls            = &smemc_sysclass,
-};
-
 static int __init smemc_init(void)
 {
-       int ret = 0;
+       if (cpu_is_pxa3xx())
+               register_syscore_ops(&smemc_syscore_ops);
 
-       if (cpu_is_pxa3xx()) {
-               ret = sysdev_class_register(&smemc_sysclass);
-               if (ret)
-                       return ret;
-
-               ret = sysdev_register(&smemc_sysdev);
-       }
-
-       return ret;
+       return 0;
 }
 subsys_initcall(smemc_init);
 #endif
index b9cfbebdfe9ce62475fae95cf6301d307f7b312e..687417a936988014da451cfaf8676fad1e08aa55 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
index b523f119e0f0183ddff38bfb28ce4fb8a69f8b52..903218eab56db6031ecf54ea2b3244edb165eb6e 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
@@ -130,20 +131,19 @@ static u8 viper_hw_version(void)
        return v1;
 }
 
-/* CPU sysdev */
-static int viper_cpu_suspend(struct sys_device *sysdev, pm_message_t state)
+/* CPU system core operations. */
+static int viper_cpu_suspend(void)
 {
        viper_icr_set_bit(VIPER_ICR_R_DIS);
        return 0;
 }
 
-static int viper_cpu_resume(struct sys_device *sysdev)
+static void viper_cpu_resume(void)
 {
        viper_icr_clear_bit(VIPER_ICR_R_DIS);
-       return 0;
 }
 
-static struct sysdev_driver viper_cpu_sysdev_driver = {
+static struct syscore_ops viper_cpu_syscore_ops = {
        .suspend        = viper_cpu_suspend,
        .resume         = viper_cpu_resume,
 };
@@ -945,7 +945,7 @@ static void __init viper_init(void)
        viper_init_vcore_gpios();
        viper_init_cpufreq();
 
-       sysdev_driver_register(&cpu_sysdev_class, &viper_cpu_sysdev_driver);
+       register_syscore_ops(&viper_cpu_syscore_ops);
 
        if (version) {
                pr_info("viper: hardware v%di%d detected. "
index f71d377c864076470c8f41c45b9f9223d1d5813e..67bd41488bf81f05f0d853e708c243a747e8cd03 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
-#include <linux/sysdev.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
index 0c5d749d7b5f17f8ad7241506a90dc8dc2d63a89..9a732195aa1cbd1ebb515d63502628e33277a979 100644 (file)
@@ -4,5 +4,5 @@
  * operation to deadlock the system.
  */
 #define mb()           dsb()
-#define rmb()          dmb()
+#define rmb()          dsb()
 #define wmb()          mb()
index 5e2f35332056e26e9a5f682a1bfd6ed9be68616a..2854129f8cc70756da0fac97a7d47be5f3b53ff6 100644 (file)
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
 
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
-       return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
-       .add            = s3c2410_irq_add,
+struct syscore_ops s3c24xx_irq_syscore_ops = {
        .suspend        = s3c24xx_irq_suspend,
        .resume         = s3c24xx_irq_resume,
 };
-
-static int __init s3c2410_irq_init(void)
-{
-       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
-
-static struct sysdev_driver s3c2410a_irq_driver = {
-       .add            = s3c2410_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
-};
-
-static int __init s3c2410a_irq_init(void)
-{
-       return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_irq_driver);
-}
-
-arch_initcall(s3c2410a_irq_init);
index 2970ea9f7c2bfced373562f3d0c8e157a23f8bf3..1e2d536adda9c101acaedaa4f630d3cf3303bf87 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/dm9000.h>
@@ -214,17 +214,16 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
 /* NAND Flash on BAST board */
 
 #ifdef CONFIG_PM
-static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int bast_pm_suspend(void)
 {
        /* ensure that an nRESET is not generated on resume. */
        gpio_direction_output(S3C2410_GPA(21), 1);
        return 0;
 }
 
-static int bast_pm_resume(struct sys_device *sd)
+static void bast_pm_resume(void)
 {
        s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
-       return 0;
 }
 
 #else
@@ -232,16 +231,11 @@ static int bast_pm_resume(struct sys_device *sd)
 #define bast_pm_resume NULL
 #endif
 
-static struct sysdev_class bast_pm_sysclass = {
-       .name           = "mach-bast",
+static struct syscore_ops bast_pm_syscore_ops = {
        .suspend        = bast_pm_suspend,
        .resume         = bast_pm_resume,
 };
 
-static struct sys_device bast_pm_sysdev = {
-       .cls            = &bast_pm_sysclass,
-};
-
 static int smartmedia_map[] = { 0 };
 static int chip0_map[] = { 1 };
 static int chip1_map[] = { 2 };
@@ -642,8 +636,7 @@ static void __init bast_map_io(void)
 
 static void __init bast_init(void)
 {
-       sysdev_class_register(&bast_pm_sysclass);
-       sysdev_register(&bast_pm_sysdev);
+       register_syscore_ops(&bast_pm_syscore_ops);
 
        s3c_i2c0_set_platdata(&bast_i2c_info);
        s3c_nand_set_platdata(&bast_nand_info);
index 725636fc4dc3a892a9a89d72d03c8804eb9ba283..4728f9aa7df1911f251fca9a50087147b7dc2c2d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 
@@ -92,7 +93,7 @@ static void s3c2410_pm_prepare(void)
        }
 }
 
-static int s3c2410_pm_resume(struct sys_device *dev)
+static void s3c2410_pm_resume(void)
 {
        unsigned long tmp;
 
@@ -104,10 +105,12 @@ static int s3c2410_pm_resume(struct sys_device *dev)
 
        if ( machine_is_aml_m5900() )
                s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
-
-       return 0;
 }
 
+struct syscore_ops s3c2410_pm_syscore_ops = {
+       .resume         = s3c2410_pm_resume,
+};
+
 static int s3c2410_pm_add(struct sys_device *dev)
 {
        pm_cpu_prep = s3c2410_pm_prepare;
@@ -119,7 +122,6 @@ static int s3c2410_pm_add(struct sys_device *dev)
 #if defined(CONFIG_CPU_S3C2410)
 static struct sysdev_driver s3c2410_pm_driver = {
        .add            = s3c2410_pm_add,
-       .resume         = s3c2410_pm_resume,
 };
 
 /* register ourselves */
@@ -133,7 +135,6 @@ arch_initcall(s3c2410_pm_drvinit);
 
 static struct sysdev_driver s3c2410a_pm_driver = {
        .add            = s3c2410_pm_add,
-       .resume         = s3c2410_pm_resume,
 };
 
 static int __init s3c2410a_pm_drvinit(void)
@@ -147,7 +148,6 @@ arch_initcall(s3c2410a_pm_drvinit);
 #if defined(CONFIG_CPU_S3C2440)
 static struct sysdev_driver s3c2440_pm_driver = {
        .add            = s3c2410_pm_add,
-       .resume         = s3c2410_pm_resume,
 };
 
 static int __init s3c2440_pm_drvinit(void)
@@ -161,7 +161,6 @@ arch_initcall(s3c2440_pm_drvinit);
 #if defined(CONFIG_CPU_S3C2442)
 static struct sysdev_driver s3c2442_pm_driver = {
        .add            = s3c2410_pm_add,
-       .resume         = s3c2410_pm_resume,
 };
 
 static int __init s3c2442_pm_drvinit(void)
index adc90a3c5890574856fbdd3d5ccd3ab559f71a08..f1d3bd8f6f179dfc9c54ab41953cde1ba389ca2b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -40,6 +41,7 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 #include <plat/pll.h>
+#include <plat/pm.h>
 
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
@@ -168,6 +170,9 @@ int __init s3c2410_init(void)
 {
        printk("S3C2410: Initialising architecture\n");
 
+       register_syscore_ops(&s3c2410_pm_syscore_ops);
+       register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
        return sysdev_register(&s3c2410_sysdev);
 }
 
index f3355d2ec634f9aa9e544c48104e0b938c906543..1a1aa220972bead73ceebf8ba76b5acf321621af 100644 (file)
@@ -202,8 +202,6 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
 
 static struct sysdev_driver s3c2412_irq_driver = {
        .add            = s3c2412_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
 };
 
 static int s3c2412_irq_init(void)
index 923e01bdf0170c370c683f5f268d87067863da3f..85dcaeb9e62f737432e0f401feb4c5e673bdacad 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
@@ -486,7 +486,7 @@ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
 /* Jive power management device */
 
 #ifdef CONFIG_PM
-static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int jive_pm_suspend(void)
 {
        /* Write the magic value u-boot uses to check for resume into
         * the INFORM0 register, and ensure INFORM1 is set to the
@@ -498,10 +498,9 @@ static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
        return 0;
 }
 
-static int jive_pm_resume(struct sys_device *sd)
+static void jive_pm_resume(void)
 {
        __raw_writel(0x0, S3C2412_INFORM0);
-       return 0;
 }
 
 #else
@@ -509,16 +508,11 @@ static int jive_pm_resume(struct sys_device *sd)
 #define jive_pm_resume NULL
 #endif
 
-static struct sysdev_class jive_pm_sysclass = {
-       .name           = "jive-pm",
+static struct syscore_ops jive_pm_syscore_ops = {
        .suspend        = jive_pm_suspend,
        .resume         = jive_pm_resume,
 };
 
-static struct sys_device jive_pm_sysdev = {
-       .cls            = &jive_pm_sysclass,
-};
-
 static void __init jive_map_io(void)
 {
        s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
@@ -536,10 +530,9 @@ static void jive_power_off(void)
 
 static void __init jive_machine_init(void)
 {
-       /* register system devices for managing low level suspend */
+       /* register system core operations for managing low level suspend */
 
-       sysdev_class_register(&jive_pm_sysclass);
-       sysdev_register(&jive_pm_sysdev);
+       register_syscore_ops(&jive_pm_syscore_ops);
 
        /* write our sleep configurations for the IO. Pull down all unused
         * IO, ensure that we have turned off all peripherals we do not
index a7417c479ffeeb5f7a1b30bf4ea631ca61c2f18f..752b13a7b3dbf15f9348d874bf928bde5ddbd018 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -86,13 +87,24 @@ static struct sleep_save s3c2412_sleep[] = {
        SAVE_ITEM(S3C2413_GPJSLPCON),
 };
 
-static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
+static struct sysdev_driver s3c2412_pm_driver = {
+       .add            = s3c2412_pm_add,
+};
+
+static __init int s3c2412_pm_init(void)
+{
+       return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
+}
+
+arch_initcall(s3c2412_pm_init);
+
+static int s3c2412_pm_suspend(void)
 {
        s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
        return 0;
 }
 
-static int s3c2412_pm_resume(struct sys_device *dev)
+static void s3c2412_pm_resume(void)
 {
        unsigned long tmp;
 
@@ -102,18 +114,9 @@ static int s3c2412_pm_resume(struct sys_device *dev)
        __raw_writel(tmp, S3C2412_PWRCFG);
 
        s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-       return 0;
 }
 
-static struct sysdev_driver s3c2412_pm_driver = {
-       .add            = s3c2412_pm_add,
+struct syscore_ops s3c2412_pm_syscore_ops = {
        .suspend        = s3c2412_pm_suspend,
        .resume         = s3c2412_pm_resume,
 };
-
-static __init int s3c2412_pm_init(void)
-{
-       return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
-}
-
-arch_initcall(s3c2412_pm_init);
index 4c6df51ddf33fea00f57ef5b8e68741960a090af..ef0958d3e5c6e1b6dda7a9586099b1ebc3da739a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -244,5 +245,8 @@ int __init s3c2412_init(void)
 {
        printk("S3C2412: Initialising architecture\n");
 
+       register_syscore_ops(&s3c2412_pm_syscore_ops);
+       register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
        return sysdev_register(&s3c2412_sysdev);
 }
index 77b38f2381c1ac3fd1aa159646e0e93501ede996..28ad20d42445bcf6107507a58546e6b3eafb22eb 100644 (file)
@@ -236,8 +236,6 @@ static int __init s3c2416_irq_add(struct sys_device *sysdev)
 
 static struct sysdev_driver s3c2416_irq_driver = {
        .add            = s3c2416_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
 };
 
 static int __init s3c2416_irq_init(void)
index 4a04205b04d5f3c5a26ebe00a7c0397dd7aac07c..41db2b21e213368e823dbafb68c5672a31bc2a30 100644 (file)
@@ -11,6 +11,7 @@
 */
 
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
@@ -55,30 +56,26 @@ static int s3c2416_pm_add(struct sys_device *sysdev)
        return 0;
 }
 
-static int s3c2416_pm_suspend(struct sys_device *dev, pm_message_t state)
+static struct sysdev_driver s3c2416_pm_driver = {
+       .add            = s3c2416_pm_add,
+};
+
+static __init int s3c2416_pm_init(void)
 {
-       return 0;
+       return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver);
 }
 
-static int s3c2416_pm_resume(struct sys_device *dev)
+arch_initcall(s3c2416_pm_init);
+
+
+static void s3c2416_pm_resume(void)
 {
        /* unset the return-from-sleep amd inform flags */
        __raw_writel(0x0, S3C2443_PWRMODE);
        __raw_writel(0x0, S3C2412_INFORM0);
        __raw_writel(0x0, S3C2412_INFORM1);
-
-       return 0;
 }
 
-static struct sysdev_driver s3c2416_pm_driver = {
-       .add            = s3c2416_pm_add,
-       .suspend        = s3c2416_pm_suspend,
+struct syscore_ops s3c2416_pm_syscore_ops = {
        .resume         = s3c2416_pm_resume,
 };
-
-static __init int s3c2416_pm_init(void)
-{
-       return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver);
-}
-
-arch_initcall(s3c2416_pm_init);
index ba7fd87374348e0b61c9624cefa155dc8418eb43..494ce913dc9571752f81590784de2213bfc46bcb 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
@@ -54,6 +55,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/sdhci.h>
+#include <plat/pm.h>
 
 #include <plat/iic-core.h>
 #include <plat/fb-core.h>
@@ -95,6 +97,9 @@ int __init s3c2416_init(void)
 
        s3c_fb_setname("s3c2443-fb");
 
+       register_syscore_ops(&s3c2416_pm_syscore_ops);
+       register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
        return sysdev_register(&s3c2416_sysdev);
 }
 
index 0db2411ef4bba7e608a5670fe6268cba194648bd..716662008ce29a2d52edec2f9716c3bf4f282b3c 100644 (file)
@@ -409,6 +409,10 @@ struct platform_device s3c24xx_pwm_device = {
        .num_resources  = 0,
 };
 
+static struct platform_device gta02_dfbmcs320_device = {
+       .name = "dfbmcs320",
+};
+
 static struct i2c_board_info gta02_i2c_devs[] __initdata = {
        {
                I2C_BOARD_INFO("pcf50633", 0x73),
@@ -523,6 +527,7 @@ static struct platform_device *gta02_devices[] __initdata = {
        &s3c_device_iis,
        &samsung_asoc_dma,
        &s3c_device_i2c0,
+       &gta02_dfbmcs320_device,
        &gta02_buttons_device,
        &s3c_device_adc,
        &s3c_device_ts,
index 14dc67897757ea4d27dcde40fab8de7af74341a5..d88536393310af45a29acb0e753757f8e14615a3 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
 #include <linux/clk.h>
 #include <linux/i2c.h>
@@ -284,7 +284,7 @@ static struct platform_device osiris_pcmcia = {
 #ifdef CONFIG_PM
 static unsigned char pm_osiris_ctrl0;
 
-static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int osiris_pm_suspend(void)
 {
        unsigned int tmp;
 
@@ -304,7 +304,7 @@ static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
        return 0;
 }
 
-static int osiris_pm_resume(struct sys_device *sd)
+static void osiris_pm_resume(void)
 {
        if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
                __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
@@ -312,8 +312,6 @@ static int osiris_pm_resume(struct sys_device *sd)
        __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
 
        s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
-
-       return 0;
 }
 
 #else
@@ -321,16 +319,11 @@ static int osiris_pm_resume(struct sys_device *sd)
 #define osiris_pm_resume NULL
 #endif
 
-static struct sysdev_class osiris_pm_sysclass = {
-       .name           = "mach-osiris",
+static struct syscore_ops osiris_pm_syscore_ops = {
        .suspend        = osiris_pm_suspend,
        .resume         = osiris_pm_resume,
 };
 
-static struct sys_device osiris_pm_sysdev = {
-       .cls            = &osiris_pm_sysclass,
-};
-
 /* Link for DVS driver to TPS65011 */
 
 static void osiris_tps_release(struct device *dev)
@@ -439,8 +432,7 @@ static void __init osiris_map_io(void)
 
 static void __init osiris_init(void)
 {
-       sysdev_class_register(&osiris_pm_sysclass);
-       sysdev_register(&osiris_pm_sysdev);
+       register_syscore_ops(&osiris_pm_syscore_ops);
 
        s3c_i2c0_set_platdata(NULL);
        s3c_nand_set_platdata(&osiris_nand_info);
index f7663f731ea0728137700c3ada958800a54296db..ce99ff72838defb31fd4fa37f04a61f2660bbc73 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -33,6 +34,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/s3c244x.h>
+#include <plat/pm.h>
 
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
@@ -51,6 +53,12 @@ int __init s3c2440_init(void)
        s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
        s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
 
+       /* register suspend/resume handlers */
+
+       register_syscore_ops(&s3c2410_pm_syscore_ops);
+       register_syscore_ops(&s3c244x_pm_syscore_ops);
+       register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
        /* register our system device for everything else */
 
        return sysdev_register(&s3c2440_sysdev);
index ecf813546554739e4d329114a0896c6d49a37288..6224bad4d604161c96676171b1ae3ea019b2c675 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mutex.h>
@@ -45,6 +46,7 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/s3c244x.h>
+#include <plat/pm.h>
 
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
@@ -167,6 +169,10 @@ int __init s3c2442_init(void)
 {
        printk("S3C2442: Initialising architecture\n");
 
+       register_syscore_ops(&s3c2410_pm_syscore_ops);
+       register_syscore_ops(&s3c244x_pm_syscore_ops);
+       register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
        return sysdev_register(&s3c2442_sysdev);
 }
 
index de07c2feaa321995bced42ae009a32895396ae64..c63e8f26d90178a9eb05f8aa872dc490cf4a000e 100644 (file)
@@ -116,8 +116,6 @@ static int s3c244x_irq_add(struct sys_device *sysdev)
 
 static struct sysdev_driver s3c2440_irq_driver = {
        .add            = s3c244x_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
 };
 
 static int s3c2440_irq_init(void)
@@ -129,8 +127,6 @@ arch_initcall(s3c2440_irq_init);
 
 static struct sysdev_driver s3c2442_irq_driver = {
        .add            = s3c244x_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
 };
 
 
index 90c1707b9c9546d0709a61ea6f49ac4e56f884fb..7e8a23d2098a3614bb9e30fab0a96db910c5e6e6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
@@ -134,45 +135,14 @@ void __init s3c244x_init_clocks(int xtal)
        s3c2410_baseclk_add();
 }
 
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c244x_sleep[] = {
-       SAVE_ITEM(S3C2440_DSC0),
-       SAVE_ITEM(S3C2440_DSC1),
-       SAVE_ITEM(S3C2440_GPJDAT),
-       SAVE_ITEM(S3C2440_GPJCON),
-       SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
-{
-       s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-       return 0;
-}
-
-static int s3c244x_resume(struct sys_device *dev)
-{
-       s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-       return 0;
-}
-
-#else
-#define s3c244x_suspend NULL
-#define s3c244x_resume  NULL
-#endif
-
 /* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
 
 struct sysdev_class s3c2440_sysclass = {
        .name           = "s3c2440-core",
-       .suspend        = s3c244x_suspend,
-       .resume         = s3c244x_resume
 };
 
 struct sysdev_class s3c2442_sysclass = {
        .name           = "s3c2442-core",
-       .suspend        = s3c244x_suspend,
-       .resume         = s3c244x_resume
 };
 
 /* need to register class before we actually register the device, and
@@ -194,3 +164,33 @@ static int __init s3c2442_core_init(void)
 }
 
 core_initcall(s3c2442_core_init);
+
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c244x_sleep[] = {
+       SAVE_ITEM(S3C2440_DSC0),
+       SAVE_ITEM(S3C2440_DSC1),
+       SAVE_ITEM(S3C2440_GPJDAT),
+       SAVE_ITEM(S3C2440_GPJCON),
+       SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(void)
+{
+       s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+       return 0;
+}
+
+static void s3c244x_resume(void)
+{
+       s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+}
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+struct syscore_ops s3c244x_pm_syscore_ops = {
+       .suspend        = s3c244x_suspend,
+       .resume         = s3c244x_resume,
+};
index da1bec64b9dadfcc38faa1f734ec16b5b1ac5cd9..8bec61e242c7a73b287a3db9b03e5f1b499180ed 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/serial_core.h>
 #include <linux/irq.h>
@@ -54,7 +54,7 @@ static struct irq_grp_save {
 
 static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
 
-static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+static int s3c64xx_irq_pm_suspend(void)
 {
        struct irq_grp_save *grp = eint_grp_save;
        int i;
@@ -75,7 +75,7 @@ static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+static void s3c64xx_irq_pm_resume(void)
 {
        struct irq_grp_save *grp = eint_grp_save;
        int i;
@@ -94,18 +94,18 @@ static int s3c64xx_irq_pm_resume(struct sys_device *dev)
        }
 
        S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
-       return 0;
 }
 
-static struct sysdev_driver s3c64xx_irq_driver = {
+struct syscore_ops s3c64xx_irq_syscore_ops = {
        .suspend = s3c64xx_irq_pm_suspend,
        .resume  = s3c64xx_irq_pm_resume,
 };
 
-static int __init s3c64xx_irq_pm_init(void)
+static __init int s3c64xx_syscore_init(void)
 {
-       return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
-}
+       register_syscore_ops(&s3c64xx_irq_syscore_ops);
 
-arch_initcall(s3c64xx_irq_pm_init);
+       return 0;
+}
 
+core_initcall(s3c64xx_syscore_init);
index 549d7924fd4cc77621bccd668f857bcc0897f986..24febae3d4c0241bf89069898aec3a7a37bc6f12 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/suspend.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 
 #include <plat/cpu.h>
@@ -140,7 +141,17 @@ static int s5pv210_pm_add(struct sys_device *sysdev)
        return 0;
 }
 
-static int s5pv210_pm_resume(struct sys_device *dev)
+static struct sysdev_driver s5pv210_pm_driver = {
+       .add            = s5pv210_pm_add,
+};
+
+static __init int s5pv210_pm_drvinit(void)
+{
+       return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+}
+arch_initcall(s5pv210_pm_drvinit);
+
+static void s5pv210_pm_resume(void)
 {
        u32 tmp;
 
@@ -150,17 +161,15 @@ static int s5pv210_pm_resume(struct sys_device *dev)
        __raw_writel(tmp , S5P_OTHERS);
 
        s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
-
-       return 0;
 }
 
-static struct sysdev_driver s5pv210_pm_driver = {
-       .add            = s5pv210_pm_add,
+static struct syscore_ops s5pv210_pm_syscore_ops = {
        .resume         = s5pv210_pm_resume,
 };
 
-static __init int s5pv210_pm_drvinit(void)
+static __init int s5pv210_pm_syscore_init(void)
 {
-       return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+       register_syscore_ops(&s5pv210_pm_syscore_ops);
+       return 0;
 }
-arch_initcall(s5pv210_pm_drvinit);
+arch_initcall(s5pv210_pm_syscore_init);
index 423ddb3d65e9c8e0b50743414559852d4b9197b0..dfbf824a69fab02326dbc52a8c1ac2799dbacc71 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/ioport.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
 #include <asm/mach/irq.h>
@@ -234,7 +234,7 @@ static struct sa1100irq_state {
        unsigned int    iccr;
 } sa1100irq_state;
 
-static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state)
+static int sa1100irq_suspend(void)
 {
        struct sa1100irq_state *st = &sa1100irq_state;
 
@@ -264,7 +264,7 @@ static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int sa1100irq_resume(struct sys_device *dev)
+static void sa1100irq_resume(void)
 {
        struct sa1100irq_state *st = &sa1100irq_state;
 
@@ -277,24 +277,17 @@ static int sa1100irq_resume(struct sys_device *dev)
 
                ICMR = st->icmr;
        }
-       return 0;
 }
 
-static struct sysdev_class sa1100irq_sysclass = {
-       .name           = "sa11x0-irq",
+static struct syscore_ops sa1100irq_syscore_ops = {
        .suspend        = sa1100irq_suspend,
        .resume         = sa1100irq_resume,
 };
 
-static struct sys_device sa1100irq_device = {
-       .id             = 0,
-       .cls            = &sa1100irq_sysclass,
-};
-
 static int __init sa1100irq_init_devicefs(void)
 {
-       sysdev_class_register(&sa1100irq_sysclass);
-       return sysdev_register(&sa1100irq_device);
+       register_syscore_ops(&sa1100irq_syscore_ops);
+       return 0;
 }
 
 device_initcall(sa1100irq_init_devicefs);
index 94912d3944d3997d55bbb0b5d71d1be287c82ceb..2d1b67a59e4ae4318a888736680ef9dc31fcfdd6 100644 (file)
 #include <linux/clk.h>
 #include <linux/sh_clk.h>
 #include <linux/bitmap.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_PM_RUNTIME
-#define BIT_ONCE 0
-#define BIT_ACTIVE 1
-#define BIT_CLK_ENABLED 2
 
-struct pm_runtime_data {
-       unsigned long flags;
-       struct clk *clk;
-};
-
-static void __devres_release(struct device *dev, void *res)
-{
-       struct pm_runtime_data *prd = res;
-
-       dev_dbg(dev, "__devres_release()\n");
-
-       if (test_bit(BIT_CLK_ENABLED, &prd->flags))
-               clk_disable(prd->clk);
-
-       if (test_bit(BIT_ACTIVE, &prd->flags))
-               clk_put(prd->clk);
-}
-
-static struct pm_runtime_data *__to_prd(struct device *dev)
-{
-       return devres_find(dev, __devres_release, NULL, NULL);
-}
-
-static void platform_pm_runtime_init(struct device *dev,
-                                    struct pm_runtime_data *prd)
-{
-       if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) {
-               prd->clk = clk_get(dev, NULL);
-               if (!IS_ERR(prd->clk)) {
-                       set_bit(BIT_ACTIVE, &prd->flags);
-                       dev_info(dev, "clocks managed by runtime pm\n");
-               }
-       }
-}
-
-static void platform_pm_runtime_bug(struct device *dev,
-                                   struct pm_runtime_data *prd)
-{
-       if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags))
-               dev_err(dev, "runtime pm suspend before resume\n");
-}
-
-int platform_pm_runtime_suspend(struct device *dev)
-{
-       struct pm_runtime_data *prd = __to_prd(dev);
-
-       dev_dbg(dev, "platform_pm_runtime_suspend()\n");
-
-       platform_pm_runtime_bug(dev, prd);
-
-       if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
-               clk_disable(prd->clk);
-               clear_bit(BIT_CLK_ENABLED, &prd->flags);
-       }
-
-       return 0;
-}
-
-int platform_pm_runtime_resume(struct device *dev)
-{
-       struct pm_runtime_data *prd = __to_prd(dev);
-
-       dev_dbg(dev, "platform_pm_runtime_resume()\n");
-
-       platform_pm_runtime_init(dev, prd);
-
-       if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
-               clk_enable(prd->clk);
-               set_bit(BIT_CLK_ENABLED, &prd->flags);
-       }
-
-       return 0;
-}
-
-int platform_pm_runtime_idle(struct device *dev)
+static int default_platform_runtime_idle(struct device *dev)
 {
        /* suspend synchronously to disable clocks immediately */
        return pm_runtime_suspend(dev);
 }
 
-static int platform_bus_notify(struct notifier_block *nb,
-                              unsigned long action, void *data)
-{
-       struct device *dev = data;
-       struct pm_runtime_data *prd;
-
-       dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
-
-       if (action == BUS_NOTIFY_BIND_DRIVER) {
-               prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL);
-               if (prd)
-                       devres_add(dev, prd);
-               else
-                       dev_err(dev, "unable to alloc memory for runtime pm\n");
-       }
-
-       return 0;
-}
-
-#else /* CONFIG_PM_RUNTIME */
-
-static int platform_bus_notify(struct notifier_block *nb,
-                              unsigned long action, void *data)
-{
-       struct device *dev = data;
-       struct clk *clk;
+static struct dev_power_domain default_power_domain = {
+       .ops = {
+               .runtime_suspend = pm_runtime_clk_suspend,
+               .runtime_resume = pm_runtime_clk_resume,
+               .runtime_idle = default_platform_runtime_idle,
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
 
-       dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
+#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain)
 
-       switch (action) {
-       case BUS_NOTIFY_BIND_DRIVER:
-               clk = clk_get(dev, NULL);
-               if (!IS_ERR(clk)) {
-                       clk_enable(clk);
-                       clk_put(clk);
-                       dev_info(dev, "runtime pm disabled, clock forced on\n");
-               }
-               break;
-       case BUS_NOTIFY_UNBOUND_DRIVER:
-               clk = clk_get(dev, NULL);
-               if (!IS_ERR(clk)) {
-                       clk_disable(clk);
-                       clk_put(clk);
-                       dev_info(dev, "runtime pm disabled, clock forced off\n");
-               }
-               break;
-       }
+#else
 
-       return 0;
-}
+#define DEFAULT_PWR_DOMAIN_PTR NULL
 
 #endif /* CONFIG_PM_RUNTIME */
 
-static struct notifier_block platform_bus_notifier = {
-       .notifier_call = platform_bus_notify
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pwr_domain = DEFAULT_PWR_DOMAIN_PTR,
+       .con_ids = { NULL, },
 };
 
 static int __init sh_pm_runtime_init(void)
 {
-       bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
+       pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
        return 0;
 }
 core_initcall(sh_pm_runtime_init);
index cc115174899bdf4253471065134a90a658f3a5d6..425b42e91ef68a83e46e875c82a9ca8719aa492f 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/outercache.h>
 
-#define rmb()          dmb()
+#define rmb()          dsb()
 #define wmb()          do { dsb(); outer_sync(); } while (0)
 #define mb()           wmb()
 
index af913741e6ec760e775f3028c4304aa1d4b7609a..6e1907fa94f0405a788acd8896b9202a8a4c67c0 100644 (file)
@@ -178,16 +178,15 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
                .irq            = NOMADIK_GPIO_TO_IRQ(217),
                .platform_data  = &mop500_tc35892_data,
        },
-};
-
-/* I2C0 devices only available prior to HREFv60 */
-static struct i2c_board_info __initdata mop500_i2c0_old_devices[] = {
+       /* I2C0 devices only available prior to HREFv60 */
        {
                I2C_BOARD_INFO("tps61052", 0x33),
                .platform_data  = &mop500_tps61052_data,
        },
 };
 
+#define NUM_PRE_V60_I2C0_DEVICES 1
+
 static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
        {
                /* lp5521 LED driver, 1st device */
@@ -425,6 +424,8 @@ static void __init mop500_uart_init(void)
 
 static void __init mop500_init_machine(void)
 {
+       int i2c0_devs;
+
        /*
         * The HREFv60 board removed a GPIO expander and routed
         * all these GPIO pins to the internal GPIO controller
@@ -448,11 +449,11 @@ static void __init mop500_init_machine(void)
 
        platform_device_register(&ab8500_device);
 
-       i2c_register_board_info(0, mop500_i2c0_devices,
-                               ARRAY_SIZE(mop500_i2c0_devices));
-       if (!machine_is_hrefv60())
-               i2c_register_board_info(0, mop500_i2c0_old_devices,
-                                       ARRAY_SIZE(mop500_i2c0_old_devices));
+       i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+       if (machine_is_hrefv60())
+               i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+       i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
        i2c_register_board_info(2, mop500_i2c2_devices,
                                ARRAY_SIZE(mop500_i2c2_devices));
 }
index e5f6fc42834892e7622664b496d3aa0288eaa2ff..e591513bb53ecdfa06b9d8bf23d483bed7dbe733 100644 (file)
@@ -392,7 +392,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
         * Convert start_pfn/end_pfn to a struct page pointer.
         */
        start_pg = pfn_to_page(start_pfn - 1) + 1;
-       end_pg = pfn_to_page(end_pfn);
+       end_pg = pfn_to_page(end_pfn - 1) + 1;
 
        /*
         * Convert to physical addresses, and
@@ -426,6 +426,14 @@ static void __init free_unused_memmap(struct meminfo *mi)
 
                bank_start = bank_pfn_start(bank);
 
+#ifdef CONFIG_SPARSEMEM
+               /*
+                * Take care not to free memmap entries that don't exist
+                * due to SPARSEMEM sections which aren't present.
+                */
+               bank_start = min(bank_start,
+                                ALIGN(prev_bank_end, PAGES_PER_SECTION));
+#endif
                /*
                 * If we had a previous bank, and there is a space
                 * between the current bank and the previous, free it.
@@ -440,6 +448,12 @@ static void __init free_unused_memmap(struct meminfo *mi)
                 */
                prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
        }
+
+#ifdef CONFIG_SPARSEMEM
+       if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
+               free_memmap(prev_bank_end,
+                           ALIGN(prev_bank_end, PAGES_PER_SECTION));
+#endif
 }
 
 static void __init free_highpages(void)
index ce233bcbf5060c14bfe89c0093020a9c17005904..42af97664c9d844f156789f23a8c1fac7a643b68 100644 (file)
@@ -395,7 +395,7 @@ ENTRY(xscale_dma_a0_map_area)
        teq     r2, #DMA_TO_DEVICE
        beq     xscale_dma_clean_range
        b       xscale_dma_flush_range
-ENDPROC(xscsale_dma_a0_map_area)
+ENDPROC(xscale_dma_a0_map_area)
 
 /*
  *     dma_unmap_area(start, size, dir)
index 7a107246fd98849b6f8efe34316d977629f4bef8..6cd6d7f686f639623da2c10b0bcc6e9213d4b4a1 100644 (file)
@@ -295,6 +295,12 @@ static int mxc_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 }
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
 int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 {
        int i, j;
@@ -311,6 +317,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
                __raw_writel(~0, port[i].base + GPIO_ISR);
                for (j = port[i].virtual_irq_start;
                        j < port[i].virtual_irq_start + 32; j++) {
+                       irq_set_lockdep_class(j, &gpio_lock_class);
                        irq_set_chip_and_handler(j, &gpio_irq_chip,
                                                 handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
index 4ddce565b353745d32f31b0023ff1df1ad93f02d..8397a2dd19f2d6caad2adb5824ca13537c8d19fd 100644 (file)
@@ -124,6 +124,8 @@ imx_ssi_fiq_start:
 1:
                @ return from FIQ
                subs    pc, lr, #4
+
+               .align
 imx_ssi_fiq_base:
                .word 0x0
 imx_ssi_fiq_rx_buffer:
index d2adcdda23cf41c351fe418e31097fe2e4773df3..bd9e32187eab87b0a83ec4db27173e20ca3f78fe 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -1372,9 +1372,7 @@ static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
        .resume_noirq = omap_mpuio_resume_noirq,
 };
 
-/* use platform_driver for this, now that there's no longer any
- * point to sys_device (other than not disturbing old code).
- */
+/* use platform_driver for this. */
 static struct platform_driver omap_mpuio_driver = {
        .driver         = {
                .name   = "mpuio",
@@ -1745,7 +1743,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 }
 
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+static int omap_gpio_suspend(void)
 {
        int i;
 
@@ -1795,12 +1793,12 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
        return 0;
 }
 
-static int omap_gpio_resume(struct sys_device *dev)
+static void omap_gpio_resume(void)
 {
        int i;
 
        if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
-               return 0;
+               return;
 
        for (i = 0; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
@@ -1836,21 +1834,13 @@ static int omap_gpio_resume(struct sys_device *dev)
                __raw_writel(bank->saved_wakeup, wake_set);
                spin_unlock_irqrestore(&bank->lock, flags);
        }
-
-       return 0;
 }
 
-static struct sysdev_class omap_gpio_sysclass = {
-       .name           = "gpio",
+static struct syscore_ops omap_gpio_syscore_ops = {
        .suspend        = omap_gpio_suspend,
        .resume         = omap_gpio_resume,
 };
 
-static struct sys_device omap_gpio_device = {
-       .id             = 0,
-       .cls            = &omap_gpio_sysclass,
-};
-
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -2108,21 +2098,14 @@ postcore_initcall(omap_gpio_drv_reg);
 
 static int __init omap_gpio_sysinit(void)
 {
-       int ret = 0;
-
        mpuio_init();
 
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-       if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-               if (ret == 0) {
-                       ret = sysdev_class_register(&omap_gpio_sysclass);
-                       if (ret == 0)
-                               ret = sysdev_register(&omap_gpio_device);
-               }
-       }
+       if (cpu_is_omap16xx() || cpu_class_is_omap2())
+               register_syscore_ops(&omap_gpio_syscore_ops);
 #endif
 
-       return ret;
+       return 0;
 }
 
 arch_initcall(omap_gpio_sysinit);
index 8a51fd58f656e15f6f1fa7d51eb0501e18143149..34fc31ee9081ff8624d77dfb664ebe059d4c9343 100644 (file)
@@ -793,6 +793,8 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
        clk_enable(obj->clk);
        errs = iommu_report_fault(obj, &da);
        clk_disable(obj->clk);
+       if (errs == 0)
+               return IRQ_HANDLED;
 
        /* Fault callback or TLB/PTE Dynamic loading */
        if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
index 9bbda9acb73b1d098c073535c79f21a85da8cc11..a37b8eb65b76a6c2b13a019545852b3c9b48a7cc 100644 (file)
@@ -536,6 +536,28 @@ int omap_early_device_register(struct omap_device *od)
        return 0;
 }
 
+static int _od_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       return omap_device_idle(pdev);
+}
+
+static int _od_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       return omap_device_enable(pdev);
+}
+
+static struct dev_power_domain omap_device_power_domain = {
+       .ops = {
+               .runtime_suspend = _od_runtime_suspend,
+               .runtime_resume = _od_runtime_resume,
+               USE_PLATFORM_PM_SLEEP_OPS
+       }
+};
+
 /**
  * omap_device_register - register an omap_device with one omap_hwmod
  * @od: struct omap_device * to register
@@ -549,6 +571,7 @@ int omap_device_register(struct omap_device *od)
        pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
        od->pdev.dev.parent = &omap_device_parent;
+       od->pdev.dev.pwr_domain = &omap_device_power_domain;
        return platform_device_register(&od->pdev);
 }
 
index dce088f4567819f3d6574f5632d4b065ef3e54bf..48ebb9479b619708b37d385a75ce752d719d835f 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
 #include <mach/gpio.h>
@@ -295,7 +295,7 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
 }
 
 #ifdef CONFIG_PM
-static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa_gpio_suspend(void)
 {
        struct pxa_gpio_chip *c;
        int gpio;
@@ -312,7 +312,7 @@ static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int pxa_gpio_resume(struct sys_device *dev)
+static void pxa_gpio_resume(void)
 {
        struct pxa_gpio_chip *c;
        int gpio;
@@ -326,22 +326,13 @@ static int pxa_gpio_resume(struct sys_device *dev)
                __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
                __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
        }
-       return 0;
 }
 #else
 #define pxa_gpio_suspend       NULL
 #define pxa_gpio_resume                NULL
 #endif
 
-struct sysdev_class pxa_gpio_sysclass = {
-       .name           = "gpio",
+struct syscore_ops pxa_gpio_syscore_ops = {
        .suspend        = pxa_gpio_suspend,
        .resume         = pxa_gpio_resume,
 };
-
-static int __init pxa_gpio_init(void)
-{
-       return sysdev_class_register(&pxa_gpio_sysclass);
-}
-
-core_initcall(pxa_gpio_init);
index a9aa5ad3f4ebdc398340d946e5ecd16e37160a2b..be12eadcce20ecbfbfc3a8dac49b744560b986fb 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/sysdev.h>
 
 #include <plat/mfp.h>
 
index 27ea852e33700ac4894ed3cb50a8e5291687b5c4..c10d10c56e2e71a632877a9576efe62a1a8a717e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -1195,19 +1195,12 @@ int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *d
 
 EXPORT_SYMBOL(s3c2410_dma_getposition);
 
-static inline struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev)
-{
-       return container_of(dev, struct s3c2410_dma_chan, dev);
-}
-
-/* system device class */
+/* system core operations */
 
 #ifdef CONFIG_PM
 
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp)
 {
-       struct s3c2410_dma_chan *cp = to_dma_chan(dev);
-
        printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
 
        if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
@@ -1222,13 +1215,21 @@ static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
 
                s3c2410_dma_dostop(cp);
        }
+}
+
+static int s3c2410_dma_suspend(void)
+{
+       struct s3c2410_dma_chan *cp = s3c2410_chans;
+       int channel;
+
+       for (channel = 0; channel < dma_channels; cp++, channel++)
+               s3c2410_dma_suspend_chan(cp);
 
        return 0;
 }
 
-static int s3c2410_dma_resume(struct sys_device *dev)
+static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp)
 {
-       struct s3c2410_dma_chan *cp = to_dma_chan(dev);
        unsigned int no = cp->number | DMACH_LOW_LEVEL;
 
        /* restore channel's hardware configuration */
@@ -1249,13 +1250,21 @@ static int s3c2410_dma_resume(struct sys_device *dev)
        return 0;
 }
 
+static void s3c2410_dma_resume(void)
+{
+       struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1;
+       int channel;
+
+       for (channel = dma_channels - 1; channel >= 0; cp++, channel--)
+               s3c2410_dma_resume_chan(cp);
+}
+
 #else
 #define s3c2410_dma_suspend NULL
 #define s3c2410_dma_resume  NULL
 #endif /* CONFIG_PM */
 
-struct sysdev_class dma_sysclass = {
-       .name           = "s3c24xx-dma",
+struct syscore_ops dma_syscore_ops = {
        .suspend        = s3c2410_dma_suspend,
        .resume         = s3c2410_dma_resume,
 };
@@ -1269,39 +1278,14 @@ static void s3c2410_dma_cache_ctor(void *p)
 
 /* initialisation code */
 
-static int __init s3c24xx_dma_sysclass_init(void)
+static int __init s3c24xx_dma_syscore_init(void)
 {
-       int ret = sysdev_class_register(&dma_sysclass);
-
-       if (ret != 0)
-               printk(KERN_ERR "dma sysclass registration failed\n");
-
-       return ret;
-}
-
-core_initcall(s3c24xx_dma_sysclass_init);
-
-static int __init s3c24xx_dma_sysdev_register(void)
-{
-       struct s3c2410_dma_chan *cp = s3c2410_chans;
-       int channel, ret;
-
-       for (channel = 0; channel < dma_channels; cp++, channel++) {
-               cp->dev.cls = &dma_sysclass;
-               cp->dev.id  = channel;
-               ret = sysdev_register(&cp->dev);
-
-               if (ret) {
-                       printk(KERN_ERR "error registering dev for dma %d\n",
-                              channel);
-                       return ret;
-               }
-       }
+       register_syscore_ops(&dma_syscore_ops);
 
        return 0;
 }
 
-late_initcall(s3c24xx_dma_sysdev_register);
+late_initcall(s3c24xx_dma_syscore_init);
 
 int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
                            unsigned int stride)
index c3624d898630713d928f63b0dd30d54c11e9f42a..0efb2e2848c8aaae2986bc118da2d587cee7b852 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
 #include <linux/irq.h>
 
 #include <plat/cpu.h>
@@ -65,7 +64,7 @@ static unsigned long save_extint[3];
 static unsigned long save_eintflt[4];
 static unsigned long save_eintmask;
 
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+int s3c24xx_irq_suspend(void)
 {
        unsigned int i;
 
@@ -81,7 +80,7 @@ int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-int s3c24xx_irq_resume(struct sys_device *dev)
+void s3c24xx_irq_resume(void)
 {
        unsigned int i;
 
@@ -93,6 +92,4 @@ int s3c24xx_irq_resume(struct sys_device *dev)
 
        s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
        __raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-       return 0;
 }
index 5259ad458bc88fe15325ac4bd69915e3f326d18e..327acb3a44644e2c2b62de2aca37c3220b4a986b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
 
 #include <plat/cpu.h>
 #include <plat/irqs.h>
@@ -77,17 +76,15 @@ static struct sleep_save eint_save[] = {
        SAVE_ITEM(S5P_EINT_MASK(3)),
 };
 
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+int s3c24xx_irq_suspend(void)
 {
        s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
 
        return 0;
 }
 
-int s3c24xx_irq_resume(struct sys_device *dev)
+void s3c24xx_irq_resume(void)
 {
        s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
-
-       return 0;
 }
 
index cedfff51c82b11f59fac4f17c2a0aff0e49256dd..3aedac0034bac2bcaa849a44aab852b634cd1597 100644 (file)
@@ -68,6 +68,12 @@ extern void s3c24xx_init_uartdevs(char *name,
 struct sys_timer;
 extern struct sys_timer s3c24xx_timer;
 
+extern struct syscore_ops s3c2410_pm_syscore_ops;
+extern struct syscore_ops s3c2412_pm_syscore_ops;
+extern struct syscore_ops s3c2416_pm_syscore_ops;
+extern struct syscore_ops s3c244x_pm_syscore_ops;
+extern struct syscore_ops s3c64xx_irq_syscore_ops;
+
 /* system device classes */
 
 extern struct sysdev_class s3c2410_sysclass;
index 937cc2ace517572283e5b097d97b359c62e3fb60..7fb6f6be8c81e6e14b74a800b1a865f8e1225d7e 100644 (file)
@@ -103,14 +103,16 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
 
 #ifdef CONFIG_PM
 extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
+extern int s3c24xx_irq_suspend(void);
+extern void s3c24xx_irq_resume(void);
 #else
 #define s3c_irqext_wake NULL
 #define s3c24xx_irq_suspend NULL
 #define s3c24xx_irq_resume  NULL
 #endif
 
+extern struct syscore_ops s3c24xx_irq_syscore_ops;
+
 /* PM debug functions */
 
 #ifdef CONFIG_SAMSUNG_PM_DEBUG
index f74695075e641ec72562e1c8194a8220327e8bc8..f25e7ec8941696f3bd10b765d387b6ea7936d4c0 100644 (file)
@@ -398,9 +398,9 @@ static void vfp_enable(void *unused)
 }
 
 #ifdef CONFIG_PM
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
-static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
+static int vfp_pm_suspend(void)
 {
        struct thread_info *ti = current_thread_info();
        u32 fpexc = fmrx(FPEXC);
@@ -420,34 +420,25 @@ static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int vfp_pm_resume(struct sys_device *dev)
+static void vfp_pm_resume(void)
 {
        /* ensure we have access to the vfp */
        vfp_enable(NULL);
 
        /* and disable it to ensure the next usage restores the state */
        fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
-
-       return 0;
 }
 
-static struct sysdev_class vfp_pm_sysclass = {
-       .name           = "vfp",
+static struct syscore_ops vfp_pm_syscore_ops = {
        .suspend        = vfp_pm_suspend,
        .resume         = vfp_pm_resume,
 };
 
-static struct sys_device vfp_pm_sysdev = {
-       .cls    = &vfp_pm_sysclass,
-};
-
 static void vfp_pm_init(void)
 {
-       sysdev_class_register(&vfp_pm_sysclass);
-       sysdev_register(&vfp_pm_sysdev);
+       register_syscore_ops(&vfp_pm_syscore_ops);
 }
 
-
 #else
 static inline void vfp_pm_init(void) { }
 #endif /* CONFIG_PM */
index 21ce35f33aa5294af0a4ce8bb747be066913ba19..3e3646186c9ffa686aa01ff86821fe1cc7639ebe 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/io.h>
 
@@ -21,7 +21,6 @@
 struct intc {
        void __iomem            *regs;
        struct irq_chip         chip;
-       struct sys_device       sysdev;
 #ifdef CONFIG_PM
        unsigned long           suspend_ipr;
        unsigned long           saved_ipr[64];
@@ -146,9 +145,8 @@ void intc_set_suspend_handler(unsigned long offset)
        intc0.suspend_ipr = offset;
 }
 
-static int intc_suspend(struct sys_device *sdev, pm_message_t state)
+static int intc_suspend(void)
 {
-       struct intc *intc = container_of(sdev, struct intc, sysdev);
        int i;
 
        if (unlikely(!irqs_disabled())) {
@@ -156,28 +154,25 @@ static int intc_suspend(struct sys_device *sdev, pm_message_t state)
                return -EINVAL;
        }
 
-       if (unlikely(!intc->suspend_ipr)) {
+       if (unlikely(!intc0.suspend_ipr)) {
                pr_err("intc_suspend: suspend_ipr not initialized\n");
                return -EINVAL;
        }
 
        for (i = 0; i < 64; i++) {
-               intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i);
-               intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr);
+               intc0.saved_ipr[i] = intc_readl(&intc0, INTPR0 + 4 * i);
+               intc_writel(&intc0, INTPR0 + 4 * i, intc0.suspend_ipr);
        }
 
        return 0;
 }
 
-static int intc_resume(struct sys_device *sdev)
+static int intc_resume(void)
 {
-       struct intc *intc = container_of(sdev, struct intc, sysdev);
        int i;
 
-       WARN_ON(!irqs_disabled());
-
        for (i = 0; i < 64; i++)
-               intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]);
+               intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]);
 
        return 0;
 }
@@ -186,27 +181,18 @@ static int intc_resume(struct sys_device *sdev)
 #define intc_resume    NULL
 #endif
 
-static struct sysdev_class intc_class = {
-       .name           = "intc",
+static struct syscore_ops intc_syscore_ops = {
        .suspend        = intc_suspend,
        .resume         = intc_resume,
 };
 
-static int __init intc_init_sysdev(void)
+static int __init intc_init_syscore(void)
 {
-       int ret;
-
-       ret = sysdev_class_register(&intc_class);
-       if (ret)
-               return ret;
+       register_syscore_ops(&intc_syscore_ops);
 
-       intc0.sysdev.id = 0;
-       intc0.sysdev.cls = &intc_class;
-       ret = sysdev_register(&intc0.sysdev);
-
-       return ret;
+       return 0;
 }
-device_initcall(intc_init_sysdev);
+device_initcall(intc_init_syscore);
 
 unsigned long intc_get_pending(unsigned int group)
 {
index 0b5f72f17fd01293a1419531b3703db5b4303d9a..401eb1d8e3b43be33a2d6fb653d9e26fa754ae2c 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/bitops.h>
 #include <linux/hardirq.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/pm.h>
 #include <linux/nmi.h>
 #include <linux/smp.h>
@@ -196,43 +196,31 @@ void touch_nmi_watchdog(void)
 
 /* Suspend/resume support */
 #ifdef CONFIG_PM
-static int nmi_wdt_suspend(struct sys_device *dev, pm_message_t state)
+static int nmi_wdt_suspend(void)
 {
        nmi_wdt_stop();
        return 0;
 }
 
-static int nmi_wdt_resume(struct sys_device *dev)
+static void nmi_wdt_resume(void)
 {
        if (nmi_active)
                nmi_wdt_start();
-       return 0;
 }
 
-static struct sysdev_class nmi_sysclass = {
-       .name           = DRV_NAME,
+static struct syscore_ops nmi_syscore_ops = {
        .resume         = nmi_wdt_resume,
        .suspend        = nmi_wdt_suspend,
 };
 
-static struct sys_device device_nmi_wdt = {
-       .id     = 0,
-       .cls    = &nmi_sysclass,
-};
-
-static int __init init_nmi_wdt_sysfs(void)
+static int __init init_nmi_wdt_syscore(void)
 {
-       int error;
-
-       if (!nmi_active)
-               return 0;
+       if (nmi_active)
+               register_syscore_ops(&nmi_syscore_ops);
 
-       error = sysdev_class_register(&nmi_sysclass);
-       if (!error)
-               error = sysdev_register(&device_nmi_wdt);
-       return error;
+       return 0;
 }
-late_initcall(init_nmi_wdt_sysfs);
+late_initcall(init_nmi_wdt_syscore);
 
 #endif /* CONFIG_PM */
 
index cdb4beb6bc8fc9507bf0531317b8b834eca9d4c8..9e9b60d969dcc468b00dd2ec2fd9227f1377feea 100644 (file)
 #include <asm/gptimers.h>
 #include <asm/nmi.h>
 
-/* 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 */
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
 
@@ -63,7 +40,6 @@ static struct clocksource bfin_cs_cycles = {
        .rating         = 400,
        .read           = bfin_read_cycles,
        .mask           = CLOCKSOURCE_MASK(64),
-       .shift          = CYC2NS_SCALE_FACTOR,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -75,10 +51,7 @@ static inline unsigned long long bfin_cs_cycles_sched_clock(void)
 
 static int __init bfin_cs_cycles_init(void)
 {
-       bfin_cs_cycles.mult = \
-               clocksource_hz2mult(get_cclk(), bfin_cs_cycles.shift);
-
-       if (clocksource_register(&bfin_cs_cycles))
+       if (clocksource_register_hz(&bfin_cs_cycles, get_cclk()))
                panic("failed to register clocksource");
 
        return 0;
@@ -111,7 +84,6 @@ static struct clocksource bfin_cs_gptimer0 = {
        .rating         = 350,
        .read           = bfin_read_gptimer0,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = CYC2NS_SCALE_FACTOR,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -125,10 +97,7 @@ static int __init bfin_cs_gptimer0_init(void)
 {
        setup_gptimer0();
 
-       bfin_cs_gptimer0.mult = \
-               clocksource_hz2mult(get_sclk(), bfin_cs_gptimer0.shift);
-
-       if (clocksource_register(&bfin_cs_gptimer0))
+       if (clocksource_register_hz(&bfin_cs_gptimer0, get_sclk()))
                panic("failed to register clocksource");
 
        return 0;
index 382099fd55619be3a4f1d40c99cdf034143943a4..5e4112e518a992c2566c14b893f5d17f05481076 100644 (file)
@@ -19,9 +19,6 @@
 
 #define DRIVER_NAME "bfin dpmc"
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, DRIVER_NAME, msg)
-
 struct bfin_dpmc_platform_data *pdata;
 
 /**
index 8bce5ed031e448ed0a51d9e77c947864eed2e2bf..1fbd94c4445700d24ac882cd7515dac3c159db4f 100644 (file)
@@ -177,6 +177,9 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
        while (msg_queue->count) {
                msg = &msg_queue->ipi_message[msg_queue->head];
                switch (msg->type) {
+               case BFIN_IPI_RESCHEDULE:
+                       scheduler_ipi();
+                       break;
                case BFIN_IPI_CALL_FUNC:
                        spin_unlock_irqrestore(&msg_queue->lock, flags);
                        ipi_call_function(cpu, msg);
index 4c9e3e1ba5d12ccb08424e6ad04ccda7341f576c..66cc75657e2f3782e6431b249fdf6f9fe5dc30fb 100644 (file)
@@ -342,15 +342,18 @@ irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id)
 
        ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi);
 
+       if (ipi.vector & IPI_SCHEDULE) {
+               scheduler_ipi();
+       }
        if (ipi.vector & IPI_CALL) {
-                func(info);
+               func(info);
        }
        if (ipi.vector & IPI_FLUSH_TLB) {
-                    if (flush_mm == FLUSH_ALL)
-                        __flush_tlb_all();
-                    else if (flush_vma == FLUSH_ALL)
+               if (flush_mm == FLUSH_ALL)
+                       __flush_tlb_all();
+               else if (flush_vma == FLUSH_ALL)
                        __flush_tlb_mm(flush_mm);
-                    else
+               else
                        __flush_tlb_page(flush_vma, flush_addr);
        }
 
index 22f61526a8e1d7a5fd576eddc332e7e26c372380..f09b174244d5b5e2e31178f300504c3330f2c601 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
-
 MODULE_AUTHOR("Venkatesh Pallipadi");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
 MODULE_LICENSE("GPL");
@@ -47,12 +45,12 @@ processor_set_pstate (
 {
        s64 retval;
 
-       dprintk("processor_set_pstate\n");
+       pr_debug("processor_set_pstate\n");
 
        retval = ia64_pal_set_pstate((u64)value);
 
        if (retval) {
-               dprintk("Failed to set freq to 0x%x, with error 0x%lx\n",
+               pr_debug("Failed to set freq to 0x%x, with error 0x%lx\n",
                        value, retval);
                return -ENODEV;
        }
@@ -67,14 +65,14 @@ processor_get_pstate (
        u64     pstate_index = 0;
        s64     retval;
 
-       dprintk("processor_get_pstate\n");
+       pr_debug("processor_get_pstate\n");
 
        retval = ia64_pal_get_pstate(&pstate_index,
                                     PAL_GET_PSTATE_TYPE_INSTANT);
        *value = (u32) pstate_index;
 
        if (retval)
-               dprintk("Failed to get current freq with "
+               pr_debug("Failed to get current freq with "
                        "error 0x%lx, idx 0x%x\n", retval, *value);
 
        return (int)retval;
@@ -90,7 +88,7 @@ extract_clock (
 {
        unsigned long i;
 
-       dprintk("extract_clock\n");
+       pr_debug("extract_clock\n");
 
        for (i = 0; i < data->acpi_data.state_count; i++) {
                if (value == data->acpi_data.states[i].status)
@@ -110,7 +108,7 @@ processor_get_freq (
        cpumask_t               saved_mask;
        unsigned long           clock_freq;
 
-       dprintk("processor_get_freq\n");
+       pr_debug("processor_get_freq\n");
 
        saved_mask = current->cpus_allowed;
        set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -148,7 +146,7 @@ processor_set_freq (
        cpumask_t               saved_mask;
        int                     retval;
 
-       dprintk("processor_set_freq\n");
+       pr_debug("processor_set_freq\n");
 
        saved_mask = current->cpus_allowed;
        set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -159,16 +157,16 @@ processor_set_freq (
 
        if (state == data->acpi_data.state) {
                if (unlikely(data->resume)) {
-                       dprintk("Called after resume, resetting to P%d\n", state);
+                       pr_debug("Called after resume, resetting to P%d\n", state);
                        data->resume = 0;
                } else {
-                       dprintk("Already at target state (P%d)\n", state);
+                       pr_debug("Already at target state (P%d)\n", state);
                        retval = 0;
                        goto migrate_end;
                }
        }
 
-       dprintk("Transitioning from P%d to P%d\n",
+       pr_debug("Transitioning from P%d to P%d\n",
                data->acpi_data.state, state);
 
        /* cpufreq frequency struct */
@@ -186,7 +184,7 @@ processor_set_freq (
 
        value = (u32) data->acpi_data.states[state].control;
 
-       dprintk("Transitioning to state: 0x%08x\n", value);
+       pr_debug("Transitioning to state: 0x%08x\n", value);
 
        ret = processor_set_pstate(value);
        if (ret) {
@@ -219,7 +217,7 @@ acpi_cpufreq_get (
 {
        struct cpufreq_acpi_io *data = acpi_io_data[cpu];
 
-       dprintk("acpi_cpufreq_get\n");
+       pr_debug("acpi_cpufreq_get\n");
 
        return processor_get_freq(data, cpu);
 }
@@ -235,7 +233,7 @@ acpi_cpufreq_target (
        unsigned int next_state = 0;
        unsigned int result = 0;
 
-       dprintk("acpi_cpufreq_setpolicy\n");
+       pr_debug("acpi_cpufreq_setpolicy\n");
 
        result = cpufreq_frequency_table_target(policy,
                        data->freq_table, target_freq, relation, &next_state);
@@ -255,7 +253,7 @@ acpi_cpufreq_verify (
        unsigned int result = 0;
        struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
 
-       dprintk("acpi_cpufreq_verify\n");
+       pr_debug("acpi_cpufreq_verify\n");
 
        result = cpufreq_frequency_table_verify(policy,
                        data->freq_table);
@@ -273,7 +271,7 @@ acpi_cpufreq_cpu_init (
        struct cpufreq_acpi_io  *data;
        unsigned int            result = 0;
 
-       dprintk("acpi_cpufreq_cpu_init\n");
+       pr_debug("acpi_cpufreq_cpu_init\n");
 
        data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
        if (!data)
@@ -288,7 +286,7 @@ acpi_cpufreq_cpu_init (
 
        /* capability check */
        if (data->acpi_data.state_count <= 1) {
-               dprintk("No P-States\n");
+               pr_debug("No P-States\n");
                result = -ENODEV;
                goto err_unreg;
        }
@@ -297,7 +295,7 @@ acpi_cpufreq_cpu_init (
                                        ACPI_ADR_SPACE_FIXED_HARDWARE) ||
            (data->acpi_data.status_register.space_id !=
                                        ACPI_ADR_SPACE_FIXED_HARDWARE)) {
-               dprintk("Unsupported address space [%d, %d]\n",
+               pr_debug("Unsupported address space [%d, %d]\n",
                        (u32) (data->acpi_data.control_register.space_id),
                        (u32) (data->acpi_data.status_register.space_id));
                result = -ENODEV;
@@ -348,7 +346,7 @@ acpi_cpufreq_cpu_init (
               "activated.\n", cpu);
 
        for (i = 0; i < data->acpi_data.state_count; i++)
-               dprintk("     %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
+               pr_debug("     %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
                        (i == data->acpi_data.state?'*':' '), i,
                        (u32) data->acpi_data.states[i].core_frequency,
                        (u32) data->acpi_data.states[i].power,
@@ -383,7 +381,7 @@ acpi_cpufreq_cpu_exit (
 {
        struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
 
-       dprintk("acpi_cpufreq_cpu_exit\n");
+       pr_debug("acpi_cpufreq_cpu_exit\n");
 
        if (data) {
                cpufreq_frequency_table_put_attr(policy->cpu);
@@ -418,7 +416,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
 static int __init
 acpi_cpufreq_init (void)
 {
-       dprintk("acpi_cpufreq_init\n");
+       pr_debug("acpi_cpufreq_init\n");
 
        return cpufreq_register_driver(&acpi_cpufreq_driver);
 }
@@ -427,7 +425,7 @@ acpi_cpufreq_init (void)
 static void __exit
 acpi_cpufreq_exit (void)
 {
-       dprintk("acpi_cpufreq_exit\n");
+       pr_debug("acpi_cpufreq_exit\n");
 
        cpufreq_unregister_driver(&acpi_cpufreq_driver);
        return;
index 1b811c61bdc618107d05bf4bc10ebf0067b86df8..f64097b5118a852eafd045a0b3af635fee3ee6ca 100644 (file)
@@ -31,8 +31,6 @@ static struct clocksource clocksource_cyclone = {
         .rating         = 300,
         .read           = read_cyclone,
         .mask           = (1LL << 40) - 1,
-        .mult           = 0, /*to be calculated*/
-        .shift          = 16,
         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -118,9 +116,7 @@ int __init init_cyclone_clock(void)
        /* initialize last tick */
        cyclone_mc = cyclone_timer;
        clocksource_cyclone.fsys_mmio = cyclone_timer;
-       clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ,
-                                               clocksource_cyclone.shift);
-       clocksource_register(&clocksource_cyclone);
+       clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
 
        return 0;
 }
index 5b704740f1608b531b2fafa75ceba40b82b774f8..782c3a357f24f4d4417ce4a2499e63f1a09a0e3b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/irq.h>
 #include <linux/ratelimit.h>
 #include <linux/acpi.h>
+#include <linux/sched.h>
 
 #include <asm/delay.h>
 #include <asm/intrinsics.h>
@@ -496,6 +497,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
                        smp_local_flush_tlb();
                        kstat_incr_irqs_this_cpu(irq, desc);
                } else if (unlikely(IS_RESCHEDULE(vector))) {
+                       scheduler_ipi();
                        kstat_incr_irqs_this_cpu(irq, desc);
                } else {
                        ia64_setreg(_IA64_REG_CR_TPR, vector);
index 156ad803d5b7aedce2b059545cf1bde0cd44d32e..04440cc09b40cbd2a124b78474f6bba30a26d0b2 100644 (file)
@@ -73,8 +73,6 @@ static struct clocksource clocksource_itc = {
        .rating         = 350,
        .read           = itc_get_cycles,
        .mask           = CLOCKSOURCE_MASK(64),
-       .mult           = 0, /*to be calculated*/
-       .shift          = 16,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 #ifdef CONFIG_PARAVIRT
        .resume         = paravirt_clocksource_resume,
@@ -365,11 +363,8 @@ ia64_init_itm (void)
        ia64_cpu_local_tick();
 
        if (!itc_clocksource) {
-               /* Sort out mult/shift values: */
-               clocksource_itc.mult =
-                       clocksource_hz2mult(local_cpu_data->itc_freq,
-                                               clocksource_itc.shift);
-               clocksource_register(&clocksource_itc);
+               clocksource_register_hz(&clocksource_itc,
+                                               local_cpu_data->itc_freq);
                itc_clocksource = &clocksource_itc;
        }
 }
index 21d6f09e34477770904277d8e66e035b67d1947d..c34efda122e1fc34cb1be9c114a63d6482e47afa 100644 (file)
@@ -33,8 +33,6 @@ static struct clocksource clocksource_sn2 = {
         .rating         = 450,
         .read           = read_sn2,
         .mask           = (1LL << 55) - 1,
-        .mult           = 0,
-        .shift          = 10,
         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -57,9 +55,7 @@ ia64_sn_udelay (unsigned long usecs)
 void __init sn_timer_init(void)
 {
        clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR;
-       clocksource_sn2.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
-                                                       clocksource_sn2.shift);
-       clocksource_register(&clocksource_sn2);
+       clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second);
 
        ia64_udelay = &ia64_sn_udelay;
 }
index 108bb858acf2cee32801a99f137ea970bdb73487..b279e142c6334dfcecf74c9cef69e60576805a0c 100644 (file)
@@ -92,6 +92,8 @@ 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.
@@ -99,7 +101,13 @@ static int xen_slab_ready;
 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;
 }
 
@@ -110,7 +118,7 @@ static struct irqaction xen_ipi_irqaction = {
 };
 
 static struct irqaction xen_resched_irqaction = {
-       .handler =      xen_dummy_handler,
+       .handler =      xen_resched_handler,
        .flags =        IRQF_DISABLED,
        .name =         "resched"
 };
index 31cef20b2996fff82b836cd54b87c126ef42fa3a..fc10b39893d42ee0cd4ed8a3e1102a79d7d51273 100644 (file)
@@ -122,8 +122,6 @@ void smp_send_reschedule(int cpu_id)
  *
  * Description:  This routine executes on CPU which received
  *               'RESCHEDULE_IPI'.
- *               Rescheduling is processed at the exit of interrupt
- *               operation.
  *
  * Born on Date: 2002.02.05
  *
@@ -138,7 +136,7 @@ void smp_send_reschedule(int cpu_id)
  *==========================================================================*/
 void smp_reschedule_interrupt(void)
 {
-       /* nothing to do */
+       scheduler_ipi();
 }
 
 /*==========================================================================*
index b995513d527fd1323b2edbdd85f439a04bb0e4c1..95022b04b62d68411ee43bf9041ebaaf3ad48909 100644 (file)
 
 /* Hook for MIDI serial driver */
 void (*atari_MIDI_interrupt_hook) (void);
-/* Hook for mouse driver */
-void (*atari_mouse_interrupt_hook) (char *);
 /* Hook for keyboard inputdev  driver */
 void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
 /* Hook for mouse inputdev  driver */
 void (*atari_input_mouse_interrupt_hook) (char *);
-EXPORT_SYMBOL(atari_mouse_interrupt_hook);
 EXPORT_SYMBOL(atari_input_keyboard_interrupt_hook);
 EXPORT_SYMBOL(atari_input_mouse_interrupt_hook);
 
@@ -263,8 +260,8 @@ repeat:
                        kb_state.buf[kb_state.len++] = scancode;
                        if (kb_state.len == 3) {
                                kb_state.state = KEYBOARD;
-                               if (atari_mouse_interrupt_hook)
-                                       atari_mouse_interrupt_hook(kb_state.buf);
+                               if (atari_input_mouse_interrupt_hook)
+                                       atari_input_mouse_interrupt_hook(kb_state.buf);
                        }
                        break;
 
@@ -575,7 +572,7 @@ int atari_keyb_init(void)
        kb_state.len = 0;
 
        error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
-                           IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
+                           IRQ_TYPE_SLOW, "keyboard,mouse,MIDI",
                            atari_keyboard_interrupt);
        if (error)
                return error;
index 604329fafbb86d2bd4219a06b6c5a384bc0225e8..ddbf43ca8858012470d7f20665e89e85f5a045f3 100644 (file)
@@ -180,7 +180,7 @@ void __init stdma_init(void)
 {
        stdma_isr = NULL;
        if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
-                       "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
+                       "ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int))
                pr_err("Couldn't register ST-DMA interrupt\n");
 }
 
index 546e7da5804fe3710b3fc065f1daa618be7ec557..68f3622bf591934b380b74715ee964ca5b0ce06d 100644 (file)
@@ -34,8 +34,6 @@ void ikbd_joystick_disable(void);
 
 /* Hook for MIDI serial driver */
 extern void (*atari_MIDI_interrupt_hook) (void);
-/* Hook for mouse driver */
-extern void (*atari_mouse_interrupt_hook) (char *);
 /* Hook for keyboard inputdev  driver */
 extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
 /* Hook for mouse inputdev  driver */
index 9d69f6e6236544156af6af6f002ddc3122b49b92..e9020f88a748f4ae5905015eaa300e793a447732 100644 (file)
@@ -181,14 +181,15 @@ static inline int find_first_zero_bit(const unsigned long *vaddr,
 {
        const unsigned long *p = vaddr;
        int res = 32;
+       unsigned int words;
        unsigned long num;
 
        if (!size)
                return 0;
 
-       size = (size + 31) >> 5;
+       words = (size + 31) >> 5;
        while (!(num = ~*p++)) {
-               if (!--size)
+               if (!--words)
                        goto out;
        }
 
@@ -196,7 +197,8 @@ static inline int find_first_zero_bit(const unsigned long *vaddr,
                              : "=d" (res) : "d" (num & -num));
        res ^= 31;
 out:
-       return ((long)p - (long)vaddr - 4) * 8 + res;
+       res += ((long)p - (long)vaddr - 4) * 8;
+       return res < size ? res : size;
 }
 
 static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
@@ -215,27 +217,32 @@ static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
                /* Look for zero in first longword */
                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
                                      : "=d" (res) : "d" (num & -num));
-               if (res < 32)
-                       return offset + (res ^ 31);
+               if (res < 32) {
+                       offset += res ^ 31;
+                       return offset < size ? offset : size;
+               }
                offset += 32;
+
+               if (offset >= size)
+                       return size;
        }
        /* No zero yet, search remaining full bytes for a zero */
-       res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8);
-       return offset + res;
+       return offset + find_first_zero_bit(p, size - offset);
 }
 
 static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
 {
        const unsigned long *p = vaddr;
        int res = 32;
+       unsigned int words;
        unsigned long num;
 
        if (!size)
                return 0;
 
-       size = (size + 31) >> 5;
+       words = (size + 31) >> 5;
        while (!(num = *p++)) {
-               if (!--size)
+               if (!--words)
                        goto out;
        }
 
@@ -243,7 +250,8 @@ static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
                              : "=d" (res) : "d" (num & -num));
        res ^= 31;
 out:
-       return ((long)p - (long)vaddr - 4) * 8 + res;
+       res += ((long)p - (long)vaddr - 4) * 8;
+       return res < size ? res : size;
 }
 
 static inline int find_next_bit(const unsigned long *vaddr, int size,
@@ -262,13 +270,17 @@ static inline int find_next_bit(const unsigned long *vaddr, int size,
                /* Look for one in first longword */
                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
                                      : "=d" (res) : "d" (num & -num));
-               if (res < 32)
-                       return offset + (res ^ 31);
+               if (res < 32) {
+                       offset += res ^ 31;
+                       return offset < size ? offset : size;
+               }
                offset += 32;
+
+               if (offset >= size)
+                       return size;
        }
        /* No one yet, search remaining full bytes for a one */
-       res = find_first_bit(p, size - ((long)p - (long)vaddr) * 8);
-       return offset + res;
+       return offset + find_first_bit(p, size - offset);
 }
 
 /*
@@ -366,23 +378,25 @@ static inline int test_bit_le(int nr, const void *vaddr)
 static inline int find_first_zero_bit_le(const void *vaddr, unsigned size)
 {
        const unsigned long *p = vaddr, *addr = vaddr;
-       int res;
+       int res = 0;
+       unsigned int words;
 
        if (!size)
                return 0;
 
-       size = (size >> 5) + ((size & 31) > 0);
-       while (*p++ == ~0UL)
-       {
-               if (--size == 0)
-                       return (p - addr) << 5;
+       words = (size >> 5) + ((size & 31) > 0);
+       while (*p++ == ~0UL) {
+               if (--words == 0)
+                       goto out;
        }
 
        --p;
        for (res = 0; res < 32; res++)
                if (!test_bit_le(res, p))
                        break;
-       return (p - addr) * 32 + res;
+out:
+       res += (p - addr) * 32;
+       return res < size ? res : size;
 }
 
 static inline unsigned long find_next_zero_bit_le(const void *addr,
@@ -400,10 +414,15 @@ static inline unsigned long find_next_zero_bit_le(const void *addr,
                offset -= bit;
                /* Look for zero in first longword */
                for (res = bit; res < 32; res++)
-                       if (!test_bit_le(res, p))
-                               return offset + res;
+                       if (!test_bit_le(res, p)) {
+                               offset += res;
+                               return offset < size ? offset : size;
+                       }
                p++;
                offset += 32;
+
+               if (offset >= size)
+                       return size;
        }
        /* No zero yet, search remaining full bytes for a zero */
        return offset + find_first_zero_bit_le(p, size - offset);
@@ -412,22 +431,25 @@ static inline unsigned long find_next_zero_bit_le(const void *addr,
 static inline int find_first_bit_le(const void *vaddr, unsigned size)
 {
        const unsigned long *p = vaddr, *addr = vaddr;
-       int res;
+       int res = 0;
+       unsigned int words;
 
        if (!size)
                return 0;
 
-       size = (size >> 5) + ((size & 31) > 0);
+       words = (size >> 5) + ((size & 31) > 0);
        while (*p++ == 0UL) {
-               if (--size == 0)
-                       return (p - addr) << 5;
+               if (--words == 0)
+                       goto out;
        }
 
        --p;
        for (res = 0; res < 32; res++)
                if (test_bit_le(res, p))
                        break;
-       return (p - addr) * 32 + res;
+out:
+       res += (p - addr) * 32;
+       return res < size ? res : size;
 }
 
 static inline unsigned long find_next_bit_le(const void *addr,
@@ -445,10 +467,15 @@ static inline unsigned long find_next_bit_le(const void *addr,
                offset -= bit;
                /* Look for one in first longword */
                for (res = bit; res < 32; res++)
-                       if (test_bit_le(res, p))
-                               return offset + res;
+                       if (test_bit_le(res, p)) {
+                               offset += res;
+                               return offset < size ? offset : size;
+                       }
                p++;
                offset += 32;
+
+               if (offset >= size)
+                       return size;
        }
        /* No set bit yet, search remaining full bytes for a set bit */
        return offset + find_first_bit_le(p, size - offset);
index 29e17907d9f2c2af079df6e5b8e0b032de792562..f3b649de2a1bf812d78dc360c828360cd3591675 100644 (file)
@@ -22,7 +22,7 @@
 #define __NR_mknod              14
 #define __NR_chmod              15
 #define __NR_chown              16
-#define __NR_break              17
+/*#define __NR_break            17*/
 #define __NR_oldstat            18
 #define __NR_lseek              19
 #define __NR_getpid             20
 #define __NR_oldfstat           28
 #define __NR_pause              29
 #define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
+/*#define __NR_stty             31*/
+/*#define __NR_gtty             32*/
 #define __NR_access             33
 #define __NR_nice               34
-#define __NR_ftime              35
+/*#define __NR_ftime            35*/
 #define __NR_sync               36
 #define __NR_kill               37
 #define __NR_rename             38
@@ -49,7 +49,7 @@
 #define __NR_dup                41
 #define __NR_pipe               42
 #define __NR_times              43
-#define __NR_prof               44
+/*#define __NR_prof             44*/
 #define __NR_brk                45
 #define __NR_setgid             46
 #define __NR_getgid             47
 #define __NR_getegid            50
 #define __NR_acct               51
 #define __NR_umount2            52
-#define __NR_lock               53
+/*#define __NR_lock             53*/
 #define __NR_ioctl              54
 #define __NR_fcntl              55
-#define __NR_mpx                56
+/*#define __NR_mpx              56*/
 #define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_oldolduname        59
+/*#define __NR_ulimit           58*/
+/*#define __NR_oldolduname      59*/
 #define __NR_umask              60
 #define __NR_chroot             61
 #define __NR_ustat              62
 #define __NR_fchown             95
 #define __NR_getpriority        96
 #define __NR_setpriority        97
-#define __NR_profil             98
+/*#define __NR_profil           98*/
 #define __NR_statfs             99
 #define __NR_fstatfs           100
-#define __NR_ioperm            101
+/*#define __NR_ioperm          101*/
 #define __NR_socketcall                102
 #define __NR_syslog            103
 #define __NR_setitimer         104
 #define __NR_stat              106
 #define __NR_lstat             107
 #define __NR_fstat             108
-#define __NR_olduname          109
-#define __NR_iopl              /* 110 */ not supported
+/*#define __NR_olduname                109*/
+/*#define __NR_iopl            110*/ /* not supported */
 #define __NR_vhangup           111
-#define __NR_idle              /* 112 */ Obsolete
-#define __NR_vm86              /* 113 */ not supported
+/*#define __NR_idle            112*/ /* Obsolete */
+/*#define __NR_vm86            113*/ /* not supported */
 #define __NR_wait4             114
 #define __NR_swapoff           115
 #define __NR_sysinfo           116
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
-#define __NR_create_module     127
+/*#define __NR_create_module   127*/
 #define __NR_init_module       128
 #define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
+/*#define __NR_get_kernel_syms 130*/
 #define __NR_quotactl          131
 #define __NR_getpgid           132
 #define __NR_fchdir            133
 #define __NR_bdflush           134
 #define __NR_sysfs             135
 #define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
+/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
 #define __NR_setfsuid          138
 #define __NR_setfsgid          139
 #define __NR__llseek           140
 #define __NR_setresuid         164
 #define __NR_getresuid         165
 #define __NR_getpagesize       166
-#define __NR_query_module      167
+/*#define __NR_query_module    167*/
 #define __NR_poll              168
 #define __NR_nfsservctl                169
 #define __NR_setresgid         170
 #define __NR_capset            185
 #define __NR_sigaltstack       186
 #define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
+/*#define __NR_getpmsg         188*/   /* some people actually want streams */
+/*#define __NR_putpmsg         189*/   /* some people actually want streams */
 #define __NR_vfork             190
 #define __NR_ugetrlimit                191
 #define __NR_mmap2             192
 #define __NR_setfsuid32                215
 #define __NR_setfsgid32                216
 #define __NR_pivot_root                217
+/* 218*/
+/* 219*/
 #define __NR_getdents64                220
 #define __NR_gettid            221
 #define __NR_tkill             222
 #define __NR_mq_notify         275
 #define __NR_mq_getsetattr     276
 #define __NR_waitid            277
-#define __NR_vserver           278
+/*#define __NR_vserver         278*/
 #define __NR_add_key           279
 #define __NR_request_key       280
 #define __NR_keyctl            281
index 55d5d6b680a211376390499ee2aee7d2e5d41b61..aced678045799bbdc46de73ca5271821983801ad 100644 (file)
@@ -10,7 +10,7 @@ endif
 extra-y        += vmlinux.lds
 
 obj-y  := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
-          sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
+          sys_m68k.o time.o setup.o m68k_ksyms.o devres.o syscalltable.o
 
 devres-y = ../../../kernel/irq/devres.o
 
index 1359ee659574135d440deea4495728c1cbb872d2..bd0ec05263b2f3bc047c8008a5453e7cd98ceb31 100644 (file)
@@ -407,351 +407,3 @@ resume:
 
        rts
 
-.data
-ALIGN
-sys_call_table:
-       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
-       .long sys_exit
-       .long sys_fork
-       .long sys_read
-       .long sys_write
-       .long sys_open          /* 5 */
-       .long sys_close
-       .long sys_waitpid
-       .long sys_creat
-       .long sys_link
-       .long sys_unlink        /* 10 */
-       .long sys_execve
-       .long sys_chdir
-       .long sys_time
-       .long sys_mknod
-       .long sys_chmod         /* 15 */
-       .long sys_chown16
-       .long sys_ni_syscall                            /* old break syscall holder */
-       .long sys_stat
-       .long sys_lseek
-       .long sys_getpid        /* 20 */
-       .long sys_mount
-       .long sys_oldumount
-       .long sys_setuid16
-       .long sys_getuid16
-       .long sys_stime         /* 25 */
-       .long sys_ptrace
-       .long sys_alarm
-       .long sys_fstat
-       .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall                            /* old stty syscall holder */
-       .long sys_ni_syscall                            /* old gtty syscall holder */
-       .long sys_access
-       .long sys_nice
-       .long sys_ni_syscall    /* 35 */        /* old ftime syscall holder */
-       .long sys_sync
-       .long sys_kill
-       .long sys_rename
-       .long sys_mkdir
-       .long sys_rmdir         /* 40 */
-       .long sys_dup
-       .long sys_pipe
-       .long sys_times
-       .long sys_ni_syscall                            /* old prof syscall holder */
-       .long sys_brk           /* 45 */
-       .long sys_setgid16
-       .long sys_getgid16
-       .long sys_signal
-       .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
-       .long sys_acct
-       .long sys_umount                                /* recycled never used phys() */
-       .long sys_ni_syscall                            /* old lock syscall holder */
-       .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall                            /* old mpx syscall holder */
-       .long sys_setpgid
-       .long sys_ni_syscall                            /* old ulimit syscall holder */
-       .long sys_ni_syscall
-       .long sys_umask         /* 60 */
-       .long sys_chroot
-       .long sys_ustat
-       .long sys_dup2
-       .long sys_getppid
-       .long sys_getpgrp       /* 65 */
-       .long sys_setsid
-       .long sys_sigaction
-       .long sys_sgetmask
-       .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
-       .long sys_setregid16
-       .long sys_sigsuspend
-       .long sys_sigpending
-       .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
-       .long sys_old_getrlimit
-       .long sys_getrusage
-       .long sys_gettimeofday
-       .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
-       .long sys_setgroups16
-       .long sys_old_select
-       .long sys_symlink
-       .long sys_lstat
-       .long sys_readlink      /* 85 */
-       .long sys_uselib
-       .long sys_swapon
-       .long sys_reboot
-       .long sys_old_readdir
-       .long sys_old_mmap      /* 90 */
-       .long sys_munmap
-       .long sys_truncate
-       .long sys_ftruncate
-       .long sys_fchmod
-       .long sys_fchown16      /* 95 */
-       .long sys_getpriority
-       .long sys_setpriority
-       .long sys_ni_syscall                            /* old profil syscall holder */
-       .long sys_statfs
-       .long sys_fstatfs       /* 100 */
-       .long sys_ni_syscall                            /* ioperm for i386 */
-       .long sys_socketcall
-       .long sys_syslog
-       .long sys_setitimer
-       .long sys_getitimer     /* 105 */
-       .long sys_newstat
-       .long sys_newlstat
-       .long sys_newfstat
-       .long sys_ni_syscall
-       .long sys_ni_syscall    /* 110 */       /* iopl for i386 */
-       .long sys_vhangup
-       .long sys_ni_syscall                            /* obsolete idle() syscall */
-       .long sys_ni_syscall                            /* vm86old for i386 */
-       .long sys_wait4
-       .long sys_swapoff       /* 115 */
-       .long sys_sysinfo
-       .long sys_ipc
-       .long sys_fsync
-       .long sys_sigreturn
-       .long sys_clone         /* 120 */
-       .long sys_setdomainname
-       .long sys_newuname
-       .long sys_cacheflush                            /* modify_ldt for i386 */
-       .long sys_adjtimex
-       .long sys_mprotect      /* 125 */
-       .long sys_sigprocmask
-       .long sys_ni_syscall            /* old "create_module" */
-       .long sys_init_module
-       .long sys_delete_module
-       .long sys_ni_syscall    /* 130 - old "get_kernel_syms" */
-       .long sys_quotactl
-       .long sys_getpgid
-       .long sys_fchdir
-       .long sys_bdflush
-       .long sys_sysfs         /* 135 */
-       .long sys_personality
-       .long sys_ni_syscall                            /* for afs_syscall */
-       .long sys_setfsuid16
-       .long sys_setfsgid16
-       .long sys_llseek        /* 140 */
-       .long sys_getdents
-       .long sys_select
-       .long sys_flock
-       .long sys_msync
-       .long sys_readv         /* 145 */
-       .long sys_writev
-       .long sys_getsid
-       .long sys_fdatasync
-       .long sys_sysctl
-       .long sys_mlock         /* 150 */
-       .long sys_munlock
-       .long sys_mlockall
-       .long sys_munlockall
-       .long sys_sched_setparam
-       .long sys_sched_getparam        /* 155 */
-       .long sys_sched_setscheduler
-       .long sys_sched_getscheduler
-       .long sys_sched_yield
-       .long sys_sched_get_priority_max
-       .long sys_sched_get_priority_min  /* 160 */
-       .long sys_sched_rr_get_interval
-       .long sys_nanosleep
-       .long sys_mremap
-       .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long sys_getpagesize
-       .long sys_ni_syscall            /* old sys_query_module */
-       .long sys_poll
-       .long sys_nfsservctl
-       .long sys_setresgid16   /* 170 */
-       .long sys_getresgid16
-       .long sys_prctl
-       .long sys_rt_sigreturn
-       .long sys_rt_sigaction
-       .long sys_rt_sigprocmask        /* 175 */
-       .long sys_rt_sigpending
-       .long sys_rt_sigtimedwait
-       .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend
-       .long sys_pread64       /* 180 */
-       .long sys_pwrite64
-       .long sys_lchown16;
-       .long sys_getcwd
-       .long sys_capget
-       .long sys_capset        /* 185 */
-       .long sys_sigaltstack
-       .long sys_sendfile
-       .long sys_ni_syscall                            /* streams1 */
-       .long sys_ni_syscall                            /* streams2 */
-       .long sys_vfork         /* 190 */
-       .long sys_getrlimit
-       .long sys_mmap2
-       .long sys_truncate64
-       .long sys_ftruncate64
-       .long sys_stat64        /* 195 */
-       .long sys_lstat64
-       .long sys_fstat64
-       .long sys_chown
-       .long sys_getuid
-       .long sys_getgid        /* 200 */
-       .long sys_geteuid
-       .long sys_getegid
-       .long sys_setreuid
-       .long sys_setregid
-       .long sys_getgroups     /* 205 */
-       .long sys_setgroups
-       .long sys_fchown
-       .long sys_setresuid
-       .long sys_getresuid
-       .long sys_setresgid     /* 210 */
-       .long sys_getresgid
-       .long sys_lchown
-       .long sys_setuid
-       .long sys_setgid
-       .long sys_setfsuid      /* 215 */
-       .long sys_setfsgid
-       .long sys_pivot_root
-       .long sys_ni_syscall
-       .long sys_ni_syscall
-       .long sys_getdents64    /* 220 */
-       .long sys_gettid
-       .long sys_tkill
-       .long sys_setxattr
-       .long sys_lsetxattr
-       .long sys_fsetxattr     /* 225 */
-       .long sys_getxattr
-       .long sys_lgetxattr
-       .long sys_fgetxattr
-       .long sys_listxattr
-       .long sys_llistxattr    /* 230 */
-       .long sys_flistxattr
-       .long sys_removexattr
-       .long sys_lremovexattr
-       .long sys_fremovexattr
-       .long sys_futex         /* 235 */
-       .long sys_sendfile64
-       .long sys_mincore
-       .long sys_madvise
-       .long sys_fcntl64
-       .long sys_readahead     /* 240 */
-       .long sys_io_setup
-       .long sys_io_destroy
-       .long sys_io_getevents
-       .long sys_io_submit
-       .long sys_io_cancel     /* 245 */
-       .long sys_fadvise64
-       .long sys_exit_group
-       .long sys_lookup_dcookie
-       .long sys_epoll_create
-       .long sys_epoll_ctl     /* 250 */
-       .long sys_epoll_wait
-       .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime /* 255 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime /* 260 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
-       .long sys_statfs64
-       .long sys_fstatfs64
-       .long sys_tgkill        /* 265 */
-       .long sys_utimes
-       .long sys_fadvise64_64
-       .long sys_mbind
-       .long sys_get_mempolicy
-       .long sys_set_mempolicy /* 270 */
-       .long sys_mq_open
-       .long sys_mq_unlink
-       .long sys_mq_timedsend
-       .long sys_mq_timedreceive
-       .long sys_mq_notify     /* 275 */
-       .long sys_mq_getsetattr
-       .long sys_waitid
-       .long sys_ni_syscall    /* for sys_vserver */
-       .long sys_add_key
-       .long sys_request_key   /* 280 */
-       .long sys_keyctl
-       .long sys_ioprio_set
-       .long sys_ioprio_get
-       .long sys_inotify_init
-       .long sys_inotify_add_watch     /* 285 */
-       .long sys_inotify_rm_watch
-       .long sys_migrate_pages
-       .long sys_openat
-       .long sys_mkdirat
-       .long sys_mknodat               /* 290 */
-       .long sys_fchownat
-       .long sys_futimesat
-       .long sys_fstatat64
-       .long sys_unlinkat
-       .long sys_renameat              /* 295 */
-       .long sys_linkat
-       .long sys_symlinkat
-       .long sys_readlinkat
-       .long sys_fchmodat
-       .long sys_faccessat             /* 300 */
-       .long sys_ni_syscall            /* Reserved for pselect6 */
-       .long sys_ni_syscall            /* Reserved for ppoll */
-       .long sys_unshare
-       .long sys_set_robust_list
-       .long sys_get_robust_list       /* 305 */
-       .long sys_splice
-       .long sys_sync_file_range
-       .long sys_tee
-       .long sys_vmsplice
-       .long sys_move_pages            /* 310 */
-       .long sys_sched_setaffinity
-       .long sys_sched_getaffinity
-       .long sys_kexec_load
-       .long sys_getcpu
-       .long sys_epoll_pwait           /* 315 */
-       .long sys_utimensat
-       .long sys_signalfd
-       .long sys_timerfd_create
-       .long sys_eventfd
-       .long sys_fallocate             /* 320 */
-       .long sys_timerfd_settime
-       .long sys_timerfd_gettime
-       .long sys_signalfd4
-       .long sys_eventfd2
-       .long sys_epoll_create1         /* 325 */
-       .long sys_dup3
-       .long sys_pipe2
-       .long sys_inotify_init1
-       .long sys_preadv
-       .long sys_pwritev               /* 330 */
-       .long sys_rt_tgsigqueueinfo
-       .long sys_perf_event_open
-       .long sys_get_thread_area
-       .long sys_set_thread_area
-       .long sys_atomic_cmpxchg_32     /* 335 */
-       .long sys_atomic_barrier
-       .long sys_fanotify_init
-       .long sys_fanotify_mark
-       .long sys_prlimit64
-       .long sys_name_to_handle_at     /* 340 */
-       .long sys_open_by_handle_at
-       .long sys_clock_adjtime
-       .long sys_syncfs
-
index 9b8393d8adb89dae4ada43f66c6d63c8670589f6..5909e392cb1e7e46e0f791ecbbe39e39c1e2f470 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/m68knommu/kernel/syscalltable.S
- *
  *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
  *
  *  Based on older entry.S files, the following copyrights apply:
  *                      Kenneth Albanowski <kjahds@kjahds.com>,
  *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Linux/m68k support by Hamish Macdonald
  */
 
 #include <linux/sys.h>
 #include <linux/linkage.h>
-#include <asm/unistd.h>
 
-.text
+#ifndef CONFIG_MMU
+#define sys_mmap2              sys_mmap_pgoff
+#endif
+
+.section .rodata
 ALIGN
 ENTRY(sys_call_table)
-       .long sys_restart_syscall       /* 0  -  old "setup()" system call */
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
        .long sys_exit
        .long sys_fork
        .long sys_read
        .long sys_write
-       .long sys_open          /* 5 */
+       .long sys_open                  /* 5 */
        .long sys_close
        .long sys_waitpid
        .long sys_creat
        .long sys_link
-       .long sys_unlink        /* 10 */
+       .long sys_unlink                /* 10 */
        .long sys_execve
        .long sys_chdir
        .long sys_time
        .long sys_mknod
-       .long sys_chmod         /* 15 */
+       .long sys_chmod                 /* 15 */
        .long sys_chown16
-       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_ni_syscall            /* old break syscall holder */
        .long sys_stat
        .long sys_lseek
-       .long sys_getpid        /* 20 */
+       .long sys_getpid                /* 20 */
        .long sys_mount
        .long sys_oldumount
        .long sys_setuid16
        .long sys_getuid16
-       .long sys_stime         /* 25 */
+       .long sys_stime                 /* 25 */
        .long sys_ptrace
        .long sys_alarm
        .long sys_fstat
        .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall    /* old stty syscall holder */
-       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_utime                 /* 30 */
+       .long sys_ni_syscall            /* old stty syscall holder */
+       .long sys_ni_syscall            /* old gtty syscall holder */
        .long sys_access
        .long sys_nice
-       .long sys_ni_syscall    /* 35 */ /* old ftime syscall holder */
+       .long sys_ni_syscall            /* 35 - old ftime syscall holder */
        .long sys_sync
        .long sys_kill
        .long sys_rename
        .long sys_mkdir
-       .long sys_rmdir         /* 40 */
+       .long sys_rmdir                 /* 40 */
        .long sys_dup
        .long sys_pipe
        .long sys_times
-       .long sys_ni_syscall    /* old prof syscall holder */
-       .long sys_brk           /* 45 */
+       .long sys_ni_syscall            /* old prof syscall holder */
+       .long sys_brk                   /* 45 */
        .long sys_setgid16
        .long sys_getgid16
        .long sys_signal
        .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
+       .long sys_getegid16             /* 50 */
        .long sys_acct
-       .long sys_umount        /* recycled never used phys() */
-       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_umount                /* recycled never used phys() */
+       .long sys_ni_syscall            /* old lock syscall holder */
        .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_fcntl                 /* 55 */
+       .long sys_ni_syscall            /* old mpx syscall holder */
        .long sys_setpgid
-       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_ni_syscall            /* old ulimit syscall holder */
        .long sys_ni_syscall
-       .long sys_umask         /* 60 */
+       .long sys_umask                 /* 60 */
        .long sys_chroot
        .long sys_ustat
        .long sys_dup2
        .long sys_getppid
-       .long sys_getpgrp       /* 65 */
+       .long sys_getpgrp               /* 65 */
        .long sys_setsid
        .long sys_sigaction
        .long sys_sgetmask
        .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
+       .long sys_setreuid16            /* 70 */
        .long sys_setregid16
        .long sys_sigsuspend
        .long sys_sigpending
        .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
+       .long sys_setrlimit             /* 75 */
        .long sys_old_getrlimit
        .long sys_getrusage
        .long sys_gettimeofday
        .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
+       .long sys_getgroups16           /* 80 */
        .long sys_setgroups16
        .long sys_old_select
        .long sys_symlink
        .long sys_lstat
-       .long sys_readlink      /* 85 */
+       .long sys_readlink              /* 85 */
        .long sys_uselib
-       .long sys_ni_syscall    /* sys_swapon */
+       .long sys_swapon
        .long sys_reboot
        .long sys_old_readdir
-       .long sys_old_mmap      /* 90 */
+       .long sys_old_mmap              /* 90 */
        .long sys_munmap
        .long sys_truncate
        .long sys_ftruncate
        .long sys_fchmod
-       .long sys_fchown16      /* 95 */
+       .long sys_fchown16              /* 95 */
        .long sys_getpriority
        .long sys_setpriority
-       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_ni_syscall            /* old profil syscall holder */
        .long sys_statfs
-       .long sys_fstatfs       /* 100 */
-       .long sys_ni_syscall    /* ioperm for i386 */
+       .long sys_fstatfs               /* 100 */
+       .long sys_ni_syscall            /* ioperm for i386 */
        .long sys_socketcall
        .long sys_syslog
        .long sys_setitimer
-       .long sys_getitimer     /* 105 */
+       .long sys_getitimer             /* 105 */
        .long sys_newstat
        .long sys_newlstat
        .long sys_newfstat
        .long sys_ni_syscall
-       .long sys_ni_syscall    /* iopl for i386 */ /* 110 */
+       .long sys_ni_syscall            /* 110 - iopl for i386 */
        .long sys_vhangup
-       .long sys_ni_syscall    /* obsolete idle() syscall */
-       .long sys_ni_syscall    /* vm86old for i386 */
+       .long sys_ni_syscall            /* obsolete idle() syscall */
+       .long sys_ni_syscall            /* vm86old for i386 */
        .long sys_wait4
-       .long sys_ni_syscall    /* 115 */ /* sys_swapoff */
+       .long sys_swapoff               /* 115 */
        .long sys_sysinfo
        .long sys_ipc
        .long sys_fsync
        .long sys_sigreturn
-       .long sys_clone         /* 120 */
+       .long sys_clone                 /* 120 */
        .long sys_setdomainname
        .long sys_newuname
-       .long sys_cacheflush    /* modify_ldt for i386 */
+       .long sys_cacheflush            /* modify_ldt for i386 */
        .long sys_adjtimex
-       .long sys_ni_syscall    /* 125 */ /* sys_mprotect */
+       .long sys_mprotect              /* 125 */
        .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "creat_module" */
+       .long sys_ni_syscall            /* old "create_module" */
        .long sys_init_module
        .long sys_delete_module
-       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_ni_syscall            /* 130 - old "get_kernel_syms" */
        .long sys_quotactl
        .long sys_getpgid
        .long sys_fchdir
        .long sys_bdflush
-       .long sys_sysfs         /* 135 */
+       .long sys_sysfs                 /* 135 */
        .long sys_personality
-       .long sys_ni_syscall    /* for afs_syscall */
+       .long sys_ni_syscall            /* for afs_syscall */
        .long sys_setfsuid16
        .long sys_setfsgid16
-       .long sys_llseek        /* 140 */
+       .long sys_llseek                /* 140 */
        .long sys_getdents
        .long sys_select
        .long sys_flock
-       .long sys_ni_syscall    /* sys_msync */
-       .long sys_readv         /* 145 */
+       .long sys_msync
+       .long sys_readv                 /* 145 */
        .long sys_writev
        .long sys_getsid
        .long sys_fdatasync
        .long sys_sysctl
-       .long sys_ni_syscall    /* 150 */ /* sys_mlock */
-       .long sys_ni_syscall    /* sys_munlock */
-       .long sys_ni_syscall    /* sys_mlockall */
-       .long sys_ni_syscall    /* sys_munlockall */
+       .long sys_mlock                 /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
        .long sys_sched_setparam
-       .long sys_sched_getparam /* 155 */
+       .long sys_sched_getparam        /* 155 */
        .long sys_sched_setscheduler
        .long sys_sched_getscheduler
        .long sys_sched_yield
@@ -181,124 +184,124 @@ ENTRY(sys_call_table)
        .long sys_sched_get_priority_min  /* 160 */
        .long sys_sched_rr_get_interval
        .long sys_nanosleep
-       .long sys_ni_syscall    /* sys_mremap */
+       .long sys_mremap
        .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long sys_getpagesize   /* sys_getpagesize */
-       .long sys_ni_syscall    /* old "query_module" */
+       .long sys_getresuid16           /* 165 */
+       .long sys_getpagesize
+       .long sys_ni_syscall            /* old "query_module" */
        .long sys_poll
-       .long sys_ni_syscall    /* sys_nfsservctl */
-       .long sys_setresgid16   /* 170 */
+       .long sys_nfsservctl
+       .long sys_setresgid16           /* 170 */
        .long sys_getresgid16
        .long sys_prctl
        .long sys_rt_sigreturn
        .long sys_rt_sigaction
-       .long sys_rt_sigprocmask /* 175 */
+       .long sys_rt_sigprocmask        /* 175 */
        .long sys_rt_sigpending
        .long sys_rt_sigtimedwait
        .long sys_rt_sigqueueinfo
        .long sys_rt_sigsuspend
-       .long sys_pread64       /* 180 */
+       .long sys_pread64               /* 180 */
        .long sys_pwrite64
        .long sys_lchown16
        .long sys_getcwd
        .long sys_capget
-       .long sys_capset        /* 185 */
+       .long sys_capset                /* 185 */
        .long sys_sigaltstack
        .long sys_sendfile
-       .long sys_ni_syscall    /* streams1 */
-       .long sys_ni_syscall    /* streams2 */
-       .long sys_vfork         /* 190 */
+       .long sys_ni_syscall            /* streams1 */
+       .long sys_ni_syscall            /* streams2 */
+       .long sys_vfork                 /* 190 */
        .long sys_getrlimit
-       .long sys_mmap_pgoff
+       .long sys_mmap2
        .long sys_truncate64
        .long sys_ftruncate64
-       .long sys_stat64        /* 195 */
+       .long sys_stat64                /* 195 */
        .long sys_lstat64
        .long sys_fstat64
        .long sys_chown
        .long sys_getuid
-       .long sys_getgid        /* 200 */
+       .long sys_getgid                /* 200 */
        .long sys_geteuid
        .long sys_getegid
        .long sys_setreuid
        .long sys_setregid
-       .long sys_getgroups     /* 205 */
+       .long sys_getgroups             /* 205 */
        .long sys_setgroups
        .long sys_fchown
        .long sys_setresuid
        .long sys_getresuid
-       .long sys_setresgid     /* 210 */
+       .long sys_setresgid             /* 210 */
        .long sys_getresgid
        .long sys_lchown
        .long sys_setuid
        .long sys_setgid
-       .long sys_setfsuid      /* 215 */
+       .long sys_setfsuid              /* 215 */
        .long sys_setfsgid
        .long sys_pivot_root
        .long sys_ni_syscall
        .long sys_ni_syscall
-       .long sys_getdents64    /* 220 */
+       .long sys_getdents64            /* 220 */
        .long sys_gettid
        .long sys_tkill
        .long sys_setxattr
        .long sys_lsetxattr
-       .long sys_fsetxattr     /* 225 */
+       .long sys_fsetxattr             /* 225 */
        .long sys_getxattr
        .long sys_lgetxattr
        .long sys_fgetxattr
        .long sys_listxattr
-       .long sys_llistxattr    /* 230 */
+       .long sys_llistxattr            /* 230 */
        .long sys_flistxattr
        .long sys_removexattr
        .long sys_lremovexattr
        .long sys_fremovexattr
-       .long sys_futex         /* 235 */
+       .long sys_futex                 /* 235 */
        .long sys_sendfile64
-       .long sys_ni_syscall    /* sys_mincore */
-       .long sys_ni_syscall    /* sys_madvise */
+       .long sys_mincore
+       .long sys_madvise
        .long sys_fcntl64
-       .long sys_readahead     /* 240 */
+       .long sys_readahead             /* 240 */
        .long sys_io_setup
        .long sys_io_destroy
        .long sys_io_getevents
        .long sys_io_submit
-       .long sys_io_cancel     /* 245 */
+       .long sys_io_cancel             /* 245 */
        .long sys_fadvise64
        .long sys_exit_group
        .long sys_lookup_dcookie
        .long sys_epoll_create
-       .long sys_epoll_ctl     /* 250 */
+       .long sys_epoll_ctl             /* 250 */
        .long sys_epoll_wait
-       .long sys_ni_syscall    /* sys_remap_file_pages */
+       .long sys_remap_file_pages
        .long sys_set_tid_address
        .long sys_timer_create
-       .long sys_timer_settime /* 255 */
+       .long sys_timer_settime         /* 255 */
        .long sys_timer_gettime
        .long sys_timer_getoverrun
        .long sys_timer_delete
        .long sys_clock_settime
-       .long sys_clock_gettime /* 260 */
+       .long sys_clock_gettime         /* 260 */
        .long sys_clock_getres
        .long sys_clock_nanosleep
        .long sys_statfs64
        .long sys_fstatfs64
-       .long sys_tgkill        /* 265 */
+       .long sys_tgkill                /* 265 */
        .long sys_utimes
        .long sys_fadvise64_64
-       .long sys_mbind 
+       .long sys_mbind
        .long sys_get_mempolicy
-       .long sys_set_mempolicy /* 270 */
+       .long sys_set_mempolicy         /* 270 */
        .long sys_mq_open
        .long sys_mq_unlink
        .long sys_mq_timedsend
        .long sys_mq_timedreceive
-       .long sys_mq_notify     /* 275 */
+       .long sys_mq_notify             /* 275 */
        .long sys_mq_getsetattr
        .long sys_waitid
-       .long sys_ni_syscall    /* for sys_vserver */
+       .long sys_ni_syscall            /* for sys_vserver */
        .long sys_add_key
-       .long sys_request_key   /* 280 */
+       .long sys_request_key           /* 280 */
        .long sys_keyctl
        .long sys_ioprio_set
        .long sys_ioprio_get
@@ -319,8 +322,8 @@ ENTRY(sys_call_table)
        .long sys_readlinkat
        .long sys_fchmodat
        .long sys_faccessat             /* 300 */
-       .long sys_ni_syscall            /* Reserved for pselect6 */
-       .long sys_ni_syscall            /* Reserved for ppoll */
+       .long sys_pselect6
+       .long sys_ppoll
        .long sys_unshare
        .long sys_set_robust_list
        .long sys_get_robust_list       /* 305 */
@@ -363,7 +366,3 @@ ENTRY(sys_call_table)
        .long sys_clock_adjtime
        .long sys_syncfs
 
-       .rept NR_syscalls-(.-sys_call_table)/4
-               .long sys_ni_syscall
-       .endr
-
index 02b7a03e422681032b1a62ebf45183e1ed629b21..8b3db1c587fcad15de15d585d33d66534ca4b00a 100644 (file)
@@ -300,6 +300,8 @@ void __init paging_init(void)
                zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
                free_area_init_node(i, zones_size,
                                    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+               if (node_present_pages(i))
+                       node_set_state(i, N_NORMAL_MEMORY);
        }
 }
 
index d8a214f11ac29d2f8569d972f989a97e7a7b6fd3..e5550ce4e0eb783f5e6a4f29e7526c1cf3cbc6b0 100644 (file)
@@ -217,16 +217,12 @@ static struct clocksource clocksource_microblaze = {
        .rating         = 300,
        .read           = microblaze_read,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 8, /* I can shift it */
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init microblaze_clocksource_init(void)
 {
-       clocksource_microblaze.mult =
-                       clocksource_hz2mult(timer_clock_freq,
-                                               clocksource_microblaze.shift);
-       if (clocksource_register(&clocksource_microblaze))
+       if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq))
                panic("failed to register clocksource");
 
        /* stop timer1 */
index 7ff9b54920419b99cbae1f74bac4c62fc3d1b73c..aef6c917b45a4cde0de557566a2ba3b4345f445b 100644 (file)
@@ -11,6 +11,7 @@ platforms += dec
 platforms += emma
 platforms += jazz
 platforms += jz4740
+platforms += lantiq
 platforms += lasat
 platforms += loongson
 platforms += mipssim
index 8e256cc5dcd9a8e18e843cc671b1f47979f0d8e8..cef1a854487d1fff86c9154aabb86027e5eba2f5 100644 (file)
@@ -212,6 +212,24 @@ config MACH_JZ4740
        select HAVE_PWM
        select HAVE_CLK
 
+config LANTIQ
+       bool "Lantiq based platforms"
+       select DMA_NONCOHERENT
+       select IRQ_CPU
+       select CEVT_R4K
+       select CSRC_R4K
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_MULTITHREADING
+       select SYS_HAS_EARLY_PRINTK
+       select ARCH_REQUIRE_GPIOLIB
+       select SWAP_IO_SPACE
+       select BOOT_RAW
+       select HAVE_CLK
+       select MIPS_MACHINE
+
 config LASAT
        bool "LASAT Networks platforms"
        select CEVT_R4K
@@ -736,6 +754,33 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
                Hikari
          Say Y here for most Octeon reference boards.
 
+config NLM_XLR_BOARD
+       bool "Netlogic XLR/XLS based systems"
+       depends on EXPERIMENTAL
+       select BOOT_ELF32
+       select NLM_COMMON
+       select NLM_XLR
+       select SYS_HAS_CPU_XLR
+       select SYS_SUPPORTS_SMP
+       select HW_HAS_PCI
+       select SWAP_IO_SPACE
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select 64BIT_PHYS_ADDR
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select DMA_COHERENT
+       select NR_CPUS_DEFAULT_32
+       select CEVT_R4K
+       select CSRC_R4K
+       select IRQ_CPU
+       select ZONE_DMA if 64BIT
+       select SYNC_R4K
+       select SYS_HAS_EARLY_PRINTK
+       help
+         Support for systems based on Netlogic XLR and XLS processors.
+         Say Y here if you have a XLR or XLS based board.
+
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
@@ -743,6 +788,7 @@ source "arch/mips/ath79/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
+source "arch/mips/lantiq/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
 source "arch/mips/powertv/Kconfig"
@@ -752,6 +798,7 @@ source "arch/mips/txx9/Kconfig"
 source "arch/mips/vr41xx/Kconfig"
 source "arch/mips/cavium-octeon/Kconfig"
 source "arch/mips/loongson/Kconfig"
+source "arch/mips/netlogic/Kconfig"
 
 endmenu
 
@@ -997,9 +1044,6 @@ config IRQ_GT641XX
 config IRQ_GIC
        bool
 
-config IRQ_CPU_OCTEON
-       bool
-
 config MIPS_BOARDS_GEN
        bool
 
@@ -1359,8 +1403,6 @@ config CPU_SB1
 config CPU_CAVIUM_OCTEON
        bool "Cavium Octeon processor"
        depends on SYS_HAS_CPU_CAVIUM_OCTEON
-       select IRQ_CPU
-       select IRQ_CPU_OCTEON
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_SMP
@@ -1425,6 +1467,17 @@ config CPU_BMIPS5000
        help
          Broadcom BMIPS5000 processors.
 
+config CPU_XLR
+       bool "Netlogic XLR SoC"
+       depends on SYS_HAS_CPU_XLR
+       select CPU_SUPPORTS_32BIT_KERNEL
+       select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HIGHMEM
+       select WEAK_ORDERING
+       select WEAK_REORDERING_BEYOND_LLSC
+       select CPU_SUPPORTS_HUGEPAGES
+       help
+         Netlogic Microsystems XLR/XLS processors.
 endchoice
 
 if CPU_LOONGSON2F
@@ -1555,6 +1608,9 @@ config SYS_HAS_CPU_BMIPS4380
 config SYS_HAS_CPU_BMIPS5000
        bool
 
+config SYS_HAS_CPU_XLR
+       bool
+
 #
 # CPU may reorder R->R, R->W, W->R, W->W
 # Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC
@@ -2339,6 +2395,7 @@ config MMU
 
 config I8253
        bool
+       select CLKSRC_I8253
        select MIPS_EXTERNAL_TIMER
 
 config ZONE_DMA32
index 53e3514ba10e93c249d837f460fb86fbe3879f52..884819cd06077f8a9648adce10923bc8928fc596 100644 (file)
@@ -191,6 +191,18 @@ endif
 #
 include $(srctree)/arch/mips/Kbuild.platforms
 
+#
+# NETLOGIC SOC Common (common)
+#
+cflags-$(CONFIG_NLM_COMMON)            += -I$(srctree)/arch/mips/include/asm/mach-netlogic
+cflags-$(CONFIG_NLM_COMMON)            += -I$(srctree)/arch/mips/include/asm/netlogic
+
+#
+# NETLOGIC XLR/XLS SoC, Simulator and boards
+#
+core-$(CONFIG_NLM_XLR)                 += arch/mips/netlogic/xlr/
+load-$(CONFIG_NLM_XLR_BOARD)           += 0xffffffff84000000
+
 cflags-y                       += -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)          += arch/mips/pci/
 
index ca0506a8585a192834fc72f50fd5fceb3af6c1e6..3a5abb54d5052980c879e81d8ce983e576c2c9b1 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 
@@ -58,7 +58,8 @@ static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock);
 /* I couldn't find a macro that did this... */
 #define ALIGN_ADDR(x, a)       ((((u32)(x)) + (a-1)) & ~(a-1))
 
-static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
+static dbdma_global_t *dbdma_gptr =
+                       (dbdma_global_t *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
 static int dbdma_initialized;
 
 static dbdev_tab_t dbdev_tab[] = {
@@ -299,7 +300,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
        if (ctp != NULL) {
                memset(ctp, 0, sizeof(chan_tab_t));
                ctp->chan_index = chan = i;
-               dcp = DDMA_CHANNEL_BASE;
+               dcp = KSEG1ADDR(AU1550_DBDMA_PHYS_ADDR);
                dcp += (0x0100 * chan);
                ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
                cp = (au1x_dma_chan_t *)dcp;
@@ -958,105 +959,75 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
 }
 
 
-struct alchemy_dbdma_sysdev {
-       struct sys_device sysdev;
-       u32 pm_regs[NUM_DBDMA_CHANS + 1][6];
-};
+static unsigned long alchemy_dbdma_pm_data[NUM_DBDMA_CHANS + 1][6];
 
-static int alchemy_dbdma_suspend(struct sys_device *dev,
-                                pm_message_t state)
+static int alchemy_dbdma_suspend(void)
 {
-       struct alchemy_dbdma_sysdev *sdev =
-               container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
        int i;
-       u32 addr;
+       void __iomem *addr;
 
-       addr = DDMA_GLOBAL_BASE;
-       sdev->pm_regs[0][0] = au_readl(addr + 0x00);
-       sdev->pm_regs[0][1] = au_readl(addr + 0x04);
-       sdev->pm_regs[0][2] = au_readl(addr + 0x08);
-       sdev->pm_regs[0][3] = au_readl(addr + 0x0c);
+       addr = (void __iomem *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
+       alchemy_dbdma_pm_data[0][0] = __raw_readl(addr + 0x00);
+       alchemy_dbdma_pm_data[0][1] = __raw_readl(addr + 0x04);
+       alchemy_dbdma_pm_data[0][2] = __raw_readl(addr + 0x08);
+       alchemy_dbdma_pm_data[0][3] = __raw_readl(addr + 0x0c);
 
        /* save channel configurations */
-       for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
-               sdev->pm_regs[i][0] = au_readl(addr + 0x00);
-               sdev->pm_regs[i][1] = au_readl(addr + 0x04);
-               sdev->pm_regs[i][2] = au_readl(addr + 0x08);
-               sdev->pm_regs[i][3] = au_readl(addr + 0x0c);
-               sdev->pm_regs[i][4] = au_readl(addr + 0x10);
-               sdev->pm_regs[i][5] = au_readl(addr + 0x14);
+       addr = (void __iomem *)KSEG1ADDR(AU1550_DBDMA_PHYS_ADDR);
+       for (i = 1; i <= NUM_DBDMA_CHANS; i++) {
+               alchemy_dbdma_pm_data[i][0] = __raw_readl(addr + 0x00);
+               alchemy_dbdma_pm_data[i][1] = __raw_readl(addr + 0x04);
+               alchemy_dbdma_pm_data[i][2] = __raw_readl(addr + 0x08);
+               alchemy_dbdma_pm_data[i][3] = __raw_readl(addr + 0x0c);
+               alchemy_dbdma_pm_data[i][4] = __raw_readl(addr + 0x10);
+               alchemy_dbdma_pm_data[i][5] = __raw_readl(addr + 0x14);
 
                /* halt channel */
-               au_writel(sdev->pm_regs[i][0] & ~1, addr + 0x00);
-               au_sync();
-               while (!(au_readl(addr + 0x14) & 1))
-                       au_sync();
+               __raw_writel(alchemy_dbdma_pm_data[i][0] & ~1, addr + 0x00);
+               wmb();
+               while (!(__raw_readl(addr + 0x14) & 1))
+                       wmb();
 
                addr += 0x100;  /* next channel base */
        }
        /* disable channel interrupts */
-       au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
-       au_sync();
+       addr = (void __iomem *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
+       __raw_writel(0, addr + 0x0c);
+       wmb();
 
        return 0;
 }
 
-static int alchemy_dbdma_resume(struct sys_device *dev)
+static void alchemy_dbdma_resume(void)
 {
-       struct alchemy_dbdma_sysdev *sdev =
-               container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
        int i;
-       u32 addr;
+       void __iomem *addr;
 
-       addr = DDMA_GLOBAL_BASE;
-       au_writel(sdev->pm_regs[0][0], addr + 0x00);
-       au_writel(sdev->pm_regs[0][1], addr + 0x04);
-       au_writel(sdev->pm_regs[0][2], addr + 0x08);
-       au_writel(sdev->pm_regs[0][3], addr + 0x0c);
+       addr = (void __iomem *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
+       __raw_writel(alchemy_dbdma_pm_data[0][0], addr + 0x00);
+       __raw_writel(alchemy_dbdma_pm_data[0][1], addr + 0x04);
+       __raw_writel(alchemy_dbdma_pm_data[0][2], addr + 0x08);
+       __raw_writel(alchemy_dbdma_pm_data[0][3], addr + 0x0c);
 
        /* restore channel configurations */
-       for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
-               au_writel(sdev->pm_regs[i][0], addr + 0x00);
-               au_writel(sdev->pm_regs[i][1], addr + 0x04);
-               au_writel(sdev->pm_regs[i][2], addr + 0x08);
-               au_writel(sdev->pm_regs[i][3], addr + 0x0c);
-               au_writel(sdev->pm_regs[i][4], addr + 0x10);
-               au_writel(sdev->pm_regs[i][5], addr + 0x14);
-               au_sync();
+       addr = (void __iomem *)KSEG1ADDR(AU1550_DBDMA_PHYS_ADDR);
+       for (i = 1; i <= NUM_DBDMA_CHANS; i++) {
+               __raw_writel(alchemy_dbdma_pm_data[i][0], addr + 0x00);
+               __raw_writel(alchemy_dbdma_pm_data[i][1], addr + 0x04);
+               __raw_writel(alchemy_dbdma_pm_data[i][2], addr + 0x08);
+               __raw_writel(alchemy_dbdma_pm_data[i][3], addr + 0x0c);
+               __raw_writel(alchemy_dbdma_pm_data[i][4], addr + 0x10);
+               __raw_writel(alchemy_dbdma_pm_data[i][5], addr + 0x14);
+               wmb();
                addr += 0x100;  /* next channel base */
        }
-
-       return 0;
 }
 
-static struct sysdev_class alchemy_dbdma_sysdev_class = {
-       .name           = "dbdma",
+static struct syscore_ops alchemy_dbdma_syscore_ops = {
        .suspend        = alchemy_dbdma_suspend,
        .resume         = alchemy_dbdma_resume,
 };
 
-static int __init alchemy_dbdma_sysdev_init(void)
-{
-       struct alchemy_dbdma_sysdev *sdev;
-       int ret;
-
-       ret = sysdev_class_register(&alchemy_dbdma_sysdev_class);
-       if (ret)
-               return ret;
-
-       sdev = kzalloc(sizeof(struct alchemy_dbdma_sysdev), GFP_KERNEL);
-       if (!sdev)
-               return -ENOMEM;
-
-       sdev->sysdev.id = -1;
-       sdev->sysdev.cls = &alchemy_dbdma_sysdev_class;
-       ret = sysdev_register(&sdev->sysdev);
-       if (ret)
-               kfree(sdev);
-
-       return ret;
-}
-
 static int __init au1xxx_dbdma_init(void)
 {
        int irq_nr, ret;
@@ -1084,11 +1055,7 @@ static int __init au1xxx_dbdma_init(void)
        else {
                dbdma_initialized = 1;
                printk(KERN_INFO "Alchemy DBDMA initialized\n");
-               ret = alchemy_dbdma_sysdev_init();
-               if (ret) {
-                       printk(KERN_ERR "DBDMA PM init failed\n");
-                       ret = 0;
-               }
+               register_syscore_ops(&alchemy_dbdma_syscore_ops);
        }
 
        return ret;
index d5278877891d924837960dbc6e04c56cf8395c69..347980e79a892048a8d7097ac5561634af5e950e 100644 (file)
@@ -58,6 +58,9 @@
  * returned from request_dma.
  */
 
+/* DMA Channel register block spacing */
+#define DMA_CHANNEL_LEN                0x00000100
+
 DEFINE_SPINLOCK(au1000_dma_spin_lock);
 
 struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = {
@@ -77,22 +80,23 @@ static const struct dma_dev {
        unsigned int fifo_addr;
        unsigned int dma_mode;
 } dma_dev_table[DMA_NUM_DEV] = {
-       {UART0_ADDR + UART_TX, 0},
-       {UART0_ADDR + UART_RX, 0},
-       {0, 0},
-       {0, 0},
-       {AC97C_DATA, DMA_DW16 },          /* coherent */
-       {AC97C_DATA, DMA_DR | DMA_DW16 }, /* coherent */
-       {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC},
-       {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC},
-       {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC},
-       {USBD_EP0WR, DMA_DW8 | DMA_NC},
-       {USBD_EP2WR, DMA_DW8 | DMA_NC},
-       {USBD_EP3WR, DMA_DW8 | DMA_NC},
-       {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC},
-       {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC},
-       {I2S_DATA, DMA_DW32 | DMA_NC},
-       {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC}
+       { AU1000_UART0_PHYS_ADDR + 0x04, DMA_DW8 },             /* UART0_TX */
+       { AU1000_UART0_PHYS_ADDR + 0x00, DMA_DW8 | DMA_DR },    /* UART0_RX */
+       { 0, 0 },       /* DMA_REQ0 */
+       { 0, 0 },       /* DMA_REQ1 */
+       { AU1000_AC97_PHYS_ADDR + 0x08, DMA_DW16 },             /* AC97 TX c */
+       { AU1000_AC97_PHYS_ADDR + 0x08, DMA_DW16 | DMA_DR },    /* AC97 RX c */
+       { AU1000_UART3_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC },    /* UART3_TX */
+       { AU1000_UART3_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* UART3_RX */
+       { AU1000_USBD_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* EP0RD */
+       { AU1000_USBD_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC }, /* EP0WR */
+       { AU1000_USBD_PHYS_ADDR + 0x08, DMA_DW8 | DMA_NC }, /* EP2WR */
+       { AU1000_USBD_PHYS_ADDR + 0x0c, DMA_DW8 | DMA_NC }, /* EP3WR */
+       { AU1000_USBD_PHYS_ADDR + 0x10, DMA_DW8 | DMA_NC | DMA_DR }, /* EP4RD */
+       { AU1000_USBD_PHYS_ADDR + 0x14, DMA_DW8 | DMA_NC | DMA_DR }, /* EP5RD */
+       /* on Au1500, these 2 are DMA_REQ2/3 (GPIO208/209) instead! */
+       { AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC},      /* I2S TX */
+       { AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC | DMA_DR}, /* I2S RX */
 };
 
 int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
@@ -123,10 +127,10 @@ int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
 
 /* Device FIFO addresses and default DMA modes - 2nd bank */
 static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = {
-       { SD0_XMIT_FIFO, DMA_DS | DMA_DW8 },            /* coherent */
-       { SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 },   /* coherent */
-       { SD1_XMIT_FIFO, DMA_DS | DMA_DW8 },            /* coherent */
-       { SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8 }    /* coherent */
+       { AU1100_SD0_PHYS_ADDR + 0x00, DMA_DS | DMA_DW8 },              /* coherent */
+       { AU1100_SD0_PHYS_ADDR + 0x04, DMA_DS | DMA_DW8 | DMA_DR },     /* coherent */
+       { AU1100_SD1_PHYS_ADDR + 0x00, DMA_DS | DMA_DW8 },              /* coherent */
+       { AU1100_SD1_PHYS_ADDR + 0x04, DMA_DS | DMA_DW8 | DMA_DR }      /* coherent */
 };
 
 void dump_au1000_dma_channel(unsigned int dmanr)
@@ -202,7 +206,7 @@ int request_au1000_dma(int dev_id, const char *dev_str,
        }
 
        /* fill it in */
-       chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN;
+       chan->io = KSEG1ADDR(AU1000_DMA_PHYS_ADDR) + i * DMA_CHANNEL_LEN;
        chan->dev_id = dev_id;
        chan->dev_str = dev_str;
        chan->fifo_addr = dev->fifo_addr;
index 55dd7c8885175b6df9464dc5f8cd6792b2f38aab..8b60ba0675e2f0f47c78b0908c53f93565f68fbb 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/mach-pb1x00/pb1000.h>
 #endif
 
+/* Interrupt Controller register offsets */
+#define IC_CFG0RD      0x40
+#define IC_CFG0SET     0x40
+#define IC_CFG0CLR     0x44
+#define IC_CFG1RD      0x48
+#define IC_CFG1SET     0x48
+#define IC_CFG1CLR     0x4C
+#define IC_CFG2RD      0x50
+#define IC_CFG2SET     0x50
+#define IC_CFG2CLR     0x54
+#define IC_REQ0INT     0x54
+#define IC_SRCRD       0x58
+#define IC_SRCSET      0x58
+#define IC_SRCCLR      0x5C
+#define IC_REQ1INT     0x5C
+#define IC_ASSIGNRD    0x60
+#define IC_ASSIGNSET   0x60
+#define IC_ASSIGNCLR   0x64
+#define IC_WAKERD      0x68
+#define IC_WAKESET     0x68
+#define IC_WAKECLR     0x6C
+#define IC_MASKRD      0x70
+#define IC_MASKSET     0x70
+#define IC_MASKCLR     0x74
+#define IC_RISINGRD    0x78
+#define IC_RISINGCLR   0x78
+#define IC_FALLINGRD   0x7C
+#define IC_FALLINGCLR  0x7C
+#define IC_TESTBIT     0x80
+
 static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type);
 
 /* NOTE on interrupt priorities: The original writers of this code said:
@@ -221,89 +251,101 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = {
 static void au1x_ic0_unmask(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
-       au_writel(1 << bit, IC0_MASKSET);
-       au_writel(1 << bit, IC0_WAKESET);
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
+
+       __raw_writel(1 << bit, base + IC_MASKSET);
+       __raw_writel(1 << bit, base + IC_WAKESET);
+       wmb();
 }
 
 static void au1x_ic1_unmask(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
-       au_writel(1 << bit, IC1_MASKSET);
-       au_writel(1 << bit, IC1_WAKESET);
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
+
+       __raw_writel(1 << bit, base + IC_MASKSET);
+       __raw_writel(1 << bit, base + IC_WAKESET);
 
 /* very hacky. does the pb1000 cpld auto-disable this int?
  * nowhere in the current kernel sources is it disabled.       --mlau
  */
 #if defined(CONFIG_MIPS_PB1000)
        if (d->irq == AU1000_GPIO15_INT)
-               au_writel(0x4000, PB1000_MDR); /* enable int */
+               __raw_writel(0x4000, (void __iomem *)PB1000_MDR); /* enable int */
 #endif
-       au_sync();
+       wmb();
 }
 
 static void au1x_ic0_mask(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
-       au_writel(1 << bit, IC0_MASKCLR);
-       au_writel(1 << bit, IC0_WAKECLR);
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
+
+       __raw_writel(1 << bit, base + IC_MASKCLR);
+       __raw_writel(1 << bit, base + IC_WAKECLR);
+       wmb();
 }
 
 static void au1x_ic1_mask(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
-       au_writel(1 << bit, IC1_MASKCLR);
-       au_writel(1 << bit, IC1_WAKECLR);
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
+
+       __raw_writel(1 << bit, base + IC_MASKCLR);
+       __raw_writel(1 << bit, base + IC_WAKECLR);
+       wmb();
 }
 
 static void au1x_ic0_ack(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 
        /*
         * This may assume that we don't get interrupts from
         * both edges at once, or if we do, that we don't care.
         */
-       au_writel(1 << bit, IC0_FALLINGCLR);
-       au_writel(1 << bit, IC0_RISINGCLR);
-       au_sync();
+       __raw_writel(1 << bit, base + IC_FALLINGCLR);
+       __raw_writel(1 << bit, base + IC_RISINGCLR);
+       wmb();
 }
 
 static void au1x_ic1_ack(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 
        /*
         * This may assume that we don't get interrupts from
         * both edges at once, or if we do, that we don't care.
         */
-       au_writel(1 << bit, IC1_FALLINGCLR);
-       au_writel(1 << bit, IC1_RISINGCLR);
-       au_sync();
+       __raw_writel(1 << bit, base + IC_FALLINGCLR);
+       __raw_writel(1 << bit, base + IC_RISINGCLR);
+       wmb();
 }
 
 static void au1x_ic0_maskack(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 
-       au_writel(1 << bit, IC0_WAKECLR);
-       au_writel(1 << bit, IC0_MASKCLR);
-       au_writel(1 << bit, IC0_RISINGCLR);
-       au_writel(1 << bit, IC0_FALLINGCLR);
-       au_sync();
+       __raw_writel(1 << bit, base + IC_WAKECLR);
+       __raw_writel(1 << bit, base + IC_MASKCLR);
+       __raw_writel(1 << bit, base + IC_RISINGCLR);
+       __raw_writel(1 << bit, base + IC_FALLINGCLR);
+       wmb();
 }
 
 static void au1x_ic1_maskack(struct irq_data *d)
 {
        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 
-       au_writel(1 << bit, IC1_WAKECLR);
-       au_writel(1 << bit, IC1_MASKCLR);
-       au_writel(1 << bit, IC1_RISINGCLR);
-       au_writel(1 << bit, IC1_FALLINGCLR);
-       au_sync();
+       __raw_writel(1 << bit, base + IC_WAKECLR);
+       __raw_writel(1 << bit, base + IC_MASKCLR);
+       __raw_writel(1 << bit, base + IC_RISINGCLR);
+       __raw_writel(1 << bit, base + IC_FALLINGCLR);
+       wmb();
 }
 
 static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
@@ -318,13 +360,13 @@ static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
                return -EINVAL;
 
        local_irq_save(flags);
-       wakemsk = au_readl(SYS_WAKEMSK);
+       wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
        if (on)
                wakemsk |= 1 << bit;
        else
                wakemsk &= ~(1 << bit);
-       au_writel(wakemsk, SYS_WAKEMSK);
-       au_sync();
+       __raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
+       wmb();
        local_irq_restore(flags);
 
        return 0;
@@ -356,81 +398,74 @@ static struct irq_chip au1x_ic1_chip = {
 static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
 {
        struct irq_chip *chip;
-       unsigned long icr[6];
-       unsigned int bit, ic, irq = d->irq;
+       unsigned int bit, irq = d->irq;
        irq_flow_handler_t handler = NULL;
        unsigned char *name = NULL;
+       void __iomem *base;
        int ret;
 
        if (irq >= AU1000_INTC1_INT_BASE) {
                bit = irq - AU1000_INTC1_INT_BASE;
                chip = &au1x_ic1_chip;
-               ic = 1;
+               base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
        } else {
                bit = irq - AU1000_INTC0_INT_BASE;
                chip = &au1x_ic0_chip;
-               ic = 0;
+               base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
        }
 
        if (bit > 31)
                return -EINVAL;
 
-       icr[0] = ic ? IC1_CFG0SET : IC0_CFG0SET;
-       icr[1] = ic ? IC1_CFG1SET : IC0_CFG1SET;
-       icr[2] = ic ? IC1_CFG2SET : IC0_CFG2SET;
-       icr[3] = ic ? IC1_CFG0CLR : IC0_CFG0CLR;
-       icr[4] = ic ? IC1_CFG1CLR : IC0_CFG1CLR;
-       icr[5] = ic ? IC1_CFG2CLR : IC0_CFG2CLR;
-
        ret = 0;
 
        switch (flow_type) {    /* cfgregs 2:1:0 */
        case IRQ_TYPE_EDGE_RISING:      /* 0:0:1 */
-               au_writel(1 << bit, icr[5]);
-               au_writel(1 << bit, icr[4]);
-               au_writel(1 << bit, icr[0]);
+               __raw_writel(1 << bit, base + IC_CFG2CLR);
+               __raw_writel(1 << bit, base + IC_CFG1CLR);
+               __raw_writel(1 << bit, base + IC_CFG0SET);
                handler = handle_edge_irq;
                name = "riseedge";
                break;
        case IRQ_TYPE_EDGE_FALLING:     /* 0:1:0 */
-               au_writel(1 << bit, icr[5]);
-               au_writel(1 << bit, icr[1]);
-               au_writel(1 << bit, icr[3]);
+               __raw_writel(1 << bit, base + IC_CFG2CLR);
+               __raw_writel(1 << bit, base + IC_CFG1SET);
+               __raw_writel(1 << bit, base + IC_CFG0CLR);
                handler = handle_edge_irq;
                name = "falledge";
                break;
        case IRQ_TYPE_EDGE_BOTH:        /* 0:1:1 */
-               au_writel(1 << bit, icr[5]);
-               au_writel(1 << bit, icr[1]);
-               au_writel(1 << bit, icr[0]);
+               __raw_writel(1 << bit, base + IC_CFG2CLR);
+               __raw_writel(1 << bit, base + IC_CFG1SET);
+               __raw_writel(1 << bit, base + IC_CFG0SET);
                handler = handle_edge_irq;
                name = "bothedge";
                break;
        case IRQ_TYPE_LEVEL_HIGH:       /* 1:0:1 */
-               au_writel(1 << bit, icr[2]);
-               au_writel(1 << bit, icr[4]);
-               au_writel(1 << bit, icr[0]);
+               __raw_writel(1 << bit, base + IC_CFG2SET);
+               __raw_writel(1 << bit, base + IC_CFG1CLR);
+               __raw_writel(1 << bit, base + IC_CFG0SET);
                handler = handle_level_irq;
                name = "hilevel";
                break;
        case IRQ_TYPE_LEVEL_LOW:        /* 1:1:0 */
-               au_writel(1 << bit, icr[2]);
-               au_writel(1 << bit, icr[1]);
-               au_writel(1 << bit, icr[3]);
+               __raw_writel(1 << bit, base + IC_CFG2SET);
+               __raw_writel(1 << bit, base + IC_CFG1SET);
+               __raw_writel(1 << bit, base + IC_CFG0CLR);
                handler = handle_level_irq;
                name = "lowlevel";
                break;
        case IRQ_TYPE_NONE:             /* 0:0:0 */
-               au_writel(1 << bit, icr[5]);
-               au_writel(1 << bit, icr[4]);
-               au_writel(1 << bit, icr[3]);
+               __raw_writel(1 << bit, base + IC_CFG2CLR);
+               __raw_writel(1 << bit, base + IC_CFG1CLR);
+               __raw_writel(1 << bit, base + IC_CFG0CLR);
                break;
        default:
                ret = -EINVAL;
        }
        __irq_set_chip_handler_name_locked(d->irq, chip, handler, name);
 
-       au_sync();
+       wmb();
 
        return ret;
 }
@@ -444,21 +479,21 @@ asmlinkage void plat_irq_dispatch(void)
                off = MIPS_CPU_IRQ_BASE + 7;
                goto handle;
        } else if (pending & CAUSEF_IP2) {
-               s = IC0_REQ0INT;
+               s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ0INT;
                off = AU1000_INTC0_INT_BASE;
        } else if (pending & CAUSEF_IP3) {
-               s = IC0_REQ1INT;
+               s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ1INT;
                off = AU1000_INTC0_INT_BASE;
        } else if (pending & CAUSEF_IP4) {
-               s = IC1_REQ0INT;
+               s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ0INT;
                off = AU1000_INTC1_INT_BASE;
        } else if (pending & CAUSEF_IP5) {
-               s = IC1_REQ1INT;
+               s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ1INT;
                off = AU1000_INTC1_INT_BASE;
        } else
                goto spurious;
 
-       s = au_readl(s);
+       s = __raw_readl((void __iomem *)s);
        if (unlikely(!s)) {
 spurious:
                spurious_interrupt();
@@ -469,48 +504,42 @@ handle:
        do_IRQ(off);
 }
 
+
+static inline void ic_init(void __iomem *base)
+{
+       /* initialize interrupt controller to a safe state */
+       __raw_writel(0xffffffff, base + IC_CFG0CLR);
+       __raw_writel(0xffffffff, base + IC_CFG1CLR);
+       __raw_writel(0xffffffff, base + IC_CFG2CLR);
+       __raw_writel(0xffffffff, base + IC_MASKCLR);
+       __raw_writel(0xffffffff, base + IC_ASSIGNCLR);
+       __raw_writel(0xffffffff, base + IC_WAKECLR);
+       __raw_writel(0xffffffff, base + IC_SRCSET);
+       __raw_writel(0xffffffff, base + IC_FALLINGCLR);
+       __raw_writel(0xffffffff, base + IC_RISINGCLR);
+       __raw_writel(0x00000000, base + IC_TESTBIT);
+       wmb();
+}
+
 static void __init au1000_init_irq(struct au1xxx_irqmap *map)
 {
        unsigned int bit, irq_nr;
-       int i;
-
-       /*
-        * Initialize interrupt controllers to a safe state.
-        */
-       au_writel(0xffffffff, IC0_CFG0CLR);
-       au_writel(0xffffffff, IC0_CFG1CLR);
-       au_writel(0xffffffff, IC0_CFG2CLR);
-       au_writel(0xffffffff, IC0_MASKCLR);
-       au_writel(0xffffffff, IC0_ASSIGNCLR);
-       au_writel(0xffffffff, IC0_WAKECLR);
-       au_writel(0xffffffff, IC0_SRCSET);
-       au_writel(0xffffffff, IC0_FALLINGCLR);
-       au_writel(0xffffffff, IC0_RISINGCLR);
-       au_writel(0x00000000, IC0_TESTBIT);
-
-       au_writel(0xffffffff, IC1_CFG0CLR);
-       au_writel(0xffffffff, IC1_CFG1CLR);
-       au_writel(0xffffffff, IC1_CFG2CLR);
-       au_writel(0xffffffff, IC1_MASKCLR);
-       au_writel(0xffffffff, IC1_ASSIGNCLR);
-       au_writel(0xffffffff, IC1_WAKECLR);
-       au_writel(0xffffffff, IC1_SRCSET);
-       au_writel(0xffffffff, IC1_FALLINGCLR);
-       au_writel(0xffffffff, IC1_RISINGCLR);
-       au_writel(0x00000000, IC1_TESTBIT);
+       void __iomem *base;
 
+       ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR));
+       ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR));
        mips_cpu_irq_init();
 
        /* register all 64 possible IC0+IC1 irq sources as type "none".
         * Use set_irq_type() to set edge/level behaviour at runtime.
         */
-       for (i = AU1000_INTC0_INT_BASE;
-            (i < AU1000_INTC0_INT_BASE + 32); i++)
-               au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE);
+       for (irq_nr = AU1000_INTC0_INT_BASE;
+            (irq_nr < AU1000_INTC0_INT_BASE + 32); irq_nr++)
+               au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE);
 
-       for (i = AU1000_INTC1_INT_BASE;
-            (i < AU1000_INTC1_INT_BASE + 32); i++)
-               au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE);
+       for (irq_nr = AU1000_INTC1_INT_BASE;
+            (irq_nr < AU1000_INTC1_INT_BASE + 32); irq_nr++)
+               au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE);
 
        /*
         * Initialize IC0, which is fixed per processor.
@@ -520,13 +549,13 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map)
 
                if (irq_nr >= AU1000_INTC1_INT_BASE) {
                        bit = irq_nr - AU1000_INTC1_INT_BASE;
-                       if (map->im_request)
-                               au_writel(1 << bit, IC1_ASSIGNSET);
+                       base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
                } else {
                        bit = irq_nr - AU1000_INTC0_INT_BASE;
-                       if (map->im_request)
-                               au_writel(1 << bit, IC0_ASSIGNSET);
+                       base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
                }
+               if (map->im_request)
+                       __raw_writel(1 << bit, base + IC_ASSIGNSET);
 
                au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type);
                ++map;
@@ -556,90 +585,62 @@ void __init arch_init_irq(void)
        }
 }
 
-struct alchemy_ic_sysdev {
-       struct sys_device sysdev;
-       void __iomem *base;
-       unsigned long pmdata[7];
-};
 
-static int alchemy_ic_suspend(struct sys_device *dev, pm_message_t state)
-{
-       struct alchemy_ic_sysdev *icdev =
-                       container_of(dev, struct alchemy_ic_sysdev, sysdev);
+static unsigned long alchemy_ic_pmdata[7 * 2];
 
-       icdev->pmdata[0] = __raw_readl(icdev->base + IC_CFG0RD);
-       icdev->pmdata[1] = __raw_readl(icdev->base + IC_CFG1RD);
-       icdev->pmdata[2] = __raw_readl(icdev->base + IC_CFG2RD);
-       icdev->pmdata[3] = __raw_readl(icdev->base + IC_SRCRD);
-       icdev->pmdata[4] = __raw_readl(icdev->base + IC_ASSIGNRD);
-       icdev->pmdata[5] = __raw_readl(icdev->base + IC_WAKERD);
-       icdev->pmdata[6] = __raw_readl(icdev->base + IC_MASKRD);
-
-       return 0;
+static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d)
+{
+       d[0] = __raw_readl(base + IC_CFG0RD);
+       d[1] = __raw_readl(base + IC_CFG1RD);
+       d[2] = __raw_readl(base + IC_CFG2RD);
+       d[3] = __raw_readl(base + IC_SRCRD);
+       d[4] = __raw_readl(base + IC_ASSIGNRD);
+       d[5] = __raw_readl(base + IC_WAKERD);
+       d[6] = __raw_readl(base + IC_MASKRD);
+       ic_init(base);          /* shut it up too while at it */
 }
 
-static int alchemy_ic_resume(struct sys_device *dev)
+static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d)
 {
-       struct alchemy_ic_sysdev *icdev =
-                       container_of(dev, struct alchemy_ic_sysdev, sysdev);
-
-       __raw_writel(0xffffffff, icdev->base + IC_MASKCLR);
-       __raw_writel(0xffffffff, icdev->base + IC_CFG0CLR);
-       __raw_writel(0xffffffff, icdev->base + IC_CFG1CLR);
-       __raw_writel(0xffffffff, icdev->base + IC_CFG2CLR);
-       __raw_writel(0xffffffff, icdev->base + IC_SRCCLR);
-       __raw_writel(0xffffffff, icdev->base + IC_ASSIGNCLR);
-       __raw_writel(0xffffffff, icdev->base + IC_WAKECLR);
-       __raw_writel(0xffffffff, icdev->base + IC_RISINGCLR);
-       __raw_writel(0xffffffff, icdev->base + IC_FALLINGCLR);
-       __raw_writel(0x00000000, icdev->base + IC_TESTBIT);
-       wmb();
-       __raw_writel(icdev->pmdata[0], icdev->base + IC_CFG0SET);
-       __raw_writel(icdev->pmdata[1], icdev->base + IC_CFG1SET);
-       __raw_writel(icdev->pmdata[2], icdev->base + IC_CFG2SET);
-       __raw_writel(icdev->pmdata[3], icdev->base + IC_SRCSET);
-       __raw_writel(icdev->pmdata[4], icdev->base + IC_ASSIGNSET);
-       __raw_writel(icdev->pmdata[5], icdev->base + IC_WAKESET);
+       ic_init(base);
+
+       __raw_writel(d[0], base + IC_CFG0SET);
+       __raw_writel(d[1], base + IC_CFG1SET);
+       __raw_writel(d[2], base + IC_CFG2SET);
+       __raw_writel(d[3], base + IC_SRCSET);
+       __raw_writel(d[4], base + IC_ASSIGNSET);
+       __raw_writel(d[5], base + IC_WAKESET);
        wmb();
 
-       __raw_writel(icdev->pmdata[6], icdev->base + IC_MASKSET);
+       __raw_writel(d[6], base + IC_MASKSET);
        wmb();
+}
 
+static int alchemy_ic_suspend(void)
+{
+       alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR),
+                              alchemy_ic_pmdata);
+       alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR),
+                              &alchemy_ic_pmdata[7]);
        return 0;
 }
 
-static struct sysdev_class alchemy_ic_sysdev_class = {
-       .name           = "ic",
+static void alchemy_ic_resume(void)
+{
+       alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR),
+                             &alchemy_ic_pmdata[7]);
+       alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR),
+                             alchemy_ic_pmdata);
+}
+
+static struct syscore_ops alchemy_ic_syscore_ops = {
        .suspend        = alchemy_ic_suspend,
        .resume         = alchemy_ic_resume,
 };
 
-static int __init alchemy_ic_sysdev_init(void)
+static int __init alchemy_ic_pm_init(void)
 {
-       struct alchemy_ic_sysdev *icdev;
-       unsigned long icbase[2] = { IC0_PHYS_ADDR, IC1_PHYS_ADDR };
-       int err, i;
-
-       err = sysdev_class_register(&alchemy_ic_sysdev_class);
-       if (err)
-               return err;
-
-       for (i = 0; i < 2; i++) {
-               icdev = kzalloc(sizeof(struct alchemy_ic_sysdev), GFP_KERNEL);
-               if (!icdev)
-                       return -ENOMEM;
-
-               icdev->base = ioremap(icbase[i], 0x1000);
-
-               icdev->sysdev.id = i;
-               icdev->sysdev.cls = &alchemy_ic_sysdev_class;
-               err = sysdev_register(&icdev->sysdev);
-               if (err) {
-                       kfree(icdev);
-                       return err;
-               }
-       }
-
+       register_syscore_ops(&alchemy_ic_syscore_ops);
        return 0;
 }
-device_initcall(alchemy_ic_sysdev_init);
+device_initcall(alchemy_ic_pm_init);
index 9e7814db3d03411d08bfe93868f84d646dd93d93..3b2c18b14341c22c10af18699bc36b844466ea9a 100644 (file)
 
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
-#include <linux/init.h>
+#include <linux/slab.h>
 
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -30,21 +31,12 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
 #ifdef CONFIG_SERIAL_8250
        switch (state) {
        case 0:
-               if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
-                       /* power-on sequence as suggested in the databooks */
-                       __raw_writel(0, port->membase + UART_MOD_CNTRL);
-                       wmb();
-                       __raw_writel(1, port->membase + UART_MOD_CNTRL);
-                       wmb();
-               }
-               __raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
-               wmb();
+               alchemy_uart_enable(CPHYSADDR(port->membase));
                serial8250_do_pm(port, state, old_state);
                break;
        case 3:         /* power off */
                serial8250_do_pm(port, state, old_state);
-               __raw_writel(0, port->membase + UART_MOD_CNTRL);
-               wmb();
+               alchemy_uart_disable(CPHYSADDR(port->membase));
                break;
        default:
                serial8250_do_pm(port, state, old_state);
@@ -65,38 +57,60 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                .pm             = alchemy_8250_pm,              \
        }
 
-static struct plat_serial8250_port au1x00_uart_data[] = {
-#if defined(CONFIG_SOC_AU1000)
-       PORT(UART0_PHYS_ADDR, AU1000_UART0_INT),
-       PORT(UART1_PHYS_ADDR, AU1000_UART1_INT),
-       PORT(UART2_PHYS_ADDR, AU1000_UART2_INT),
-       PORT(UART3_PHYS_ADDR, AU1000_UART3_INT),
-#elif defined(CONFIG_SOC_AU1500)
-       PORT(UART0_PHYS_ADDR, AU1500_UART0_INT),
-       PORT(UART3_PHYS_ADDR, AU1500_UART3_INT),
-#elif defined(CONFIG_SOC_AU1100)
-       PORT(UART0_PHYS_ADDR, AU1100_UART0_INT),
-       PORT(UART1_PHYS_ADDR, AU1100_UART1_INT),
-       PORT(UART3_PHYS_ADDR, AU1100_UART3_INT),
-#elif defined(CONFIG_SOC_AU1550)
-       PORT(UART0_PHYS_ADDR, AU1550_UART0_INT),
-       PORT(UART1_PHYS_ADDR, AU1550_UART1_INT),
-       PORT(UART3_PHYS_ADDR, AU1550_UART3_INT),
-#elif defined(CONFIG_SOC_AU1200)
-       PORT(UART0_PHYS_ADDR, AU1200_UART0_INT),
-       PORT(UART1_PHYS_ADDR, AU1200_UART1_INT),
-#endif
-       { },
+static struct plat_serial8250_port au1x00_uart_data[][4] __initdata = {
+       [ALCHEMY_CPU_AU1000] = {
+               PORT(AU1000_UART0_PHYS_ADDR, AU1000_UART0_INT),
+               PORT(AU1000_UART1_PHYS_ADDR, AU1000_UART1_INT),
+               PORT(AU1000_UART2_PHYS_ADDR, AU1000_UART2_INT),
+               PORT(AU1000_UART3_PHYS_ADDR, AU1000_UART3_INT),
+       },
+       [ALCHEMY_CPU_AU1500] = {
+               PORT(AU1000_UART0_PHYS_ADDR, AU1500_UART0_INT),
+               PORT(AU1000_UART3_PHYS_ADDR, AU1500_UART3_INT),
+       },
+       [ALCHEMY_CPU_AU1100] = {
+               PORT(AU1000_UART0_PHYS_ADDR, AU1100_UART0_INT),
+               PORT(AU1000_UART1_PHYS_ADDR, AU1100_UART1_INT),
+               PORT(AU1000_UART3_PHYS_ADDR, AU1100_UART3_INT),
+       },
+       [ALCHEMY_CPU_AU1550] = {
+               PORT(AU1000_UART0_PHYS_ADDR, AU1550_UART0_INT),
+               PORT(AU1000_UART1_PHYS_ADDR, AU1550_UART1_INT),
+               PORT(AU1000_UART3_PHYS_ADDR, AU1550_UART3_INT),
+       },
+       [ALCHEMY_CPU_AU1200] = {
+               PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT),
+               PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT),
+       },
 };
 
 static struct platform_device au1xx0_uart_device = {
        .name                   = "serial8250",
        .id                     = PLAT8250_DEV_AU1X00,
-       .dev                    = {
-               .platform_data  = au1x00_uart_data,
-       },
 };
 
+static void __init alchemy_setup_uarts(int ctype)
+{
+       unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
+       int s = sizeof(struct plat_serial8250_port);
+       int c = alchemy_get_uarts(ctype);
+       struct plat_serial8250_port *ports;
+
+       ports = kzalloc(s * (c + 1), GFP_KERNEL);
+       if (!ports) {
+               printk(KERN_INFO "Alchemy: no memory for UART data\n");
+               return;
+       }
+       memcpy(ports, au1x00_uart_data[ctype], s * c);
+       au1xx0_uart_device.dev.platform_data = ports;
+
+       /* Fill up uartclk. */
+       for (s = 0; s < c; s++)
+               ports[s].uartclk = uartclk;
+       if (platform_device_register(&au1xx0_uart_device))
+               printk(KERN_INFO "Alchemy: failed to register UARTs\n");
+}
+
 /* OHCI (USB full speed host controller) */
 static struct resource au1xxx_usb_ohci_resources[] = {
        [0] = {
@@ -269,8 +283,8 @@ extern struct au1xmmc_platform_data au1xmmc_platdata[2];
 
 static struct resource au1200_mmc0_resources[] = {
        [0] = {
-               .start          = SD0_PHYS_ADDR,
-               .end            = SD0_PHYS_ADDR + 0x7ffff,
+               .start          = AU1100_SD0_PHYS_ADDR,
+               .end            = AU1100_SD0_PHYS_ADDR + 0xfff,
                .flags          = IORESOURCE_MEM,
        },
        [1] = {
@@ -305,8 +319,8 @@ static struct platform_device au1200_mmc0_device = {
 #ifndef CONFIG_MIPS_DB1200
 static struct resource au1200_mmc1_resources[] = {
        [0] = {
-               .start          = SD1_PHYS_ADDR,
-               .end            = SD1_PHYS_ADDR + 0x7ffff,
+               .start          = AU1100_SD1_PHYS_ADDR,
+               .end            = AU1100_SD1_PHYS_ADDR + 0xfff,
                .flags          = IORESOURCE_MEM,
        },
        [1] = {
@@ -359,15 +373,16 @@ static struct platform_device pbdb_smbus_device = {
 #endif
 
 /* Macro to help defining the Ethernet MAC resources */
+#define MAC_RES_COUNT  3       /* MAC regs base, MAC enable reg, MAC INT */
 #define MAC_RES(_base, _enable, _irq)                  \
        {                                               \
-               .start  = CPHYSADDR(_base),             \
-               .end    = CPHYSADDR(_base + 0xffff),    \
+               .start  = _base,                        \
+               .end    = _base + 0xffff,               \
                .flags  = IORESOURCE_MEM,               \
        },                                              \
        {                                               \
-               .start  = CPHYSADDR(_enable),           \
-               .end    = CPHYSADDR(_enable + 0x3),     \
+               .start  = _enable,                      \
+               .end    = _enable + 0x3,                \
                .flags  = IORESOURCE_MEM,               \
        },                                              \
        {                                               \
@@ -376,19 +391,29 @@ static struct platform_device pbdb_smbus_device = {
                .flags  = IORESOURCE_IRQ                \
        }
 
-static struct resource au1xxx_eth0_resources[] = {
-#if defined(CONFIG_SOC_AU1000)
-       MAC_RES(AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT),
-#elif defined(CONFIG_SOC_AU1100)
-       MAC_RES(AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT),
-#elif defined(CONFIG_SOC_AU1550)
-       MAC_RES(AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT),
-#elif defined(CONFIG_SOC_AU1500)
-       MAC_RES(AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT),
-#endif
+static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = {
+       [ALCHEMY_CPU_AU1000] = {
+               MAC_RES(AU1000_MAC0_PHYS_ADDR,
+                       AU1000_MACEN_PHYS_ADDR,
+                       AU1000_MAC0_DMA_INT)
+       },
+       [ALCHEMY_CPU_AU1500] = {
+               MAC_RES(AU1500_MAC0_PHYS_ADDR,
+                       AU1500_MACEN_PHYS_ADDR,
+                       AU1500_MAC0_DMA_INT)
+       },
+       [ALCHEMY_CPU_AU1100] = {
+               MAC_RES(AU1000_MAC0_PHYS_ADDR,
+                       AU1000_MACEN_PHYS_ADDR,
+                       AU1100_MAC0_DMA_INT)
+       },
+       [ALCHEMY_CPU_AU1550] = {
+               MAC_RES(AU1000_MAC0_PHYS_ADDR,
+                       AU1000_MACEN_PHYS_ADDR,
+                       AU1550_MAC0_DMA_INT)
+       },
 };
 
-
 static struct au1000_eth_platform_data au1xxx_eth0_platform_data = {
        .phy1_search_mac0 = 1,
 };
@@ -396,20 +421,26 @@ static struct au1000_eth_platform_data au1xxx_eth0_platform_data = {
 static struct platform_device au1xxx_eth0_device = {
        .name           = "au1000-eth",
        .id             = 0,
-       .num_resources  = ARRAY_SIZE(au1xxx_eth0_resources),
-       .resource       = au1xxx_eth0_resources,
+       .num_resources  = MAC_RES_COUNT,
        .dev.platform_data = &au1xxx_eth0_platform_data,
 };
 
-#ifndef CONFIG_SOC_AU1100
-static struct resource au1xxx_eth1_resources[] = {
-#if defined(CONFIG_SOC_AU1000)
-       MAC_RES(AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT),
-#elif defined(CONFIG_SOC_AU1550)
-       MAC_RES(AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT),
-#elif defined(CONFIG_SOC_AU1500)
-       MAC_RES(AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT),
-#endif
+static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = {
+       [ALCHEMY_CPU_AU1000] = {
+               MAC_RES(AU1000_MAC1_PHYS_ADDR,
+                       AU1000_MACEN_PHYS_ADDR + 4,
+                       AU1000_MAC1_DMA_INT)
+       },
+       [ALCHEMY_CPU_AU1500] = {
+               MAC_RES(AU1500_MAC1_PHYS_ADDR,
+                       AU1500_MACEN_PHYS_ADDR + 4,
+                       AU1500_MAC1_DMA_INT)
+       },
+       [ALCHEMY_CPU_AU1550] = {
+               MAC_RES(AU1000_MAC1_PHYS_ADDR,
+                       AU1000_MACEN_PHYS_ADDR + 4,
+                       AU1550_MAC1_DMA_INT)
+       },
 };
 
 static struct au1000_eth_platform_data au1xxx_eth1_platform_data = {
@@ -419,11 +450,9 @@ static struct au1000_eth_platform_data au1xxx_eth1_platform_data = {
 static struct platform_device au1xxx_eth1_device = {
        .name           = "au1000-eth",
        .id             = 1,
-       .num_resources  = ARRAY_SIZE(au1xxx_eth1_resources),
-       .resource       = au1xxx_eth1_resources,
+       .num_resources  = MAC_RES_COUNT,
        .dev.platform_data = &au1xxx_eth1_platform_data,
 };
-#endif
 
 void __init au1xxx_override_eth_cfg(unsigned int port,
                        struct au1000_eth_platform_data *eth_data)
@@ -434,15 +463,65 @@ void __init au1xxx_override_eth_cfg(unsigned int port,
        if (port == 0)
                memcpy(&au1xxx_eth0_platform_data, eth_data,
                        sizeof(struct au1000_eth_platform_data));
-#ifndef CONFIG_SOC_AU1100
        else
                memcpy(&au1xxx_eth1_platform_data, eth_data,
                        sizeof(struct au1000_eth_platform_data));
-#endif
+}
+
+static void __init alchemy_setup_macs(int ctype)
+{
+       int ret, i;
+       unsigned char ethaddr[6];
+       struct resource *macres;
+
+       /* Handle 1st MAC */
+       if (alchemy_get_macs(ctype) < 1)
+               return;
+
+       macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
+       if (!macres) {
+               printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n");
+               return;
+       }
+       memcpy(macres, au1xxx_eth0_resources[ctype],
+              sizeof(struct resource) * MAC_RES_COUNT);
+       au1xxx_eth0_device.resource = macres;
+
+       i = prom_get_ethernet_addr(ethaddr);
+       if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac))
+               memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6);
+
+       ret = platform_device_register(&au1xxx_eth0_device);
+       if (!ret)
+               printk(KERN_INFO "Alchemy: failed to register MAC0\n");
+
+
+       /* Handle 2nd MAC */
+       if (alchemy_get_macs(ctype) < 2)
+               return;
+
+       macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
+       if (!macres) {
+               printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n");
+               return;
+       }
+       memcpy(macres, au1xxx_eth1_resources[ctype],
+              sizeof(struct resource) * MAC_RES_COUNT);
+       au1xxx_eth1_device.resource = macres;
+
+       ethaddr[5] += 1;        /* next addr for 2nd MAC */
+       if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac))
+               memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
+
+       /* Register second MAC if enabled in pinfunc */
+       if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) {
+               ret = platform_device_register(&au1xxx_eth1_device);
+               if (ret)
+                       printk(KERN_INFO "Alchemy: failed to register MAC1\n");
+       }
 }
 
 static struct platform_device *au1xxx_platform_devices[] __initdata = {
-       &au1xx0_uart_device,
        &au1xxx_usb_ohci_device,
 #ifdef CONFIG_FB_AU1100
        &au1100_lcd_device,
@@ -460,36 +539,17 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
 #ifdef SMBUS_PSC_BASE
        &pbdb_smbus_device,
 #endif
-       &au1xxx_eth0_device,
 };
 
 static int __init au1xxx_platform_init(void)
 {
-       unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
-       int err, i;
-       unsigned char ethaddr[6];
+       int err, ctype = alchemy_get_cputype();
 
-       /* Fill up uartclk. */
-       for (i = 0; au1x00_uart_data[i].flags; i++)
-               au1x00_uart_data[i].uartclk = uartclk;
-
-       /* use firmware-provided mac addr if available and necessary */
-       i = prom_get_ethernet_addr(ethaddr);
-       if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac))
-               memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6);
+       alchemy_setup_uarts(ctype);
+       alchemy_setup_macs(ctype);
 
        err = platform_add_devices(au1xxx_platform_devices,
                                   ARRAY_SIZE(au1xxx_platform_devices));
-#ifndef CONFIG_SOC_AU1100
-       ethaddr[5] += 1;        /* next addr for 2nd MAC */
-       if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac))
-               memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
-
-       /* Register second MAC if enabled in pinfunc */
-       if (!err && !(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2))
-               err = platform_device_register(&au1xxx_eth1_device);
-#endif
-
        return err;
 }
 
index 561e5da2658b36f999c6da9bc8377c9f0b203289..1b887c86841754133e2539a2e5f4c9748ed2e7df 100644 (file)
@@ -52,8 +52,6 @@ void __init plat_mem_setup(void)
        /* this is faster than wasting cycles trying to approximate it */
        preset_lpj = (est_freq >> 1) / HZ;
 
-       board_setup();  /* board specific setup */
-
        if (au1xxx_cpu_needs_config_od())
                /* Various early Au1xx0 errata corrected by this */
                set_c0_config(1 << 19); /* Set Config[OD] */
@@ -61,6 +59,8 @@ void __init plat_mem_setup(void)
                /* Clear to obtain best system bus performance */
                clear_c0_config(1 << 19); /* Clear Config[OD] */
 
+       board_setup();  /* board specific setup */
+
        /* IO/MEM resources. */
        set_io_port_base(0);
        ioport_resource.start = IOPORT_RESOURCE_START;
index 2aecb2fdf9827a6d3849916056a4661d14d93cfc..d5da6adbf63491566330f9a22309c69274d132ad 100644 (file)
@@ -141,8 +141,7 @@ static int __init alchemy_time_init(unsigned int m2int)
                goto cntr_err;
 
        /* register counter1 clocksource and event device */
-       clocksource_set_clock(&au1x_counter1_clocksource, 32768);
-       clocksource_register(&au1x_counter1_clocksource);
+       clocksource_register_hz(&au1x_counter1_clocksource, 32768);
 
        cd->shift = 32;
        cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift);
index 4a8980027ecf83538229e71ea67fe3c27c2a4517..1dac4f27d33452e7c572b06f4000bd6a44de232b 100644 (file)
@@ -23,6 +23,13 @@ void __init board_setup(void)
        unsigned long freq0, clksrc, div, pfc;
        unsigned short whoami;
 
+       /* Set Config[OD] (disable overlapping bus transaction):
+        * This gets rid of a _lot_ of spurious interrupts (especially
+        * wrt. IDE); but incurs ~10% performance hit in some
+        * cpu-bound applications.
+        */
+       set_c0_config(1 << 19);
+
        bcsr_init(DB1200_BCSR_PHYS_ADDR,
                  DB1200_BCSR_PHYS_ADDR + DB1200_BCSR_HEXLED_OFS);
 
index 05f120ff90f9c244312a57f9a2619a627e9e28ab..5c956fe8760ffc9e99c5b928eaedfb6af7ef2cbe 100644 (file)
@@ -127,13 +127,10 @@ const char *get_system_type(void)
 void __init board_setup(void)
 {
        unsigned long bcsr1, bcsr2;
-       u32 pin_func;
 
        bcsr1 = DB1000_BCSR_PHYS_ADDR;
        bcsr2 = DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS;
 
-       pin_func = 0;
-
 #ifdef CONFIG_MIPS_DB1000
        printk(KERN_INFO "AMD Alchemy Au1000/Db1000 Board\n");
 #endif
@@ -164,12 +161,16 @@ void __init board_setup(void)
        /* Not valid for Au1550 */
 #if defined(CONFIG_IRDA) && \
    (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
-       /* Set IRFIRSEL instead of GPIO15 */
-       pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF;
-       au_writel(pin_func, SYS_PINFUNC);
-       /* Power off until the driver is in use */
-       bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK,
-                               BCSR_RESETS_IRDA_MODE_OFF);
+       {
+               u32 pin_func;
+
+               /* Set IRFIRSEL instead of GPIO15 */
+               pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF;
+               au_writel(pin_func, SYS_PINFUNC);
+               /* Power off until the driver is in use */
+               bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK,
+                        BCSR_RESETS_IRDA_MODE_OFF);
+       }
 #endif
        bcsr_write(BCSR_PCMCIA, 0);     /* turn off PCMCIA power */
 
@@ -177,31 +178,35 @@ void __init board_setup(void)
        alchemy_gpio1_input_enable();
 
 #ifdef CONFIG_MIPS_MIRAGE
-       /* GPIO[20] is output */
-       alchemy_gpio_direction_output(20, 0);
+       {
+               u32 pin_func;
 
-       /* Set GPIO[210:208] instead of SSI_0 */
-       pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0;
+               /* GPIO[20] is output */
+               alchemy_gpio_direction_output(20, 0);
 
-       /* Set GPIO[215:211] for LEDs */
-       pin_func |= 5 << 2;
+               /* Set GPIO[210:208] instead of SSI_0 */
+               pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0;
 
-       /* Set GPIO[214:213] for more LEDs */
-       pin_func |= 5 << 12;
+               /* Set GPIO[215:211] for LEDs */
+               pin_func |= 5 << 2;
 
-       /* Set GPIO[207:200] instead of PCMCIA/LCD */
-       pin_func |= SYS_PF_LCD | SYS_PF_PC;
-       au_writel(pin_func, SYS_PINFUNC);
+               /* Set GPIO[214:213] for more LEDs */
+               pin_func |= 5 << 12;
 
-       /*
-        * Enable speaker amplifier.  This should
-        * be part of the audio driver.
-        */
-       alchemy_gpio_direction_output(209, 1);
+               /* Set GPIO[207:200] instead of PCMCIA/LCD */
+               pin_func |= SYS_PF_LCD | SYS_PF_PC;
+               au_writel(pin_func, SYS_PINFUNC);
 
-       pm_power_off = mirage_power_off;
-       _machine_halt = mirage_power_off;
-       _machine_restart = (void(*)(char *))mips_softreset;
+               /*
+                * Enable speaker amplifier.  This should
+                * be part of the audio driver.
+                */
+               alchemy_gpio_direction_output(209, 1);
+
+               pm_power_off = mirage_power_off;
+               _machine_halt = mirage_power_off;
+               _machine_restart = (void(*)(char *))mips_softreset;
+       }
 #endif
 
 #ifdef CONFIG_MIPS_BOSPORUS
index 2d85c4b5be096f530266f6cfc620886aa1c8b4c6..e64fdcbf75d081890c1cafc3c190b2869d3ff4a6 100644 (file)
@@ -65,7 +65,7 @@ void __init board_setup(void)
 
        /* Set AUX clock to 12 MHz * 8 = 96 MHz */
        au_writel(8, SYS_AUXPLL);
-       au_writel(0, SYS_PINSTATERD);
+       alchemy_gpio1_input_enable();
        udelay(100);
 
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
index 83f46215eb0c3b7b652a2abea4f7a41dda0c7a15..3b4fa32069692fbd384dbb9890ac98d7c2505261 100644 (file)
@@ -56,7 +56,7 @@ void __init board_setup(void)
        sys_clksrc = sys_freqctrl = pin_func = 0;
        /* Set AUX clock to 12 MHz * 8 = 96 MHz */
        au_writel(8, SYS_AUXPLL);
-       au_writel(0, SYS_PINSTATERD);
+       alchemy_gpio1_input_enable();
        udelay(100);
 
        /* GPIO201 is input for PCMCIA card detect */
index baeb21385058b8d5efe5e046620e66746b754d73..e5306b56da6d011face7e6072c93eb82ed3ab0fc 100644 (file)
@@ -62,5 +62,5 @@ void __init prom_init(void)
 
 void prom_putchar(unsigned char c)
 {
-    alchemy_uart_putchar(UART0_PHYS_ADDR, c);
+       alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
 }
index ad2e3f1379338e1d209d73d0276825df8cc97d28..5f8f0691ed2d4fe4d01776f88e4b70685d6efbfe 100644 (file)
@@ -36,9 +36,6 @@
 
 #include <prom.h>
 
-#define UART1_ADDR     KSEG1ADDR(UART1_PHYS_ADDR)
-#define UART3_ADDR     KSEG1ADDR(UART3_PHYS_ADDR)
-
 char irq_tab_alchemy[][5] __initdata = {
        [0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff },
 };
@@ -67,18 +64,15 @@ static void gpr_power_off(void)
 
 void __init board_setup(void)
 {
-       printk(KERN_INFO "Tarpeze ITS GPR board\n");
+       printk(KERN_INFO "Trapeze ITS GPR board\n");
 
        pm_power_off = gpr_power_off;
        _machine_halt = gpr_power_off;
        _machine_restart = gpr_reset;
 
-       /* Enable UART3 */
-       au_writel(0x1, UART3_ADDR + UART_MOD_CNTRL);/* clock enable (CE) */
-       au_writel(0x3, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */
-       /* Enable UART1 */
-       au_writel(0x1, UART1_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */
-       au_writel(0x3, UART1_ADDR + UART_MOD_CNTRL); /* CE and "enable" */
+       /* Enable UART1/3 */
+       alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
+       alchemy_uart_enable(AU1000_UART1_PHYS_ADDR);
 
        /* Take away Reset of UMTS-card */
        alchemy_gpio_direction_output(215, 1);
index f044f4c541d7a78f06244245c280ced4ba66d16a..229aafae680cadc3be1fa1bcb5b5eb2eb2a57c46 100644 (file)
@@ -59,5 +59,5 @@ void __init prom_init(void)
 
 void prom_putchar(unsigned char c)
 {
-       alchemy_uart_putchar(UART0_PHYS_ADDR, c);
+       alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
 }
index cf436ab679ae81f6abdb2ba422bc75617c3d5fed..3ae984cf98cf25ce8c695f6c06808d7dc6379647 100644 (file)
@@ -87,7 +87,7 @@ void __init board_setup(void)
        au_writel(SYS_PF_NI2, SYS_PINFUNC);
 
        /* Initialize GPIO */
-       au_writel(0xFFFFFFFF, SYS_TRIOUTCLR);
+       au_writel(~0, KSEG1ADDR(AU1000_SYS_PHYS_ADDR) + SYS_TRIOUTCLR);
        alchemy_gpio_direction_output(0, 0);    /* Disable M66EN (PCI 66MHz) */
        alchemy_gpio_direction_output(3, 1);    /* Disable PCI CLKRUN# */
        alchemy_gpio_direction_output(1, 1);    /* Enable EXT_IO3 */
index f8d25575fa05a78bb6afce909191691a96a9ba2e..2e81cc7f34229136bde29cf054ebd62511de0e2c 100644 (file)
@@ -62,5 +62,5 @@ void __init prom_init(void)
 
 void prom_putchar(unsigned char c)
 {
-       alchemy_uart_putchar(UART0_PHYS_ADDR, c);
+       alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
 }
index 956f946218c519eb3b1c86cf76540150eac244e7..55628e390fd7460c4a9d25ede7ffb7cd1c6addfe 100644 (file)
@@ -53,8 +53,8 @@ static struct platform_device mtx1_button = {
 
 static struct resource mtx1_wdt_res[] = {
        [0] = {
-               .start  = 15,
-               .end    = 15,
+               .start  = 215,
+               .end    = 215,
                .name   = "mtx1-wdt-gpio",
                .flags  = IORESOURCE_IRQ,
        }
index febfb0fb0896dcd979ca52bc40ecf0fcb3bfcbe2..81e57fad07ab4bd5567bec068d70c0b18955b0fb 100644 (file)
@@ -66,13 +66,10 @@ void __init board_setup(void)
        au_writel(pin_func, SYS_PINFUNC);
 
        /* Enable UART */
-       au_writel(0x01, UART3_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */
-       mdelay(10);
-       au_writel(0x03, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */
-       mdelay(10);
-
-       /* Enable DTR = USB power up */
-       au_writel(0x01, UART3_ADDR + UART_MCR); /* UART_MCR_DTR is 0x01??? */
+       alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
+       /* Enable DTR (MCR bit 0) = USB power up */
+       __raw_writel(1, (void __iomem *)KSEG1ADDR(AU1000_UART3_PHYS_ADDR + 0x18));
+       wmb();
 
 #ifdef CONFIG_PCI
 #if defined(__MIPSEB__)
index 15125c2fda7d7397de3dcee2ec1f1555babc1f85..0ee02cfa989dc55e7c56772f346fa152fbcae1dd 100644 (file)
@@ -51,14 +51,13 @@ void __init prom_init(void)
        prom_init_cmdline();
 
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
                memsize = 0x04000000;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
+
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
 void prom_putchar(unsigned char c)
 {
-       alchemy_uart_putchar(UART0_PHYS_ADDR, c);
+       alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
 }
index 425dfa5d6e12c69380b160edde7edf58477860af..bb571bcdb8f2f06d5d2cb8b2d787591f35b4e66d 100644 (file)
@@ -325,9 +325,7 @@ int __init ar7_gpio_init(void)
                size = 0x1f;
        }
 
-       gpch->regs = ioremap_nocache(AR7_REGS_GPIO,
-                                       AR7_REGS_GPIO + 0x10);
-
+       gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size);
        if (!gpch->regs) {
                printk(KERN_ERR "%s: failed to ioremap regs\n",
                                        gpch->chip.label);
index e5b6615731e5c24dd963190bc2d244930ba08299..54db815bc86c46e3586e5b9c7061cb32e96f1e37 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2005 Broadcom Corporation
  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.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
@@ -23,7 +24,7 @@
 static char nvram_buf[NVRAM_SPACE];
 
 /* Probe for NVRAM header */
-static void __init early_nvram_init(void)
+static void early_nvram_init(void)
 {
        struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
        struct nvram_header *header;
index c95f90bf734ca9c1765b14728f391a14af62917b..73b529b57433d359ab75d6a9733d79ed925417d9 100644 (file)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
  *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+ *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.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
@@ -57,10 +58,49 @@ static void bcm47xx_machine_halt(void)
 }
 
 #define READ_FROM_NVRAM(_outvar, name, buf) \
-       if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
+       if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
                sprom->_outvar = simple_strtoul(buf, NULL, 0);
 
-static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
+       if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
+           nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
+
+static inline int nvram_getprefix(const char *prefix, char *name,
+                                 char *buf, int len)
+{
+       if (prefix) {
+               char key[100];
+
+               snprintf(key, sizeof(key), "%s%s", prefix, name);
+               return nvram_getenv(key, buf, len);
+       }
+
+       return nvram_getenv(name, buf, len);
+}
+
+static u32 nvram_getu32(const char *name, char *buf, int len)
+{
+       int rv;
+       char key[100];
+       u16 var0, var1;
+
+       snprintf(key, sizeof(key), "%s0", name);
+       rv = nvram_getenv(key, buf, len);
+       /* return 0 here so this looks like unset */
+       if (rv < 0)
+               return 0;
+       var0 = simple_strtoul(buf, NULL, 0);
+
+       snprintf(key, sizeof(key), "%s1", name);
+       rv = nvram_getenv(key, buf, len);
+       if (rv < 0)
+               return 0;
+       var1 = simple_strtoul(buf, NULL, 0);
+       return var1 << 16 | var0;
+}
+
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
 {
        char buf[100];
        u32 boardflags;
@@ -69,11 +109,12 @@ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
 
        sprom->revision = 1; /* Fallback: Old hardware does not define this. */
        READ_FROM_NVRAM(revision, "sromrev", buf);
-       if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+       if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
+           nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
                nvram_parse_macaddr(buf, sprom->il0mac);
-       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+       if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
                nvram_parse_macaddr(buf, sprom->et0mac);
-       if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+       if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
                nvram_parse_macaddr(buf, sprom->et1mac);
        READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
        READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
@@ -95,20 +136,36 @@ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
        READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
        READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
        READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
-       READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
-       READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
-       READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
-       READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
-       READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
-       READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
-       READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
-       READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
-       READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
-       READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
+       READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
+       READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
+       READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
+       READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
+       READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
+       READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
+       READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
+       READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
+       READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
+       READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
        READ_FROM_NVRAM(tri2g, "tri2g", buf);
        READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
        READ_FROM_NVRAM(tri5g, "tri5g", buf);
        READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
+       READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
+       READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
+       READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
+       READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
+       READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
+       READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
+       READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
+       READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
+       READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
+       READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
+       READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
+       READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
+       READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
+       READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
+       READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
+       READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
        READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
        READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
        READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
@@ -120,19 +177,27 @@ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
        READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
        READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
        READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
-       READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
-       READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
-       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
-       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
 
-       if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
+       sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
+       sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
+       sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
+       sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
+
+       READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
+       READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
+       READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
+       READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
+       memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
+              sizeof(sprom->antenna_gain.ghz5));
+
+       if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
                boardflags = simple_strtoul(buf, NULL, 0);
                if (boardflags) {
                        sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
                        sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
                }
        }
-       if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
+       if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
                boardflags = simple_strtoul(buf, NULL, 0);
                if (boardflags) {
                        sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
@@ -141,6 +206,22 @@ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
        }
 }
 
+int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+       char prefix[10];
+
+       if (bus->bustype == SSB_BUSTYPE_PCI) {
+               snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+                        bus->host_pci->bus->number + 1,
+                        PCI_SLOT(bus->host_pci->devfn));
+               bcm47xx_fill_sprom(out, prefix);
+               return 0;
+       } else {
+               printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
+               return -EINVAL;
+       }
+}
+
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                   struct ssb_init_invariants *iv)
 {
@@ -158,7 +239,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
        if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
-       bcm47xx_fill_sprom(&iv->sprom);
+       bcm47xx_fill_sprom(&iv->sprom, NULL);
 
        if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
                iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
@@ -172,6 +253,11 @@ void __init plat_mem_setup(void)
        char buf[100];
        struct ssb_mipscore *mcore;
 
+       err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
+       if (err)
+               printk(KERN_WARNING "bcm47xx: someone else already registered"
+                       " a ssb SPROM callback handler (err %d)\n", err);
+
        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
                                      bcm47xx_get_invariants);
        if (err)
index 8dba8cfb752fa62a8fbc04025785c3ee78d71b30..40b223b603be588ea6702579cd658c170e2f0384 100644 (file)
@@ -643,6 +643,17 @@ static struct ssb_sprom bcm63xx_sprom = {
        .boardflags_lo          = 0x2848,
        .boardflags_hi          = 0x0000,
 };
+
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+       if (bus->bustype == SSB_BUSTYPE_PCI) {
+               memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+               return 0;
+       } else {
+               printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+               return -EINVAL;
+       }
+}
 #endif
 
 /*
@@ -793,8 +804,9 @@ void __init board_prom_init(void)
        if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
                memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
                memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
-               if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
-                       printk(KERN_ERR "failed to register fallback SPROM\n");
+               if (ssb_arch_register_fallback_sprom(
+                               &bcm63xx_get_fallback_sprom) < 0)
+                       printk(KERN_ERR PFX "failed to register fallback SPROM\n");
        }
 #endif
 }
index 88c9d963be88872df85924046a614858c59593af..9a6243676e2203b4c3f9addcc3c236fb27ba6060 100644 (file)
@@ -16,8 +16,8 @@
 
 int main(int argc, char *argv[])
 {
+       unsigned long long vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
        struct stat sb;
-       uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
 
        if (argc != 3) {
                fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
index 1bff22fa089bc08ef1432aaa3270d0c0ae364470..eb063e6dead923b2a26077b5c4262e5fd0c53a31 100644 (file)
@@ -3,5 +3,5 @@
 void putc(char c)
 {
        /* all current (Jan. 2010) in-kernel boards */
-       alchemy_uart_putchar(UART0_PHYS_ADDR, c);
+       alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
 }
index caae22858163a193b681e0adb920590d3d0bcd20..cad555ebeca3b855356d928b66e736e6a286cef6 100644 (file)
@@ -1,11 +1,7 @@
-config CAVIUM_OCTEON_SPECIFIC_OPTIONS
-       bool "Enable Octeon specific options"
-       depends on CPU_CAVIUM_OCTEON
-       default "y"
+if CPU_CAVIUM_OCTEON
 
 config CAVIUM_CN63XXP1
        bool "Enable CN63XXP1 errata worarounds"
-       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
        default "n"
        help
          The CN63XXP1 chip requires build time workarounds to
@@ -16,7 +12,6 @@ config CAVIUM_CN63XXP1
 
 config CAVIUM_OCTEON_2ND_KERNEL
        bool "Build the kernel to be used as a 2nd kernel on the same chip"
-       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
        default "n"
        help
          This option configures this kernel to be linked at a different
@@ -26,7 +21,6 @@ config CAVIUM_OCTEON_2ND_KERNEL
 
 config CAVIUM_OCTEON_HW_FIX_UNALIGNED
        bool "Enable hardware fixups of unaligned loads and stores"
-       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
        default "y"
        help
          Configure the Octeon hardware to automatically fix unaligned loads
@@ -38,7 +32,6 @@ config CAVIUM_OCTEON_HW_FIX_UNALIGNED
 
 config CAVIUM_OCTEON_CVMSEG_SIZE
        int "Number of L1 cache lines reserved for CVMSEG memory"
-       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
        range 0 54
        default 1
        help
@@ -50,7 +43,6 @@ config CAVIUM_OCTEON_CVMSEG_SIZE
 
 config CAVIUM_OCTEON_LOCK_L2
        bool "Lock often used kernel code in the L2"
-       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
        default "y"
        help
          Enable locking parts of the kernel into the L2 cache.
@@ -93,7 +85,6 @@ config CAVIUM_OCTEON_LOCK_L2_MEMCPY
 config ARCH_SPARSEMEM_ENABLE
        def_bool y
        select SPARSEMEM_STATIC
-       depends on CPU_CAVIUM_OCTEON
 
 config CAVIUM_OCTEON_HELPER
        def_bool y
@@ -107,6 +98,8 @@ config NEED_SG_DMA_LENGTH
 
 config SWIOTLB
        def_bool y
-       depends on CPU_CAVIUM_OCTEON
        select IOMMU_HELPER
        select NEED_SG_DMA_LENGTH
+
+
+endif # CPU_CAVIUM_OCTEON
index 26bf71130bf8b1dd6fe1d24c8b5e336a2b30b78d..29d56afbb02d889e68b959eafe27626d7cfe9498 100644 (file)
@@ -105,8 +105,7 @@ unsigned long long notrace sched_clock(void)
 void __init plat_time_init(void)
 {
        clocksource_mips.rating = 300;
-       clocksource_set_clock(&clocksource_mips, octeon_get_clock_rate());
-       clocksource_register(&clocksource_mips);
+       clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate());
 }
 
 static u64 octeon_udelay_factor;
index 0707fae3f0eeaf28526cef8f7d5baa5fbb7b0b8f..2d9028f1474c0a3f343d6a6c75b12de71cbd2231 100644 (file)
@@ -288,7 +288,6 @@ void octeon_user_io_init(void)
        union octeon_cvmemctl cvmmemctl;
        union cvmx_iob_fau_timeout fau_timeout;
        union cvmx_pow_nw_tim nm_tim;
-       uint64_t cvmctl;
 
        /* Get the current settings for CP0_CVMMEMCTL_REG */
        cvmmemctl.u64 = read_c0_cvmmemctl();
@@ -392,12 +391,6 @@ void octeon_user_io_init(void)
                          CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
                          CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
 
-       /* Move the performance counter interrupts to IRQ 6 */
-       cvmctl = read_c0_cvmctl();
-       cvmctl &= ~(7 << 7);
-       cvmctl |= 6 << 7;
-       write_c0_cvmctl(cvmctl);
-
        /* Set a default for the hardware timeouts */
        fau_timeout.u64 = 0;
        fau_timeout.s.tout_val = 0xfff;
index ba78b21cc8d0496b7be966550c9612d3a547ad4e..8b606423bbd7f84dcacd4b043297844fc59200d4 100644 (file)
@@ -37,13 +37,15 @@ static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
        uint64_t action;
 
        /* Load the mailbox register to figure out what we're supposed to do */
-       action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid));
+       action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)) & 0xffff;
 
        /* Clear the mailbox to clear the interrupt */
        cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
 
        if (action & SMP_CALL_FUNCTION)
                smp_call_function_interrupt();
+       if (action & SMP_RESCHEDULE_YOURSELF)
+               scheduler_ipi();
 
        /* Check if we've been told to flush the icache */
        if (action & SMP_ICACHE_FLUSH)
@@ -200,16 +202,15 @@ void octeon_prepare_cpus(unsigned int max_cpus)
        if (labi->labi_signature != LABI_SIGNATURE)
                panic("The bootloader version on this board is incorrect.");
 #endif
-
-       cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
+       /*
+        * Only the low order mailbox bits are used for IPIs, leave
+        * the other bits alone.
+        */
+       cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff);
        if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
-                       "mailbox0", mailbox_interrupt)) {
+                       "SMP-IPI", mailbox_interrupt)) {
                panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
        }
-       if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_DISABLED,
-                       "mailbox1", mailbox_interrupt)) {
-               panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
-       }
 }
 
 /**
index 167c1d07b8091d03a86eef28960af143a48dccae..b6acd2f256b682f4c3ab37774eb3ba70bcee7595 100644 (file)
@@ -86,8 +86,8 @@ CONFIG_NET_SCHED=y
 CONFIG_NET_EMATCH=y
 CONFIG_NET_CLS_ACT=y
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=m
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=m
@@ -329,7 +329,7 @@ CONFIG_USB_LED=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_GADGET_M66592=y
 CONFIG_MMC=m
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_STAGING=y
 # CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_FB_SM7XX=y
index 7270f3183bdaacf27af3e347236dfb5961a1293c..5527abbb7dea56ea634a0ab1f32c628f373163e0 100644 (file)
@@ -374,7 +374,7 @@ CONFIG_FB_CIRRUS=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_HID=m
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_IDE_DISK=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
index a97a42c6b2c84407df63a22a4b1581b1ddb18f56..37862b2ce3633a3f87f3aeb0ce3f8e119688a143 100644 (file)
@@ -225,8 +225,8 @@ CONFIG_TOSHIBA_FIR=m
 CONFIG_VLSI_FIR=m
 CONFIG_MCS_FIR=m
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=m
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=m
diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig
new file mode 100644 (file)
index 0000000..e4b399f
--- /dev/null
@@ -0,0 +1,574 @@
+CONFIG_NLM_XLR_BOARD=y
+CONFIG_HIGHMEM=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_SMP=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_KEXEC=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="mips64-unknown-linux-gnu-"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/dev_file_list usr/rootfs"
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NET_IPIP=m
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+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
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_TIPC=m
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_DECNET=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_DCB=y
+CONFIG_NET_PKTGEN=m
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=m
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_MISC_DEVICES=y
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_ISCSI_TCP=m
+CONFIG_LIBFCOE=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_N_HDLC=m
+# CONFIG_DEVKMEM is not set
+CONFIG_STALDRV=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=48
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_RAW_DRIVER=m
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=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_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=m
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+CONFIG_CACHEFILES=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_NTFS_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_ADFS_FS=m
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=y
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+CONFIG_EXOFS_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_EXPERIMENTAL=y
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+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_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+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_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_SCHED_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_KGDB=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC7=m
index 650ac9ba734c9bb254baec52f6d076b9ce53583f..b4db69fbc40ce212a557b235679ec0ebf2208060 100644 (file)
@@ -17,6 +17,6 @@
 #define SMP_CACHE_SHIFT                L1_CACHE_SHIFT
 #define SMP_CACHE_BYTES                L1_CACHE_BYTES
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #endif /* _ASM_CACHE_H */
index fa4328f9124f7d539f4ecf3ec78caaec43def36a..65f9bdd02f1f787d35f03cc8a51f11c87704e1ee 100644 (file)
@@ -14,6 +14,9 @@
 #ifndef __ASM_CEVT_R4K_H
 #define __ASM_CEVT_R4K_H
 
+#include <linux/clockchips.h>
+#include <asm/time.h>
+
 DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
 void mips_event_handler(struct clock_event_device *dev);
index 86877539c6e83679f248d7245324693a690105e6..34c0d3cb116fb36f720498304419d127d5561209 100644 (file)
@@ -33,6 +33,7 @@
 #define PRID_COMP_TOSHIBA      0x070000
 #define PRID_COMP_LSI          0x080000
 #define PRID_COMP_LEXRA                0x0b0000
+#define PRID_COMP_NETLOGIC     0x0c0000
 #define PRID_COMP_CAVIUM       0x0d0000
 #define PRID_COMP_INGENIC      0xd00000
 
 
 #define PRID_IMP_JZRISC        0x0200
 
+/*
+ * These are the PRID's for when 23:16 == PRID_COMP_NETLOGIC
+ */
+#define PRID_IMP_NETLOGIC_XLR732       0x0000
+#define PRID_IMP_NETLOGIC_XLR716       0x0200
+#define PRID_IMP_NETLOGIC_XLR532       0x0900
+#define PRID_IMP_NETLOGIC_XLR308       0x0600
+#define PRID_IMP_NETLOGIC_XLR532C      0x0800
+#define PRID_IMP_NETLOGIC_XLR516C      0x0a00
+#define PRID_IMP_NETLOGIC_XLR508C      0x0b00
+#define PRID_IMP_NETLOGIC_XLR308C      0x0f00
+#define PRID_IMP_NETLOGIC_XLS608       0x8000
+#define PRID_IMP_NETLOGIC_XLS408       0x8800
+#define PRID_IMP_NETLOGIC_XLS404       0x8c00
+#define PRID_IMP_NETLOGIC_XLS208       0x8e00
+#define PRID_IMP_NETLOGIC_XLS204       0x8f00
+#define PRID_IMP_NETLOGIC_XLS108       0xce00
+#define PRID_IMP_NETLOGIC_XLS104       0xcf00
+#define PRID_IMP_NETLOGIC_XLS616B      0x4000
+#define PRID_IMP_NETLOGIC_XLS608B      0x4a00
+#define PRID_IMP_NETLOGIC_XLS416B      0x4400
+#define PRID_IMP_NETLOGIC_XLS412B      0x4c00
+#define PRID_IMP_NETLOGIC_XLS408B      0x4e00
+#define PRID_IMP_NETLOGIC_XLS404B      0x4f00
+
 /*
  * Definitions for 7:0 on legacy processors
  */
@@ -234,6 +260,7 @@ enum cpu_type_enum {
         */
        CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
        CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
+       CPU_XLR,
 
        CPU_LAST
 };
index 655f849bd08d8767e81f6846ce205ce40e487980..7aa37ddfca4ba59b25603183a1d5bca23099fa9c 100644 (file)
@@ -5,7 +5,9 @@
 #include <asm/cache.h>
 #include <asm-generic/dma-coherent.h>
 
+#ifndef CONFIG_SGI_IP27        /* Kludge to fix 2.6.39 build for IP27 */
 #include <dma-coherence.h>
+#endif
 
 extern struct dma_map_ops *mips_dma_map_ops;
 
index f5e856015329cbeda2d8e33303f2baf6817ab804..c565b7c3f0b5b071833c751e4edddfb61aba84f4 100644 (file)
@@ -70,6 +70,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
                                         unsigned long addr, pte_t *ptep)
 {
+       flush_tlb_mm(vma->vm_mm);
 }
 
 static inline int huge_pte_none(pte_t pte)
index 48bb82372994c839f9e0f2d9be04b57bac38580c..9ad011366f73190cce3527dbc754d3abad61ffb5 100644 (file)
 #define PIT_CH0                        0x40
 #define PIT_CH2                        0x42
 
+#define PIT_LATCH              LATCH
+
 extern raw_spinlock_t i8253_lock;
 
 extern void setup_pit_timer(void);
 
+#define inb_pit inb_p
+#define outb_pit outb_p
+
 #endif /* __ASM_I8253_H */
index 7622ccf75076d7f48c73ca555e4d18c9a753e37e..1881b316ca4503b07b5998968a799e625e4a5229 100644 (file)
 #define WORD_INSN ".word"
 #endif
 
-#define JUMP_LABEL(key, label)                                         \
-       do {                                                            \
-               asm goto("1:\tnop\n\t"                                  \
-                       "nop\n\t"                                       \
-                       ".pushsection __jump_table,  \"a\"\n\t"         \
-                       WORD_INSN " 1b, %l[" #label "], %0\n\t"         \
-                       ".popsection\n\t"                               \
-                       : :  "i" (key) :  : label);                     \
-       } while (0)
-
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("1:\tnop\n\t"
+               "nop\n\t"
+               ".pushsection __jump_table,  \"aw\"\n\t"
+               WORD_INSN " 1b, %l[l_yes], %0\n\t"
+               ".popsection\n\t"
+               : :  "i" (key) : : l_yes);
+       return false;
+l_yes:
+       return true;
+}
 
 #endif /* __KERNEL__ */
 
index a6976619160ab9e7c2ec7990781e454704dd191d..f260ebed713b4cf72e00eb8db2dca24a83c42b6f 100644 (file)
@@ -161,6 +161,45 @@ static inline int alchemy_get_cputype(void)
        return ALCHEMY_CPU_UNKNOWN;
 }
 
+/* return number of uarts on a given cputype */
+static inline int alchemy_get_uarts(int type)
+{
+       switch (type) {
+       case ALCHEMY_CPU_AU1000:
+               return 4;
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1200:
+               return 2;
+       case ALCHEMY_CPU_AU1100:
+       case ALCHEMY_CPU_AU1550:
+               return 3;
+       }
+       return 0;
+}
+
+/* enable an UART block if it isn't already */
+static inline void alchemy_uart_enable(u32 uart_phys)
+{
+       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+
+       /* reset, enable clock, deassert reset */
+       if ((__raw_readl(addr + 0x100) & 3) != 3) {
+               __raw_writel(0, addr + 0x100);
+               wmb();
+               __raw_writel(1, addr + 0x100);
+               wmb();
+       }
+       __raw_writel(3, addr + 0x100);
+       wmb();
+}
+
+static inline void alchemy_uart_disable(u32 uart_phys)
+{
+       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+       __raw_writel(0, addr + 0x100);  /* UART_MOD_CNTRL */
+       wmb();
+}
+
 static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(uart_phys);
@@ -180,6 +219,20 @@ static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
        wmb();
 }
 
+/* return number of ethernet MACs on a given cputype */
+static inline int alchemy_get_macs(int type)
+{
+       switch (type) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1550:
+               return 2;
+       case ALCHEMY_CPU_AU1100:
+               return 1;
+       }
+       return 0;
+}
+
 /* arch/mips/au1000/common/clocks.c */
 extern void set_au1x00_speed(unsigned int new_freq);
 extern unsigned int get_au1x00_speed(void);
@@ -630,38 +683,42 @@ enum soc_au1200_ints {
 
 /*
  * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200
  */
 
+#define AU1000_AC97_PHYS_ADDR          0x10000000 /* 012 */
+#define AU1000_USBD_PHYS_ADDR          0x10200000 /* 0123 */
+#define AU1000_IC0_PHYS_ADDR           0x10400000 /* 01234 */
+#define AU1000_MAC0_PHYS_ADDR          0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR          0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR         0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR           0x10600000 /* 24 */
+#define AU1100_SD1_PHYS_ADDR           0x10680000 /* 24 */
+#define AU1000_I2S_PHYS_ADDR           0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR          0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR          0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR         0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR         0x11100000 /* 01234 */
+#define AU1000_UART1_PHYS_ADDR         0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR         0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR         0x11400000 /* 0123 */
+#define AU1500_GPIO2_PHYS_ADDR         0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR           0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR           0x11900000 /* 01234 */
+#define AU1000_DMA_PHYS_ADDR           0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR         0x14002000 /* 34 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR    0x14003000 /* 34 */
+#define AU1000_MACDMA0_PHYS_ADDR       0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR       0x14004200 /* 0123 */
+
+
 #ifdef CONFIG_SOC_AU1000
 #define        MEM_PHYS_ADDR           0x14000000
 #define        STATIC_MEM_PHYS_ADDR    0x14001000
-#define        DMA0_PHYS_ADDR          0x14002000
-#define        DMA1_PHYS_ADDR          0x14002100
-#define        DMA2_PHYS_ADDR          0x14002200
-#define        DMA3_PHYS_ADDR          0x14002300
-#define        DMA4_PHYS_ADDR          0x14002400
-#define        DMA5_PHYS_ADDR          0x14002500
-#define        DMA6_PHYS_ADDR          0x14002600
-#define        DMA7_PHYS_ADDR          0x14002700
-#define        IC0_PHYS_ADDR           0x10400000
-#define        IC1_PHYS_ADDR           0x11800000
-#define        AC97_PHYS_ADDR          0x10000000
 #define        USBH_PHYS_ADDR          0x10100000
-#define        USBD_PHYS_ADDR          0x10200000
 #define        IRDA_PHYS_ADDR          0x10300000
-#define        MAC0_PHYS_ADDR          0x10500000
-#define        MAC1_PHYS_ADDR          0x10510000
-#define        MACEN_PHYS_ADDR         0x10520000
-#define        MACDMA0_PHYS_ADDR       0x14004000
-#define        MACDMA1_PHYS_ADDR       0x14004200
-#define        I2S_PHYS_ADDR           0x11000000
-#define        UART0_PHYS_ADDR         0x11100000
-#define        UART1_PHYS_ADDR         0x11200000
-#define        UART2_PHYS_ADDR         0x11300000
-#define        UART3_PHYS_ADDR         0x11400000
 #define        SSI0_PHYS_ADDR          0x11600000
 #define        SSI1_PHYS_ADDR          0x11680000
-#define        SYS_PHYS_ADDR           0x11900000
 #define PCMCIA_IO_PHYS_ADDR    0xF00000000ULL
 #define PCMCIA_ATTR_PHYS_ADDR  0xF40000000ULL
 #define PCMCIA_MEM_PHYS_ADDR   0xF80000000ULL
@@ -672,30 +729,8 @@ enum soc_au1200_ints {
 #ifdef CONFIG_SOC_AU1500
 #define        MEM_PHYS_ADDR           0x14000000
 #define        STATIC_MEM_PHYS_ADDR    0x14001000
-#define        DMA0_PHYS_ADDR          0x14002000
-#define        DMA1_PHYS_ADDR          0x14002100
-#define        DMA2_PHYS_ADDR          0x14002200
-#define        DMA3_PHYS_ADDR          0x14002300
-#define        DMA4_PHYS_ADDR          0x14002400
-#define        DMA5_PHYS_ADDR          0x14002500
-#define        DMA6_PHYS_ADDR          0x14002600
-#define        DMA7_PHYS_ADDR          0x14002700
-#define        IC0_PHYS_ADDR           0x10400000
-#define        IC1_PHYS_ADDR           0x11800000
-#define        AC97_PHYS_ADDR          0x10000000
 #define        USBH_PHYS_ADDR          0x10100000
-#define        USBD_PHYS_ADDR          0x10200000
 #define PCI_PHYS_ADDR          0x14005000
-#define        MAC0_PHYS_ADDR          0x11500000
-#define        MAC1_PHYS_ADDR          0x11510000
-#define        MACEN_PHYS_ADDR         0x11520000
-#define        MACDMA0_PHYS_ADDR       0x14004000
-#define        MACDMA1_PHYS_ADDR       0x14004200
-#define        I2S_PHYS_ADDR           0x11000000
-#define        UART0_PHYS_ADDR         0x11100000
-#define        UART3_PHYS_ADDR         0x11400000
-#define GPIO2_PHYS_ADDR                0x11700000
-#define        SYS_PHYS_ADDR           0x11900000
 #define PCI_MEM_PHYS_ADDR      0x400000000ULL
 #define PCI_IO_PHYS_ADDR       0x500000000ULL
 #define PCI_CONFIG0_PHYS_ADDR  0x600000000ULL
@@ -710,34 +745,10 @@ enum soc_au1200_ints {
 #ifdef CONFIG_SOC_AU1100
 #define        MEM_PHYS_ADDR           0x14000000
 #define        STATIC_MEM_PHYS_ADDR    0x14001000
-#define        DMA0_PHYS_ADDR          0x14002000
-#define        DMA1_PHYS_ADDR          0x14002100
-#define        DMA2_PHYS_ADDR          0x14002200
-#define        DMA3_PHYS_ADDR          0x14002300
-#define        DMA4_PHYS_ADDR          0x14002400
-#define        DMA5_PHYS_ADDR          0x14002500
-#define        DMA6_PHYS_ADDR          0x14002600
-#define        DMA7_PHYS_ADDR          0x14002700
-#define        IC0_PHYS_ADDR           0x10400000
-#define SD0_PHYS_ADDR          0x10600000
-#define SD1_PHYS_ADDR          0x10680000
-#define        IC1_PHYS_ADDR           0x11800000
-#define        AC97_PHYS_ADDR          0x10000000
 #define        USBH_PHYS_ADDR          0x10100000
-#define        USBD_PHYS_ADDR          0x10200000
 #define        IRDA_PHYS_ADDR          0x10300000
-#define        MAC0_PHYS_ADDR          0x10500000
-#define        MACEN_PHYS_ADDR         0x10520000
-#define        MACDMA0_PHYS_ADDR       0x14004000
-#define        MACDMA1_PHYS_ADDR       0x14004200
-#define        I2S_PHYS_ADDR           0x11000000
-#define        UART0_PHYS_ADDR         0x11100000
-#define        UART1_PHYS_ADDR         0x11200000
-#define        UART3_PHYS_ADDR         0x11400000
 #define        SSI0_PHYS_ADDR          0x11600000
 #define        SSI1_PHYS_ADDR          0x11680000
-#define GPIO2_PHYS_ADDR                0x11700000
-#define        SYS_PHYS_ADDR           0x11900000
 #define LCD_PHYS_ADDR          0x15000000
 #define PCMCIA_IO_PHYS_ADDR    0xF00000000ULL
 #define PCMCIA_ATTR_PHYS_ADDR  0xF40000000ULL
@@ -749,22 +760,8 @@ enum soc_au1200_ints {
 #ifdef CONFIG_SOC_AU1550
 #define        MEM_PHYS_ADDR           0x14000000
 #define        STATIC_MEM_PHYS_ADDR    0x14001000
-#define        IC0_PHYS_ADDR           0x10400000
-#define        IC1_PHYS_ADDR           0x11800000
 #define        USBH_PHYS_ADDR          0x14020000
-#define        USBD_PHYS_ADDR          0x10200000
 #define PCI_PHYS_ADDR          0x14005000
-#define        MAC0_PHYS_ADDR          0x10500000
-#define        MAC1_PHYS_ADDR          0x10510000
-#define        MACEN_PHYS_ADDR         0x10520000
-#define        MACDMA0_PHYS_ADDR       0x14004000
-#define        MACDMA1_PHYS_ADDR       0x14004200
-#define        UART0_PHYS_ADDR         0x11100000
-#define        UART1_PHYS_ADDR         0x11200000
-#define        UART3_PHYS_ADDR         0x11400000
-#define GPIO2_PHYS_ADDR                0x11700000
-#define        SYS_PHYS_ADDR           0x11900000
-#define        DDMA_PHYS_ADDR          0x14002000
 #define PE_PHYS_ADDR           0x14008000
 #define PSC0_PHYS_ADDR         0x11A00000
 #define PSC1_PHYS_ADDR         0x11B00000
@@ -786,19 +783,10 @@ enum soc_au1200_ints {
 #define        STATIC_MEM_PHYS_ADDR    0x14001000
 #define AES_PHYS_ADDR          0x10300000
 #define CIM_PHYS_ADDR          0x14004000
-#define        IC0_PHYS_ADDR           0x10400000
-#define        IC1_PHYS_ADDR           0x11800000
 #define USBM_PHYS_ADDR         0x14020000
 #define        USBH_PHYS_ADDR          0x14020100
-#define        UART0_PHYS_ADDR         0x11100000
-#define        UART1_PHYS_ADDR         0x11200000
-#define GPIO2_PHYS_ADDR                0x11700000
-#define        SYS_PHYS_ADDR           0x11900000
-#define        DDMA_PHYS_ADDR          0x14002000
 #define PSC0_PHYS_ADDR         0x11A00000
 #define PSC1_PHYS_ADDR         0x11B00000
-#define SD0_PHYS_ADDR          0x10600000
-#define SD1_PHYS_ADDR          0x10680000
 #define LCD_PHYS_ADDR          0x15000000
 #define SWCNT_PHYS_ADDR                0x1110010C
 #define MAEFE_PHYS_ADDR                0x14012000
@@ -835,183 +823,43 @@ enum soc_au1200_ints {
 #endif
 
 
-/* Interrupt Controller register offsets */
-#define IC_CFG0RD              0x40
-#define IC_CFG0SET             0x40
-#define IC_CFG0CLR             0x44
-#define IC_CFG1RD              0x48
-#define IC_CFG1SET             0x48
-#define IC_CFG1CLR             0x4C
-#define IC_CFG2RD              0x50
-#define IC_CFG2SET             0x50
-#define IC_CFG2CLR             0x54
-#define IC_REQ0INT             0x54
-#define IC_SRCRD               0x58
-#define IC_SRCSET              0x58
-#define IC_SRCCLR              0x5C
-#define IC_REQ1INT             0x5C
-#define IC_ASSIGNRD            0x60
-#define IC_ASSIGNSET           0x60
-#define IC_ASSIGNCLR           0x64
-#define IC_WAKERD              0x68
-#define IC_WAKESET             0x68
-#define IC_WAKECLR             0x6C
-#define IC_MASKRD              0x70
-#define IC_MASKSET             0x70
-#define IC_MASKCLR             0x74
-#define IC_RISINGRD            0x78
-#define IC_RISINGCLR           0x78
-#define IC_FALLINGRD           0x7C
-#define IC_FALLINGCLR          0x7C
-#define IC_TESTBIT             0x80
-
-
-/* Interrupt Controller 0 */
-#define IC0_CFG0RD             0xB0400040
-#define IC0_CFG0SET            0xB0400040
-#define IC0_CFG0CLR            0xB0400044
-
-#define IC0_CFG1RD             0xB0400048
-#define IC0_CFG1SET            0xB0400048
-#define IC0_CFG1CLR            0xB040004C
-
-#define IC0_CFG2RD             0xB0400050
-#define IC0_CFG2SET            0xB0400050
-#define IC0_CFG2CLR            0xB0400054
-
-#define IC0_REQ0INT            0xB0400054
-#define IC0_SRCRD              0xB0400058
-#define IC0_SRCSET             0xB0400058
-#define IC0_SRCCLR             0xB040005C
-#define IC0_REQ1INT            0xB040005C
-
-#define IC0_ASSIGNRD           0xB0400060
-#define IC0_ASSIGNSET          0xB0400060
-#define IC0_ASSIGNCLR          0xB0400064
-
-#define IC0_WAKERD             0xB0400068
-#define IC0_WAKESET            0xB0400068
-#define IC0_WAKECLR            0xB040006C
-
-#define IC0_MASKRD             0xB0400070
-#define IC0_MASKSET            0xB0400070
-#define IC0_MASKCLR            0xB0400074
-
-#define IC0_RISINGRD           0xB0400078
-#define IC0_RISINGCLR          0xB0400078
-#define IC0_FALLINGRD          0xB040007C
-#define IC0_FALLINGCLR         0xB040007C
-
-#define IC0_TESTBIT            0xB0400080
-
-/* Interrupt Controller 1 */
-#define IC1_CFG0RD             0xB1800040
-#define IC1_CFG0SET            0xB1800040
-#define IC1_CFG0CLR            0xB1800044
-
-#define IC1_CFG1RD             0xB1800048
-#define IC1_CFG1SET            0xB1800048
-#define IC1_CFG1CLR            0xB180004C
-
-#define IC1_CFG2RD             0xB1800050
-#define IC1_CFG2SET            0xB1800050
-#define IC1_CFG2CLR            0xB1800054
-
-#define IC1_REQ0INT            0xB1800054
-#define IC1_SRCRD              0xB1800058
-#define IC1_SRCSET             0xB1800058
-#define IC1_SRCCLR             0xB180005C
-#define IC1_REQ1INT            0xB180005C
-
-#define IC1_ASSIGNRD            0xB1800060
-#define IC1_ASSIGNSET           0xB1800060
-#define IC1_ASSIGNCLR           0xB1800064
-
-#define IC1_WAKERD             0xB1800068
-#define IC1_WAKESET            0xB1800068
-#define IC1_WAKECLR            0xB180006C
-
-#define IC1_MASKRD             0xB1800070
-#define IC1_MASKSET            0xB1800070
-#define IC1_MASKCLR            0xB1800074
-
-#define IC1_RISINGRD           0xB1800078
-#define IC1_RISINGCLR          0xB1800078
-#define IC1_FALLINGRD          0xB180007C
-#define IC1_FALLINGCLR         0xB180007C
-
-#define IC1_TESTBIT            0xB1800080
 
 
 /* Au1000 */
 #ifdef CONFIG_SOC_AU1000
 
-#define UART0_ADDR             0xB1100000
-#define UART3_ADDR             0xB1400000
-
 #define USB_OHCI_BASE          0x10100000      /* phys addr for ioremap */
 #define USB_HOST_CONFIG        0xB017FFFC
 #define FOR_PLATFORM_C_USB_HOST_INT AU1000_USB_HOST_INT
-
-#define AU1000_ETH0_BASE       0xB0500000
-#define AU1000_ETH1_BASE       0xB0510000
-#define AU1000_MAC0_ENABLE     0xB0520000
-#define AU1000_MAC1_ENABLE     0xB0520004
-#define NUM_ETH_INTERFACES 2
 #endif /* CONFIG_SOC_AU1000 */
 
 /* Au1500 */
 #ifdef CONFIG_SOC_AU1500
 
-#define UART0_ADDR             0xB1100000
-#define UART3_ADDR             0xB1400000
-
 #define USB_OHCI_BASE          0x10100000      /* phys addr for ioremap */
 #define USB_HOST_CONFIG        0xB017fffc
 #define FOR_PLATFORM_C_USB_HOST_INT AU1500_USB_HOST_INT
-
-#define AU1500_ETH0_BASE       0xB1500000
-#define AU1500_ETH1_BASE       0xB1510000
-#define AU1500_MAC0_ENABLE     0xB1520000
-#define AU1500_MAC1_ENABLE     0xB1520004
-#define NUM_ETH_INTERFACES 2
 #endif /* CONFIG_SOC_AU1500 */
 
 /* Au1100 */
 #ifdef CONFIG_SOC_AU1100
 
-#define UART0_ADDR             0xB1100000
-#define UART3_ADDR             0xB1400000
-
 #define USB_OHCI_BASE          0x10100000      /* phys addr for ioremap */
 #define USB_HOST_CONFIG        0xB017FFFC
 #define FOR_PLATFORM_C_USB_HOST_INT AU1100_USB_HOST_INT
-
-#define AU1100_ETH0_BASE       0xB0500000
-#define AU1100_MAC0_ENABLE     0xB0520000
-#define NUM_ETH_INTERFACES 1
 #endif /* CONFIG_SOC_AU1100 */
 
 #ifdef CONFIG_SOC_AU1550
-#define UART0_ADDR             0xB1100000
 
 #define USB_OHCI_BASE          0x14020000      /* phys addr for ioremap */
 #define USB_OHCI_LEN           0x00060000
 #define USB_HOST_CONFIG        0xB4027ffc
 #define FOR_PLATFORM_C_USB_HOST_INT AU1550_USB_HOST_INT
-
-#define AU1550_ETH0_BASE       0xB0500000
-#define AU1550_ETH1_BASE       0xB0510000
-#define AU1550_MAC0_ENABLE     0xB0520000
-#define AU1550_MAC1_ENABLE     0xB0520004
-#define NUM_ETH_INTERFACES 2
 #endif /* CONFIG_SOC_AU1550 */
 
 
 #ifdef CONFIG_SOC_AU1200
 
-#define UART0_ADDR             0xB1100000
-
 #define USB_UOC_BASE           0x14020020
 #define USB_UOC_LEN            0x20
 #define USB_OHCI_BASE          0x14020100
@@ -1504,22 +1352,6 @@ enum soc_au1200_ints {
 #define SYS_PINFUNC_S1B        (1 << 2)
 #endif
 
-#define SYS_TRIOUTRD           0xB1900100
-#define SYS_TRIOUTCLR          0xB1900100
-#define SYS_OUTPUTRD           0xB1900108
-#define SYS_OUTPUTSET          0xB1900108
-#define SYS_OUTPUTCLR          0xB190010C
-#define SYS_PINSTATERD         0xB1900110
-#define SYS_PININPUTEN         0xB1900110
-
-/* GPIO2, Au1500, Au1550 only */
-#define GPIO2_BASE             0xB1700000
-#define GPIO2_DIR              (GPIO2_BASE + 0)
-#define GPIO2_OUTPUT           (GPIO2_BASE + 8)
-#define GPIO2_PINSTATE         (GPIO2_BASE + 0xC)
-#define GPIO2_INTENABLE        (GPIO2_BASE + 0x10)
-#define GPIO2_ENABLE           (GPIO2_BASE + 0x14)
-
 /* Power Management */
 #define SYS_SCRATCH0           0xB1900018
 #define SYS_SCRATCH1           0xB190001C
@@ -1635,12 +1467,6 @@ enum soc_au1200_ints {
 #  define AC97C_RS             (1 << 1)
 #  define AC97C_CE             (1 << 0)
 
-/* Secure Digital (SD) Controller */
-#define SD0_XMIT_FIFO  0xB0600000
-#define SD0_RECV_FIFO  0xB0600004
-#define SD1_XMIT_FIFO  0xB0680000
-#define SD1_RECV_FIFO  0xB0680004
-
 #if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
 /* Au1500 PCI Controller */
 #define Au1500_CFG_BASE        0xB4005000      /* virtual, KSEG1 addr */
index c333b4e1cd4472020ecebcd268db20605e887f75..59f5b55b22000baff7df5afb720c02ea0bc5d024 100644 (file)
 
 #define NUM_AU1000_DMA_CHANNELS        8
 
-/* DMA Channel Base Addresses */
-#define DMA_CHANNEL_BASE       0xB4002000
-#define DMA_CHANNEL_LEN                0x00000100
-
 /* DMA Channel Register Offsets */
 #define DMA_MODE_SET           0x00000000
 #define DMA_MODE_READ          DMA_MODE_SET
index c8a553a36ba421e1003018f13b1925e137b2011f..2fdacfe85e2357d1c53e295355ce5804c21efbb0 100644 (file)
 
 #ifndef _LANGUAGE_ASSEMBLY
 
-/*
- * The DMA base addresses.
- * The channels are every 256 bytes (0x0100) from the channel 0 base.
- * Interrupt status/enable is bits 15:0 for channels 15 to zero.
- */
-#define DDMA_GLOBAL_BASE       0xb4003000
-#define DDMA_CHANNEL_BASE      0xb4002000
-
 typedef volatile struct dbdma_global {
        u32     ddma_config;
        u32     ddma_intstat;
index 62d2f136d94115d1334ff726881b77fd6a6ae4fa..1f41a522906d072b24ee8e78aeb5dfdd3af668a8 100644 (file)
 
 #define MAKE_IRQ(intc, off)    (AU1000_INTC##intc##_INT_BASE + (off))
 
+/* GPIO1 registers within SYS_ area */
+#define SYS_TRIOUTRD           0x100
+#define SYS_TRIOUTCLR          0x100
+#define SYS_OUTPUTRD           0x108
+#define SYS_OUTPUTSET          0x108
+#define SYS_OUTPUTCLR          0x10C
+#define SYS_PINSTATERD         0x110
+#define SYS_PININPUTEN         0x110
+
+/* register offsets within GPIO2 block */
+#define GPIO2_DIR              0x00
+#define GPIO2_OUTPUT           0x08
+#define GPIO2_PINSTATE         0x0C
+#define GPIO2_INTENABLE                0x10
+#define GPIO2_ENABLE           0x14
+
+struct gpio;
 
 static inline int au1000_gpio1_to_irq(int gpio)
 {
@@ -200,23 +217,26 @@ static inline int au1200_irq_to_gpio(int irq)
  */
 static inline void alchemy_gpio1_set_value(int gpio, int v)
 {
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
        unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
-       au_writel(mask, r);
-       au_sync();
+       __raw_writel(mask, base + r);
+       wmb();
 }
 
 static inline int alchemy_gpio1_get_value(int gpio)
 {
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-       return au_readl(SYS_PINSTATERD) & mask;
+       return __raw_readl(base + SYS_PINSTATERD) & mask;
 }
 
 static inline int alchemy_gpio1_direction_input(int gpio)
 {
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-       au_writel(mask, SYS_TRIOUTCLR);
-       au_sync();
+       __raw_writel(mask, base + SYS_TRIOUTCLR);
+       wmb();
        return 0;
 }
 
@@ -257,27 +277,31 @@ static inline int alchemy_gpio1_to_irq(int gpio)
  */
 static inline void __alchemy_gpio2_mod_dir(int gpio, int to_out)
 {
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
-       unsigned long d = au_readl(GPIO2_DIR);
+       unsigned long d = __raw_readl(base + GPIO2_DIR);
+
        if (to_out)
                d |= mask;
        else
                d &= ~mask;
-       au_writel(d, GPIO2_DIR);
-       au_sync();
+       __raw_writel(d, base + GPIO2_DIR);
+       wmb();
 }
 
 static inline void alchemy_gpio2_set_value(int gpio, int v)
 {
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
        unsigned long mask;
        mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
-       au_writel(mask, GPIO2_OUTPUT);
-       au_sync();
+       __raw_writel(mask, base + GPIO2_OUTPUT);
+       wmb();
 }
 
 static inline int alchemy_gpio2_get_value(int gpio)
 {
-       return au_readl(GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
+       return __raw_readl(base + GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
 }
 
 static inline int alchemy_gpio2_direction_input(int gpio)
@@ -329,21 +353,23 @@ static inline int alchemy_gpio2_to_irq(int gpio)
  */
 static inline void alchemy_gpio1_input_enable(void)
 {
-       au_writel(0, SYS_PININPUTEN);   /* the write op is key */
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+       __raw_writel(0, base + SYS_PININPUTEN); /* the write op is key */
+       wmb();
 }
 
 /* GPIO2 shared interrupts and control */
 
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
 {
-       unsigned long r = au_readl(GPIO2_INTENABLE);
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
+       unsigned long r = __raw_readl(base + GPIO2_INTENABLE);
        if (en)
                r |= 1 << gpio2;
        else
                r &= ~(1 << gpio2);
-       au_writel(r, GPIO2_INTENABLE);
-       au_sync();
+       __raw_writel(r, base + GPIO2_INTENABLE);
+       wmb();
 }
 
 /**
@@ -418,10 +444,11 @@ static inline void alchemy_gpio2_disable_int(int gpio2)
  */
 static inline void alchemy_gpio2_enable(void)
 {
-       au_writel(3, GPIO2_ENABLE);     /* reset, clock enabled */
-       au_sync();
-       au_writel(1, GPIO2_ENABLE);     /* clock enabled */
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
+       __raw_writel(3, base + GPIO2_ENABLE);   /* reset, clock enabled */
+       wmb();
+       __raw_writel(1, base + GPIO2_ENABLE);   /* clock enabled */
+       wmb();
 }
 
 /**
@@ -431,8 +458,9 @@ static inline void alchemy_gpio2_enable(void)
  */
 static inline void alchemy_gpio2_disable(void)
 {
-       au_writel(2, GPIO2_ENABLE);     /* reset, clock disabled */
-       au_sync();
+       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
+       __raw_writel(2, base + GPIO2_ENABLE);   /* reset, clock disabled */
+       wmb();
 }
 
 /**********************************************************************/
@@ -556,6 +584,16 @@ static inline void gpio_set_value(int gpio, int v)
        alchemy_gpio_set_value(gpio, v);
 }
 
+static inline int gpio_get_value_cansleep(unsigned gpio)
+{
+       return gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+{
+       gpio_set_value(gpio, value);
+}
+
 static inline int gpio_is_valid(int gpio)
 {
        return alchemy_gpio_is_valid(gpio);
@@ -581,10 +619,50 @@ static inline int gpio_request(unsigned gpio, const char *label)
        return 0;
 }
 
+static inline int gpio_request_one(unsigned gpio,
+                                       unsigned long flags, const char *label)
+{
+       return 0;
+}
+
+static inline int gpio_request_array(struct gpio *array, size_t num)
+{
+       return 0;
+}
+
 static inline void gpio_free(unsigned gpio)
 {
 }
 
+static inline void gpio_free_array(struct gpio *array, size_t num)
+{
+}
+
+static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+{
+       return -ENOSYS;
+}
+
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+       return -ENOSYS;
+}
+
+static inline int gpio_export_link(struct device *dev, const char *name,
+                                  unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
+{
+       return -ENOSYS;
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+}
+
 #endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
 
 
index 9759588ba3cff0c81da6cd454148a6787e4babcf..184d5ecb5f51bbec1f7b0584adfe0e273a383a42 100644 (file)
@@ -39,8 +39,16 @@ extern int nvram_getenv(char *name, char *val, size_t val_len);
 
 static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
 {
-       sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1],
-              &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]);
+       if (strchr(buf, ':'))
+               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
+                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+                       &macaddr[5]);
+       else if (strchr(buf, '-'))
+               sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
+                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+                       &macaddr[5]);
+       else
+               printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
 }
 
 #endif
index 32978d32561a035810cf4e8e90fb6516510c99c0..ed72e6a26b736d2686f0fc68f7e297be5c805250 100644 (file)
@@ -88,7 +88,7 @@ struct bcm_tag {
        char kernel_crc[CRC_LEN];
        /* 228-235: Unused at present */
        char reserved1[8];
-       /* 236-239: CRC32 of header excluding tagVersion */
+       /* 236-239: CRC32 of header excluding last 20 bytes */
        char header_crc[CRC_LEN];
        /* 240-255: Unused at present */
        char reserved2[16];
index 0b2b5eb22e9b7a2d0781f9c67b3e3b00aa7c6cbe..dedef7d2b01f579f9081a536e7540c54c353e154 100644 (file)
        # CN30XX Disable instruction prefetching
        or  v0, v0, 0x2000
 skip:
+       # First clear off CvmCtl[IPPCI] bit and move the performance
+       # counters interrupt to IRQ 6
+       li      v1, ~(7 << 7)
+       and     v0, v0, v1
+       ori     v0, v0, (6 << 7)
        # Write the cavium control register
        dmtc0   v0, CP0_CVMCTL_REG
        sync
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
new file mode 100644 (file)
index 0000000..ce2f029
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+#ifndef _LANTIQ_H__
+#define _LANTIQ_H__
+
+#include <linux/irq.h>
+
+/* generic reg access functions */
+#define ltq_r32(reg)           __raw_readl(reg)
+#define ltq_w32(val, reg)      __raw_writel(val, reg)
+#define ltq_w32_mask(clear, set, reg)  \
+       ltq_w32((ltq_r32(reg) & ~(clear)) | (set), reg)
+#define ltq_r8(reg)            __raw_readb(reg)
+#define ltq_w8(val, reg)       __raw_writeb(val, reg)
+
+/* register access macros for EBU and CGU */
+#define ltq_ebu_w32(x, y)      ltq_w32((x), ltq_ebu_membase + (y))
+#define ltq_ebu_r32(x)         ltq_r32(ltq_ebu_membase + (x))
+#define ltq_cgu_w32(x, y)      ltq_w32((x), ltq_cgu_membase + (y))
+#define ltq_cgu_r32(x)         ltq_r32(ltq_cgu_membase + (x))
+
+extern __iomem void *ltq_ebu_membase;
+extern __iomem void *ltq_cgu_membase;
+
+extern unsigned int ltq_get_cpu_ver(void);
+extern unsigned int ltq_get_soc_type(void);
+
+/* clock speeds */
+#define CLOCK_60M      60000000
+#define CLOCK_83M      83333333
+#define CLOCK_111M     111111111
+#define CLOCK_133M     133333333
+#define CLOCK_167M     166666667
+#define CLOCK_200M     200000000
+#define CLOCK_266M     266666666
+#define CLOCK_333M     333333333
+#define CLOCK_400M     400000000
+
+/* spinlock all ebu i/o */
+extern spinlock_t ebu_lock;
+
+/* some irq helpers */
+extern void ltq_disable_irq(struct irq_data *data);
+extern void ltq_mask_and_ack_irq(struct irq_data *data);
+extern void ltq_enable_irq(struct irq_data *data);
+
+/* find out what caused the last cpu reset */
+extern int ltq_reset_cause(void);
+#define LTQ_RST_CAUSE_WDTRST   0x20
+
+#define IOPORT_RESOURCE_START  0x10000000
+#define IOPORT_RESOURCE_END    0xffffffff
+#define IOMEM_RESOURCE_START   0x10000000
+#define IOMEM_RESOURCE_END     0xffffffff
+#define LTQ_FLASH_START                0x10000000
+#define LTQ_FLASH_MAX          0x04000000
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
new file mode 100644 (file)
index 0000000..a305f1d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LANTIQ_PLATFORM_H__
+#define _LANTIQ_PLATFORM_H__
+
+#include <linux/mtd/partitions.h>
+#include <linux/socket.h>
+
+/* struct used to pass info to the pci core */
+enum {
+       PCI_CLOCK_INT = 0,
+       PCI_CLOCK_EXT
+};
+
+#define PCI_EXIN0      0x0001
+#define PCI_EXIN1      0x0002
+#define PCI_EXIN2      0x0004
+#define PCI_EXIN3      0x0008
+#define PCI_EXIN4      0x0010
+#define PCI_EXIN5      0x0020
+#define PCI_EXIN_MAX   6
+
+#define PCI_GNT1       0x0040
+#define PCI_GNT2       0x0080
+#define PCI_GNT3       0x0100
+#define PCI_GNT4       0x0200
+
+#define PCI_REQ1       0x0400
+#define PCI_REQ2       0x0800
+#define PCI_REQ3       0x1000
+#define PCI_REQ4       0x2000
+#define PCI_REQ_SHIFT  10
+#define PCI_REQ_MASK   0xf
+
+struct ltq_pci_data {
+       int clock;
+       int gpio;
+       int irq[16];
+};
+
+/* struct used to pass info to network drivers */
+struct ltq_eth_data {
+       struct sockaddr mac;
+       int mii_mode;
+};
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/war.h b/arch/mips/include/asm/mach-lantiq/war.h
new file mode 100644 (file)
index 0000000..01b08ef
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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_MIPS_MACH_LANTIQ_WAR_H
+#define __ASM_MIPS_MACH_LANTIQ_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR     0
+#define R4600_V1_HIT_CACHEOP_WAR        0
+#define R4600_V2_HIT_CACHEOP_WAR        0
+#define R5432_CP0_INTERRUPT_WAR         0
+#define BCM1250_M3_WAR                  0
+#define SIBYTE_1956_WAR                 0
+#define MIPS4K_ICACHE_REFILL_WAR        0
+#define MIPS_CACHE_SYNC_WAR             0
+#define TX49XX_ICACHE_INDEX_INV_WAR     0
+#define RM9000_CDEX_SMP_WAR             0
+#define ICACHE_REFILLS_WORKAROUND_WAR   0
+#define R10000_LLSC_WAR                 0
+#define MIPS34K_MISSED_ITLB_WAR         0
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/xway/irq.h b/arch/mips/include/asm/mach-lantiq/xway/irq.h
new file mode 100644 (file)
index 0000000..a1471d2
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef __LANTIQ_IRQ_H
+#define __LANTIQ_IRQ_H
+
+#include <lantiq_irq.h>
+
+#define NR_IRQS 256
+
+#include_next <irq.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
new file mode 100644 (file)
index 0000000..b4465a8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LANTIQ_XWAY_IRQ_H__
+#define _LANTIQ_XWAY_IRQ_H__
+
+#define INT_NUM_IRQ0           8
+#define INT_NUM_IM0_IRL0       (INT_NUM_IRQ0 + 0)
+#define INT_NUM_IM1_IRL0       (INT_NUM_IRQ0 + 32)
+#define INT_NUM_IM2_IRL0       (INT_NUM_IRQ0 + 64)
+#define INT_NUM_IM3_IRL0       (INT_NUM_IRQ0 + 96)
+#define INT_NUM_IM4_IRL0       (INT_NUM_IRQ0 + 128)
+#define INT_NUM_IM_OFFSET      (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
+
+#define LTQ_ASC_TIR(x)         (INT_NUM_IM3_IRL0 + (x * 8))
+#define LTQ_ASC_RIR(x)         (INT_NUM_IM3_IRL0 + (x * 8) + 1)
+#define LTQ_ASC_EIR(x)         (INT_NUM_IM3_IRL0 + (x * 8) + 2)
+
+#define LTQ_ASC_ASE_TIR                INT_NUM_IM2_IRL0
+#define LTQ_ASC_ASE_RIR                (INT_NUM_IM2_IRL0 + 2)
+#define LTQ_ASC_ASE_EIR                (INT_NUM_IM2_IRL0 + 3)
+
+#define LTQ_SSC_TIR            (INT_NUM_IM0_IRL0 + 15)
+#define LTQ_SSC_RIR            (INT_NUM_IM0_IRL0 + 14)
+#define LTQ_SSC_EIR            (INT_NUM_IM0_IRL0 + 16)
+
+#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
+#define LTQ_MEI_INT            (INT_NUM_IM1_IRL0 + 23)
+
+#define LTQ_TIMER6_INT         (INT_NUM_IM1_IRL0 + 23)
+#define LTQ_USB_INT            (INT_NUM_IM1_IRL0 + 22)
+#define LTQ_USB_OC_INT         (INT_NUM_IM4_IRL0 + 23)
+
+#define MIPS_CPU_TIMER_IRQ             7
+
+#define LTQ_DMA_CH0_INT                (INT_NUM_IM2_IRL0)
+#define LTQ_DMA_CH1_INT                (INT_NUM_IM2_IRL0 + 1)
+#define LTQ_DMA_CH2_INT                (INT_NUM_IM2_IRL0 + 2)
+#define LTQ_DMA_CH3_INT                (INT_NUM_IM2_IRL0 + 3)
+#define LTQ_DMA_CH4_INT                (INT_NUM_IM2_IRL0 + 4)
+#define LTQ_DMA_CH5_INT                (INT_NUM_IM2_IRL0 + 5)
+#define LTQ_DMA_CH6_INT                (INT_NUM_IM2_IRL0 + 6)
+#define LTQ_DMA_CH7_INT                (INT_NUM_IM2_IRL0 + 7)
+#define LTQ_DMA_CH8_INT                (INT_NUM_IM2_IRL0 + 8)
+#define LTQ_DMA_CH9_INT                (INT_NUM_IM2_IRL0 + 9)
+#define LTQ_DMA_CH10_INT       (INT_NUM_IM2_IRL0 + 10)
+#define LTQ_DMA_CH11_INT       (INT_NUM_IM2_IRL0 + 11)
+#define LTQ_DMA_CH12_INT       (INT_NUM_IM2_IRL0 + 25)
+#define LTQ_DMA_CH13_INT       (INT_NUM_IM2_IRL0 + 26)
+#define LTQ_DMA_CH14_INT       (INT_NUM_IM2_IRL0 + 27)
+#define LTQ_DMA_CH15_INT       (INT_NUM_IM2_IRL0 + 28)
+#define LTQ_DMA_CH16_INT       (INT_NUM_IM2_IRL0 + 29)
+#define LTQ_DMA_CH17_INT       (INT_NUM_IM2_IRL0 + 30)
+#define LTQ_DMA_CH18_INT       (INT_NUM_IM2_IRL0 + 16)
+#define LTQ_DMA_CH19_INT       (INT_NUM_IM2_IRL0 + 21)
+
+#define LTQ_PPE_MBOX_INT       (INT_NUM_IM2_IRL0 + 24)
+
+#define INT_NUM_IM4_IRL14      (INT_NUM_IM4_IRL0 + 14)
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
new file mode 100644 (file)
index 0000000..8a3c6be
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_XWAY_H__
+#define _LTQ_XWAY_H__
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+
+#include <lantiq.h>
+
+/* Chip IDs */
+#define SOC_ID_DANUBE1         0x129
+#define SOC_ID_DANUBE2         0x12B
+#define SOC_ID_TWINPASS                0x12D
+#define SOC_ID_AMAZON_SE       0x152
+#define SOC_ID_ARX188          0x16C
+#define SOC_ID_ARX168          0x16D
+#define SOC_ID_ARX182          0x16F
+
+/* SoC Types */
+#define SOC_TYPE_DANUBE                0x01
+#define SOC_TYPE_TWINPASS      0x02
+#define SOC_TYPE_AR9           0x03
+#define SOC_TYPE_VR9           0x04
+#define SOC_TYPE_AMAZON_SE     0x05
+
+/* ASC0/1 - serial port */
+#define LTQ_ASC0_BASE_ADDR     0x1E100400
+#define LTQ_ASC1_BASE_ADDR     0x1E100C00
+#define LTQ_ASC_SIZE           0x400
+
+/* RCU - reset control unit */
+#define LTQ_RCU_BASE_ADDR      0x1F203000
+#define LTQ_RCU_SIZE           0x1000
+
+/* GPTU - general purpose timer unit */
+#define LTQ_GPTU_BASE_ADDR     0x18000300
+#define LTQ_GPTU_SIZE          0x100
+
+/* EBU - external bus unit */
+#define LTQ_EBU_GPIO_START     0x14000000
+#define LTQ_EBU_GPIO_SIZE      0x1000
+
+#define LTQ_EBU_BASE_ADDR      0x1E105300
+#define LTQ_EBU_SIZE           0x100
+
+#define LTQ_EBU_BUSCON0                0x0060
+#define LTQ_EBU_PCC_CON                0x0090
+#define LTQ_EBU_PCC_IEN                0x00A4
+#define LTQ_EBU_PCC_ISTAT      0x00A0
+#define LTQ_EBU_BUSCON1                0x0064
+#define LTQ_EBU_ADDRSEL1       0x0024
+#define EBU_WRDIS              0x80000000
+
+/* CGU - clock generation unit */
+#define LTQ_CGU_BASE_ADDR      0x1F103000
+#define LTQ_CGU_SIZE           0x1000
+
+/* ICU - interrupt control unit */
+#define LTQ_ICU_BASE_ADDR      0x1F880200
+#define LTQ_ICU_SIZE           0x100
+
+/* EIU - external interrupt unit */
+#define LTQ_EIU_BASE_ADDR      0x1F101000
+#define LTQ_EIU_SIZE           0x1000
+
+/* PMU - power management unit */
+#define LTQ_PMU_BASE_ADDR      0x1F102000
+#define LTQ_PMU_SIZE           0x1000
+
+#define PMU_DMA                        0x0020
+#define PMU_USB                        0x8041
+#define PMU_LED                        0x0800
+#define PMU_GPT                        0x1000
+#define PMU_PPE                        0x2000
+#define PMU_FPI                        0x4000
+#define PMU_SWITCH             0x10000000
+
+/* ETOP - ethernet */
+#define LTQ_ETOP_BASE_ADDR     0x1E180000
+#define LTQ_ETOP_SIZE          0x40000
+
+/* DMA */
+#define LTQ_DMA_BASE_ADDR      0x1E104100
+#define LTQ_DMA_SIZE           0x800
+
+/* PCI */
+#define PCI_CR_BASE_ADDR       0x1E105400
+#define PCI_CR_SIZE            0x400
+
+/* WDT */
+#define LTQ_WDT_BASE_ADDR      0x1F8803F0
+#define LTQ_WDT_SIZE           0x10
+
+/* STP - serial to parallel conversion unit */
+#define LTQ_STP_BASE_ADDR      0x1E100BB0
+#define LTQ_STP_SIZE           0x40
+
+/* GPIO */
+#define LTQ_GPIO0_BASE_ADDR    0x1E100B10
+#define LTQ_GPIO1_BASE_ADDR    0x1E100B40
+#define LTQ_GPIO2_BASE_ADDR    0x1E100B70
+#define LTQ_GPIO_SIZE          0x30
+
+/* SSC */
+#define LTQ_SSC_BASE_ADDR      0x1e100800
+#define LTQ_SSC_SIZE           0x100
+
+/* MEI - dsl core */
+#define LTQ_MEI_BASE_ADDR      0x1E116000
+
+/* DEU - data encryption unit */
+#define LTQ_DEU_BASE_ADDR      0x1E103100
+
+/* MPS - multi processor unit (voice) */
+#define LTQ_MPS_BASE_ADDR      (KSEG1 + 0x1F107000)
+#define LTQ_MPS_CHIPID         ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
+
+/* request a non-gpio and set the PIO config */
+extern int  ltq_gpio_request(unsigned int pin, unsigned int alt0,
+       unsigned int alt1, unsigned int dir, const char *name);
+extern void ltq_pmu_enable(unsigned int module);
+extern void ltq_pmu_disable(unsigned int module);
+
+static inline int ltq_is_ar9(void)
+{
+       return (ltq_get_soc_type() == SOC_TYPE_AR9);
+}
+
+static inline int ltq_is_vr9(void)
+{
+       return (ltq_get_soc_type() == SOC_TYPE_VR9);
+}
+
+#endif /* CONFIG_SOC_TYPE_XWAY */
+#endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
new file mode 100644 (file)
index 0000000..872943a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License version 2 as published
+ *   by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef LTQ_DMA_H__
+#define LTQ_DMA_H__
+
+#define LTQ_DESC_SIZE          0x08    /* each descriptor is 64bit */
+#define LTQ_DESC_NUM           0x40    /* 64 descriptors / channel */
+
+#define LTQ_DMA_OWN            BIT(31) /* owner bit */
+#define LTQ_DMA_C              BIT(30) /* complete bit */
+#define LTQ_DMA_SOP            BIT(29) /* start of packet */
+#define LTQ_DMA_EOP            BIT(28) /* end of packet */
+#define LTQ_DMA_TX_OFFSET(x)   ((x & 0x1f) << 23) /* data bytes offset */
+#define LTQ_DMA_RX_OFFSET(x)   ((x & 0x7) << 23) /* data bytes offset */
+#define LTQ_DMA_SIZE_MASK      (0xffff) /* the size field is 16 bit */
+
+struct ltq_dma_desc {
+       u32 ctl;
+       u32 addr;
+};
+
+struct ltq_dma_channel {
+       int nr;                         /* the channel number */
+       int irq;                        /* the mapped irq */
+       int desc;                       /* the current descriptor */
+       struct ltq_dma_desc *desc_base; /* the descriptor base */
+       int phys;                       /* physical addr */
+};
+
+enum {
+       DMA_PORT_ETOP = 0,
+       DMA_PORT_DEU,
+};
+
+extern void ltq_dma_enable_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_disable_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_ack_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_open(struct ltq_dma_channel *ch);
+extern void ltq_dma_close(struct ltq_dma_channel *ch);
+extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
+extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
+extern void ltq_dma_free(struct ltq_dma_channel *ch);
+extern void ltq_dma_init_port(int p);
+
+#endif
diff --git a/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h b/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..3b72827
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Netlogic Microsystems
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_NETLOGIC_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_NETLOGIC_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_4kex           1
+#define cpu_has_4k_cache       1
+#define cpu_has_watch          1
+#define cpu_has_mips16         0
+#define cpu_has_counter                1
+#define cpu_has_divec          1
+#define cpu_has_vce            0
+#define cpu_has_cache_cdex_p   0
+#define cpu_has_cache_cdex_s   0
+#define cpu_has_prefetch       1
+#define cpu_has_mcheck         1
+#define cpu_has_ejtag          1
+
+#define cpu_has_llsc           1
+#define cpu_has_vtag_icache    0
+#define cpu_has_dc_aliases     0
+#define cpu_has_ic_fills_f_dc  0
+#define cpu_has_dsp            0
+#define cpu_has_mipsmt         0
+#define cpu_has_userlocal      0
+#define cpu_icache_snoops_remote_store 0
+
+#define cpu_has_nofpuex                0
+#define cpu_has_64bits         1
+
+#define cpu_has_mips32r1       1
+#define cpu_has_mips32r2       0
+#define cpu_has_mips64r1       1
+#define cpu_has_mips64r2       0
+
+#define cpu_has_inclusive_pcaches      0
+
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+
+#endif /* __ASM_MACH_NETLOGIC_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-netlogic/irq.h b/arch/mips/include/asm/mach-netlogic/irq.h
new file mode 100644 (file)
index 0000000..b590245
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Netlogic Microsystems.
+ */
+#ifndef __ASM_NETLOGIC_IRQ_H
+#define __ASM_NETLOGIC_IRQ_H
+
+#define NR_IRQS                        64
+#define MIPS_CPU_IRQ_BASE      0
+
+#endif /* __ASM_NETLOGIC_IRQ_H */
diff --git a/arch/mips/include/asm/mach-netlogic/war.h b/arch/mips/include/asm/mach-netlogic/war.h
new file mode 100644 (file)
index 0000000..22da893
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Netlogic Microsystems.
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_NLM_WAR_H
+#define __ASM_MIPS_MACH_NLM_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR    0
+#define R4600_V1_HIT_CACHEOP_WAR       0
+#define R4600_V2_HIT_CACHEOP_WAR       0
+#define R5432_CP0_INTERRUPT_WAR                0
+#define BCM1250_M3_WAR                 0
+#define SIBYTE_1956_WAR                        0
+#define MIPS4K_ICACHE_REFILL_WAR       0
+#define MIPS_CACHE_SYNC_WAR            0
+#define TX49XX_ICACHE_INDEX_INV_WAR    0
+#define RM9000_CDEX_SMP_WAR            0
+#define ICACHE_REFILLS_WORKAROUND_WAR  0
+#define R10000_LLSC_WAR                        0
+#define MIPS34K_MISSED_ITLB_WAR                0
+
+#endif /* __ASM_MIPS_MACH_NLM_WAR_H */
index d94085a3eafbb20577f2205fe388f30f90a01928..bc01a02cacd8fd95ee3ab50378ae64aee3c701bb 100644 (file)
@@ -118,6 +118,8 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "LOONGSON2 "
 #elif defined CONFIG_CPU_CAVIUM_OCTEON
 #define MODULE_PROC_FAMILY "OCTEON "
+#elif defined CONFIG_CPU_XLR
+#define MODULE_PROC_FAMILY "XLR "
 #else
 #error MODULE_PROC_FAMILY undefined for your processor configuration
 #endif
diff --git a/arch/mips/include/asm/netlogic/interrupt.h b/arch/mips/include/asm/netlogic/interrupt.h
new file mode 100644 (file)
index 0000000..a85aadb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_INTERRUPT_H
+#define _ASM_NLM_INTERRUPT_H
+
+/* Defines for the IRQ numbers */
+
+#define IRQ_IPI_SMP_FUNCTION   3
+#define IRQ_IPI_SMP_RESCHEDULE 4
+#define IRQ_MSGRING            6
+#define IRQ_TIMER              7
+
+#endif
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
new file mode 100644 (file)
index 0000000..8c53d0b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_MIPS_EXTS_H
+#define _ASM_NLM_MIPS_EXTS_H
+
+/*
+ * XLR and XLP interrupt request and interrupt mask registers
+ */
+#define read_c0_eirr()         __read_64bit_c0_register($9, 6)
+#define read_c0_eimr()         __read_64bit_c0_register($9, 7)
+#define write_c0_eirr(val)     __write_64bit_c0_register($9, 6, val)
+
+/*
+ * Writing EIMR in 32 bit is a special case, the lower 8 bit of the
+ * EIMR is shadowed in the status register, so we cannot save and
+ * restore status register for split read.
+ */
+#define write_c0_eimr(val)                                             \
+do {                                                                   \
+       if (sizeof(unsigned long) == 4) {                               \
+               unsigned long __flags;                                  \
+                                                                       \
+               local_irq_save(__flags);                                \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dsll\t%L0, %L0, 32\n\t"                        \
+                       "dsrl\t%L0, %L0, 32\n\t"                        \
+                       "dsll\t%M0, %M0, 32\n\t"                        \
+                       "or\t%L0, %L0, %M0\n\t"                         \
+                       "dmtc0\t%L0, $9, 7\n\t"                         \
+                       ".set\tmips0"                                   \
+                       : : "r" (val));                                 \
+               __flags = (__flags & 0xffff00ff) | (((val) & 0xff) << 8);\
+               local_irq_restore(__flags);                             \
+       } else                                                          \
+               __write_64bit_c0_register($9, 7, (val));                \
+} while (0)
+
+static inline int hard_smp_processor_id(void)
+{
+       return __read_32bit_c0_register($15, 1) & 0x3ff;
+}
+
+#endif /*_ASM_NLM_MIPS_EXTS_H */
diff --git a/arch/mips/include/asm/netlogic/psb-bootinfo.h b/arch/mips/include/asm/netlogic/psb-bootinfo.h
new file mode 100644 (file)
index 0000000..6878307
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NETLOGIC_BOOTINFO_H
+#define _ASM_NETLOGIC_BOOTINFO_H
+
+struct psb_info {
+       uint64_t boot_level;
+       uint64_t io_base;
+       uint64_t output_device;
+       uint64_t uart_print;
+       uint64_t led_output;
+       uint64_t init;
+       uint64_t exit;
+       uint64_t warm_reset;
+       uint64_t wakeup;
+       uint64_t online_cpu_map;
+       uint64_t master_reentry_sp;
+       uint64_t master_reentry_gp;
+       uint64_t master_reentry_fn;
+       uint64_t slave_reentry_fn;
+       uint64_t magic_dword;
+       uint64_t uart_putchar;
+       uint64_t size;
+       uint64_t uart_getchar;
+       uint64_t nmi_handler;
+       uint64_t psb_version;
+       uint64_t mac_addr;
+       uint64_t cpu_frequency;
+       uint64_t board_version;
+       uint64_t malloc;
+       uint64_t free;
+       uint64_t global_shmem_addr;
+       uint64_t global_shmem_size;
+       uint64_t psb_os_cpu_map;
+       uint64_t userapp_cpu_map;
+       uint64_t wakeup_os;
+       uint64_t psb_mem_map;
+       uint64_t board_major_version;
+       uint64_t board_minor_version;
+       uint64_t board_manf_revision;
+       uint64_t board_serial_number;
+       uint64_t psb_physaddr_map;
+       uint64_t xlr_loaderip_config;
+       uint64_t bldr_envp;
+       uint64_t avail_mem_map;
+};
+
+enum {
+       NETLOGIC_IO_SPACE = 0x10,
+       PCIX_IO_SPACE,
+       PCIX_CFG_SPACE,
+       PCIX_MEMORY_SPACE,
+       HT_IO_SPACE,
+       HT_CFG_SPACE,
+       HT_MEMORY_SPACE,
+       SRAM_SPACE,
+       FLASH_CONTROLLER_SPACE
+};
+
+#define NLM_MAX_ARGS   64
+#define NLM_MAX_ENVS   32
+
+/* This is what netlboot passes and linux boot_mem_map is subtly different */
+#define NLM_BOOT_MEM_MAP_MAX   32
+struct nlm_boot_mem_map {
+       int nr_map;
+       struct nlm_boot_mem_map_entry {
+               uint64_t addr;          /* start of memory segment */
+               uint64_t size;          /* size of memory segment */
+               uint32_t type;          /* type of memory segment */
+       } map[NLM_BOOT_MEM_MAP_MAX];
+};
+
+/* Pointer to saved boot loader info */
+extern struct psb_info nlm_prom_info;
+
+#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/gpio.h b/arch/mips/include/asm/netlogic/xlr/gpio.h
new file mode 100644 (file)
index 0000000..51f6ad4
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_GPIO_H
+#define _ASM_NLM_GPIO_H
+
+#define NETLOGIC_GPIO_INT_EN_REG               0
+#define NETLOGIC_GPIO_INPUT_INVERSION_REG      1
+#define NETLOGIC_GPIO_IO_DIR_REG               2
+#define NETLOGIC_GPIO_IO_DATA_WR_REG           3
+#define NETLOGIC_GPIO_IO_DATA_RD_REG           4
+
+#define NETLOGIC_GPIO_SWRESET_REG              8
+#define NETLOGIC_GPIO_DRAM1_CNTRL_REG          9
+#define NETLOGIC_GPIO_DRAM1_RATIO_REG          10
+#define NETLOGIC_GPIO_DRAM1_RESET_REG          11
+#define NETLOGIC_GPIO_DRAM1_STATUS_REG         12
+#define NETLOGIC_GPIO_DRAM2_CNTRL_REG          13
+#define NETLOGIC_GPIO_DRAM2_RATIO_REG          14
+#define NETLOGIC_GPIO_DRAM2_RESET_REG          15
+#define NETLOGIC_GPIO_DRAM2_STATUS_REG         16
+
+#define NETLOGIC_GPIO_PWRON_RESET_CFG_REG      21
+#define NETLOGIC_GPIO_BIST_ALL_GO_STATUS_REG   24
+#define NETLOGIC_GPIO_BIST_CPU_GO_STATUS_REG   25
+#define NETLOGIC_GPIO_BIST_DEV_GO_STATUS_REG   26
+
+#define NETLOGIC_GPIO_FUSE_BANK_REG            35
+#define NETLOGIC_GPIO_CPU_RESET_REG            40
+#define NETLOGIC_GPIO_RNG_REG                  43
+
+#define NETLOGIC_PWRON_RESET_PCMCIA_BOOT       17
+#define NETLOGIC_GPIO_LED_BITMAP       0x1700000
+#define NETLOGIC_GPIO_LED_0_SHIFT              20
+#define NETLOGIC_GPIO_LED_1_SHIFT              24
+
+#define NETLOGIC_GPIO_LED_OUTPUT_CODE_RESET    0x01
+#define NETLOGIC_GPIO_LED_OUTPUT_CODE_HARD_RESET 0x02
+#define NETLOGIC_GPIO_LED_OUTPUT_CODE_SOFT_RESET 0x03
+#define NETLOGIC_GPIO_LED_OUTPUT_CODE_MAIN     0x04
+
+#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/iomap.h b/arch/mips/include/asm/netlogic/xlr/iomap.h
new file mode 100644 (file)
index 0000000..2e3a4dd
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_IOMAP_H
+#define _ASM_NLM_IOMAP_H
+
+#define DEFAULT_NETLOGIC_IO_BASE           CKSEG1ADDR(0x1ef00000)
+#define NETLOGIC_IO_DDR2_CHN0_OFFSET       0x01000
+#define NETLOGIC_IO_DDR2_CHN1_OFFSET       0x02000
+#define NETLOGIC_IO_DDR2_CHN2_OFFSET       0x03000
+#define NETLOGIC_IO_DDR2_CHN3_OFFSET       0x04000
+#define NETLOGIC_IO_PIC_OFFSET             0x08000
+#define NETLOGIC_IO_UART_0_OFFSET          0x14000
+#define NETLOGIC_IO_UART_1_OFFSET          0x15100
+
+#define NETLOGIC_IO_SIZE                   0x1000
+
+#define NETLOGIC_IO_BRIDGE_OFFSET          0x00000
+
+#define NETLOGIC_IO_RLD2_CHN0_OFFSET       0x05000
+#define NETLOGIC_IO_RLD2_CHN1_OFFSET       0x06000
+
+#define NETLOGIC_IO_SRAM_OFFSET            0x07000
+
+#define NETLOGIC_IO_PCIX_OFFSET            0x09000
+#define NETLOGIC_IO_HT_OFFSET              0x0A000
+
+#define NETLOGIC_IO_SECURITY_OFFSET        0x0B000
+
+#define NETLOGIC_IO_GMAC_0_OFFSET          0x0C000
+#define NETLOGIC_IO_GMAC_1_OFFSET          0x0D000
+#define NETLOGIC_IO_GMAC_2_OFFSET          0x0E000
+#define NETLOGIC_IO_GMAC_3_OFFSET          0x0F000
+
+/* XLS devices */
+#define NETLOGIC_IO_GMAC_4_OFFSET          0x20000
+#define NETLOGIC_IO_GMAC_5_OFFSET          0x21000
+#define NETLOGIC_IO_GMAC_6_OFFSET          0x22000
+#define NETLOGIC_IO_GMAC_7_OFFSET          0x23000
+
+#define NETLOGIC_IO_PCIE_0_OFFSET          0x1E000
+#define NETLOGIC_IO_PCIE_1_OFFSET          0x1F000
+#define NETLOGIC_IO_SRIO_0_OFFSET          0x1E000
+#define NETLOGIC_IO_SRIO_1_OFFSET          0x1F000
+
+#define NETLOGIC_IO_USB_0_OFFSET           0x24000
+#define NETLOGIC_IO_USB_1_OFFSET           0x25000
+
+#define NETLOGIC_IO_COMP_OFFSET            0x1D000
+/* end XLS devices */
+
+/* XLR devices */
+#define NETLOGIC_IO_SPI4_0_OFFSET          0x10000
+#define NETLOGIC_IO_XGMAC_0_OFFSET         0x11000
+#define NETLOGIC_IO_SPI4_1_OFFSET          0x12000
+#define NETLOGIC_IO_XGMAC_1_OFFSET         0x13000
+/* end XLR devices */
+
+#define NETLOGIC_IO_I2C_0_OFFSET           0x16000
+#define NETLOGIC_IO_I2C_1_OFFSET           0x17000
+
+#define NETLOGIC_IO_GPIO_OFFSET            0x18000
+#define NETLOGIC_IO_FLASH_OFFSET           0x19000
+#define NETLOGIC_IO_TB_OFFSET              0x1C000
+
+#define NETLOGIC_CPLD_OFFSET               KSEG1ADDR(0x1d840000)
+
+/*
+ * Base Address (Virtual) of the PCI Config address space
+ * For now, choose 256M phys in kseg1 = 0xA0000000 + (1<<28)
+ * Config space spans 256 (num of buses) * 256 (num functions) * 256 bytes
+ * ie 1<<24 = 16M
+ */
+#define DEFAULT_PCI_CONFIG_BASE         0x18000000
+#define DEFAULT_HT_TYPE0_CFG_BASE       0x16000000
+#define DEFAULT_HT_TYPE1_CFG_BASE       0x17000000
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+typedef volatile __u32 nlm_reg_t;
+extern unsigned long netlogic_io_base;
+
+/* FIXME read once in write_reg */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define netlogic_read_reg(base, offset)                ((base)[(offset)])
+#define netlogic_write_reg(base, offset, value)        ((base)[(offset)] = (value))
+#else
+#define netlogic_read_reg(base, offset)                (be32_to_cpu((base)[(offset)]))
+#define netlogic_write_reg(base, offset, value) \
+                               ((base)[(offset)] = cpu_to_be32((value)))
+#endif
+
+#define netlogic_read_reg_le32(base, offset) (le32_to_cpu((base)[(offset)]))
+#define netlogic_write_reg_le32(base, offset, value) \
+                               ((base)[(offset)] = cpu_to_le32((value)))
+#define netlogic_io_mmio(offset) ((nlm_reg_t *)(netlogic_io_base+(offset)))
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h
new file mode 100644 (file)
index 0000000..5cceb74
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_XLR_PIC_H
+#define _ASM_NLM_XLR_PIC_H
+
+#define PIC_CLKS_PER_SEC               66666666ULL
+/* PIC hardware interrupt numbers */
+#define PIC_IRT_WD_INDEX               0
+#define PIC_IRT_TIMER_0_INDEX          1
+#define PIC_IRT_TIMER_1_INDEX          2
+#define PIC_IRT_TIMER_2_INDEX          3
+#define PIC_IRT_TIMER_3_INDEX          4
+#define PIC_IRT_TIMER_4_INDEX          5
+#define PIC_IRT_TIMER_5_INDEX          6
+#define PIC_IRT_TIMER_6_INDEX          7
+#define PIC_IRT_TIMER_7_INDEX          8
+#define PIC_IRT_CLOCK_INDEX            PIC_IRT_TIMER_7_INDEX
+#define PIC_IRT_UART_0_INDEX           9
+#define PIC_IRT_UART_1_INDEX           10
+#define PIC_IRT_I2C_0_INDEX            11
+#define PIC_IRT_I2C_1_INDEX            12
+#define PIC_IRT_PCMCIA_INDEX           13
+#define PIC_IRT_GPIO_INDEX             14
+#define PIC_IRT_HYPER_INDEX            15
+#define PIC_IRT_PCIX_INDEX             16
+/* XLS */
+#define PIC_IRT_CDE_INDEX              15
+#define PIC_IRT_BRIDGE_TB_XLS_INDEX    16
+/* XLS */
+#define PIC_IRT_GMAC0_INDEX            17
+#define PIC_IRT_GMAC1_INDEX            18
+#define PIC_IRT_GMAC2_INDEX            19
+#define PIC_IRT_GMAC3_INDEX            20
+#define PIC_IRT_XGS0_INDEX             21
+#define PIC_IRT_XGS1_INDEX             22
+#define PIC_IRT_HYPER_FATAL_INDEX      23
+#define PIC_IRT_PCIX_FATAL_INDEX       24
+#define PIC_IRT_BRIDGE_AERR_INDEX      25
+#define PIC_IRT_BRIDGE_BERR_INDEX      26
+#define PIC_IRT_BRIDGE_TB_XLR_INDEX    27
+#define PIC_IRT_BRIDGE_AERR_NMI_INDEX  28
+/* XLS */
+#define PIC_IRT_GMAC4_INDEX            21
+#define PIC_IRT_GMAC5_INDEX            22
+#define PIC_IRT_GMAC6_INDEX            23
+#define PIC_IRT_GMAC7_INDEX            24
+#define PIC_IRT_BRIDGE_ERR_INDEX       25
+#define PIC_IRT_PCIE_LINK0_INDEX       26
+#define PIC_IRT_PCIE_LINK1_INDEX       27
+#define PIC_IRT_PCIE_LINK2_INDEX       23
+#define PIC_IRT_PCIE_LINK3_INDEX       24
+#define PIC_IRT_PCIE_XLSB0_LINK2_INDEX 28
+#define PIC_IRT_PCIE_XLSB0_LINK3_INDEX 29
+#define PIC_IRT_SRIO_LINK0_INDEX       26
+#define PIC_IRT_SRIO_LINK1_INDEX       27
+#define PIC_IRT_SRIO_LINK2_INDEX       28
+#define PIC_IRT_SRIO_LINK3_INDEX       29
+#define PIC_IRT_PCIE_INT_INDEX         28
+#define PIC_IRT_PCIE_FATAL_INDEX       29
+#define PIC_IRT_GPIO_B_INDEX           30
+#define PIC_IRT_USB_INDEX              31
+/* XLS */
+#define PIC_NUM_IRTS                   32
+
+
+#define PIC_CLOCK_TIMER                        7
+
+/* PIC Registers */
+#define PIC_CTRL                       0x00
+#define PIC_IPI                                0x04
+#define PIC_INT_ACK                    0x06
+
+#define WD_MAX_VAL_0                   0x08
+#define WD_MAX_VAL_1                   0x09
+#define WD_MASK_0                      0x0a
+#define WD_MASK_1                      0x0b
+#define WD_HEARBEAT_0                  0x0c
+#define WD_HEARBEAT_1                  0x0d
+
+#define PIC_IRT_0_BASE                 0x40
+#define PIC_IRT_1_BASE                 0x80
+#define PIC_TIMER_MAXVAL_0_BASE                0x100
+#define PIC_TIMER_MAXVAL_1_BASE                0x110
+#define PIC_TIMER_COUNT_0_BASE         0x120
+#define PIC_TIMER_COUNT_1_BASE         0x130
+
+#define PIC_IRT_0(picintr)      (PIC_IRT_0_BASE + (picintr))
+#define PIC_IRT_1(picintr)     (PIC_IRT_1_BASE + (picintr))
+
+#define PIC_TIMER_MAXVAL_0(i)  (PIC_TIMER_MAXVAL_0_BASE + (i))
+#define PIC_TIMER_MAXVAL_1(i)  (PIC_TIMER_MAXVAL_1_BASE + (i))
+#define PIC_TIMER_COUNT_0(i)   (PIC_TIMER_COUNT_0_BASE + (i))
+#define PIC_TIMER_COUNT_1(i)   (PIC_TIMER_COUNT_0_BASE + (i))
+
+/*
+ * Mapping between hardware interrupt numbers and IRQs on CPU
+ * we use a simple scheme to map PIC interrupts 0-31 to IRQs
+ * 8-39. This leaves the IRQ 0-7 for cpu interrupts like
+ * count/compare and FMN
+ */
+#define PIC_IRQ_BASE            8
+#define PIC_INTR_TO_IRQ(i)      (PIC_IRQ_BASE + (i))
+#define PIC_IRQ_TO_INTR(i)      ((i) - PIC_IRQ_BASE)
+
+#define PIC_IRT_FIRST_IRQ      PIC_IRQ_BASE
+#define PIC_WD_IRQ             PIC_INTR_TO_IRQ(PIC_IRT_WD_INDEX)
+#define PIC_TIMER_0_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_0_INDEX)
+#define PIC_TIMER_1_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_1_INDEX)
+#define PIC_TIMER_2_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_2_INDEX)
+#define PIC_TIMER_3_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_3_INDEX)
+#define PIC_TIMER_4_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_4_INDEX)
+#define PIC_TIMER_5_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_5_INDEX)
+#define PIC_TIMER_6_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_6_INDEX)
+#define PIC_TIMER_7_IRQ                PIC_INTR_TO_IRQ(PIC_IRT_TIMER_7_INDEX)
+#define PIC_CLOCK_IRQ          (PIC_TIMER_7_IRQ)
+#define PIC_UART_0_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_UART_0_INDEX)
+#define PIC_UART_1_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_UART_1_INDEX)
+#define PIC_I2C_0_IRQ          PIC_INTR_TO_IRQ(PIC_IRT_I2C_0_INDEX)
+#define PIC_I2C_1_IRQ          PIC_INTR_TO_IRQ(PIC_IRT_I2C_1_INDEX)
+#define PIC_PCMCIA_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_PCMCIA_INDEX)
+#define PIC_GPIO_IRQ           PIC_INTR_TO_IRQ(PIC_IRT_GPIO_INDEX)
+#define PIC_HYPER_IRQ          PIC_INTR_TO_IRQ(PIC_IRT_HYPER_INDEX)
+#define PIC_PCIX_IRQ           PIC_INTR_TO_IRQ(PIC_IRT_PCIX_INDEX)
+/* XLS */
+#define PIC_CDE_IRQ            PIC_INTR_TO_IRQ(PIC_IRT_CDE_INDEX)
+#define PIC_BRIDGE_TB_XLS_IRQ  PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_TB_XLS_INDEX)
+/* end XLS */
+#define PIC_GMAC_0_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC0_INDEX)
+#define PIC_GMAC_1_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC1_INDEX)
+#define PIC_GMAC_2_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC2_INDEX)
+#define PIC_GMAC_3_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC3_INDEX)
+#define PIC_XGS_0_IRQ          PIC_INTR_TO_IRQ(PIC_IRT_XGS0_INDEX)
+#define PIC_XGS_1_IRQ          PIC_INTR_TO_IRQ(PIC_IRT_XGS1_INDEX)
+#define PIC_HYPER_FATAL_IRQ    PIC_INTR_TO_IRQ(PIC_IRT_HYPER_FATAL_INDEX)
+#define PIC_PCIX_FATAL_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIX_FATAL_INDEX)
+#define PIC_BRIDGE_AERR_IRQ    PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_AERR_INDEX)
+#define PIC_BRIDGE_BERR_IRQ    PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_BERR_INDEX)
+#define PIC_BRIDGE_TB_XLR_IRQ  PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_TB_XLR_INDEX)
+#define PIC_BRIDGE_AERR_NMI_IRQ        PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_AERR_NMI_INDEX)
+/* XLS defines */
+#define PIC_GMAC_4_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC4_INDEX)
+#define PIC_GMAC_5_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC5_INDEX)
+#define PIC_GMAC_6_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC6_INDEX)
+#define PIC_GMAC_7_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GMAC7_INDEX)
+#define PIC_BRIDGE_ERR_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_BRIDGE_ERR_INDEX)
+#define PIC_PCIE_LINK0_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIE_LINK0_INDEX)
+#define PIC_PCIE_LINK1_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIE_LINK1_INDEX)
+#define PIC_PCIE_LINK2_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIE_LINK2_INDEX)
+#define PIC_PCIE_LINK3_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIE_LINK3_INDEX)
+#define PIC_PCIE_XLSB0_LINK2_IRQ PIC_INTR_TO_IRQ(PIC_IRT_PCIE_XLSB0_LINK2_INDEX)
+#define PIC_PCIE_XLSB0_LINK3_IRQ PIC_INTR_TO_IRQ(PIC_IRT_PCIE_XLSB0_LINK3_INDEX)
+#define PIC_SRIO_LINK0_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_SRIO_LINK0_INDEX)
+#define PIC_SRIO_LINK1_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_SRIO_LINK1_INDEX)
+#define PIC_SRIO_LINK2_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_SRIO_LINK2_INDEX)
+#define PIC_SRIO_LINK3_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_SRIO_LINK3_INDEX)
+#define PIC_PCIE_INT_IRQ       PIC_INTR_TO_IRQ(PIC_IRT_PCIE_INT__INDEX)
+#define PIC_PCIE_FATAL_IRQ     PIC_INTR_TO_IRQ(PIC_IRT_PCIE_FATAL_INDEX)
+#define PIC_GPIO_B_IRQ         PIC_INTR_TO_IRQ(PIC_IRT_GPIO_B_INDEX)
+#define PIC_USB_IRQ            PIC_INTR_TO_IRQ(PIC_IRT_USB_INDEX)
+#define PIC_IRT_LAST_IRQ       PIC_USB_IRQ
+/* end XLS */
+
+#ifndef __ASSEMBLY__
+static inline void pic_send_ipi(u32 ipi)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+
+       netlogic_write_reg(mmio, PIC_IPI, ipi);
+}
+
+static inline u32 pic_read_control(void)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+
+       return netlogic_read_reg(mmio, PIC_CTRL);
+}
+
+static inline void pic_write_control(u32 control)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+
+       netlogic_write_reg(mmio, PIC_CTRL, control);
+}
+
+static inline void pic_update_control(u32 control)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+
+       netlogic_write_reg(mmio, PIC_CTRL,
+               (control | netlogic_read_reg(mmio, PIC_CTRL)));
+}
+
+#define PIC_IRQ_IS_EDGE_TRIGGERED(irq) (((irq) >= PIC_TIMER_0_IRQ) && \
+                                       ((irq) <= PIC_TIMER_7_IRQ))
+#define PIC_IRQ_IS_IRT(irq)            (((irq) >= PIC_IRT_FIRST_IRQ) && \
+                                       ((irq) <= PIC_IRT_LAST_IRQ))
+#endif
+
+#endif /* _ASM_NLM_XLR_PIC_H */
diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h
new file mode 100644 (file)
index 0000000..3e63726
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_NLM_XLR_H
+#define _ASM_NLM_XLR_H
+
+/* Platform UART functions */
+struct uart_port;
+unsigned int nlm_xlr_uart_in(struct uart_port *, int);
+void nlm_xlr_uart_out(struct uart_port *, int, int);
+
+/* SMP support functions */
+struct irq_desc;
+void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
+void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
+int nlm_wakeup_secondary_cpus(u32 wakeup_mask);
+void nlm_smp_irq_init(void);
+void nlm_boot_smp_nmi(void);
+void prom_pre_boot_secondary_cpus(void);
+
+extern struct plat_smp_ops nlm_smp_ops;
+extern unsigned long nlm_common_ebase;
+
+/* XLS B silicon "Rook" */
+static inline unsigned int nlm_chip_is_xls_b(void)
+{
+       uint32_t prid = read_c0_prid();
+
+       return ((prid & 0xf000) == 0x4000);
+}
+
+/*
+ *  XLR chip types
+ */
+ /* The XLS product line has chip versions 0x[48c]? */
+static inline unsigned int nlm_chip_is_xls(void)
+{
+       uint32_t prid = read_c0_prid();
+
+       return ((prid & 0xf000) == 0x8000 || (prid & 0xf000) == 0x4000 ||
+               (prid & 0xf000) == 0xc000);
+}
+
+#endif /* _ASM_NLM_XLR_H */
index 9f1b8dba2c81aa1b7dea3d5269ddcea4bb33692b..de39b1f343ea2537b459eed56f53ea9b35732554 100644 (file)
@@ -141,7 +141,8 @@ extern int ptrace_set_watch_regs(struct task_struct *child,
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
+extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
+extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
 
 extern NORET_TYPE void die(const char *, struct pt_regs *) ATTRIB_NORET;
 
index d71160de4d10f19fc73e54d0a0a18dd442ecb44f..97f8bf6639e7b6f15620e552e05fe7cd1f26d7f7 100644 (file)
@@ -149,6 +149,9 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_FPUBOUND          (1<<TIF_FPUBOUND)
 #define _TIF_LOAD_WATCH                (1<<TIF_LOAD_WATCH)
 
+/* work to do in syscall_trace_leave() */
+#define _TIF_WORK_SYSCALL_EXIT (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
+
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         (0x0000ffef &                           \
                                        ~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT))
index c7f1bfef157411e4faca94fce62e7af62512cc36..bc14447e69b5999c01db66f9506e3c0e9d7ac8f1 100644 (file)
@@ -84,12 +84,6 @@ static inline int init_mips_clocksource(void)
 #endif
 }
 
-static inline void clocksource_set_clock(struct clocksource *cs,
-                                        unsigned int clock)
-{
-       clocksource_calc_mult_shift(cs, clock, 4);
-}
-
 static inline void clockevent_set_clock(struct clock_event_device *cd,
                                        unsigned int clock)
 {
index 9ce9f64cb76fa8fce272100f00373694e8f6d4f7..2d8e447cb8281577ea2d7b01064c62f649f1d58c 100644 (file)
@@ -211,7 +211,7 @@ EXPORT_SYMBOL(vdma_free);
  */
 int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
 {
-       int first, pages, npages;
+       int first, pages;
 
        if (laddr > 0xffffff) {
                if (vdma_debug)
@@ -228,8 +228,7 @@ int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
                return -EINVAL; /* invalid physical address */
        }
 
-       npages = pages =
-           (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
+       pages = (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
        first = laddr >> 12;
        if (vdma_debug)
                printk("vdma_remap: first=%x, pages=%x\n", first, pages);
index 5ebe75a68350a186e5d5b1a9965ac5a757092b3d..d7feb898692c5cf6c1997bcaab742d29e9a91bb2 100644 (file)
@@ -242,9 +242,7 @@ EXPORT_SYMBOL_GPL(jz4740_dma_get_residue);
 
 static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma)
 {
-       uint32_t status;
-
-       status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
+       (void) jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
 
        jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
                JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
index 6a9e14dab91eb88d68f7b25dc6565af47449e40e..d97cfbf882f5fdf16f7cd7ed3bb1f16b0cbe117c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  Copyright (C) 2011, Maarten ter Huurne <maarten@treewalker.org>
  *  JZ4740 setup code
  *
  *  This program is free software; you can redistribute it and/or modify it
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 
+#include <asm/bootinfo.h>
+
+#include <asm/mach-jz4740/base.h>
+
 #include "reset.h"
 
+
+#define JZ4740_EMC_SDRAM_CTRL 0x80
+
+
+static void __init jz4740_detect_mem(void)
+{
+       void __iomem *jz_emc_base;
+       u32 ctrl, bus, bank, rows, cols;
+       phys_t size;
+
+       jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100);
+       ctrl = readl(jz_emc_base + JZ4740_EMC_SDRAM_CTRL);
+       bus = 2 - ((ctrl >> 31) & 1);
+       bank = 1 + ((ctrl >> 19) & 1);
+       cols = 8 + ((ctrl >> 26) & 7);
+       rows = 11 + ((ctrl >> 20) & 3);
+       printk(KERN_DEBUG
+               "SDRAM preconfigured: bus:%u bank:%u rows:%u cols:%u\n",
+               bus, bank, rows, cols);
+       iounmap(jz_emc_base);
+
+       size = 1 << (bus + bank + cols + rows);
+       add_memory_region(0, size, BOOT_MEM_RAM);
+}
+
 void __init plat_mem_setup(void)
 {
        jz4740_reset_init();
+       jz4740_detect_mem();
 }
 
 const char *get_system_type(void)
index fe01678d94fd4c439cd2353e3b74f57da6efebaf..f83c2dd07a2732ab61972d353546bdbad137b307 100644 (file)
@@ -89,7 +89,7 @@ static int jz4740_clockevent_set_next(unsigned long evt,
 
 static struct clock_event_device jz4740_clockevent = {
        .name = "jz4740-timer",
-       .features = CLOCK_EVT_FEAT_PERIODIC,
+       .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_next_event = jz4740_clockevent_set_next,
        .set_mode = jz4740_clockevent_set_mode,
        .rating = 200,
@@ -121,8 +121,7 @@ void __init plat_time_init(void)
 
        clockevents_register_device(&jz4740_clockevent);
 
-       clocksource_set_clock(&jz4740_clocksource, clk_rate);
-       ret = clocksource_register(&jz4740_clocksource);
+       ret = clocksource_register_hz(&jz4740_clocksource, clk_rate);
 
        if (ret)
                printk(KERN_ERR "Failed to register clocksource: %d\n", ret);
index b2c01512905587fb775869396aeb5719b14a94a9..654d5c3900b66282a06c0a0a6a02383a957c3a72 100644 (file)
@@ -27,11 +27,13 @@ void jz4740_timer_enable_watchdog(void)
 {
        writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
 }
+EXPORT_SYMBOL_GPL(jz4740_timer_enable_watchdog);
 
 void jz4740_timer_disable_watchdog(void)
 {
        writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
 }
+EXPORT_SYMBOL_GPL(jz4740_timer_disable_watchdog);
 
 void __init jz4740_timer_init(void)
 {
index cedee2bcbd182c8eab8ad59aadfc0d02e1fdb79d..83bba332bbfc17d78d372555ab2c251a9e6d3732 100644 (file)
@@ -52,6 +52,7 @@ obj-$(CONFIG_CPU_TX39XX)      += r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)       += r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_VR41XX)       += r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += octeon_switch.o
+obj-$(CONFIG_CPU_XLR)          += r4k_fpu.o r4k_switch.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_SMP_UP)           += smp-up.o
index 0b7377361e22fa8b3d76afc335344c35613cac59..f0ab92a1b0573b49637f648b9e36c91adf14ae48 100644 (file)
@@ -51,8 +51,7 @@ void __init txx9_clocksource_init(unsigned long baseaddr,
 {
        struct txx9_tmr_reg __iomem *tmrptr;
 
-       clocksource_set_clock(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
-       clocksource_register(&txx9_clocksource.cs);
+       clocksource_register_hz(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
 
        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
        __raw_writel(TCR_BASE, &tmrptr->tcr);
index f65d4c8c65a6a19ec4be040091861444a8ea78a3..bb133d10b14566470ca8cd9bfb823126198076fc 100644 (file)
@@ -291,6 +291,12 @@ static inline int cpu_has_confreg(void)
 #endif
 }
 
+static inline void set_elf_platform(int cpu, const char *plat)
+{
+       if (cpu == 0)
+               __elf_platform = plat;
+}
+
 /*
  * Get the FPU Implementation/Revision.
  */
@@ -614,6 +620,16 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
        case PRID_IMP_LOONGSON2:
                c->cputype = CPU_LOONGSON2;
                __cpu_name[cpu] = "ICT Loongson-2";
+
+               switch (c->processor_id & PRID_REV_MASK) {
+               case PRID_REV_LOONGSON2E:
+                       set_elf_platform(cpu, "loongson2e");
+                       break;
+               case PRID_REV_LOONGSON2F:
+                       set_elf_platform(cpu, "loongson2f");
+                       break;
+               }
+
                c->isa_level = MIPS_CPU_ISA_III;
                c->options = R4K_OPTS |
                             MIPS_CPU_FPU | MIPS_CPU_LLSC |
@@ -911,12 +927,14 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
        case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
                __cpu_name[cpu] = "Broadcom BMIPS32";
+               set_elf_platform(cpu, "bmips32");
                break;
        case PRID_IMP_BMIPS3300:
        case PRID_IMP_BMIPS3300_ALT:
        case PRID_IMP_BMIPS3300_BUG:
                c->cputype = CPU_BMIPS3300;
                __cpu_name[cpu] = "Broadcom BMIPS3300";
+               set_elf_platform(cpu, "bmips3300");
                break;
        case PRID_IMP_BMIPS43XX: {
                int rev = c->processor_id & 0xff;
@@ -925,15 +943,18 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                                rev <= PRID_REV_BMIPS4380_HI) {
                        c->cputype = CPU_BMIPS4380;
                        __cpu_name[cpu] = "Broadcom BMIPS4380";
+                       set_elf_platform(cpu, "bmips4380");
                } else {
                        c->cputype = CPU_BMIPS4350;
                        __cpu_name[cpu] = "Broadcom BMIPS4350";
+                       set_elf_platform(cpu, "bmips4350");
                }
                break;
        }
        case PRID_IMP_BMIPS5000:
                c->cputype = CPU_BMIPS5000;
                __cpu_name[cpu] = "Broadcom BMIPS5000";
+               set_elf_platform(cpu, "bmips5000");
                c->options |= MIPS_CPU_ULRI;
                break;
        }
@@ -956,14 +977,12 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_CAVIUM_OCTEON_PLUS;
                __cpu_name[cpu] = "Cavium Octeon+";
 platform:
-               if (cpu == 0)
-                       __elf_platform = "octeon";
+               set_elf_platform(cpu, "octeon");
                break;
        case PRID_IMP_CAVIUM_CN63XX:
                c->cputype = CPU_CAVIUM_OCTEON2;
                __cpu_name[cpu] = "Cavium Octeon II";
-               if (cpu == 0)
-                       __elf_platform = "octeon2";
+               set_elf_platform(cpu, "octeon2");
                break;
        default:
                printk(KERN_INFO "Unknown Octeon chip!\n");
@@ -988,6 +1007,59 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
        }
 }
 
+static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
+{
+       decode_configs(c);
+
+       c->options = (MIPS_CPU_TLB       |
+                       MIPS_CPU_4KEX    |
+                       MIPS_CPU_COUNTER |
+                       MIPS_CPU_DIVEC   |
+                       MIPS_CPU_WATCH   |
+                       MIPS_CPU_EJTAG   |
+                       MIPS_CPU_LLSC);
+
+       switch (c->processor_id & 0xff00) {
+       case PRID_IMP_NETLOGIC_XLR732:
+       case PRID_IMP_NETLOGIC_XLR716:
+       case PRID_IMP_NETLOGIC_XLR532:
+       case PRID_IMP_NETLOGIC_XLR308:
+       case PRID_IMP_NETLOGIC_XLR532C:
+       case PRID_IMP_NETLOGIC_XLR516C:
+       case PRID_IMP_NETLOGIC_XLR508C:
+       case PRID_IMP_NETLOGIC_XLR308C:
+               c->cputype = CPU_XLR;
+               __cpu_name[cpu] = "Netlogic XLR";
+               break;
+
+       case PRID_IMP_NETLOGIC_XLS608:
+       case PRID_IMP_NETLOGIC_XLS408:
+       case PRID_IMP_NETLOGIC_XLS404:
+       case PRID_IMP_NETLOGIC_XLS208:
+       case PRID_IMP_NETLOGIC_XLS204:
+       case PRID_IMP_NETLOGIC_XLS108:
+       case PRID_IMP_NETLOGIC_XLS104:
+       case PRID_IMP_NETLOGIC_XLS616B:
+       case PRID_IMP_NETLOGIC_XLS608B:
+       case PRID_IMP_NETLOGIC_XLS416B:
+       case PRID_IMP_NETLOGIC_XLS412B:
+       case PRID_IMP_NETLOGIC_XLS408B:
+       case PRID_IMP_NETLOGIC_XLS404B:
+               c->cputype = CPU_XLR;
+               __cpu_name[cpu] = "Netlogic XLS";
+               break;
+
+       default:
+               printk(KERN_INFO "Unknown Netlogic chip id [%02x]!\n",
+                      c->processor_id);
+               c->cputype = CPU_XLR;
+               break;
+       }
+
+       c->isa_level = MIPS_CPU_ISA_M64R1;
+       c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1;
+}
+
 #ifdef CONFIG_64BIT
 /* For use by uaccess.h */
 u64 __ua_limit;
@@ -1035,6 +1107,9 @@ __cpuinit void cpu_probe(void)
        case PRID_COMP_INGENIC:
                cpu_probe_ingenic(c, cpu);
                break;
+       case PRID_COMP_NETLOGIC:
+               cpu_probe_netlogic(c, cpu);
+               break;
        }
 
        BUG_ON(!__cpu_name[cpu]);
index 51489f8a825e3c90c43f9040eb38bd621f1f3f90..f96f99c794a32add278e8b41d4cd4ead3796c336 100644 (file)
@@ -49,6 +49,5 @@ void __init sb1480_clocksource_init(void)
 
        plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
        zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000);
-       clocksource_set_clock(cs, zbbus);
-       clocksource_register(cs);
+       clocksource_register_hz(cs, zbbus);
 }
index 23da108506b0a325a8c0c4f8de12d744129d2676..46bd7fa98d6ca6efba607d3134e80a2d97b61f30 100644 (file)
@@ -59,7 +59,5 @@ void __init dec_ioasic_clocksource_init(void)
        printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
 
        clocksource_dec.rating = 200 + freq / 10000000;
-       clocksource_set_clock(&clocksource_dec, freq);
-
-       clocksource_register(&clocksource_dec);
+       clocksource_register_hz(&clocksource_dec, freq);
 }
index a27c16c8690e3c3583ebe42df8a570cd50e17b5c..2e7c5232da8d72c09c399bacaf3ad45e2eaa726e 100644 (file)
@@ -78,9 +78,7 @@ static void __init powertv_c0_hpt_clocksource_init(void)
 
        clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
 
-       clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
-
-       clocksource_register(&clocksource_mips);
+       clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
 }
 
 /**
@@ -130,43 +128,16 @@ static struct clocksource clocksource_tim_c = {
 /**
  * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
  *
- * The hard part here is coming up with a constant k and shift s such that
- * the 48-bit TIM_C value multiplied by k doesn't overflow and that value,
- * when shifted right by s, yields the corresponding number of nanoseconds.
  * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
- * 1 / (27,000,000/8) seconds. Multiply that by a billion and you get the
- * number of nanoseconds. Since the TIM_C value has 48 bits and the math is
- * done in 64 bits, avoiding an overflow means that k must be less than
- * 64 - 48 = 16 bits.
+ * 1 / (27,000,000/8) seconds.
  */
 static void __init powertv_tim_c_clocksource_init(void)
 {
-       int                     prescale;
-       unsigned long           dividend;
-       unsigned long           k;
-       int                     s;
-       const int               max_k_bits = (64 - 48) - 1;
-       const unsigned long     billion = 1000000000;
        const unsigned long     counts_per_second = 27000000 / 8;
 
-       prescale = BITS_PER_LONG - ilog2(billion) - 1;
-       dividend = billion << prescale;
-       k = dividend / counts_per_second;
-       s = ilog2(k) - max_k_bits;
-
-       if (s < 0)
-               s = prescale;
-
-       else {
-               k >>= s;
-               s += prescale;
-       }
-
-       clocksource_tim_c.mult = k;
-       clocksource_tim_c.shift = s;
        clocksource_tim_c.rating = 200;
 
-       clocksource_register(&clocksource_tim_c);
+       clocksource_register_hz(&clocksource_tim_c, counts_per_second);
        tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
 }
 
index e95a3cd48eeacac0c03f22b8e8ac2fcf2e3a7f52..decd1fa38d551bf132f9bba4aa2a48400e129ac8 100644 (file)
@@ -30,9 +30,7 @@ int __init init_r4k_clocksource(void)
        /* Calculate a somewhat reasonable rating value */
        clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
 
-       clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
-
-       clocksource_register(&clocksource_mips);
+       clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
 
        return 0;
 }
index d14d3d1907fa6c8103cc1e398a24542905200359..e9606d9076858f74f78a0180d8c9edc6a2410249 100644 (file)
@@ -65,6 +65,5 @@ void __init sb1250_clocksource_init(void)
                     IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
                                                 R_SCD_TIMER_CFG)));
 
-       clocksource_set_clock(cs, V_SCD_TIMER_FREQ);
-       clocksource_register(cs);
+       clocksource_register_hz(cs, V_SCD_TIMER_FREQ);
 }
index ffa331029e086ce3720dc1ac9d60b936d68dba0a..37acfa036d441421dfe979aebdb0ba2a37655d92 100644 (file)
@@ -167,14 +167,13 @@ work_notifysig:                           # deal with pending signals and
 FEXPORT(syscall_exit_work_partial)
        SAVE_STATIC
 syscall_exit_work:
-       li      t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+       li      t0, _TIF_WORK_SYSCALL_EXIT
        and     t0, a2                  # a2 is preloaded with TI_FLAGS
        beqz    t0, work_pending        # trace bit set?
-       local_irq_enable                # could let do_syscall_trace()
+       local_irq_enable                # could let syscall_trace_leave()
                                        # call schedule() instead
        move    a0, sp
-       li      a1, 1
-       jal     do_syscall_trace
+       jal     syscall_trace_leave
        b       resume_userspace
 
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
index 94ca2b018af70ff3191d4e44055311efc09e800d..feb8021a305f49a4e6f366183e27626316398ed3 100644 (file)
@@ -23,6 +23,7 @@
 
 #define JAL 0x0c000000         /* jump & link: ip --> ra, jump to target */
 #define ADDR_MASK 0x03ffffff   /*  op_code|addr : 31...26|25 ....0 */
+#define JUMP_RANGE_MASK ((1UL << 28) - 1)
 
 #define INSN_NOP 0x00000000    /* nop */
 #define INSN_JAL(addr) \
@@ -44,12 +45,12 @@ static inline void ftrace_dyn_arch_init_insns(void)
 
        /* jal (ftrace_caller + 8), jump over the first two instruction */
        buf = (u32 *)&insn_jal_ftrace_caller;
-       uasm_i_jal(&buf, (FTRACE_ADDR + 8));
+       uasm_i_jal(&buf, (FTRACE_ADDR + 8) & JUMP_RANGE_MASK);
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        /* j ftrace_graph_caller */
        buf = (u32 *)&insn_j_ftrace_graph_caller;
-       uasm_i_j(&buf, (unsigned long)ftrace_graph_caller);
+       uasm_i_j(&buf, (unsigned long)ftrace_graph_caller & JUMP_RANGE_MASK);
 #endif
 }
 
index 2392a7a296d41d4585fc406948ed58d4f83443f9..391221b6a6aaf4d6d8b523f61a7b6f48faf0ea5e 100644 (file)
@@ -125,87 +125,11 @@ void __init setup_pit_timer(void)
        setup_irq(0, &irq0);
 }
 
-/*
- * Since the PIT overflows every tick, its not very useful
- * to just read by itself. So use jiffies to emulate a free
- * running counter:
- */
-static cycle_t pit_read(struct clocksource *cs)
-{
-       unsigned long flags;
-       int count;
-       u32 jifs;
-       static int old_count;
-       static u32 old_jifs;
-
-       raw_spin_lock_irqsave(&i8253_lock, flags);
-       /*
-        * Although our caller may have the read side of xtime_lock,
-        * this is now a seqlock, and we are cheating in this routine
-        * by having side effects on state that we cannot undo if
-        * there is a collision on the seqlock and our caller has to
-        * retry.  (Namely, old_jifs and old_count.)  So we must treat
-        * jiffies as volatile despite the lock.  We read jiffies
-        * before latching the timer count to guarantee that although
-        * the jiffies value might be older than the count (that is,
-        * the counter may underflow between the last point where
-        * jiffies was incremented and the point where we latch the
-        * count), it cannot be newer.
-        */
-       jifs = jiffies;
-       outb_p(0x00, PIT_MODE); /* latch the count ASAP */
-       count = inb_p(PIT_CH0); /* read the latched count */
-       count |= inb_p(PIT_CH0) << 8;
-
-       /* VIA686a test code... reset the latch if count > max + 1 */
-       if (count > LATCH) {
-               outb_p(0x34, PIT_MODE);
-               outb_p(LATCH & 0xff, PIT_CH0);
-               outb(LATCH >> 8, PIT_CH0);
-               count = LATCH - 1;
-       }
-
-       /*
-        * It's possible for count to appear to go the wrong way for a
-        * couple of reasons:
-        *
-        *  1. The timer counter underflows, but we haven't handled the
-        *     resulting interrupt and incremented jiffies yet.
-        *  2. Hardware problem with the timer, not giving us continuous time,
-        *     the counter does small "jumps" upwards on some Pentium systems,
-        *     (see c't 95/10 page 335 for Neptun bug.)
-        *
-        * Previous attempts to handle these cases intelligently were
-        * buggy, so we just do the simple thing now.
-        */
-       if (count > old_count && jifs == old_jifs) {
-               count = old_count;
-       }
-       old_count = count;
-       old_jifs = jifs;
-
-       raw_spin_unlock_irqrestore(&i8253_lock, flags);
-
-       count = (LATCH - 1) - count;
-
-       return (cycle_t)(jifs * LATCH) + count;
-}
-
-static struct clocksource clocksource_pit = {
-       .name   = "pit",
-       .rating = 110,
-       .read   = pit_read,
-       .mask   = CLOCKSOURCE_MASK(32),
-       .mult   = 0,
-       .shift  = 20,
-};
-
 static int __init init_pit_clocksource(void)
 {
        if (num_possible_cpus() > 1) /* PIT does not scale! */
                return 0;
 
-       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
-       return clocksource_register(&clocksource_pit);
+       return clocksource_i8253_init();
 }
 arch_initcall(init_pit_clocksource);
index d21c388c0116f06abfee3ebef3d9764245d818ed..4e6ea1ffad46617b3e1c0880c4061371f7aa5885 100644 (file)
@@ -533,15 +533,10 @@ static inline int audit_arch(void)
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
-asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
+asmlinkage void syscall_trace_enter(struct pt_regs *regs)
 {
        /* do the secure computing check first */
-       if (!entryexit)
-               secure_computing(regs->regs[2]);
-
-       if (unlikely(current->audit_context) && entryexit)
-               audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
-                                  regs->regs[2]);
+       secure_computing(regs->regs[2]);
 
        if (!(current->ptrace & PT_PTRACED))
                goto out;
@@ -565,8 +560,40 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
        }
 
 out:
-       if (unlikely(current->audit_context) && !entryexit)
+       if (unlikely(current->audit_context))
                audit_syscall_entry(audit_arch(), regs->regs[2],
                                    regs->regs[4], regs->regs[5],
                                    regs->regs[6], regs->regs[7]);
 }
+
+/*
+ * Notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+asmlinkage void syscall_trace_leave(struct pt_regs *regs)
+{
+       if (unlikely(current->audit_context))
+               audit_syscall_exit(AUDITSC_RESULT(regs->regs[7]),
+                                  -regs->regs[2]);
+
+       if (!(current->ptrace & PT_PTRACED))
+               return;
+
+       if (!test_thread_flag(TIF_SYSCALL_TRACE))
+               return;
+
+       /* The 0x80 provides a way for the tracing parent to distinguish
+          between a syscall stop and SIGTRAP delivery */
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
+                                0x80 : 0));
+
+       /*
+        * this isn't the same as continuing with a signal, but it will do
+        * for normal use.  strace only continues with a signal if the
+        * stopping signal is not SIGTRAP.  -brl
+        */
+       if (current->exit_code) {
+               send_sig(current->exit_code, current, 1);
+               current->exit_code = 0;
+       }
+}
index 7f5468b38d4cb08e3b1b6abf7bce6b8733003b41..7a8e1dd7f6f2188af20aaf4bfff978bf4a39f59d 100644 (file)
@@ -88,8 +88,7 @@ syscall_trace_entry:
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       li      a1, 0
-       jal     do_syscall_trace
+       jal     syscall_trace_enter
 
        move    t0, s0
        RESTORE_STATIC
@@ -565,7 +564,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_ioprio_get          2       /* 4315 */
        sys     sys_utimensat           4
        sys     sys_signalfd            3
-       sys     sys_ni_syscall          0
+       sys     sys_ni_syscall          0       /* was timerfd */
        sys     sys_eventfd             1
        sys     sys_fallocate           6       /* 4320 */
        sys     sys_timerfd_create      2
index a2e1fcbc41dce87add7a456301548fb1f38aaba6..2d31c83224f988fc240a8b9ba6a7fcbd68750740 100644 (file)
@@ -91,8 +91,7 @@ syscall_trace_entry:
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       li      a1, 0
-       jal     do_syscall_trace
+       jal     syscall_trace_enter
 
        move    t0, s0
        RESTORE_STATIC
@@ -404,7 +403,7 @@ sys_call_table:
        PTR     sys_ioprio_get
        PTR     sys_utimensat                   /* 5275 */
        PTR     sys_signalfd
-       PTR     sys_ni_syscall
+       PTR     sys_ni_syscall                  /* was timerfd */
        PTR     sys_eventfd
        PTR     sys_fallocate
        PTR     sys_timerfd_create              /* 5280 */
index b2c7624995b8068e3d8ae21b7faa56c016225ec9..38a0503b9a4a5c062ed9ff3b3baf6a72fd09f2d7 100644 (file)
@@ -89,8 +89,7 @@ n32_syscall_trace_entry:
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       li      a1, 0
-       jal     do_syscall_trace
+       jal     syscall_trace_enter
 
        move    t0, s0
        RESTORE_STATIC
@@ -403,7 +402,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_ioprio_get
        PTR     compat_sys_utimensat
        PTR     compat_sys_signalfd             /* 6280 */
-       PTR     sys_ni_syscall
+       PTR     sys_ni_syscall                  /* was timerfd */
        PTR     sys_eventfd
        PTR     sys_fallocate
        PTR     sys_timerfd_create
index 049a9c8c49a0fbf2f12055d4d98ad4e87d5ca8d0..91ea5e4041ddd5683e7c1e63bd2d63ec0835d633 100644 (file)
@@ -123,8 +123,7 @@ trace_a_syscall:
 
        move    s0, t2                  # Save syscall pointer
        move    a0, sp
-       li      a1, 0
-       jal     do_syscall_trace
+       jal     syscall_trace_enter
 
        move    t0, s0
        RESTORE_STATIC
@@ -522,7 +521,7 @@ sys_call_table:
        PTR     sys_ioprio_get                  /* 4315 */
        PTR     compat_sys_utimensat
        PTR     compat_sys_signalfd
-       PTR     sys_ni_syscall
+       PTR     sys_ni_syscall                  /* was timerfd */
        PTR     sys_eventfd
        PTR     sys32_fallocate                 /* 4320 */
        PTR     sys_timerfd_create
index 5a88cc4ccd5a761c468d98f6f710a38dae2013b8..cedac4633741b24c14393da27cb6423c79ecac3f 100644 (file)
@@ -929,7 +929,7 @@ static void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
 
 static void ipi_resched_interrupt(void)
 {
-       /* Return from interrupt should be enough to cause scheduler check */
+       scheduler_ipi();
 }
 
 static void ipi_call_interrupt(void)
index 58beabf50b3c34a022ec49b9a3c3a245aa130666..d02765708ddb9672a8ebe787068f1709d0e8d09b 100644 (file)
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
-#include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
-#include <linux/mman.h>
 #include <linux/ptrace.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/syscalls.h>
 #include <linux/file.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/compiler.h>
-#include <linux/module.h>
 #include <linux/ipc.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/random.h>
 #include <linux/elf.h>
 
 #include <asm/asm.h>
@@ -66,121 +61,6 @@ out:
        return res;
 }
 
-unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
-
-EXPORT_SYMBOL(shm_align_mask);
-
-#define COLOUR_ALIGN(addr,pgoff)                               \
-       ((((addr) + shm_align_mask) & ~shm_align_mask) +        \
-        (((pgoff) << PAGE_SHIFT) & shm_align_mask))
-
-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
-       unsigned long len, unsigned long pgoff, unsigned long flags)
-{
-       struct vm_area_struct * vmm;
-       int do_color_align;
-       unsigned long task_size;
-
-#ifdef CONFIG_32BIT
-       task_size = TASK_SIZE;
-#else /* Must be CONFIG_64BIT*/
-       task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE;
-#endif
-
-       if (len > task_size)
-               return -ENOMEM;
-
-       if (flags & MAP_FIXED) {
-               /* Even MAP_FIXED mappings must reside within task_size.  */
-               if (task_size - len < addr)
-                       return -EINVAL;
-
-               /*
-                * We do not accept a shared mapping if it would violate
-                * cache aliasing constraints.
-                */
-               if ((flags & MAP_SHARED) &&
-                   ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
-                       return -EINVAL;
-               return addr;
-       }
-
-       do_color_align = 0;
-       if (filp || (flags & MAP_SHARED))
-               do_color_align = 1;
-       if (addr) {
-               if (do_color_align)
-                       addr = COLOUR_ALIGN(addr, pgoff);
-               else
-                       addr = PAGE_ALIGN(addr);
-               vmm = find_vma(current->mm, addr);
-               if (task_size - len >= addr &&
-                   (!vmm || addr + len <= vmm->vm_start))
-                       return addr;
-       }
-       addr = current->mm->mmap_base;
-       if (do_color_align)
-               addr = COLOUR_ALIGN(addr, pgoff);
-       else
-               addr = PAGE_ALIGN(addr);
-
-       for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
-               /* At this point:  (!vmm || addr < vmm->vm_end). */
-               if (task_size - len < addr)
-                       return -ENOMEM;
-               if (!vmm || addr + len <= vmm->vm_start)
-                       return addr;
-               addr = vmm->vm_end;
-               if (do_color_align)
-                       addr = COLOUR_ALIGN(addr, pgoff);
-       }
-}
-
-void arch_pick_mmap_layout(struct mm_struct *mm)
-{
-       unsigned long random_factor = 0UL;
-
-       if (current->flags & PF_RANDOMIZE) {
-               random_factor = get_random_int();
-               random_factor = random_factor << PAGE_SHIFT;
-               if (TASK_IS_32BIT_ADDR)
-                       random_factor &= 0xfffffful;
-               else
-                       random_factor &= 0xffffffful;
-       }
-
-       mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
-       mm->get_unmapped_area = arch_get_unmapped_area;
-       mm->unmap_area = arch_unmap_area;
-}
-
-static inline unsigned long brk_rnd(void)
-{
-       unsigned long rnd = get_random_int();
-
-       rnd = rnd << PAGE_SHIFT;
-       /* 8MB for 32bit, 256MB for 64bit */
-       if (TASK_IS_32BIT_ADDR)
-               rnd = rnd & 0x7ffffful;
-       else
-               rnd = rnd & 0xffffffful;
-
-       return rnd;
-}
-
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
-       unsigned long base = mm->brk;
-       unsigned long ret;
-
-       ret = PAGE_ALIGN(base + brk_rnd());
-
-       if (ret < mm->brk)
-               return mm->brk;
-
-       return ret;
-}
-
 SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
        unsigned long, prot, unsigned long, flags, unsigned long,
        fd, off_t, offset)
index 71350f7f2d8857507cc8da104c3dcee9a6a0a072..e9b3af27d844b5db837dc641bdd9c87ba326f9ba 100644 (file)
@@ -374,7 +374,8 @@ void __noreturn die(const char *str, struct pt_regs *regs)
        unsigned long dvpret = dvpe();
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-       notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV);
+       if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
+               sig = 0;
 
        console_verbose();
        spin_lock_irq(&die_lock);
@@ -383,9 +384,6 @@ void __noreturn die(const char *str, struct pt_regs *regs)
        mips_mt_regdump(dvpret);
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-       if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
-               sig = 0;
-
        printk("%s[#%d]:\n", str, ++die_counter);
        show_registers(regs);
        add_taint(TAINT_DIE);
index 832afbb87588bedcf2b8265495fd44b6874ccabb..cd2ca544454b1378cb1e831f0f445cc0a2abeea7 100644 (file)
@@ -68,12 +68,14 @@ SECTIONS
        RODATA
 
        /* writeable */
+       _sdata = .;                             /* Start of data section */
        .data : {       /* Data */
                . = . + DATAOFFSET;             /* for CONFIG_MAPPED_KERNEL */
 
                INIT_TASK_DATA(PAGE_SIZE)
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
+               READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
                DATA_DATA
                CONSTRUCTORS
        }
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
new file mode 100644 (file)
index 0000000..3fccf21
--- /dev/null
@@ -0,0 +1,23 @@
+if LANTIQ
+
+config SOC_TYPE_XWAY
+       bool
+       default n
+
+choice
+       prompt "SoC Type"
+       default SOC_XWAY
+
+config SOC_AMAZON_SE
+       bool "Amazon SE"
+       select SOC_TYPE_XWAY
+
+config SOC_XWAY
+       bool "XWAY"
+       select SOC_TYPE_XWAY
+       select HW_HAS_PCI
+endchoice
+
+source "arch/mips/lantiq/xway/Kconfig"
+
+endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
new file mode 100644 (file)
index 0000000..e5dae0e
--- /dev/null
@@ -0,0 +1,11 @@
+# Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+
+obj-y := irq.o setup.o clk.o prom.o devices.o
+
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
new file mode 100644 (file)
index 0000000..f3dff05
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Lantiq
+#
+
+platform-$(CONFIG_LANTIQ)      += lantiq/
+cflags-$(CONFIG_LANTIQ)                += -I$(srctree)/arch/mips/include/asm/mach-lantiq
+load-$(CONFIG_LANTIQ)          = 0xffffffff80002000
+cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
new file mode 100644 (file)
index 0000000..9456089
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/list.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+#include "clk.h"
+
+struct clk {
+       const char *name;
+       unsigned long rate;
+       unsigned long (*get_rate) (void);
+};
+
+static struct clk *cpu_clk;
+static int cpu_clk_cnt;
+
+/* lantiq socs have 3 static clocks */
+static struct clk cpu_clk_generic[] = {
+       {
+               .name = "cpu",
+               .get_rate = ltq_get_cpu_hz,
+       }, {
+               .name = "fpi",
+               .get_rate = ltq_get_fpi_hz,
+       }, {
+               .name = "io",
+               .get_rate = ltq_get_io_region_clock,
+       },
+};
+
+static struct resource ltq_cgu_resource = {
+       .name   = "cgu",
+       .start  = LTQ_CGU_BASE_ADDR,
+       .end    = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+/* remapped clock register range */
+void __iomem *ltq_cgu_membase;
+
+void clk_init(void)
+{
+       cpu_clk = cpu_clk_generic;
+       cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
+}
+
+static inline int clk_good(struct clk *clk)
+{
+       return clk && !IS_ERR(clk);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (unlikely(!clk_good(clk)))
+               return 0;
+
+       if (clk->rate != 0)
+               return clk->rate;
+
+       if (clk->get_rate != NULL)
+               return clk->get_rate();
+
+       return 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       int i;
+
+       for (i = 0; i < cpu_clk_cnt; i++)
+               if (!strcmp(id, cpu_clk[i].name))
+                       return &cpu_clk[i];
+       BUG();
+       return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       /* not used */
+}
+EXPORT_SYMBOL(clk_put);
+
+static inline u32 ltq_get_counter_resolution(void)
+{
+       u32 res;
+
+       __asm__ __volatile__(
+               ".set   push\n"
+               ".set   mips32r2\n"
+               "rdhwr  %0, $3\n"
+               ".set pop\n"
+               : "=&r" (res)
+               : /* no input */
+               : "memory");
+
+       return res;
+}
+
+void __init plat_time_init(void)
+{
+       struct clk *clk;
+
+       if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
+               panic("Failed to insert cgu memory\n");
+
+       if (request_mem_region(ltq_cgu_resource.start,
+                       resource_size(&ltq_cgu_resource), "cgu") < 0)
+               panic("Failed to request cgu memory\n");
+
+       ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
+                               resource_size(&ltq_cgu_resource));
+       if (!ltq_cgu_membase) {
+               pr_err("Failed to remap cgu memory\n");
+               unreachable();
+       }
+       clk = clk_get(0, "cpu");
+       mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
+       write_c0_compare(read_c0_count());
+       clk_put(clk);
+}
diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
new file mode 100644 (file)
index 0000000..3328925
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_CLK_H__
+#define _LTQ_CLK_H__
+
+extern void clk_init(void);
+
+extern unsigned long ltq_get_cpu_hz(void);
+extern unsigned long ltq_get_fpi_hz(void);
+extern unsigned long ltq_get_io_region_clock(void);
+
+#endif
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
new file mode 100644 (file)
index 0000000..7b82c34
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/etherdevice.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+/* nor flash */
+static struct resource ltq_nor_resource = {
+       .name   = "nor",
+       .start  = LTQ_FLASH_START,
+       .end    = LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device ltq_nor = {
+       .name           = "ltq_nor",
+       .resource       = &ltq_nor_resource,
+       .num_resources  = 1,
+};
+
+void __init ltq_register_nor(struct physmap_flash_data *data)
+{
+       ltq_nor.dev.platform_data = data;
+       platform_device_register(&ltq_nor);
+}
+
+/* watchdog */
+static struct resource ltq_wdt_resource = {
+       .name   = "watchdog",
+       .start  = LTQ_WDT_BASE_ADDR,
+       .end    = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+void __init ltq_register_wdt(void)
+{
+       platform_device_register_simple("ltq_wdt", 0, &ltq_wdt_resource, 1);
+}
+
+/* asc ports */
+static struct resource ltq_asc0_resources[] = {
+       {
+               .name   = "asc0",
+               .start  = LTQ_ASC0_BASE_ADDR,
+               .end    = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ_RES(tx, LTQ_ASC_TIR(0)),
+       IRQ_RES(rx, LTQ_ASC_RIR(0)),
+       IRQ_RES(err, LTQ_ASC_EIR(0)),
+};
+
+static struct resource ltq_asc1_resources[] = {
+       {
+               .name   = "asc1",
+               .start  = LTQ_ASC1_BASE_ADDR,
+               .end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ_RES(tx, LTQ_ASC_TIR(1)),
+       IRQ_RES(rx, LTQ_ASC_RIR(1)),
+       IRQ_RES(err, LTQ_ASC_EIR(1)),
+};
+
+void __init ltq_register_asc(int port)
+{
+       switch (port) {
+       case 0:
+               platform_device_register_simple("ltq_asc", 0,
+                       ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources));
+               break;
+       case 1:
+               platform_device_register_simple("ltq_asc", 1,
+                       ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources));
+               break;
+       default:
+               break;
+       }
+}
+
+#ifdef CONFIG_PCI
+/* pci */
+static struct platform_device ltq_pci = {
+       .name           = "ltq_pci",
+       .num_resources  = 0,
+};
+
+void __init ltq_register_pci(struct ltq_pci_data *data)
+{
+       ltq_pci.dev.platform_data = data;
+       platform_device_register(&ltq_pci);
+}
+#else
+void __init ltq_register_pci(struct ltq_pci_data *data)
+{
+       pr_err("kernel is compiled without PCI support\n");
+}
+#endif
diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
new file mode 100644 (file)
index 0000000..2947bb1
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_DEVICES_H__
+#define _LTQ_DEVICES_H__
+
+#include <lantiq_platform.h>
+#include <linux/mtd/physmap.h>
+
+#define IRQ_RES(resname, irq) \
+       {.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
+
+extern void ltq_register_nor(struct physmap_flash_data *data);
+extern void ltq_register_wdt(void);
+extern void ltq_register_asc(int port);
+extern void ltq_register_pci(struct ltq_pci_data *data);
+
+#endif
diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
new file mode 100644 (file)
index 0000000..972e05f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+
+#include <lantiq.h>
+#include <lantiq_soc.h>
+
+/* no ioremap possible at this early stage, lets use KSEG1 instead  */
+#define LTQ_ASC_BASE   KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
+#define ASC_BUF                1024
+#define LTQ_ASC_FSTAT  ((u32 *)(LTQ_ASC_BASE + 0x0048))
+#define LTQ_ASC_TBUF   ((u32 *)(LTQ_ASC_BASE + 0x0020))
+#define TXMASK         0x3F00
+#define TXOFFSET       8
+
+void prom_putchar(char c)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
+       if (c == '\n')
+               ltq_w32('\r', LTQ_ASC_TBUF);
+       ltq_w32(c, LTQ_ASC_TBUF);
+       local_irq_restore(flags);
+}
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
new file mode 100644 (file)
index 0000000..fc89795
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq_cpu.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+/* register definitions */
+#define LTQ_ICU_IM0_ISR                0x0000
+#define LTQ_ICU_IM0_IER                0x0008
+#define LTQ_ICU_IM0_IOSR       0x0010
+#define LTQ_ICU_IM0_IRSR       0x0018
+#define LTQ_ICU_IM0_IMR                0x0020
+#define LTQ_ICU_IM1_ISR                0x0028
+#define LTQ_ICU_OFFSET         (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
+
+#define LTQ_EIU_EXIN_C         0x0000
+#define LTQ_EIU_EXIN_INIC      0x0004
+#define LTQ_EIU_EXIN_INEN      0x000C
+
+/* irq numbers used by the external interrupt unit (EIU) */
+#define LTQ_EIU_IR0            (INT_NUM_IM4_IRL0 + 30)
+#define LTQ_EIU_IR1            (INT_NUM_IM3_IRL0 + 31)
+#define LTQ_EIU_IR2            (INT_NUM_IM1_IRL0 + 26)
+#define LTQ_EIU_IR3            INT_NUM_IM1_IRL0
+#define LTQ_EIU_IR4            (INT_NUM_IM1_IRL0 + 1)
+#define LTQ_EIU_IR5            (INT_NUM_IM1_IRL0 + 2)
+#define LTQ_EIU_IR6            (INT_NUM_IM2_IRL0 + 30)
+
+#define MAX_EIU                        6
+
+/* irqs generated by device attached to the EBU need to be acked in
+ * a special manner
+ */
+#define LTQ_ICU_EBU_IRQ                22
+
+#define ltq_icu_w32(x, y)      ltq_w32((x), ltq_icu_membase + (y))
+#define ltq_icu_r32(x)         ltq_r32(ltq_icu_membase + (x))
+
+#define ltq_eiu_w32(x, y)      ltq_w32((x), ltq_eiu_membase + (y))
+#define ltq_eiu_r32(x)         ltq_r32(ltq_eiu_membase + (x))
+
+static unsigned short ltq_eiu_irq[MAX_EIU] = {
+       LTQ_EIU_IR0,
+       LTQ_EIU_IR1,
+       LTQ_EIU_IR2,
+       LTQ_EIU_IR3,
+       LTQ_EIU_IR4,
+       LTQ_EIU_IR5,
+};
+
+static struct resource ltq_icu_resource = {
+       .name   = "icu",
+       .start  = LTQ_ICU_BASE_ADDR,
+       .end    = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct resource ltq_eiu_resource = {
+       .name   = "eiu",
+       .start  = LTQ_EIU_BASE_ADDR,
+       .end    = LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static void __iomem *ltq_icu_membase;
+static void __iomem *ltq_eiu_membase;
+
+void ltq_disable_irq(struct irq_data *d)
+{
+       u32 ier = LTQ_ICU_IM0_IER;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+       irq_nr %= INT_NUM_IM_OFFSET;
+       ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
+}
+
+void ltq_mask_and_ack_irq(struct irq_data *d)
+{
+       u32 ier = LTQ_ICU_IM0_IER;
+       u32 isr = LTQ_ICU_IM0_ISR;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+       isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+       irq_nr %= INT_NUM_IM_OFFSET;
+       ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
+       ltq_icu_w32((1 << irq_nr), isr);
+}
+
+static void ltq_ack_irq(struct irq_data *d)
+{
+       u32 isr = LTQ_ICU_IM0_ISR;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+       irq_nr %= INT_NUM_IM_OFFSET;
+       ltq_icu_w32((1 << irq_nr), isr);
+}
+
+void ltq_enable_irq(struct irq_data *d)
+{
+       u32 ier = LTQ_ICU_IM0_IER;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       ier += LTQ_ICU_OFFSET  * (irq_nr / INT_NUM_IM_OFFSET);
+       irq_nr %= INT_NUM_IM_OFFSET;
+       ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
+}
+
+static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
+{
+       int i;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       ltq_enable_irq(d);
+       for (i = 0; i < MAX_EIU; i++) {
+               if (irq_nr == ltq_eiu_irq[i]) {
+                       /* low level - we should really handle set_type */
+                       ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
+                               (0x6 << (i * 4)), LTQ_EIU_EXIN_C);
+                       /* clear all pending */
+                       ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i),
+                               LTQ_EIU_EXIN_INIC);
+                       /* enable */
+                       ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i),
+                               LTQ_EIU_EXIN_INEN);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static void ltq_shutdown_eiu_irq(struct irq_data *d)
+{
+       int i;
+       int irq_nr = d->irq - INT_NUM_IRQ0;
+
+       ltq_disable_irq(d);
+       for (i = 0; i < MAX_EIU; i++) {
+               if (irq_nr == ltq_eiu_irq[i]) {
+                       /* disable */
+                       ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
+                               LTQ_EIU_EXIN_INEN);
+                       break;
+               }
+       }
+}
+
+static struct irq_chip ltq_irq_type = {
+       "icu",
+       .irq_enable = ltq_enable_irq,
+       .irq_disable = ltq_disable_irq,
+       .irq_unmask = ltq_enable_irq,
+       .irq_ack = ltq_ack_irq,
+       .irq_mask = ltq_disable_irq,
+       .irq_mask_ack = ltq_mask_and_ack_irq,
+};
+
+static struct irq_chip ltq_eiu_type = {
+       "eiu",
+       .irq_startup = ltq_startup_eiu_irq,
+       .irq_shutdown = ltq_shutdown_eiu_irq,
+       .irq_enable = ltq_enable_irq,
+       .irq_disable = ltq_disable_irq,
+       .irq_unmask = ltq_enable_irq,
+       .irq_ack = ltq_ack_irq,
+       .irq_mask = ltq_disable_irq,
+       .irq_mask_ack = ltq_mask_and_ack_irq,
+};
+
+static void ltq_hw_irqdispatch(int module)
+{
+       u32 irq;
+
+       irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
+       if (irq == 0)
+               return;
+
+       /* silicon bug causes only the msb set to 1 to be valid. all
+        * other bits might be bogus
+        */
+       irq = __fls(irq);
+       do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
+
+       /* if this is a EBU irq, we need to ack it or get a deadlock */
+       if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
+               ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
+                       LTQ_EBU_PCC_ISTAT);
+}
+
+#define DEFINE_HWx_IRQDISPATCH(x)                                      \
+       static void ltq_hw ## x ## _irqdispatch(void)                   \
+       {                                                               \
+               ltq_hw_irqdispatch(x);                                  \
+       }
+DEFINE_HWx_IRQDISPATCH(0)
+DEFINE_HWx_IRQDISPATCH(1)
+DEFINE_HWx_IRQDISPATCH(2)
+DEFINE_HWx_IRQDISPATCH(3)
+DEFINE_HWx_IRQDISPATCH(4)
+
+static void ltq_hw5_irqdispatch(void)
+{
+       do_IRQ(MIPS_CPU_TIMER_IRQ);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+       unsigned int i;
+
+       if (pending & CAUSEF_IP7) {
+               do_IRQ(MIPS_CPU_TIMER_IRQ);
+               goto out;
+       } else {
+               for (i = 0; i < 5; i++) {
+                       if (pending & (CAUSEF_IP2 << i)) {
+                               ltq_hw_irqdispatch(i);
+                               goto out;
+                       }
+               }
+       }
+       pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
+
+out:
+       return;
+}
+
+static struct irqaction cascade = {
+       .handler = no_action,
+       .flags = IRQF_DISABLED,
+       .name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+       int i;
+
+       if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
+               panic("Failed to insert icu memory\n");
+
+       if (request_mem_region(ltq_icu_resource.start,
+                       resource_size(&ltq_icu_resource), "icu") < 0)
+               panic("Failed to request icu memory\n");
+
+       ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
+                               resource_size(&ltq_icu_resource));
+       if (!ltq_icu_membase)
+               panic("Failed to remap icu memory\n");
+
+       if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
+               panic("Failed to insert eiu memory\n");
+
+       if (request_mem_region(ltq_eiu_resource.start,
+                       resource_size(&ltq_eiu_resource), "eiu") < 0)
+               panic("Failed to request eiu memory\n");
+
+       ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
+                               resource_size(&ltq_eiu_resource));
+       if (!ltq_eiu_membase)
+               panic("Failed to remap eiu memory\n");
+
+       /* make sure all irqs are turned off by default */
+       for (i = 0; i < 5; i++)
+               ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
+
+       /* clear all possibly pending interrupts */
+       ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
+
+       mips_cpu_irq_init();
+
+       for (i = 2; i <= 6; i++)
+               setup_irq(i, &cascade);
+
+       if (cpu_has_vint) {
+               pr_info("Setting up vectored interrupts\n");
+               set_vi_handler(2, ltq_hw0_irqdispatch);
+               set_vi_handler(3, ltq_hw1_irqdispatch);
+               set_vi_handler(4, ltq_hw2_irqdispatch);
+               set_vi_handler(5, ltq_hw3_irqdispatch);
+               set_vi_handler(6, ltq_hw4_irqdispatch);
+               set_vi_handler(7, ltq_hw5_irqdispatch);
+       }
+
+       for (i = INT_NUM_IRQ0;
+               i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
+               if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
+                       (i == LTQ_EIU_IR2))
+                       irq_set_chip_and_handler(i, &ltq_eiu_type,
+                               handle_level_irq);
+               /* EIU3-5 only exist on ar9 and vr9 */
+               else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
+                       (i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
+                       irq_set_chip_and_handler(i, &ltq_eiu_type,
+                               handle_level_irq);
+               else
+                       irq_set_chip_and_handler(i, &ltq_irq_type,
+                               handle_level_irq);
+
+#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
+               IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
+#else
+       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
+               IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
+#endif
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+       return CP0_LEGACY_COMPARE_IRQ;
+}
diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
new file mode 100644 (file)
index 0000000..7e01b8c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LANTIQ_MACH_H__
+#define _LANTIQ_MACH_H__
+
+#include <asm/mips_machine.h>
+
+enum lantiq_mach_type {
+       LTQ_MACH_GENERIC = 0,
+       LTQ_MACH_EASY50712,     /* Danube evaluation board */
+       LTQ_MACH_EASY50601,     /* Amazon SE evaluation board */
+};
+
+#endif
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
new file mode 100644 (file)
index 0000000..56ba007
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+#include <lantiq.h>
+
+#include "prom.h"
+#include "clk.h"
+
+static struct ltq_soc_info soc_info;
+
+unsigned int ltq_get_cpu_ver(void)
+{
+       return soc_info.rev;
+}
+EXPORT_SYMBOL(ltq_get_cpu_ver);
+
+unsigned int ltq_get_soc_type(void)
+{
+       return soc_info.type;
+}
+EXPORT_SYMBOL(ltq_get_soc_type);
+
+const char *get_system_type(void)
+{
+       return soc_info.sys_type;
+}
+
+void prom_free_prom_memory(void)
+{
+}
+
+static void __init prom_init_cmdline(void)
+{
+       int argc = fw_arg0;
+       char **argv = (char **) KSEG1ADDR(fw_arg1);
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               char *p = (char *)  KSEG1ADDR(argv[i]);
+
+               if (p && *p) {
+                       strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+                       strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+               }
+       }
+}
+
+void __init prom_init(void)
+{
+       struct clk *clk;
+
+       ltq_soc_detect(&soc_info);
+       clk_init();
+       clk = clk_get(0, "cpu");
+       snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
+               soc_info.name, soc_info.rev);
+       clk_put(clk);
+       soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
+       pr_info("SoC: %s\n", soc_info.sys_type);
+       prom_init_cmdline();
+}
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
new file mode 100644 (file)
index 0000000..b4229d9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_PROM_H__
+#define _LTQ_PROM_H__
+
+#define LTQ_SYS_TYPE_LEN       0x100
+
+struct ltq_soc_info {
+       unsigned char *name;
+       unsigned int rev;
+       unsigned int partnum;
+       unsigned int type;
+       unsigned char sys_type[LTQ_SYS_TYPE_LEN];
+};
+
+extern void ltq_soc_detect(struct ltq_soc_info *i);
+extern void ltq_soc_setup(void);
+
+#endif
diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
new file mode 100644 (file)
index 0000000..9b8af77
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <asm/bootinfo.h>
+
+#include <lantiq_soc.h>
+
+#include "machtypes.h"
+#include "devices.h"
+#include "prom.h"
+
+void __init plat_mem_setup(void)
+{
+       /* assume 16M as default incase uboot fails to pass proper ramsize */
+       unsigned long memsize = 16;
+       char **envp = (char **) KSEG1ADDR(fw_arg2);
+
+       ioport_resource.start = IOPORT_RESOURCE_START;
+       ioport_resource.end = IOPORT_RESOURCE_END;
+       iomem_resource.start = IOMEM_RESOURCE_START;
+       iomem_resource.end = IOMEM_RESOURCE_END;
+
+       set_io_port_base((unsigned long) KSEG1);
+
+       while (*envp) {
+               char *e = (char *)KSEG1ADDR(*envp);
+               if (!strncmp(e, "memsize=", 8)) {
+                       e += 8;
+                       if (strict_strtoul(e, 0, &memsize))
+                               pr_warn("bad memsize specified\n");
+               }
+               envp++;
+       }
+       memsize *= 1024 * 1024;
+       add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+}
+
+static int __init
+lantiq_setup(void)
+{
+       ltq_soc_setup();
+       mips_machine_setup();
+       return 0;
+}
+
+arch_initcall(lantiq_setup);
+
+static void __init
+lantiq_generic_init(void)
+{
+       /* Nothing to do */
+}
+
+MIPS_MACHINE(LTQ_MACH_GENERIC,
+            "Generic",
+            "Generic Lantiq based board",
+            lantiq_generic_init);
diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
new file mode 100644 (file)
index 0000000..2b857de
--- /dev/null
@@ -0,0 +1,23 @@
+if SOC_XWAY
+
+menu "MIPS Machine"
+
+config LANTIQ_MACH_EASY50712
+       bool "Easy50712 - Danube"
+       default y
+
+endmenu
+
+endif
+
+if SOC_AMAZON_SE
+
+menu "MIPS Machine"
+
+config LANTIQ_MACH_EASY50601
+       bool "Easy50601 - Amazon SE"
+       default y
+
+endmenu
+
+endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
new file mode 100644 (file)
index 0000000..c517f2e
--- /dev/null
@@ -0,0 +1,7 @@
+obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
+
+obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
+obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+
+obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
new file mode 100644 (file)
index 0000000..22d823a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+/* cgu registers */
+#define LTQ_CGU_SYS    0x0010
+
+unsigned int ltq_get_io_region_clock(void)
+{
+       return CLOCK_133M;
+}
+EXPORT_SYMBOL(ltq_get_io_region_clock);
+
+unsigned int ltq_get_fpi_bus_clock(int fpi)
+{
+       return CLOCK_133M;
+}
+EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
+
+unsigned int ltq_get_cpu_hz(void)
+{
+       if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
+               return CLOCK_266M;
+       else
+               return CLOCK_133M;
+}
+EXPORT_SYMBOL(ltq_get_cpu_hz);
+
+unsigned int ltq_get_fpi_hz(void)
+{
+       return CLOCK_133M;
+}
+EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
new file mode 100644 (file)
index 0000000..ddd3959
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+static unsigned int ltq_ram_clocks[] = {
+       CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
+#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
+
+#define BASIC_FREQUENCY_1      35328000
+#define BASIC_FREQUENCY_2      36000000
+#define BASIS_REQUENCY_USB     12000000
+
+#define GET_BITS(x, msb, lsb) \
+       (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
+
+#define LTQ_CGU_PLL0_CFG       0x0004
+#define LTQ_CGU_PLL1_CFG       0x0008
+#define LTQ_CGU_PLL2_CFG       0x000C
+#define LTQ_CGU_SYS            0x0010
+#define LTQ_CGU_UPDATE         0x0014
+#define LTQ_CGU_IF_CLK         0x0018
+#define LTQ_CGU_OSC_CON                0x001C
+#define LTQ_CGU_SMD            0x0020
+#define LTQ_CGU_CT1SR          0x0028
+#define LTQ_CGU_CT2SR          0x002C
+#define LTQ_CGU_PCMCR          0x0030
+#define LTQ_CGU_PCI_CR         0x0034
+#define LTQ_CGU_PD_PC          0x0038
+#define LTQ_CGU_FMR            0x003C
+
+#define CGU_PLL0_PHASE_DIVIDER_ENABLE  \
+       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
+#define CGU_PLL0_BYPASS                        \
+       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
+#define CGU_PLL0_CFG_DSMSEL            \
+       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
+#define CGU_PLL0_CFG_FRAC_EN           \
+       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
+#define CGU_PLL1_SRC                   \
+       (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
+#define CGU_PLL2_PHASE_DIVIDER_ENABLE  \
+       (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
+#define CGU_SYS_FPI_SEL                        (1 << 6)
+#define CGU_SYS_DDR_SEL                        0x3
+#define CGU_PLL0_SRC                   (1 << 29)
+
+#define CGU_PLL0_CFG_PLLK      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
+#define CGU_PLL0_CFG_PLLN      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
+#define CGU_PLL0_CFG_PLLM      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
+#define CGU_PLL2_SRC           GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
+#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
+
+static unsigned int ltq_get_pll0_fdiv(void);
+
+static inline unsigned int get_input_clock(int pll)
+{
+       switch (pll) {
+       case 0:
+               if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
+                       return BASIS_REQUENCY_USB;
+               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
+                       return BASIC_FREQUENCY_1;
+               else
+                       return BASIC_FREQUENCY_2;
+       case 1:
+               if (CGU_PLL1_SRC)
+                       return BASIS_REQUENCY_USB;
+               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
+                       return BASIC_FREQUENCY_1;
+               else
+                       return BASIC_FREQUENCY_2;
+       case 2:
+               switch (CGU_PLL2_SRC) {
+               case 0:
+                       return ltq_get_pll0_fdiv();
+               case 1:
+                       return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
+                               BASIC_FREQUENCY_1 :
+                               BASIC_FREQUENCY_2;
+               case 2:
+                       return BASIS_REQUENCY_USB;
+               }
+       default:
+               return 0;
+       }
+}
+
+static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
+{
+       u64 res, clock = get_input_clock(pll);
+
+       res = num * clock;
+       do_div(res, den);
+       return res;
+}
+
+static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
+       unsigned int K)
+{
+       unsigned int num = ((N + 1) << 10) + K;
+       unsigned int den = (M + 1) << 10;
+
+       return cal_dsm(pll, num, den);
+}
+
+static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
+       unsigned int K)
+{
+       unsigned int num = ((N + 1) << 11) + K + 512;
+       unsigned int den = (M + 1) << 11;
+
+       return cal_dsm(pll, num, den);
+}
+
+static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
+       unsigned int K)
+{
+       unsigned int num = K >= 512 ?
+               ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
+       unsigned int den = (M + 1) << 12;
+
+       return cal_dsm(pll, num, den);
+}
+
+static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
+       unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
+{
+       if (!dsmsel)
+               return mash_dsm(pll, M, N, K);
+       else if (!phase_div_en)
+               return mash_dsm(pll, M, N, K);
+       else
+               return ssff_dsm_2(pll, M, N, K);
+}
+
+static inline unsigned int ltq_get_pll0_fosc(void)
+{
+       if (CGU_PLL0_BYPASS)
+               return get_input_clock(0);
+       else
+               return !CGU_PLL0_CFG_FRAC_EN
+                       ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
+                               CGU_PLL0_CFG_DSMSEL,
+                               CGU_PLL0_PHASE_DIVIDER_ENABLE)
+                       : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
+                               CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
+                               CGU_PLL0_PHASE_DIVIDER_ENABLE);
+}
+
+static unsigned int ltq_get_pll0_fdiv(void)
+{
+       unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
+
+       return (ltq_get_pll0_fosc() + (div >> 1)) / div;
+}
+
+unsigned int ltq_get_io_region_clock(void)
+{
+       unsigned int ret = ltq_get_pll0_fosc();
+
+       switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
+       default:
+       case 0:
+               return (ret + 1) / 2;
+       case 1:
+               return (ret * 2 + 2) / 5;
+       case 2:
+               return (ret + 1) / 3;
+       case 3:
+               return (ret + 2) / 4;
+       }
+}
+EXPORT_SYMBOL(ltq_get_io_region_clock);
+
+unsigned int ltq_get_fpi_bus_clock(int fpi)
+{
+       unsigned int ret = ltq_get_io_region_clock();
+
+       if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
+               ret >>= 1;
+       return ret;
+}
+EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
+
+unsigned int ltq_get_cpu_hz(void)
+{
+       switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
+       case 0:
+               return CLOCK_333M;
+       case 4:
+               return DDR_HZ;
+       case 8:
+               return DDR_HZ << 1;
+       default:
+               return DDR_HZ >> 1;
+       }
+}
+EXPORT_SYMBOL(ltq_get_cpu_hz);
+
+unsigned int ltq_get_fpi_hz(void)
+{
+       unsigned int ddr_clock = DDR_HZ;
+
+       if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
+               return ddr_clock >> 1;
+       return ddr_clock;
+}
+EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
new file mode 100644 (file)
index 0000000..e09e789
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mtd/physmap.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/etherdevice.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
+#include <lantiq_platform.h>
+
+#include "devices.h"
+
+/* gpio */
+static struct resource ltq_gpio_resource[] = {
+       {
+               .name   = "gpio0",
+               .start  = LTQ_GPIO0_BASE_ADDR,
+               .end    = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "gpio1",
+               .start  = LTQ_GPIO1_BASE_ADDR,
+               .end    = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "gpio2",
+               .start  = LTQ_GPIO2_BASE_ADDR,
+               .end    = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+void __init ltq_register_gpio(void)
+{
+       platform_device_register_simple("ltq_gpio", 0,
+               &ltq_gpio_resource[0], 1);
+       platform_device_register_simple("ltq_gpio", 1,
+               &ltq_gpio_resource[1], 1);
+
+       /* AR9 and VR9 have an extra gpio block */
+       if (ltq_is_ar9() || ltq_is_vr9()) {
+               platform_device_register_simple("ltq_gpio", 2,
+                       &ltq_gpio_resource[2], 1);
+       }
+}
+
+/* serial to parallel conversion */
+static struct resource ltq_stp_resource = {
+       .name   = "stp",
+       .start  = LTQ_STP_BASE_ADDR,
+       .end    = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+void __init ltq_register_gpio_stp(void)
+{
+       platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
+}
+
+/* asc ports - amazon se has its own serial mapping */
+static struct resource ltq_ase_asc_resources[] = {
+       {
+               .name   = "asc0",
+               .start  = LTQ_ASC1_BASE_ADDR,
+               .end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ_RES(tx, LTQ_ASC_ASE_TIR),
+       IRQ_RES(rx, LTQ_ASC_ASE_RIR),
+       IRQ_RES(err, LTQ_ASC_ASE_EIR),
+};
+
+void __init ltq_register_ase_asc(void)
+{
+       platform_device_register_simple("ltq_asc", 0,
+               ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
+}
+
+/* ethernet */
+static struct resource ltq_etop_resources = {
+       .name   = "etop",
+       .start  = LTQ_ETOP_BASE_ADDR,
+       .end    = LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device ltq_etop = {
+       .name           = "ltq_etop",
+       .resource       = &ltq_etop_resources,
+       .num_resources  = 1,
+};
+
+void __init
+ltq_register_etop(struct ltq_eth_data *eth)
+{
+       if (eth) {
+               ltq_etop.dev.platform_data = eth;
+               platform_device_register(&ltq_etop);
+       }
+}
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
new file mode 100644 (file)
index 0000000..e904934
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_DEVICES_XWAY_H__
+#define _LTQ_DEVICES_XWAY_H__
+
+#include "../devices.h"
+#include <linux/phy.h>
+
+extern void ltq_register_gpio(void);
+extern void ltq_register_gpio_stp(void);
+extern void ltq_register_ase_asc(void);
+extern void ltq_register_etop(struct ltq_eth_data *eth);
+
+#endif
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
new file mode 100644 (file)
index 0000000..4278a45
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License version 2 as published
+ *   by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include <lantiq_soc.h>
+#include <xway_dma.h>
+
+#define LTQ_DMA_CTRL           0x10
+#define LTQ_DMA_CPOLL          0x14
+#define LTQ_DMA_CS             0x18
+#define LTQ_DMA_CCTRL          0x1C
+#define LTQ_DMA_CDBA           0x20
+#define LTQ_DMA_CDLEN          0x24
+#define LTQ_DMA_CIS            0x28
+#define LTQ_DMA_CIE            0x2C
+#define LTQ_DMA_PS             0x40
+#define LTQ_DMA_PCTRL          0x44
+#define LTQ_DMA_IRNEN          0xf4
+
+#define DMA_DESCPT             BIT(3)          /* descriptor complete irq */
+#define DMA_TX                 BIT(8)          /* TX channel direction */
+#define DMA_CHAN_ON            BIT(0)          /* channel on / off bit */
+#define DMA_PDEN               BIT(6)          /* enable packet drop */
+#define DMA_CHAN_RST           BIT(1)          /* channel on / off bit */
+#define DMA_RESET              BIT(0)          /* channel on / off bit */
+#define DMA_IRQ_ACK            0x7e            /* IRQ status register */
+#define DMA_POLL               BIT(31)         /* turn on channel polling */
+#define DMA_CLK_DIV4           BIT(6)          /* polling clock divider */
+#define DMA_2W_BURST           BIT(1)          /* 2 word burst length */
+#define DMA_MAX_CHANNEL                20              /* the soc has 20 channels */
+#define DMA_ETOP_ENDIANESS     (0xf << 8) /* endianess swap etop channels */
+#define DMA_WEIGHT     (BIT(17) | BIT(16))     /* default channel wheight */
+
+#define ltq_dma_r32(x)                 ltq_r32(ltq_dma_membase + (x))
+#define ltq_dma_w32(x, y)              ltq_w32(x, ltq_dma_membase + (y))
+#define ltq_dma_w32_mask(x, y, z)      ltq_w32_mask(x, y, \
+                                               ltq_dma_membase + (z))
+
+static struct resource ltq_dma_resource = {
+       .name   = "dma",
+       .start  = LTQ_DMA_BASE_ADDR,
+       .end    = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static void __iomem *ltq_dma_membase;
+
+void
+ltq_dma_enable_irq(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_enable_irq);
+
+void
+ltq_dma_disable_irq(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_disable_irq);
+
+void
+ltq_dma_ack_irq(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_ack_irq);
+
+void
+ltq_dma_open(struct ltq_dma_channel *ch)
+{
+       unsigned long flag;
+
+       local_irq_save(flag);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
+       ltq_dma_enable_irq(ch);
+       local_irq_restore(flag);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_open);
+
+void
+ltq_dma_close(struct ltq_dma_channel *ch)
+{
+       unsigned long flag;
+
+       local_irq_save(flag);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+       ltq_dma_disable_irq(ch);
+       local_irq_restore(flag);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_close);
+
+static void
+ltq_dma_alloc(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       ch->desc = 0;
+       ch->desc_base = dma_alloc_coherent(NULL,
+                               LTQ_DESC_NUM * LTQ_DESC_SIZE,
+                               &ch->phys, GFP_ATOMIC);
+       memset(ch->desc_base, 0, LTQ_DESC_NUM * LTQ_DESC_SIZE);
+
+       local_irq_save(flags);
+       ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+       ltq_dma_w32(ch->phys, LTQ_DMA_CDBA);
+       ltq_dma_w32(LTQ_DESC_NUM, LTQ_DMA_CDLEN);
+       ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+       wmb();
+       ltq_dma_w32_mask(0, DMA_CHAN_RST, LTQ_DMA_CCTRL);
+       while (ltq_dma_r32(LTQ_DMA_CCTRL) & DMA_CHAN_RST)
+               ;
+       local_irq_restore(flags);
+}
+
+void
+ltq_dma_alloc_tx(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       ltq_dma_alloc(ch);
+
+       local_irq_save(flags);
+       ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
+       ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+       ltq_dma_w32(DMA_WEIGHT | DMA_TX, LTQ_DMA_CCTRL);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_alloc_tx);
+
+void
+ltq_dma_alloc_rx(struct ltq_dma_channel *ch)
+{
+       unsigned long flags;
+
+       ltq_dma_alloc(ch);
+
+       local_irq_save(flags);
+       ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
+       ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+       ltq_dma_w32(DMA_WEIGHT, LTQ_DMA_CCTRL);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_alloc_rx);
+
+void
+ltq_dma_free(struct ltq_dma_channel *ch)
+{
+       if (!ch->desc_base)
+               return;
+       ltq_dma_close(ch);
+       dma_free_coherent(NULL, LTQ_DESC_NUM * LTQ_DESC_SIZE,
+               ch->desc_base, ch->phys);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_free);
+
+void
+ltq_dma_init_port(int p)
+{
+       ltq_dma_w32(p, LTQ_DMA_PS);
+       switch (p) {
+       case DMA_PORT_ETOP:
+               /*
+                * Tell the DMA engine to swap the endianess of data frames and
+                * drop packets if the channel arbitration fails.
+                */
+               ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
+                       LTQ_DMA_PCTRL);
+               break;
+
+       case DMA_PORT_DEU:
+               ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
+                       LTQ_DMA_PCTRL);
+               break;
+
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(ltq_dma_init_port);
+
+int __init
+ltq_dma_init(void)
+{
+       int i;
+
+       /* insert and request the memory region */
+       if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
+               panic("Failed to insert dma memory\n");
+
+       if (request_mem_region(ltq_dma_resource.start,
+                       resource_size(&ltq_dma_resource), "dma") < 0)
+               panic("Failed to request dma memory\n");
+
+       /* remap dma register range */
+       ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
+                               resource_size(&ltq_dma_resource));
+       if (!ltq_dma_membase)
+               panic("Failed to remap dma memory\n");
+
+       /* power up and reset the dma engine */
+       ltq_pmu_enable(PMU_DMA);
+       ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
+
+       /* disable all interrupts */
+       ltq_dma_w32(0, LTQ_DMA_IRNEN);
+
+       /* reset/configure each channel */
+       for (i = 0; i < DMA_MAX_CHANNEL; i++) {
+               ltq_dma_w32(i, LTQ_DMA_CS);
+               ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
+               ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
+               ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+       }
+       return 0;
+}
+
+postcore_initcall(ltq_dma_init);
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
new file mode 100644 (file)
index 0000000..66eb52f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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.
+ *
+ *  EBU - the external bus unit attaches PCI, NOR and NAND
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/ioport.h>
+
+#include <lantiq_soc.h>
+
+/* all access to the ebu must be locked */
+DEFINE_SPINLOCK(ebu_lock);
+EXPORT_SYMBOL_GPL(ebu_lock);
+
+static struct resource ltq_ebu_resource = {
+       .name   = "ebu",
+       .start  = LTQ_EBU_BASE_ADDR,
+       .end    = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+/* remapped base addr of the clock unit and external bus unit */
+void __iomem *ltq_ebu_membase;
+
+static int __init lantiq_ebu_init(void)
+{
+       /* insert and request the memory region */
+       if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
+               panic("Failed to insert ebu memory\n");
+
+       if (request_mem_region(ltq_ebu_resource.start,
+                       resource_size(&ltq_ebu_resource), "ebu") < 0)
+               panic("Failed to request ebu memory\n");
+
+       /* remap ebu register range */
+       ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
+                               resource_size(&ltq_ebu_resource));
+       if (!ltq_ebu_membase)
+               panic("Failed to remap ebu memory\n");
+
+       /* make sure to unprotect the memory region where flash is located */
+       ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+       return 0;
+}
+
+postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
new file mode 100644 (file)
index 0000000..a321451
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+
+#include <lantiq_soc.h>
+
+#define LTQ_GPIO_OUT           0x00
+#define LTQ_GPIO_IN            0x04
+#define LTQ_GPIO_DIR           0x08
+#define LTQ_GPIO_ALTSEL0       0x0C
+#define LTQ_GPIO_ALTSEL1       0x10
+#define LTQ_GPIO_OD            0x14
+
+#define PINS_PER_PORT          16
+#define MAX_PORTS              3
+
+#define ltq_gpio_getbit(m, r, p)       (!!(ltq_r32(m + r) & (1 << p)))
+#define ltq_gpio_setbit(m, r, p)       ltq_w32_mask(0, (1 << p), m + r)
+#define ltq_gpio_clearbit(m, r, p)     ltq_w32_mask((1 << p), 0, m + r)
+
+struct ltq_gpio {
+       void __iomem *membase;
+       struct gpio_chip chip;
+};
+
+static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
+
+int gpio_to_irq(unsigned int gpio)
+{
+       return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned int gpio)
+{
+       return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
+int ltq_gpio_request(unsigned int pin, unsigned int alt0,
+       unsigned int alt1, unsigned int dir, const char *name)
+{
+       int id = 0;
+
+       if (pin >= (MAX_PORTS * PINS_PER_PORT))
+               return -EINVAL;
+       if (gpio_request(pin, name)) {
+               pr_err("failed to setup lantiq gpio: %s\n", name);
+               return -EBUSY;
+       }
+       if (dir)
+               gpio_direction_output(pin, 1);
+       else
+               gpio_direction_input(pin);
+       while (pin >= PINS_PER_PORT) {
+               pin -= PINS_PER_PORT;
+               id++;
+       }
+       if (alt0)
+               ltq_gpio_setbit(ltq_gpio_port[id].membase,
+                       LTQ_GPIO_ALTSEL0, pin);
+       else
+               ltq_gpio_clearbit(ltq_gpio_port[id].membase,
+                       LTQ_GPIO_ALTSEL0, pin);
+       if (alt1)
+               ltq_gpio_setbit(ltq_gpio_port[id].membase,
+                       LTQ_GPIO_ALTSEL1, pin);
+       else
+               ltq_gpio_clearbit(ltq_gpio_port[id].membase,
+                       LTQ_GPIO_ALTSEL1, pin);
+       return 0;
+}
+EXPORT_SYMBOL(ltq_gpio_request);
+
+static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+       struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
+
+       if (value)
+               ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
+       else
+               ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
+}
+
+static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
+
+       return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
+}
+
+static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+       struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
+
+       ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+       ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
+
+       return 0;
+}
+
+static int ltq_gpio_direction_output(struct gpio_chip *chip,
+       unsigned int offset, int value)
+{
+       struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
+
+       ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+       ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
+       ltq_gpio_set(chip, offset, value);
+
+       return 0;
+}
+
+static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
+{
+       struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
+
+       ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
+       ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
+       return 0;
+}
+
+static int ltq_gpio_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+
+       if (pdev->id >= MAX_PORTS) {
+               dev_err(&pdev->dev, "invalid gpio port %d\n",
+                       pdev->id);
+               return -EINVAL;
+       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
+                       pdev->id);
+               return -ENOENT;
+       }
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               resource_size(res), dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev,
+                       "failed to request memory for gpio port %d\n",
+                       pdev->id);
+               return -EBUSY;
+       }
+       ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
+               res->start, resource_size(res));
+       if (!ltq_gpio_port[pdev->id].membase) {
+               dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
+                       pdev->id);
+               return -ENOMEM;
+       }
+       ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
+       ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
+       ltq_gpio_port[pdev->id].chip.direction_output =
+               ltq_gpio_direction_output;
+       ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
+       ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
+       ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
+       ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
+       ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
+       platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
+       return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
+}
+
+static struct platform_driver
+ltq_gpio_driver = {
+       .probe = ltq_gpio_probe,
+       .driver = {
+               .name = "ltq_gpio",
+               .owner = THIS_MODULE,
+       },
+};
+
+int __init ltq_gpio_init(void)
+{
+       int ret = platform_driver_register(&ltq_gpio_driver);
+
+       if (ret)
+               pr_info("ltq_gpio : Error registering platfom driver!");
+       return ret;
+}
+
+postcore_initcall(ltq_gpio_init);
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
new file mode 100644 (file)
index 0000000..a479355
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <lantiq_soc.h>
+
+/*
+ * By attaching hardware latches to the EBU it is possible to create output
+ * only gpios. This driver configures a special memory address, which when
+ * written to outputs 16 bit to the latches.
+ */
+
+#define LTQ_EBU_BUSCON 0x1e7ff         /* 16 bit access, slowest timing */
+#define LTQ_EBU_WP     0x80000000      /* write protect bit */
+
+/* we keep a shadow value of the last value written to the ebu */
+static int ltq_ebu_gpio_shadow = 0x0;
+static void __iomem *ltq_ebu_gpio_membase;
+
+static void ltq_ebu_apply(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ebu_lock, flags);
+       ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
+       *((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
+       ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
+       spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       if (value)
+               ltq_ebu_gpio_shadow |= (1 << offset);
+       else
+               ltq_ebu_gpio_shadow &= ~(1 << offset);
+       ltq_ebu_apply();
+}
+
+static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
+       int value)
+{
+       ltq_ebu_set(chip, offset, value);
+
+       return 0;
+}
+
+static struct gpio_chip ltq_ebu_chip = {
+       .label = "ltq_ebu",
+       .direction_output = ltq_ebu_direction_output,
+       .set = ltq_ebu_set,
+       .base = 72,
+       .ngpio = 16,
+       .can_sleep = 1,
+       .owner = THIS_MODULE,
+};
+
+static int ltq_ebu_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get memory resource\n");
+               return -ENOENT;
+       }
+
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               resource_size(res), dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev, "failed to request memory resource\n");
+               return -EBUSY;
+       }
+
+       ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+               resource_size(res));
+       if (!ltq_ebu_gpio_membase) {
+               dev_err(&pdev->dev, "Failed to ioremap mem region\n");
+               return -ENOMEM;
+       }
+
+       /* grab the default shadow value passed form the platform code */
+       ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
+
+       /* tell the ebu controller which memory address we will be using */
+       ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
+
+       /* write protect the region */
+       ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
+
+       ret = gpiochip_add(&ltq_ebu_chip);
+       if (!ret)
+               ltq_ebu_apply();
+       return ret;
+}
+
+static struct platform_driver ltq_ebu_driver = {
+       .probe = ltq_ebu_probe,
+       .driver = {
+               .name = "ltq_ebu",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init ltq_ebu_init(void)
+{
+       int ret = platform_driver_register(&ltq_ebu_driver);
+
+       if (ret)
+               pr_info("ltq_ebu : Error registering platfom driver!");
+       return ret;
+}
+
+postcore_initcall(ltq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
new file mode 100644 (file)
index 0000000..67d59d6
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2007 John Crispin <blogic@openwrt.org>
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <lantiq_soc.h>
+
+#define LTQ_STP_CON0           0x00
+#define LTQ_STP_CON1           0x04
+#define LTQ_STP_CPU0           0x08
+#define LTQ_STP_CPU1           0x0C
+#define LTQ_STP_AR             0x10
+
+#define LTQ_STP_CON_SWU                (1 << 31)
+#define LTQ_STP_2HZ            0
+#define LTQ_STP_4HZ            (1 << 23)
+#define LTQ_STP_8HZ            (2 << 23)
+#define LTQ_STP_10HZ           (3 << 23)
+#define LTQ_STP_SPEED_MASK     (0xf << 23)
+#define LTQ_STP_UPD_FPI                (1 << 31)
+#define LTQ_STP_UPD_MASK       (3 << 30)
+#define LTQ_STP_ADSL_SRC       (3 << 24)
+
+#define LTQ_STP_GROUP0         (1 << 0)
+
+#define LTQ_STP_RISING         0
+#define LTQ_STP_FALLING                (1 << 26)
+#define LTQ_STP_EDGE_MASK      (1 << 26)
+
+#define ltq_stp_r32(reg)       __raw_readl(ltq_stp_membase + reg)
+#define ltq_stp_w32(val, reg)  __raw_writel(val, ltq_stp_membase + reg)
+#define ltq_stp_w32_mask(clear, set, reg) \
+               ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
+               ltq_stp_membase + (reg))
+
+static int ltq_stp_shadow = 0xffff;
+static void __iomem *ltq_stp_membase;
+
+static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       if (value)
+               ltq_stp_shadow |= (1 << offset);
+       else
+               ltq_stp_shadow &= ~(1 << offset);
+       ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
+}
+
+static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
+       int value)
+{
+       ltq_stp_set(chip, offset, value);
+
+       return 0;
+}
+
+static struct gpio_chip ltq_stp_chip = {
+       .label = "ltq_stp",
+       .direction_output = ltq_stp_direction_output,
+       .set = ltq_stp_set,
+       .base = 48,
+       .ngpio = 24,
+       .can_sleep = 1,
+       .owner = THIS_MODULE,
+};
+
+static int ltq_stp_hw_init(void)
+{
+       /* the 3 pins used to control the external stp */
+       ltq_gpio_request(4, 1, 0, 1, "stp-st");
+       ltq_gpio_request(5, 1, 0, 1, "stp-d");
+       ltq_gpio_request(6, 1, 0, 1, "stp-sh");
+
+       /* sane defaults */
+       ltq_stp_w32(0, LTQ_STP_AR);
+       ltq_stp_w32(0, LTQ_STP_CPU0);
+       ltq_stp_w32(0, LTQ_STP_CPU1);
+       ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
+       ltq_stp_w32(0, LTQ_STP_CON1);
+
+       /* rising or falling edge */
+       ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
+
+       /* per default stp 15-0 are set */
+       ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
+
+       /* stp are update periodically by the FPI bus */
+       ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
+
+       /* set stp update speed */
+       ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
+
+       /* tell the hardware that pin (led) 0 and 1 are controlled
+        *  by the dsl arc
+        */
+       ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
+
+       ltq_pmu_enable(PMU_LED);
+       return 0;
+}
+
+static int __devinit ltq_stp_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int ret = 0;
+
+       if (!res)
+               return -ENOENT;
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               resource_size(res), dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev, "failed to request STP memory\n");
+               return -EBUSY;
+       }
+       ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+               resource_size(res));
+       if (!ltq_stp_membase) {
+               dev_err(&pdev->dev, "failed to remap STP memory\n");
+               return -ENOMEM;
+       }
+       ret = gpiochip_add(&ltq_stp_chip);
+       if (!ret)
+               ret = ltq_stp_hw_init();
+
+       return ret;
+}
+
+static struct platform_driver ltq_stp_driver = {
+       .probe = ltq_stp_probe,
+       .driver = {
+               .name = "ltq_stp",
+               .owner = THIS_MODULE,
+       },
+};
+
+int __init ltq_stp_init(void)
+{
+       int ret = platform_driver_register(&ltq_stp_driver);
+
+       if (ret)
+               pr_info("ltq_stp: error registering platfom driver");
+       return ret;
+}
+
+postcore_initcall(ltq_stp_init);
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
new file mode 100644 (file)
index 0000000..d5aaf63
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+
+#include <lantiq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+
+static struct mtd_partition easy50601_partitions[] = {
+       {
+               .name   = "uboot",
+               .offset = 0x0,
+               .size   = 0x10000,
+       },
+       {
+               .name   = "uboot_env",
+               .offset = 0x10000,
+               .size   = 0x10000,
+       },
+       {
+               .name   = "linux",
+               .offset = 0x20000,
+               .size   = 0xE0000,
+       },
+       {
+               .name   = "rootfs",
+               .offset = 0x100000,
+               .size   = 0x300000,
+       },
+};
+
+static struct physmap_flash_data easy50601_flash_data = {
+       .nr_parts       = ARRAY_SIZE(easy50601_partitions),
+       .parts          = easy50601_partitions,
+};
+
+static void __init easy50601_init(void)
+{
+       ltq_register_nor(&easy50601_flash_data);
+}
+
+MIPS_MACHINE(LTQ_MACH_EASY50601,
+                       "EASY50601",
+                       "EASY50601 Eval Board",
+                       easy50601_init);
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
new file mode 100644 (file)
index 0000000..ea5027b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/phy.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+
+static struct mtd_partition easy50712_partitions[] = {
+       {
+               .name   = "uboot",
+               .offset = 0x0,
+               .size   = 0x10000,
+       },
+       {
+               .name   = "uboot_env",
+               .offset = 0x10000,
+               .size   = 0x10000,
+       },
+       {
+               .name   = "linux",
+               .offset = 0x20000,
+               .size   = 0xe0000,
+       },
+       {
+               .name   = "rootfs",
+               .offset = 0x100000,
+               .size   = 0x300000,
+       },
+};
+
+static struct physmap_flash_data easy50712_flash_data = {
+       .nr_parts       = ARRAY_SIZE(easy50712_partitions),
+       .parts          = easy50712_partitions,
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+       .clock  = PCI_CLOCK_INT,
+       .gpio   = PCI_GNT1 | PCI_REQ1,
+       .irq    = {
+               [14] = INT_NUM_IM0_IRL0 + 22,
+       },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+       .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+static void __init easy50712_init(void)
+{
+       ltq_register_gpio_stp();
+       ltq_register_nor(&easy50712_flash_data);
+       ltq_register_pci(&ltq_pci_data);
+       ltq_register_etop(&ltq_eth_data);
+}
+
+MIPS_MACHINE(LTQ_MACH_EASY50712,
+            "EASY50712",
+            "EASY50712 Eval Board",
+             easy50712_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
new file mode 100644 (file)
index 0000000..9d69f01
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/ioport.h>
+
+#include <lantiq_soc.h>
+
+/* PMU - the power management unit allows us to turn part of the core
+ * on and off
+ */
+
+/* the enable / disable registers */
+#define LTQ_PMU_PWDCR  0x1C
+#define LTQ_PMU_PWDSR  0x20
+
+#define ltq_pmu_w32(x, y)      ltq_w32((x), ltq_pmu_membase + (y))
+#define ltq_pmu_r32(x)         ltq_r32(ltq_pmu_membase + (x))
+
+static struct resource ltq_pmu_resource = {
+       .name   = "pmu",
+       .start  = LTQ_PMU_BASE_ADDR,
+       .end    = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static void __iomem *ltq_pmu_membase;
+
+void ltq_pmu_enable(unsigned int module)
+{
+       int err = 1000000;
+
+       ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
+       do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
+
+       if (!err)
+               panic("activating PMU module failed!\n");
+}
+EXPORT_SYMBOL(ltq_pmu_enable);
+
+void ltq_pmu_disable(unsigned int module)
+{
+       ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
+}
+EXPORT_SYMBOL(ltq_pmu_disable);
+
+int __init ltq_pmu_init(void)
+{
+       if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
+               panic("Failed to insert pmu memory\n");
+
+       if (request_mem_region(ltq_pmu_resource.start,
+                       resource_size(&ltq_pmu_resource), "pmu") < 0)
+               panic("Failed to request pmu memory\n");
+
+       ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
+                               resource_size(&ltq_pmu_resource));
+       if (!ltq_pmu_membase)
+               panic("Failed to remap pmu memory\n");
+       return 0;
+}
+
+core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
new file mode 100644 (file)
index 0000000..abe49f4
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+
+#define SOC_AMAZON_SE  "Amazon_SE"
+
+#define PART_SHIFT     12
+#define PART_MASK      0x0FFFFFFF
+#define REV_SHIFT      28
+#define REV_MASK       0xF0000000
+
+void __init ltq_soc_detect(struct ltq_soc_info *i)
+{
+       i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
+       i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+       switch (i->partnum) {
+       case SOC_ID_AMAZON_SE:
+               i->name = SOC_AMAZON_SE;
+               i->type = SOC_TYPE_AMAZON_SE;
+               break;
+
+       default:
+               unreachable();
+               break;
+       }
+}
diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
new file mode 100644 (file)
index 0000000..1686692
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+
+#define SOC_DANUBE     "Danube"
+#define SOC_TWINPASS   "Twinpass"
+#define SOC_AR9                "AR9"
+
+#define PART_SHIFT     12
+#define PART_MASK      0x0FFFFFFF
+#define REV_SHIFT      28
+#define REV_MASK       0xF0000000
+
+void __init ltq_soc_detect(struct ltq_soc_info *i)
+{
+       i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
+       i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+       switch (i->partnum) {
+       case SOC_ID_DANUBE1:
+       case SOC_ID_DANUBE2:
+               i->name = SOC_DANUBE;
+               i->type = SOC_TYPE_DANUBE;
+               break;
+
+       case SOC_ID_TWINPASS:
+               i->name = SOC_TWINPASS;
+               i->type = SOC_TYPE_DANUBE;
+               break;
+
+       case SOC_ID_ARX188:
+       case SOC_ID_ARX168:
+       case SOC_ID_ARX182:
+               i->name = SOC_AR9;
+               i->type = SOC_TYPE_AR9;
+               break;
+
+       default:
+               unreachable();
+               break;
+       }
+}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
new file mode 100644 (file)
index 0000000..a1be36d
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/module.h>
+#include <asm/reboot.h>
+
+#include <lantiq_soc.h>
+
+#define ltq_rcu_w32(x, y)      ltq_w32((x), ltq_rcu_membase + (y))
+#define ltq_rcu_r32(x)         ltq_r32(ltq_rcu_membase + (x))
+
+/* register definitions */
+#define LTQ_RCU_RST            0x0010
+#define LTQ_RCU_RST_ALL                0x40000000
+
+#define LTQ_RCU_RST_STAT       0x0014
+#define LTQ_RCU_STAT_SHIFT     26
+
+static struct resource ltq_rcu_resource = {
+       .name   = "rcu",
+       .start  = LTQ_RCU_BASE_ADDR,
+       .end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+/* remapped base addr of the reset control unit */
+static void __iomem *ltq_rcu_membase;
+
+/* This function is used by the watchdog driver */
+int ltq_reset_cause(void)
+{
+       u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
+       return val >> LTQ_RCU_STAT_SHIFT;
+}
+EXPORT_SYMBOL_GPL(ltq_reset_cause);
+
+static void ltq_machine_restart(char *command)
+{
+       pr_notice("System restart\n");
+       local_irq_disable();
+       ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
+       unreachable();
+}
+
+static void ltq_machine_halt(void)
+{
+       pr_notice("System halted.\n");
+       local_irq_disable();
+       unreachable();
+}
+
+static void ltq_machine_power_off(void)
+{
+       pr_notice("Please turn off the power now.\n");
+       local_irq_disable();
+       unreachable();
+}
+
+static int __init mips_reboot_setup(void)
+{
+       /* insert and request the memory region */
+       if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
+               panic("Failed to insert rcu memory\n");
+
+       if (request_mem_region(ltq_rcu_resource.start,
+                       resource_size(&ltq_rcu_resource), "rcu") < 0)
+               panic("Failed to request rcu memory\n");
+
+       /* remap rcu register range */
+       ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
+                               resource_size(&ltq_rcu_resource));
+       if (!ltq_rcu_membase)
+               panic("Failed to remap rcu memory\n");
+
+       _machine_restart = ltq_machine_restart;
+       _machine_halt = ltq_machine_halt;
+       pm_power_off = ltq_machine_power_off;
+
+       return 0;
+}
+
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
new file mode 100644 (file)
index 0000000..f6f3267
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+#include "devices.h"
+
+void __init ltq_soc_setup(void)
+{
+       ltq_register_ase_asc();
+       ltq_register_gpio();
+       ltq_register_wdt();
+}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
new file mode 100644 (file)
index 0000000..c292f64
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+#include "devices.h"
+
+void __init ltq_soc_setup(void)
+{
+       ltq_register_asc(0);
+       ltq_register_asc(1);
+       ltq_register_gpio();
+       ltq_register_wdt();
+}
index 2adead5a8a376e54a8f9c58dade0c4e817fd82c7..b2cad4fd5fc4a6720c3eae65384f1c94b62f7f8f 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_CPU_TX39XX)      += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX49XX)       += dump_tlb.o
 obj-$(CONFIG_CPU_VR41XX)       += dump_tlb.o
 obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += dump_tlb.o
+obj-$(CONFIG_CPU_XLR)          += dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
 obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
index 8c807c9651990bb973d2c13123ac911abb35e23f..0cb1b9760e34f32c19b57f8a0de4f9442766190e 100644 (file)
@@ -201,8 +201,6 @@ static struct clocksource clocksource_mfgpt = {
        .rating = 120, /* Functional for real use, but not desired */
        .read = mfgpt_read,
        .mask = CLOCKSOURCE_MASK(32),
-       .mult = 0,
-       .shift = 22,
 };
 
 int __init init_mfgpt_clocksource(void)
@@ -210,8 +208,7 @@ int __init init_mfgpt_clocksource(void)
        if (num_possible_cpus() > 1)    /* MFGPT does not scale! */
                return 0;
 
-       clocksource_mfgpt.mult = clocksource_hz2mult(MFGPT_TICK_RATE, 22);
-       return clocksource_register(&clocksource_mfgpt);
+       return clocksource_register_hz(&clocksource_mfgpt, MFGPT_TICK_RATE);
 }
 
 arch_initcall(init_mfgpt_clocksource);
index 11b193f848f88b7aa1c5ab5a842c2cf4e80ed7d7..d93830ad6113619e9f50f4c368bf4cbefd083d2d 100644 (file)
@@ -29,9 +29,10 @@ unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
-       int ret;                                                        \
+       unsigned int tmp __maybe_unused;                                \
+                                                                       \
        if (strncmp(option, (char *)p, strlen(option)) == 0)            \
-               ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
+               tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
index d679c772d082a2bf8b09612f7837b89576e051e7..4d8c1623eee2978a00bb792a6e714bfe668f27d7 100644 (file)
@@ -3,7 +3,8 @@
 #
 
 obj-y                          += cache.o dma-default.o extable.o fault.o \
-                                  init.o tlbex.o tlbex-fault.o uasm.o page.o
+                                  init.o mmap.o tlbex.o tlbex-fault.o uasm.o \
+                                  page.o
 
 obj-$(CONFIG_32BIT)            += ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)            += pgtable-64.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_CPU_TX39XX)      += c-tx39.o tlb-r3k.o
 obj-$(CONFIG_CPU_TX49XX)       += c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_VR41XX)       += c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += c-octeon.o cex-oct.o tlb-r4k.o
+obj-$(CONFIG_CPU_XLR)          += c-r4k.o tlb-r4k.o cex-gen.o
 
 obj-$(CONFIG_IP22_CPU_SCACHE)  += sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
index b4923a75cb4b8c12354a3e0821797349db4cd0ef..d9bc5d3593b697d463f6bff7d4da1971c125e2a4 100644 (file)
@@ -1006,6 +1006,7 @@ static void __cpuinit probe_pcache(void)
        case CPU_25KF:
        case CPU_SB1:
        case CPU_SB1A:
+       case CPU_XLR:
                c->dcache.flags |= MIPS_CACHE_PINDEX;
                break;
 
@@ -1075,7 +1076,6 @@ static int __cpuinit probe_scache(void)
        unsigned long flags, addr, begin, end, pow2;
        unsigned int config = read_c0_config();
        struct cpuinfo_mips *c = &current_cpu_data;
-       int tmp;
 
        if (config & CONF_SC)
                return 0;
@@ -1108,7 +1108,6 @@ static int __cpuinit probe_scache(void)
 
        /* Now search for the wrap around point. */
        pow2 = (128 * 1024);
-       tmp = 0;
        for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {
                cache_op(Index_Load_Tag_SD, addr);
                __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
new file mode 100644 (file)
index 0000000..ae3c20a
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+
+unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
+
+EXPORT_SYMBOL(shm_align_mask);
+
+#define COLOUR_ALIGN(addr,pgoff)                               \
+       ((((addr) + shm_align_mask) & ~shm_align_mask) +        \
+        (((pgoff) << PAGE_SHIFT) & shm_align_mask))
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+       unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct vm_area_struct * vmm;
+       int do_color_align;
+
+       if (len > TASK_SIZE)
+               return -ENOMEM;
+
+       if (flags & MAP_FIXED) {
+               /* Even MAP_FIXED mappings must reside within TASK_SIZE.  */
+               if (TASK_SIZE - len < addr)
+                       return -EINVAL;
+
+               /*
+                * We do not accept a shared mapping if it would violate
+                * cache aliasing constraints.
+                */
+               if ((flags & MAP_SHARED) &&
+                   ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+                       return -EINVAL;
+               return addr;
+       }
+
+       do_color_align = 0;
+       if (filp || (flags & MAP_SHARED))
+               do_color_align = 1;
+       if (addr) {
+               if (do_color_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
+               else
+                       addr = PAGE_ALIGN(addr);
+               vmm = find_vma(current->mm, addr);
+               if (TASK_SIZE - len >= addr &&
+                   (!vmm || addr + len <= vmm->vm_start))
+                       return addr;
+       }
+       addr = current->mm->mmap_base;
+       if (do_color_align)
+               addr = COLOUR_ALIGN(addr, pgoff);
+       else
+               addr = PAGE_ALIGN(addr);
+
+       for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+               /* At this point:  (!vmm || addr < vmm->vm_end). */
+               if (TASK_SIZE - len < addr)
+                       return -ENOMEM;
+               if (!vmm || addr + len <= vmm->vm_start)
+                       return addr;
+               addr = vmm->vm_end;
+               if (do_color_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
+       }
+}
+
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE) {
+               random_factor = get_random_int();
+               random_factor = random_factor << PAGE_SHIFT;
+               if (TASK_IS_32BIT_ADDR)
+                       random_factor &= 0xfffffful;
+               else
+                       random_factor &= 0xffffffful;
+       }
+
+       mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+       mm->get_unmapped_area = arch_get_unmapped_area;
+       mm->unmap_area = arch_unmap_area;
+}
+
+static inline unsigned long brk_rnd(void)
+{
+       unsigned long rnd = get_random_int();
+
+       rnd = rnd << PAGE_SHIFT;
+       /* 8MB for 32bit, 256MB for 64bit */
+       if (TASK_IS_32BIT_ADDR)
+               rnd = rnd & 0x7ffffful;
+       else
+               rnd = rnd & 0xffffffful;
+
+       return rnd;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+       unsigned long base = mm->brk;
+       unsigned long ret;
+
+       ret = PAGE_ALIGN(base + brk_rnd());
+
+       if (ret < mm->brk)
+               return mm->brk;
+
+       return ret;
+}
index 5ef294fbb6e7e118684c3913183cbcfb089dd0aa..424ed4b92e6d9435107a96f260329b3a40ac2992 100644 (file)
@@ -404,6 +404,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
        case CPU_5KC:
        case CPU_TX49XX:
        case CPU_PR4450:
+       case CPU_XLR:
                uasm_i_nop(p);
                tlbw(p);
                break;
@@ -1151,8 +1152,8 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
        struct uasm_reloc *r = relocs;
        u32 *f;
        unsigned int final_len;
-       struct mips_huge_tlb_info htlb_info;
-       enum vmalloc64_mode vmalloc_mode;
+       struct mips_huge_tlb_info htlb_info __maybe_unused;
+       enum vmalloc64_mode vmalloc_mode __maybe_unused;
 
        memset(tlb_handler, 0, sizeof(tlb_handler));
        memset(labels, 0, sizeof(labels));
index 414f0c99b1965f01baf2f81a9858dec1a5e17f0a..31180c321a1a29b1f7c5d7a2c1b1a5f6188ee0ed 100644 (file)
@@ -193,8 +193,6 @@ extern struct plat_smp_ops msmtc_smp_ops;
 
 void __init prom_init(void)
 {
-       int result;
-
        prom_argc = fw_arg0;
        _prom_argv = (int *) fw_arg1;
        _prom_envp = (int *) fw_arg2;
@@ -360,20 +358,14 @@ void __init prom_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
        console_config();
 #endif
-       /* Early detection of CMP support */
-       result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
-
 #ifdef CONFIG_MIPS_CMP
-       if (result)
+       /* Early detection of CMP support */
+       if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
                register_smp_ops(&cmp_smp_ops);
+       else
 #endif
 #ifdef CONFIG_MIPS_MT_SMP
-#ifdef CONFIG_MIPS_CMP
-       if (!result)
                register_smp_ops(&vsmp_smp_ops);
-#else
-       register_smp_ops(&vsmp_smp_ops);
-#endif
 #endif
 #ifdef CONFIG_MIPS_MT_SMTC
        register_smp_ops(&msmtc_smp_ops);
index 9027061f0ead0d8ba259681dacdee9da9330e1ce..1d36c511a7a5951c227800f917dd815449baf064 100644 (file)
@@ -56,7 +56,6 @@ static DEFINE_RAW_SPINLOCK(mips_irq_lock);
 static inline int mips_pcibios_iack(void)
 {
        int irq;
-       u32 dummy;
 
        /*
         * Determine highest priority pending interrupt by performing
@@ -83,7 +82,7 @@ static inline int mips_pcibios_iack(void)
                BONITO_PCIMAP_CFG = 0x20000;
 
                /* Flush Bonito register block */
-               dummy = BONITO_PCIMAP_CFG;
+               (void) BONITO_PCIMAP_CFG;
                iob();    /* sync */
 
                irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
@@ -309,6 +308,8 @@ static void ipi_call_dispatch(void)
 
 static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 {
+       scheduler_ipi();
+
        return IRQ_HANDLED;
 }
 
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
new file mode 100644 (file)
index 0000000..a5ca743
--- /dev/null
@@ -0,0 +1,5 @@
+config NLM_COMMON
+       bool
+
+config NLM_XLR
+       bool
diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile
new file mode 100644 (file)
index 0000000..9bd3f73
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y                          += setup.o platform.o irq.o setup.o time.o
+obj-$(CONFIG_SMP)              += smp.o smpboot.o
+obj-$(CONFIG_EARLY_PRINTK)     += xlr_console.o
+
+EXTRA_CFLAGS                   += -Werror
diff --git a/arch/mips/netlogic/xlr/irq.c b/arch/mips/netlogic/xlr/irq.c
new file mode 100644 (file)
index 0000000..1446d58
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/xlr/iomap.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/xlr.h>
+
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/mips-extns.h>
+
+static u64 nlm_irq_mask;
+static DEFINE_SPINLOCK(nlm_pic_lock);
+
+static void xlr_pic_enable(struct irq_data *d)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+       unsigned long flags;
+       nlm_reg_t reg;
+       int irq = d->irq;
+
+       WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq);
+
+       spin_lock_irqsave(&nlm_pic_lock, flags);
+       reg = netlogic_read_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE);
+       netlogic_write_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE,
+                         reg | (1 << 6) | (1 << 30) | (1 << 31));
+       spin_unlock_irqrestore(&nlm_pic_lock, flags);
+}
+
+static void xlr_pic_mask(struct irq_data *d)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+       unsigned long flags;
+       nlm_reg_t reg;
+       int irq = d->irq;
+
+       WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq);
+
+       spin_lock_irqsave(&nlm_pic_lock, flags);
+       reg = netlogic_read_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE);
+       netlogic_write_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE,
+                         reg | (1 << 6) | (1 << 30) | (0 << 31));
+       spin_unlock_irqrestore(&nlm_pic_lock, flags);
+}
+
+#ifdef CONFIG_PCI
+/* Extra ACK needed for XLR on chip PCI controller */
+static void xlr_pci_ack(struct irq_data *d)
+{
+       nlm_reg_t *pci_mmio = netlogic_io_mmio(NETLOGIC_IO_PCIX_OFFSET);
+
+       netlogic_read_reg(pci_mmio, (0x140 >> 2));
+}
+
+/* Extra ACK needed for XLS on chip PCIe controller */
+static void xls_pcie_ack(struct irq_data *d)
+{
+       nlm_reg_t *pcie_mmio_le = netlogic_io_mmio(NETLOGIC_IO_PCIE_1_OFFSET);
+
+       switch (d->irq) {
+       case PIC_PCIE_LINK0_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x90 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_LINK1_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x94 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_LINK2_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x190 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_LINK3_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x194 >> 2), 0xffffffff);
+               break;
+       }
+}
+
+/* For XLS B silicon, the 3,4 PCI interrupts are different */
+static void xls_pcie_ack_b(struct irq_data *d)
+{
+       nlm_reg_t *pcie_mmio_le = netlogic_io_mmio(NETLOGIC_IO_PCIE_1_OFFSET);
+
+       switch (d->irq) {
+       case PIC_PCIE_LINK0_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x90 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_LINK1_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x94 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_XLSB0_LINK2_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x190 >> 2), 0xffffffff);
+               break;
+       case PIC_PCIE_XLSB0_LINK3_IRQ:
+               netlogic_write_reg(pcie_mmio_le, (0x194 >> 2), 0xffffffff);
+               break;
+       }
+}
+#endif
+
+static void xlr_pic_ack(struct irq_data *d)
+{
+       unsigned long flags;
+       nlm_reg_t *mmio;
+       int irq = d->irq;
+       void *hd = irq_data_get_irq_handler_data(d);
+
+       WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq);
+
+       if (hd) {
+               void (*extra_ack)(void *) = hd;
+               extra_ack(d);
+       }
+       mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+       spin_lock_irqsave(&nlm_pic_lock, flags);
+       netlogic_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
+       spin_unlock_irqrestore(&nlm_pic_lock, flags);
+}
+
+/*
+ * This chip definition handles interrupts routed thru the XLR
+ * hardware PIC, currently IRQs 8-39 are mapped to hardware intr
+ * 0-31 wired the XLR PIC
+ */
+static struct irq_chip xlr_pic = {
+       .name           = "XLR-PIC",
+       .irq_enable     = xlr_pic_enable,
+       .irq_mask       = xlr_pic_mask,
+       .irq_ack        = xlr_pic_ack,
+};
+
+static void rsvd_irq_handler(struct irq_data *d)
+{
+       WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq);
+}
+
+/*
+ * Chip definition for CPU originated interrupts(timer, msg) and
+ * IPIs
+ */
+struct irq_chip nlm_cpu_intr = {
+       .name           = "XLR-CPU-INTR",
+       .irq_enable     = rsvd_irq_handler,
+       .irq_mask       = rsvd_irq_handler,
+       .irq_ack        = rsvd_irq_handler,
+};
+
+void __init init_xlr_irqs(void)
+{
+       nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET);
+       uint32_t thread_mask = 1;
+       int level, i;
+
+       pr_info("Interrupt thread mask [%x]\n", thread_mask);
+       for (i = 0; i < PIC_NUM_IRTS; i++) {
+               level = PIC_IRQ_IS_EDGE_TRIGGERED(i);
+
+               /* Bind all PIC irqs to boot cpu */
+               netlogic_write_reg(mmio, PIC_IRT_0_BASE + i, thread_mask);
+
+               /*
+                * Use local scheduling and high polarity for all IRTs
+                * Invalidate all IRTs, by default
+                */
+               netlogic_write_reg(mmio, PIC_IRT_1_BASE + i,
+                               (level << 30) | (1 << 6) | (PIC_IRQ_BASE + i));
+       }
+
+       /* Make all IRQs as level triggered by default */
+       for (i = 0; i < NR_IRQS; i++) {
+               if (PIC_IRQ_IS_IRT(i))
+                       irq_set_chip_and_handler(i, &xlr_pic, handle_level_irq);
+               else
+                       irq_set_chip_and_handler(i, &nlm_cpu_intr,
+                                               handle_level_irq);
+       }
+#ifdef CONFIG_SMP
+       irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
+                        nlm_smp_function_ipi_handler);
+       irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
+                        nlm_smp_resched_ipi_handler);
+       nlm_irq_mask |=
+           ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
+#endif
+
+#ifdef CONFIG_PCI
+       /*
+        * For PCI interrupts, we need to ack the PIC controller too, overload
+        * irq handler data to do this
+        */
+       if (nlm_chip_is_xls()) {
+               if (nlm_chip_is_xls_b()) {
+                       irq_set_handler_data(PIC_PCIE_LINK0_IRQ,
+                                                       xls_pcie_ack_b);
+                       irq_set_handler_data(PIC_PCIE_LINK1_IRQ,
+                                                       xls_pcie_ack_b);
+                       irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ,
+                                                       xls_pcie_ack_b);
+                       irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ,
+                                                       xls_pcie_ack_b);
+               } else {
+                       irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack);
+                       irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack);
+                       irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack);
+                       irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack);
+               }
+       } else {
+               /* XLR PCI controller ACK */
+               irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, xlr_pci_ack);
+       }
+#endif
+       /* unmask all PIC related interrupts. If no handler is installed by the
+        * drivers, it'll just ack the interrupt and return
+        */
+       for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++)
+               nlm_irq_mask |= (1ULL << i);
+
+       nlm_irq_mask |= (1ULL << IRQ_TIMER);
+}
+
+void __init arch_init_irq(void)
+{
+       /* Initialize the irq descriptors */
+       init_xlr_irqs();
+       write_c0_eimr(nlm_irq_mask);
+}
+
+void __cpuinit nlm_smp_irq_init(void)
+{
+       /* set interrupt mask for non-zero cpus */
+       write_c0_eimr(nlm_irq_mask);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       uint64_t eirr;
+       int i;
+
+       eirr = read_c0_eirr() & read_c0_eimr();
+       if (!eirr)
+               return;
+
+       /* no need of EIRR here, writing compare clears interrupt */
+       if (eirr & (1 << IRQ_TIMER)) {
+               do_IRQ(IRQ_TIMER);
+               return;
+       }
+
+       /* use dcltz: optimize below code */
+       for (i = 63; i != -1; i--) {
+               if (eirr & (1ULL << i))
+                       break;
+       }
+       if (i == -1) {
+               pr_err("no interrupt !!\n");
+               return;
+       }
+
+       /* Ack eirr */
+       write_c0_eirr(1ULL << i);
+
+       do_IRQ(i);
+}
diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c
new file mode 100644 (file)
index 0000000..609ec25
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011, Netlogic Microsystems.
+ * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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/device.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+
+#include <asm/netlogic/xlr/iomap.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/xlr.h>
+
+unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
+{
+       nlm_reg_t *mmio;
+       unsigned int value;
+
+       /* XLR uart does not need any mapping of regs */
+       mmio = (nlm_reg_t *)(p->membase + (offset << p->regshift));
+       value = netlogic_read_reg(mmio, 0);
+
+       /* See XLR/XLS errata */
+       if (offset == UART_MSR)
+               value ^= 0xF0;
+       else if (offset == UART_MCR)
+               value ^= 0x3;
+
+       return value;
+}
+
+void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
+{
+       nlm_reg_t *mmio;
+
+       /* XLR uart does not need any mapping of regs */
+       mmio = (nlm_reg_t *)(p->membase + (offset << p->regshift));
+
+       /* See XLR/XLS errata */
+       if (offset == UART_MSR)
+               value ^= 0xF0;
+       else if (offset == UART_MCR)
+               value ^= 0x3;
+
+       netlogic_write_reg(mmio, 0, value);
+}
+
+#define PORT(_irq)                                     \
+       {                                               \
+               .irq            = _irq,                 \
+               .regshift       = 2,                    \
+               .iotype         = UPIO_MEM32,           \
+               .flags          = (UPF_SKIP_TEST |      \
+                        UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
+               .uartclk        = PIC_CLKS_PER_SEC,     \
+               .type           = PORT_16550A,          \
+               .serial_in      = nlm_xlr_uart_in,      \
+               .serial_out     = nlm_xlr_uart_out,     \
+       }
+
+static struct plat_serial8250_port xlr_uart_data[] = {
+       PORT(PIC_UART_0_IRQ),
+       PORT(PIC_UART_1_IRQ),
+       {},
+};
+
+static struct platform_device uart_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev = {
+               .platform_data = xlr_uart_data,
+       },
+};
+
+static int __init nlm_uart_init(void)
+{
+       nlm_reg_t *mmio;
+
+       mmio = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET);
+       xlr_uart_data[0].membase = (void __iomem *)mmio;
+       xlr_uart_data[0].mapbase = CPHYSADDR((unsigned long)mmio);
+
+       mmio = netlogic_io_mmio(NETLOGIC_IO_UART_1_OFFSET);
+       xlr_uart_data[1].membase = (void __iomem *)mmio;
+       xlr_uart_data[1].mapbase = CPHYSADDR((unsigned long)mmio);
+
+       return platform_device_register(&uart_device);
+}
+
+arch_initcall(nlm_uart_init);
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
new file mode 100644 (file)
index 0000000..4828025
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial_8250.h>
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/smp-ops.h>
+
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/psb-bootinfo.h>
+
+#include <asm/netlogic/xlr/xlr.h>
+#include <asm/netlogic/xlr/iomap.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/gpio.h>
+
+unsigned long netlogic_io_base = (unsigned long)(DEFAULT_NETLOGIC_IO_BASE);
+unsigned long nlm_common_ebase = 0x0;
+struct psb_info nlm_prom_info;
+
+static void nlm_early_serial_setup(void)
+{
+       struct uart_port s;
+       nlm_reg_t *uart_base;
+
+       uart_base = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET);
+       memset(&s, 0, sizeof(s));
+       s.flags         = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+       s.iotype        = UPIO_MEM32;
+       s.regshift      = 2;
+       s.irq           = PIC_UART_0_IRQ;
+       s.uartclk       = PIC_CLKS_PER_SEC;
+       s.serial_in     = nlm_xlr_uart_in;
+       s.serial_out    = nlm_xlr_uart_out;
+       s.mapbase       = (unsigned long)uart_base;
+       s.membase       = (unsigned char __iomem *)uart_base;
+       early_serial_setup(&s);
+}
+
+static void nlm_linux_exit(void)
+{
+       nlm_reg_t *mmio;
+
+       mmio = netlogic_io_mmio(NETLOGIC_IO_GPIO_OFFSET);
+       /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */
+       netlogic_write_reg(mmio, NETLOGIC_GPIO_SWRESET_REG, 1);
+       for ( ; ; )
+               cpu_wait();
+}
+
+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;
+}
+
+const char *get_system_type(void)
+{
+       return "Netlogic XLR/XLS Series";
+}
+
+void __init prom_free_prom_memory(void)
+{
+       /* Nothing yet */
+}
+
+static void build_arcs_cmdline(int *argv)
+{
+       int i, remain, len;
+       char *arg;
+
+       remain = sizeof(arcs_cmdline) - 1;
+       arcs_cmdline[0] = '\0';
+       for (i = 0; argv[i] != 0; i++) {
+               arg = (char *)(long)argv[i];
+               len = strlen(arg);
+               if (len + 1 > remain)
+                       break;
+               strcat(arcs_cmdline, arg);
+               strcat(arcs_cmdline, " ");
+               remain -=  len + 1;
+       }
+
+       /* Add the default options here */
+       if ((strstr(arcs_cmdline, "console=")) == NULL) {
+               arg = "console=ttyS0,38400 ";
+               len = strlen(arg);
+               if (len > remain)
+                       goto fail;
+               strcat(arcs_cmdline, arg);
+               remain -= len;
+       }
+#ifdef CONFIG_BLK_DEV_INITRD
+       if ((strstr(arcs_cmdline, "rdinit=")) == NULL) {
+               arg = "rdinit=/sbin/init ";
+               len = strlen(arg);
+               if (len > remain)
+                       goto fail;
+               strcat(arcs_cmdline, arg);
+               remain -= len;
+       }
+#endif
+       return;
+fail:
+       panic("Cannot add %s, command line too big!", arg);
+}
+
+static void prom_add_memory(void)
+{
+       struct nlm_boot_mem_map *bootm;
+       u64 start, size;
+       u64 pref_backup = 512;  /* avoid pref walking beyond end */
+       int i;
+
+       bootm = (void *)(long)nlm_prom_info.psb_mem_map;
+       for (i = 0; i < bootm->nr_map; i++) {
+               if (bootm->map[i].type != BOOT_MEM_RAM)
+                       continue;
+               start = bootm->map[i].addr;
+               size   = bootm->map[i].size;
+
+               /* Work around for using bootloader mem */
+               if (i == 0 && start == 0 && size == 0x0c000000)
+                       size = 0x0ff00000;
+
+               add_memory_region(start, size - pref_backup, BOOT_MEM_RAM);
+       }
+}
+
+void __init prom_init(void)
+{
+       int *argv, *envp;               /* passed as 32 bit ptrs */
+       struct psb_info *prom_infop;
+
+       /* truncate to 32 bit and sign extend all args */
+       argv = (int *)(long)(int)fw_arg1;
+       envp = (int *)(long)(int)fw_arg2;
+       prom_infop = (struct psb_info *)(long)(int)fw_arg3;
+
+       nlm_prom_info = *prom_infop;
+
+       nlm_early_serial_setup();
+       build_arcs_cmdline(argv);
+       nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
+       prom_add_memory();
+
+#ifdef CONFIG_SMP
+       nlm_wakeup_secondary_cpus(nlm_prom_info.online_cpu_map);
+       register_smp_ops(&nlm_smp_ops);
+#endif
+}
diff --git a/arch/mips/netlogic/xlr/smp.c b/arch/mips/netlogic/xlr/smp.c
new file mode 100644 (file)
index 0000000..b495a7f
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+
+#include <asm/mmu_context.h>
+
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/mips-extns.h>
+
+#include <asm/netlogic/xlr/iomap.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/xlr.h>
+
+void core_send_ipi(int logical_cpu, unsigned int action)
+{
+       int cpu = cpu_logical_map(logical_cpu);
+       u32 tid = cpu & 0x3;
+       u32 pid = (cpu >> 2) & 0x07;
+       u32 ipi = (tid << 16) | (pid << 20);
+
+       if (action & SMP_CALL_FUNCTION)
+               ipi |= IRQ_IPI_SMP_FUNCTION;
+       else if (action & SMP_RESCHEDULE_YOURSELF)
+               ipi |= IRQ_IPI_SMP_RESCHEDULE;
+       else
+               return;
+
+       pic_send_ipi(ipi);
+}
+
+void nlm_send_ipi_single(int cpu, unsigned int action)
+{
+       core_send_ipi(cpu, action);
+}
+
+void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+       int cpu;
+
+       for_each_cpu(cpu, mask) {
+               core_send_ipi(cpu, action);
+       }
+}
+
+/* IRQ_IPI_SMP_FUNCTION Handler */
+void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
+{
+       smp_call_function_interrupt();
+}
+
+/* IRQ_IPI_SMP_RESCHEDULE  handler */
+void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
+{
+       set_need_resched();
+}
+
+void nlm_common_ipi_handler(int irq, struct pt_regs *regs)
+{
+       if (irq == IRQ_IPI_SMP_FUNCTION) {
+               smp_call_function_interrupt();
+       } else {
+               /* Announce that we are for reschduling */
+               set_need_resched();
+       }
+}
+
+/*
+ * Called before going into mips code, early cpu init
+ */
+void nlm_early_init_secondary(void)
+{
+       write_c0_ebase((uint32_t)nlm_common_ebase);
+       /* TLB partition here later */
+}
+
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+static void __cpuinit nlm_init_secondary(void)
+{
+       nlm_smp_irq_init();
+}
+
+void nlm_smp_finish(void)
+{
+#ifdef notyet
+       nlm_common_msgring_cpu_init();
+#endif
+}
+
+void nlm_cpus_done(void)
+{
+}
+
+/*
+ * Boot all other cpus in the system, initialize them, and bring them into
+ * the boot function
+ */
+int nlm_cpu_unblock[NR_CPUS];
+int nlm_cpu_ready[NR_CPUS];
+unsigned long nlm_next_gp;
+unsigned long nlm_next_sp;
+cpumask_t phys_cpu_present_map;
+
+void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
+{
+       unsigned long gp = (unsigned long)task_thread_info(idle);
+       unsigned long sp = (unsigned long)__KSTK_TOS(idle);
+       int cpu = cpu_logical_map(logical_cpu);
+
+       nlm_next_sp = sp;
+       nlm_next_gp = gp;
+
+       /* barrier */
+       __sync();
+       nlm_cpu_unblock[cpu] = 1;
+}
+
+void __init nlm_smp_setup(void)
+{
+       unsigned int boot_cpu;
+       int num_cpus, i;
+
+       boot_cpu = hard_smp_processor_id();
+       cpus_clear(phys_cpu_present_map);
+
+       cpu_set(boot_cpu, phys_cpu_present_map);
+       __cpu_number_map[boot_cpu] = 0;
+       __cpu_logical_map[0] = boot_cpu;
+       cpu_set(0, cpu_possible_map);
+
+       num_cpus = 1;
+       for (i = 0; i < NR_CPUS; i++) {
+               if (nlm_cpu_ready[i]) {
+                       cpu_set(i, phys_cpu_present_map);
+                       __cpu_number_map[i] = num_cpus;
+                       __cpu_logical_map[num_cpus] = i;
+                       cpu_set(num_cpus, cpu_possible_map);
+                       ++num_cpus;
+               }
+       }
+
+       pr_info("Phys CPU present map: %lx, possible map %lx\n",
+               (unsigned long)phys_cpu_present_map.bits[0],
+               (unsigned long)cpu_possible_map.bits[0]);
+
+       pr_info("Detected %i Slave CPU(s)\n", num_cpus);
+}
+
+void nlm_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+struct plat_smp_ops nlm_smp_ops = {
+       .send_ipi_single        = nlm_send_ipi_single,
+       .send_ipi_mask          = nlm_send_ipi_mask,
+       .init_secondary         = nlm_init_secondary,
+       .smp_finish             = nlm_smp_finish,
+       .cpus_done              = nlm_cpus_done,
+       .boot_secondary         = nlm_boot_secondary,
+       .smp_setup              = nlm_smp_setup,
+       .prepare_cpus           = nlm_prepare_cpus,
+};
+
+unsigned long secondary_entry_point;
+
+int nlm_wakeup_secondary_cpus(u32 wakeup_mask)
+{
+       unsigned int tid, pid, ipi, i, boot_cpu;
+       void *reset_vec;
+
+       secondary_entry_point = (unsigned long)prom_pre_boot_secondary_cpus;
+       reset_vec = (void *)CKSEG1ADDR(0x1fc00000);
+       memcpy(reset_vec, nlm_boot_smp_nmi, 0x80);
+       boot_cpu = hard_smp_processor_id();
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (i == boot_cpu)
+                       continue;
+               if (wakeup_mask & (1u << i)) {
+                       tid = i & 0x3;
+                       pid = (i >> 2) & 0x7;
+                       ipi = (tid << 16) | (pid << 20) | (1 << 8);
+                       pic_send_ipi(ipi);
+               }
+       }
+
+       return 0;
+}
diff --git a/arch/mips/netlogic/xlr/smpboot.S b/arch/mips/netlogic/xlr/smpboot.S
new file mode 100644 (file)
index 0000000..b8e0744
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+
+/* Don't jump to linux function from Bootloader stack. Change it
+ * here. Kernel might allocate bootloader memory before all the CPUs are
+ * brought up (eg: Inode cache region) and we better don't overwrite this
+ * memory
+ */
+NESTED(prom_pre_boot_secondary_cpus, 16, sp)
+       .set    mips64
+       mfc0    t0, $15, 1      # read ebase
+       andi    t0, 0x1f        # t0 has the processor_id()
+       sll     t0, 2           # offset in cpu array
+
+       PTR_LA  t1, nlm_cpu_ready # mark CPU ready
+       PTR_ADDU t1, t0
+       li      t2, 1
+       sw      t2, 0(t1)
+
+       PTR_LA  t1, nlm_cpu_unblock
+       PTR_ADDU t1, t0
+1:     lw      t2, 0(t1)       # wait till unblocked
+       beqz    t2, 1b
+       nop
+
+       PTR_LA  t1, nlm_next_sp
+       PTR_L   sp, 0(t1)
+       PTR_LA  t1, nlm_next_gp
+       PTR_L   gp, 0(t1)
+
+       PTR_LA  t0, nlm_early_init_secondary
+       jalr    t0
+       nop
+
+       PTR_LA  t0, smp_bootstrap
+       jr      t0
+       nop
+END(prom_pre_boot_secondary_cpus)
+
+NESTED(nlm_boot_smp_nmi, 0, sp)
+       .set push
+       .set noat
+       .set mips64
+       .set noreorder
+
+       /* Clear the  NMI and BEV bits */
+       MFC0    k0, CP0_STATUS
+       li      k1, 0xffb7ffff
+       and     k0, k0, k1
+       MTC0    k0, CP0_STATUS
+
+       PTR_LA  k1, secondary_entry_point
+       PTR_L   k0, 0(k1)
+       jr      k0
+       nop
+       .set pop
+END(nlm_boot_smp_nmi)
diff --git a/arch/mips/netlogic/xlr/time.c b/arch/mips/netlogic/xlr/time.c
new file mode 100644 (file)
index 0000000..0d81b26
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+
+#include <asm/time.h>
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/psb-bootinfo.h>
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+       return IRQ_TIMER;
+}
+
+void __init plat_time_init(void)
+{
+       mips_hpt_frequency = nlm_prom_info.cpu_frequency;
+       pr_info("MIPS counter frequency [%ld]\n",
+               (unsigned long)mips_hpt_frequency);
+}
diff --git a/arch/mips/netlogic/xlr/xlr_console.c b/arch/mips/netlogic/xlr/xlr_console.c
new file mode 100644 (file)
index 0000000..759df06
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/types.h>
+#include <asm/netlogic/xlr/iomap.h>
+
+void prom_putchar(char c)
+{
+       nlm_reg_t *mmio;
+
+       mmio = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET);
+       while (netlogic_read_reg(mmio, 0x5) == 0)
+               ;
+       netlogic_write_reg(mmio, 0x0, c);
+}
index c9209ca6c8e7177c6ece17d6ac12d94d6edaff6d..4df879937446c16d252e9d3a9d00922f5e4c15f3 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_SIBYTE_SB1250)   += fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM112X)   += fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM1x80)   += pci-bcm1480.o pci-bcm1480ht.o
 obj-$(CONFIG_SNI_RM)           += fixup-sni.o ops-sni.o
+obj-$(CONFIG_SOC_XWAY)         += pci-lantiq.o ops-lantiq.o
 obj-$(CONFIG_TANBAC_TB0219)    += fixup-tb0219.o
 obj-$(CONFIG_TANBAC_TB0226)    += fixup-tb0226.o
 obj-$(CONFIG_TANBAC_TB0287)    += fixup-tb0287.o
@@ -55,6 +56,7 @@ obj-$(CONFIG_ZAO_CAPCELLA)    += fixup-capcella.o
 obj-$(CONFIG_WR_PPMC)          += fixup-wrppmc.o
 obj-$(CONFIG_MIKROTIK_RB532)   += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
 obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += pci-octeon.o pcie-octeon.o
+obj-$(CONFIG_NLM_XLR)          += pci-xlr.o
 
 ifdef CONFIG_PCI_MSI
 obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += msi-octeon.o
diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c
new file mode 100644 (file)
index 0000000..1f2afb5
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <asm/addrspace.h>
+#include <linux/vmalloc.h>
+
+#include <lantiq_soc.h>
+
+#include "pci-lantiq.h"
+
+#define LTQ_PCI_CFG_BUSNUM_SHF 16
+#define LTQ_PCI_CFG_DEVNUM_SHF 11
+#define LTQ_PCI_CFG_FUNNUM_SHF 8
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
+       unsigned int devfn, unsigned int where, u32 *data)
+{
+       unsigned long cfg_base;
+       unsigned long flags;
+       u32 temp;
+
+       /* we support slot from 0 to 15 dev_fn & 0x68 (AD29) is the
+          SoC itself */
+       if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
+               || ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
+               return 1;
+
+       spin_lock_irqsave(&ebu_lock, flags);
+
+       cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+       cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
+                       LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
+
+       /* Perform access */
+       if (access_type == PCI_ACCESS_WRITE) {
+               ltq_w32(swab32(*data), ((u32 *)cfg_base));
+       } else {
+               *data = ltq_r32(((u32 *)(cfg_base)));
+               *data = swab32(*data);
+       }
+       wmb();
+
+       /* clean possible Master abort */
+       cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+       cfg_base |= (0x0 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+       temp = ltq_r32(((u32 *)(cfg_base)));
+       temp = swab32(temp);
+       cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+       cfg_base |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+       ltq_w32(temp, ((u32 *)cfg_base));
+
+       spin_unlock_irqrestore(&ebu_lock, flags);
+
+       if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
+               return 1;
+
+       return 0;
+}
+
+int ltq_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 *val)
+{
+       u32 data = 0;
+
+       if (ltq_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (size == 1)
+               *val = (data >> ((where & 3) << 3)) & 0xff;
+       else if (size == 2)
+               *val = (data >> ((where & 3) << 3)) & 0xffff;
+       else
+               *val = data;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+int ltq_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 val)
+{
+       u32 data = 0;
+
+       if (size == 4) {
+               data = val;
+       } else {
+               if (ltq_pci_config_access(PCI_ACCESS_READ, bus,
+                               devfn, where, &data))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+               if (size == 1)
+                       data = (data & ~(0xff << ((where & 3) << 3))) |
+                               (val << ((where & 3) << 3));
+               else if (size == 2)
+                       data = (data & ~(0xffff << ((where & 3) << 3))) |
+                               (val << ((where & 3) << 3));
+       }
+
+       if (ltq_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
new file mode 100644 (file)
index 0000000..603d749
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+
+#include <asm/pci.h>
+#include <asm/gpio.h>
+#include <asm/addrspace.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
+#include <lantiq_platform.h>
+
+#include "pci-lantiq.h"
+
+#define LTQ_PCI_CFG_BASE               0x17000000
+#define LTQ_PCI_CFG_SIZE               0x00008000
+#define LTQ_PCI_MEM_BASE               0x18000000
+#define LTQ_PCI_MEM_SIZE               0x02000000
+#define LTQ_PCI_IO_BASE                        0x1AE00000
+#define LTQ_PCI_IO_SIZE                        0x00200000
+
+#define PCI_CR_FCI_ADDR_MAP0           0x00C0
+#define PCI_CR_FCI_ADDR_MAP1           0x00C4
+#define PCI_CR_FCI_ADDR_MAP2           0x00C8
+#define PCI_CR_FCI_ADDR_MAP3           0x00CC
+#define PCI_CR_FCI_ADDR_MAP4           0x00D0
+#define PCI_CR_FCI_ADDR_MAP5           0x00D4
+#define PCI_CR_FCI_ADDR_MAP6           0x00D8
+#define PCI_CR_FCI_ADDR_MAP7           0x00DC
+#define PCI_CR_CLK_CTRL                        0x0000
+#define PCI_CR_PCI_MOD                 0x0030
+#define PCI_CR_PC_ARB                  0x0080
+#define PCI_CR_FCI_ADDR_MAP11hg                0x00E4
+#define PCI_CR_BAR11MASK               0x0044
+#define PCI_CR_BAR12MASK               0x0048
+#define PCI_CR_BAR13MASK               0x004C
+#define PCI_CS_BASE_ADDR1              0x0010
+#define PCI_CR_PCI_ADDR_MAP11          0x0064
+#define PCI_CR_FCI_BURST_LENGTH                0x00E8
+#define PCI_CR_PCI_EOI                 0x002C
+#define PCI_CS_STS_CMD                 0x0004
+
+#define PCI_MASTER0_REQ_MASK_2BITS     8
+#define PCI_MASTER1_REQ_MASK_2BITS     10
+#define PCI_MASTER2_REQ_MASK_2BITS     12
+#define INTERNAL_ARB_ENABLE_BIT                0
+
+#define LTQ_CGU_IFCCR          0x0018
+#define LTQ_CGU_PCICR          0x0034
+
+#define ltq_pci_w32(x, y)      ltq_w32((x), ltq_pci_membase + (y))
+#define ltq_pci_r32(x)         ltq_r32(ltq_pci_membase + (x))
+
+#define ltq_pci_cfg_w32(x, y)  ltq_w32((x), ltq_pci_mapped_cfg + (y))
+#define ltq_pci_cfg_r32(x)     ltq_r32(ltq_pci_mapped_cfg + (x))
+
+struct ltq_pci_gpio_map {
+       int pin;
+       int alt0;
+       int alt1;
+       int dir;
+       char *name;
+};
+
+/* the pci core can make use of the following gpios */
+static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
+       { 0, 1, 0, 0, "pci-exin0" },
+       { 1, 1, 0, 0, "pci-exin1" },
+       { 2, 1, 0, 0, "pci-exin2" },
+       { 39, 1, 0, 0, "pci-exin3" },
+       { 10, 1, 0, 0, "pci-exin4" },
+       { 9, 1, 0, 0, "pci-exin5" },
+       { 30, 1, 0, 1, "pci-gnt1" },
+       { 23, 1, 0, 1, "pci-gnt2" },
+       { 19, 1, 0, 1, "pci-gnt3" },
+       { 38, 1, 0, 1, "pci-gnt4" },
+       { 29, 1, 0, 0, "pci-req1" },
+       { 31, 1, 0, 0, "pci-req2" },
+       { 3, 1, 0, 0, "pci-req3" },
+       { 37, 1, 0, 0, "pci-req4" },
+};
+
+__iomem void *ltq_pci_mapped_cfg;
+static __iomem void *ltq_pci_membase;
+
+int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
+
+/* Since the PCI REQ pins can be reused for other functionality, make it
+   possible to exclude those from interpretation by the PCI controller */
+static int ltq_pci_req_mask = 0xf;
+
+static int *ltq_pci_irq_map;
+
+struct pci_ops ltq_pci_ops = {
+       .read   = ltq_pci_read_config_dword,
+       .write  = ltq_pci_write_config_dword
+};
+
+static struct resource pci_io_resource = {
+       .name   = "pci io space",
+       .start  = LTQ_PCI_IO_BASE,
+       .end    = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+       .name   = "pci memory space",
+       .start  = LTQ_PCI_MEM_BASE,
+       .end    = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+static struct pci_controller ltq_pci_controller = {
+       .pci_ops        = &ltq_pci_ops,
+       .mem_resource   = &pci_mem_resource,
+       .mem_offset     = 0x00000000UL,
+       .io_resource    = &pci_io_resource,
+       .io_offset      = 0x00000000UL,
+};
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       if (ltqpci_plat_dev_init)
+               return ltqpci_plat_dev_init(dev);
+
+       return 0;
+}
+
+static u32 ltq_calc_bar11mask(void)
+{
+       u32 mem, bar11mask;
+
+       /* BAR11MASK value depends on available memory on system. */
+       mem = num_physpages * PAGE_SIZE;
+       bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8;
+
+       return bar11mask;
+}
+
+static void ltq_pci_setup_gpio(int gpio)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
+               if (gpio & (1 << i)) {
+                       ltq_gpio_request(ltq_pci_gpio_map[i].pin,
+                               ltq_pci_gpio_map[i].alt0,
+                               ltq_pci_gpio_map[i].alt1,
+                               ltq_pci_gpio_map[i].dir,
+                               ltq_pci_gpio_map[i].name);
+               }
+       }
+       ltq_gpio_request(21, 0, 0, 1, "pci-reset");
+       ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
+}
+
+static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
+{
+       u32 temp_buffer;
+
+       /* set clock to 33Mhz */
+       ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
+       ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+
+       /* external or internal clock ? */
+       if (conf->clock) {
+               ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
+                       LTQ_CGU_IFCCR);
+               ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
+       } else {
+               ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
+                       LTQ_CGU_IFCCR);
+               ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
+       }
+
+       /* setup pci clock and gpis used by pci */
+       ltq_pci_setup_gpio(conf->gpio);
+
+       /* enable auto-switching between PCI and EBU */
+       ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
+
+       /* busy, i.e. configuration is not done, PCI access has to be retried */
+       ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD);
+       wmb();
+       /* BUS Master/IO/MEM access */
+       ltq_pci_cfg_w32(ltq_pci_cfg_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD);
+
+       /* enable external 2 PCI masters */
+       temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
+       temp_buffer &= (~(ltq_pci_req_mask << 16));
+       /* enable internal arbiter */
+       temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
+       /* enable internal PCI master reqest */
+       temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS));
+
+       /* enable EBU request */
+       temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS));
+
+       /* enable all external masters request */
+       temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS));
+       ltq_pci_w32(temp_buffer, PCI_CR_PC_ARB);
+       wmb();
+
+       /* setup BAR memory regions */
+       ltq_pci_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0);
+       ltq_pci_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1);
+       ltq_pci_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2);
+       ltq_pci_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3);
+       ltq_pci_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4);
+       ltq_pci_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5);
+       ltq_pci_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6);
+       ltq_pci_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7);
+       ltq_pci_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg);
+       ltq_pci_w32(ltq_calc_bar11mask(), PCI_CR_BAR11MASK);
+       ltq_pci_w32(0, PCI_CR_PCI_ADDR_MAP11);
+       ltq_pci_w32(0, PCI_CS_BASE_ADDR1);
+       /* both TX and RX endian swap are enabled */
+       ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI);
+       wmb();
+       ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR12MASK) | 0x80000000,
+               PCI_CR_BAR12MASK);
+       ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR13MASK) | 0x80000000,
+               PCI_CR_BAR13MASK);
+       /*use 8 dw burst length */
+       ltq_pci_w32(0x303, PCI_CR_FCI_BURST_LENGTH);
+       ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD);
+       wmb();
+
+       /* setup irq line */
+       ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON);
+       ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
+
+       /* toggle reset pin */
+       __gpio_set_value(21, 0);
+       wmb();
+       mdelay(1);
+       __gpio_set_value(21, 1);
+       return 0;
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (ltq_pci_irq_map[slot])
+               return ltq_pci_irq_map[slot];
+       printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
+               slot);
+
+       return 0;
+}
+
+static int __devinit ltq_pci_probe(struct platform_device *pdev)
+{
+       struct ltq_pci_data *ltq_pci_data =
+               (struct ltq_pci_data *) pdev->dev.platform_data;
+       pci_probe_only = 0;
+       ltq_pci_irq_map = ltq_pci_data->irq;
+       ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
+       ltq_pci_mapped_cfg =
+               ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
+       ltq_pci_controller.io_map_base =
+               (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
+       ltq_pci_startup(ltq_pci_data);
+       register_pci_controller(&ltq_pci_controller);
+
+       return 0;
+}
+
+static struct platform_driver
+ltq_pci_driver = {
+       .probe = ltq_pci_probe,
+       .driver = {
+               .name = "ltq_pci",
+               .owner = THIS_MODULE,
+       },
+};
+
+int __init pcibios_init(void)
+{
+       int ret = platform_driver_register(&ltq_pci_driver);
+       if (ret)
+               printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
+       return ret;
+}
+
+arch_initcall(pcibios_init);
diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h
new file mode 100644 (file)
index 0000000..66bf6cd
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_PCI_H__
+#define _LTQ_PCI_H__
+
+extern __iomem void *ltq_pci_mapped_cfg;
+extern int ltq_pci_read_config_dword(struct pci_bus *bus,
+       unsigned int devfn, int where, int size, u32 *val);
+extern int ltq_pci_write_config_dword(struct pci_bus *bus,
+       unsigned int devfn, int where, int size, u32 val);
+
+#endif
diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
new file mode 100644 (file)
index 0000000..38fece1
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
+ * reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the NetLogic
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/xlr/iomap.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/xlr.h>
+
+static void *pci_config_base;
+
+#define        pci_cfg_addr(bus, devfn, off) (((bus) << 16) | ((devfn) << 8) | (off))
+
+/* PCI ops */
+static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
+       int where)
+{
+       u32 data;
+       u32 *cfgaddr;
+
+       cfgaddr = (u32 *)(pci_config_base +
+                       pci_cfg_addr(bus->number, devfn, where & ~3));
+       data = *cfgaddr;
+       return cpu_to_le32(data);
+}
+
+static inline void pci_cfg_write_32bit(struct pci_bus *bus, unsigned int devfn,
+       int where, u32 data)
+{
+       u32 *cfgaddr;
+
+       cfgaddr = (u32 *)(pci_config_base +
+                       pci_cfg_addr(bus->number, devfn, where & ~3));
+       *cfgaddr = cpu_to_le32(data);
+}
+
+static int nlm_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 *val)
+{
+       u32 data;
+
+       if ((size == 2) && (where & 1))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       else if ((size == 4) && (where & 3))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       data = pci_cfg_read_32bit(bus, devfn, where);
+
+       if (size == 1)
+               *val = (data >> ((where & 3) << 3)) & 0xff;
+       else if (size == 2)
+               *val = (data >> ((where & 3) << 3)) & 0xffff;
+       else
+               *val = data;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int nlm_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+               int where, int size, u32 val)
+{
+       u32 data;
+
+       if ((size == 2) && (where & 1))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       else if ((size == 4) && (where & 3))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       data = pci_cfg_read_32bit(bus, devfn, where);
+
+       if (size == 1)
+               data = (data & ~(0xff << ((where & 3) << 3))) |
+                       (val << ((where & 3) << 3));
+       else if (size == 2)
+               data = (data & ~(0xffff << ((where & 3) << 3))) |
+                       (val << ((where & 3) << 3));
+       else
+               data = val;
+
+       pci_cfg_write_32bit(bus, devfn, where, data);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops nlm_pci_ops = {
+       .read  = nlm_pcibios_read,
+       .write = nlm_pcibios_write
+};
+
+static struct resource nlm_pci_mem_resource = {
+       .name           = "XLR PCI MEM",
+       .start          = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */
+       .end            = 0xdfffffffUL,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct resource nlm_pci_io_resource = {
+       .name           = "XLR IO MEM",
+       .start          = 0x10000000UL, /* 16MB PCI IO @ 0x1000_0000 */
+       .end            = 0x100fffffUL,
+       .flags          = IORESOURCE_IO,
+};
+
+struct pci_controller nlm_pci_controller = {
+       .index          = 0,
+       .pci_ops        = &nlm_pci_ops,
+       .mem_resource   = &nlm_pci_mem_resource,
+       .mem_offset     = 0x00000000UL,
+       .io_resource    = &nlm_pci_io_resource,
+       .io_offset      = 0x00000000UL,
+};
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (!nlm_chip_is_xls())
+               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ*/
+
+       /*
+        * For XLS PCIe, there is an IRQ per Link, find out which
+        * link the device is on to assign interrupts
+       */
+       if (dev->bus->self == NULL)
+               return 0;
+
+       switch  (dev->bus->self->devfn) {
+       case 0x0:
+               return PIC_PCIE_LINK0_IRQ;
+       case 0x8:
+               return PIC_PCIE_LINK1_IRQ;
+       case 0x10:
+               if (nlm_chip_is_xls_b())
+                       return PIC_PCIE_XLSB0_LINK2_IRQ;
+               else
+                       return PIC_PCIE_LINK2_IRQ;
+       case 0x18:
+               if (nlm_chip_is_xls_b())
+                       return PIC_PCIE_XLSB0_LINK3_IRQ;
+               else
+                       return PIC_PCIE_LINK3_IRQ;
+       }
+       WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
+       return 0;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
+
+static int __init pcibios_init(void)
+{
+       /* PSB assigns PCI resources */
+       pci_probe_only = 1;
+       pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
+
+       /* Extend IO port for memory mapped io */
+       ioport_resource.start =  0;
+       ioport_resource.end   = ~0;
+
+       set_io_port_base(CKSEG1);
+       nlm_pci_controller.io_map_base = CKSEG1;
+
+       pr_info("Registering XLR/XLS PCIX/PCIE Controller.\n");
+       register_pci_controller(&nlm_pci_controller);
+
+       return 0;
+}
+
+arch_initcall(pcibios_init);
+
+struct pci_fixup pcibios_fixups[] = {
+       {0}
+};
index f9b9dcdfa9ddc1c5db23066f9259339e8e2ccc47..98fd0099d964becd05c7e57fd5404be50c5773f3 100644 (file)
@@ -97,7 +97,7 @@ static int msp_per_irq_set_affinity(struct irq_data *d,
 
 static struct irq_chip msp_per_irq_controller = {
        .name = "MSP_PER",
-       .irq_enable = unmask_per_irq.
+       .irq_enable = unmask_per_irq,
        .irq_disable = mask_per_irq,
        .irq_ack = msp_per_irq_ack,
 #ifdef CONFIG_SMP
index efc9e889b34939d6a3cbd5f14303317eb0e51bef..2608752898c0823671b51773178edcd6e945398c 100644 (file)
@@ -55,6 +55,8 @@ void titan_mailbox_irq(void)
 
                if (status & 0x2)
                        smp_call_function_interrupt();
+               if (status & 0x4)
+                       scheduler_ipi();
                break;
 
        case 1:
@@ -63,6 +65,8 @@ void titan_mailbox_irq(void)
 
                if (status & 0x2)
                        smp_call_function_interrupt();
+               if (status & 0x4)
+                       scheduler_ipi();
                break;
        }
 }
index dbb5c7b4b70fcebdd25229bf084470dd9d60d6ef..f8a751c032823f25f088530d53acb23fdd11d5e2 100644 (file)
@@ -35,7 +35,7 @@ LEAF(swsusp_arch_resume)
 0:
        PTR_L t1, PBE_ADDRESS(t0)   /* source */
        PTR_L t2, PBE_ORIG_ADDRESS(t0) /* destination */
-       PTR_ADDIU t3, t1, PAGE_SIZE
+       PTR_ADDU t3, t1, PAGE_SIZE
 1:
        REG_L t8, (t1)
        REG_S t8, (t2)
index 37de05d595e725ebdc59513181d3f43709ce1cb4..6c47dfeb7be326bf2dc4c5a7a1cbb1984b87efec 100644 (file)
@@ -185,7 +185,7 @@ int __init rb532_gpio_init(void)
        struct resource *r;
 
        r = rb532_gpio_reg0_res;
-       rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start);
+       rb532_gpio_chip->regbase = ioremap_nocache(r->start, resource_size(r));
 
        if (!rb532_gpio_chip->regbase) {
                printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
index deddbf0ebe5c839175353b3f7f8cce68a594106c..698904daf901d17a921ae5c3c24effa85706fb6a 100644 (file)
@@ -132,7 +132,7 @@ static struct platform_device eth1_device = {
  */
 static int __init sgiseeq_devinit(void)
 {
-       unsigned int tmp;
+       unsigned int pbdma __maybe_unused;
        int res, i;
 
        eth0_pd.hpc = hpc3c0;
@@ -151,7 +151,7 @@ static int __init sgiseeq_devinit(void)
 
        /* Second HPC is missing? */
        if (ip22_is_fullhouse() ||
-           get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
+           get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1]))
                return 0;
 
        sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 |
index 603fc91c1030539b8bc33ad88902b240ea84a203..1a94c989418843e22267110bab6e43e6d1d2c937 100644 (file)
@@ -32,7 +32,7 @@
 static unsigned long dosample(void)
 {
        u32 ct0, ct1;
-       u8 msb, lsb;
+       u8 msb;
 
        /* Start the counter. */
        sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL |
@@ -46,7 +46,7 @@ static unsigned long dosample(void)
        /* Latch and spin until top byte of counter2 is zero */
        do {
                writeb(SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT, &sgint->tcword);
-               lsb = readb(&sgint->tcnt2);
+               (void) readb(&sgint->tcnt2);
                msb = readb(&sgint->tcnt2);
                ct1 = read_c0_count();
        } while (msb);
index a1fa4abb3f6a719ad0122a0861f3b2d659d293a4..cd0d5b06cd8385dc9c73d89bcd0fa6691a78622e 100644 (file)
@@ -29,7 +29,6 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
                          unsigned long xtalk_addr, size_t size)
 {
        nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
-       volatile hubreg_t junk;
        unsigned i;
 
        /* use small-window mapping if possible */
@@ -64,7 +63,7 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
                 * after we write it.
                 */
                IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
-               junk = HUB_L(IIO_ITTE_GET(nasid, i));
+               (void) HUB_L(IIO_ITTE_GET(nasid, i));
 
                return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
        }
index 0a04603d577c840f6e70c8a9876987535054150d..b18b04e48577550f6b42c43d393d06c91741285b 100644 (file)
@@ -147,8 +147,10 @@ static void ip27_do_irq_mask0(void)
 #ifdef CONFIG_SMP
        if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) {
                LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
+               scheduler_ipi();
        } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) {
                LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
+               scheduler_ipi();
        } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) {
                LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
                smp_call_function_interrupt();
index c3d30a88daf3a1555f9a1495f058210479a3b0ce..1d1919a44e88c350685866d8420b24fa9e168dc9 100644 (file)
@@ -54,11 +54,8 @@ void __init setup_replication_mask(void)
 
 static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
 {
-       cnodeid_t client_cnode;
        kern_vars_t *kvp;
 
-       client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
-
        kvp = &hub_data(client_nasid)->kern_vars;
 
        KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
index a152538d3c9744cb27f40a0e18d5a69eeb94c91c..ef74f3267f9102bfa870e713311520d94fe6c723 100644 (file)
@@ -66,18 +66,7 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
 static void rt_set_mode(enum clock_event_mode mode,
                struct clock_event_device *evt)
 {
-       switch (mode) {
-       case CLOCK_EVT_MODE_ONESHOT:
-               /* The only mode supported */
-               break;
-
-       case CLOCK_EVT_MODE_PERIODIC:
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_RESUME:
-               /* Nothing to do  */
-               break;
-       }
+       /* Nothing to do ...  */
 }
 
 int rt_timer_irq;
@@ -174,8 +163,7 @@ static void __init hub_rt_clocksource_init(void)
 {
        struct clocksource *cs = &hub_rt_clocksource;
 
-       clocksource_set_clock(cs, CYCLES_PER_SEC);
-       clocksource_register(cs);
+       clocksource_register_hz(cs, CYCLES_PER_SEC);
 }
 
 void __init plat_time_init(void)
index 47b347c992eaf129a3a6df335aeb6739d60a7632..d667875be564ef97dbd55cc6ffced70e207ff202 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/smp.h>
 #include <linux/kernel_stat.h>
+#include <linux/sched.h>
 
 #include <asm/mmu_context.h>
 #include <asm/io.h>
@@ -189,10 +190,8 @@ void bcm1480_mailbox_interrupt(void)
        /* Clear the mailbox to clear the interrupt */
        __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
 
-       /*
-        * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
-        * interrupt will do the reschedule for us
-        */
+       if (action & SMP_RESCHEDULE_YOURSELF)
+               scheduler_ipi();
 
        if (action & SMP_CALL_FUNCTION)
                smp_call_function_interrupt();
index c00a5cb1128d324ed678afec5d9c6cc6cd2620df..38e7f6bd7922edd6c25e2169515cdccacfc81ea7 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <linux/kernel_stat.h>
+#include <linux/sched.h>
 
 #include <asm/mmu_context.h>
 #include <asm/io.h>
@@ -177,10 +178,8 @@ void sb1250_mailbox_interrupt(void)
        /* Clear the mailbox to clear the interrupt */
        ____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
 
-       /*
-        * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
-        * interrupt will do the reschedule for us
-        */
+       if (action & SMP_RESCHEDULE_YOURSELF)
+               scheduler_ipi();
 
        if (action & SMP_CALL_FUNCTION)
                smp_call_function_interrupt();
index c76151b56568ee241e345fe779d3454df0179add..0904d4d30cb338d1bdd4beaaf136472b488f4657 100644 (file)
@@ -95,7 +95,7 @@ static void __init sni_a20r_timer_setup(void)
 static __init unsigned long dosample(void)
 {
        u32 ct0, ct1;
-       volatile u8 msb, lsb;
+       volatile u8 msb;
 
        /* Start the counter. */
        outb_p(0x34, 0x43);
@@ -108,7 +108,7 @@ static __init unsigned long dosample(void)
        /* Latch and spin until top byte of counter0 is zero */
        do {
                outb(0x00, 0x43);
-               lsb = inb(0x40);
+               (void) inb(0x40);
                msb = inb(0x40);
                ct1 = read_c0_count();
        } while (msb);
index 226c826a21940c79a778b6c7284116cdedc647ea..83fb2791223134aece3c8d29587dc810aed87d31 100644 (file)
@@ -494,14 +494,11 @@ void smp_send_stop(void)
  * @irq: The interrupt number.
  * @dev_id: The device ID.
  *
- * We need do nothing here, since the scheduling will be effected on our way
- * back through entry.S.
- *
  * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
  */
 static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
 {
-       /* do nothing */
+       scheduler_ipi();
        return IRQ_HANDLED;
 }
 
index 69d63d354ef05fac8f86a1ff69e98ddefdd93125..828305f19cfffd202e6c0244bff54a561eb7fe3f 100644 (file)
@@ -155,10 +155,7 @@ ipi_interrupt(int irq, void *dev_id)
                                
                        case IPI_RESCHEDULE:
                                smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu);
-                               /*
-                                * Reschedule callback.  Everything to be
-                                * done is done by the interrupt return path.
-                                */
+                               scheduler_ipi();
                                break;
 
                        case IPI_CALL_FUNC:
index b7ed8d7a9b33a10e784722a3fa5b8a55f7eabbcb..b1d126258dee10612054ac3bb1a472c562b37cbc 100644 (file)
@@ -266,8 +266,10 @@ static void __init setup_bootmem(void)
        }
        memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
-       for (i = 0; i < npmem_ranges; i++)
+       for (i = 0; i < npmem_ranges; i++) {
+               node_set_state(i, N_NORMAL_MEMORY);
                node_set_online(i);
+       }
 #endif
 
        /*
index 6b6dc20b0bebab9b1154e7cd5bab13ebd669c85a..bdf0563ba423886a5cde9ff2a63a47e8a3365604 100644 (file)
@@ -393,8 +393,8 @@ typedef struct fec {
        uint    fec_addr_low;           /* lower 32 bits of station address     */
        ushort  fec_addr_high;          /* upper 16 bits of station address     */
        ushort  res1;                   /* reserved                             */
-       uint    fec_hash_table_high;    /* upper 32-bits of hash table          */
-       uint    fec_hash_table_low;     /* lower 32-bits of hash table          */
+       uint    fec_grp_hash_table_high;        /* upper 32-bits of hash table          */
+       uint    fec_grp_hash_table_low; /* lower 32-bits of hash table          */
        uint    fec_r_des_start;        /* beginning of Rx descriptor ring      */
        uint    fec_x_des_start;        /* beginning of Tx descriptor ring      */
        uint    fec_r_buff_size;        /* Rx buffer size                       */
index 7005ee0b074d744e6905fd8e0c6dfc144a3a4cb3..49baddcdd14e7eec81aaa31a4d54e7aa5a621382 100644 (file)
@@ -3,7 +3,6 @@
 #ifdef __KERNEL__
 
 #include <linux/irq.h>
-#include <linux/sysdev.h>
 #include <asm/dcr.h>
 #include <asm/msi_bitmap.h>
 
@@ -320,8 +319,6 @@ struct mpic
        /* link */
        struct mpic             *next;
 
-       struct sys_device       sysdev;
-
 #ifdef CONFIG_PM
        struct mpic_irq_save    *save_data;
 #endif
index ae9c899c8a6d119526ded6d78f883c6fdf452c88..d12b11d7641e662286d3ef1d2a3e306a352388b0 100644 (file)
@@ -60,7 +60,7 @@
  *
  * Obviously, the GART is not cache coherent and so any change to it
  * must be flushed to memory (or maybe just make the GART space non
- * cachable). AGP memory itself does't seem to be cache coherent neither.
+ * cachable). AGP memory itself doesn't seem to be cache coherent neither.
  *
  * In order to invalidate the GART (which is probably necessary to inval
  * the bridge internal TLBs), the following sequence has to be written,
index 55613e33e263ac7abb3b1d478f4a27bb9912b86f..a6ae1cfad86ce86040553fa94346ad2043c3a0bb 100644 (file)
@@ -933,12 +933,16 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
        if (data && !(data & DABR_TRANSLATION))
                return -EIO;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
+       if (ptrace_get_breakpoints(task) < 0)
+               return -ESRCH;
+
        bp = thread->ptrace_bps[0];
        if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
                if (bp) {
                        unregister_hw_breakpoint(bp);
                        thread->ptrace_bps[0] = NULL;
                }
+               ptrace_put_breakpoints(task);
                return 0;
        }
        if (bp) {
@@ -948,9 +952,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                                        (DABR_DATA_WRITE | DABR_DATA_READ),
                                                        &attr.bp_type);
                ret =  modify_user_hw_breakpoint(bp, &attr);
-               if (ret)
+               if (ret) {
+                       ptrace_put_breakpoints(task);
                        return ret;
+               }
                thread->ptrace_bps[0] = bp;
+               ptrace_put_breakpoints(task);
                thread->dabr = data;
                return 0;
        }
@@ -965,9 +972,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                                                        ptrace_triggered, task);
        if (IS_ERR(bp)) {
                thread->ptrace_bps[0] = NULL;
+               ptrace_put_breakpoints(task);
                return PTR_ERR(bp);
        }
 
+       ptrace_put_breakpoints(task);
+
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
        /* Move contents to the DABR register */
index cbdbb14be4b07b0eb31faefec1bfb06e572761c4..9f9c204bef69b3e8523a0e339d5d58251a9184e2 100644 (file)
@@ -116,7 +116,7 @@ void smp_message_recv(int msg)
                generic_smp_call_function_interrupt();
                break;
        case PPC_MSG_RESCHEDULE:
-               /* we notice need_resched on exit */
+               scheduler_ipi();
                break;
        case PPC_MSG_CALL_FUNC_SINGLE:
                generic_smp_call_function_single_interrupt();
@@ -146,7 +146,7 @@ static irqreturn_t call_function_action(int irq, void *data)
 
 static irqreturn_t reschedule_action(int irq, void *data)
 {
-       /* we just need the return path side effect of checking need_resched */
+       scheduler_ipi();
        return IRQ_HANDLED;
 }
 
index 188272934cfb3c6818754dae0260216b5c4ccb65..104faa8aa23c783da70b2dd97dac842ff8198c3c 100644 (file)
@@ -318,17 +318,20 @@ static const struct platform_suspend_ops mpc83xx_suspend_ops = {
        .end = mpc83xx_suspend_end,
 };
 
+static struct of_device_id pmc_match[];
 static int pmc_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct device_node *np = ofdev->dev.of_node;
        struct resource res;
        struct pmc_type *type;
        int ret = 0;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(pmc_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
 
-       type = ofdev->dev.of_match->data;
+       type = match->data;
 
        if (!of_device_is_available(np))
                return -ENODEV;
index acfaccea5f4fa4d08f36bab9efe60d24a366f554..3675da73623f156fb86528b8d9132b7399d72a17 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/io.h>
 #include <linux/mutex.h>
 #include <linux/linux_logo.h>
+#include <linux/syscore_ops.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
 #include <asm/spu_csa.h>
@@ -521,18 +522,8 @@ void spu_init_channels(struct spu *spu)
 }
 EXPORT_SYMBOL_GPL(spu_init_channels);
 
-static int spu_shutdown(struct sys_device *sysdev)
-{
-       struct spu *spu = container_of(sysdev, struct spu, sysdev);
-
-       spu_free_irqs(spu);
-       spu_destroy_spu(spu);
-       return 0;
-}
-
 static struct sysdev_class spu_sysdev_class = {
        .name = "spu",
-       .shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -797,6 +788,22 @@ static inline void crash_register_spus(struct list_head *list)
 }
 #endif
 
+static void spu_shutdown(void)
+{
+       struct spu *spu;
+
+       mutex_lock(&spu_full_list_mutex);
+       list_for_each_entry(spu, &spu_full_list, full_list) {
+               spu_free_irqs(spu);
+               spu_destroy_spu(spu);
+       }
+       mutex_unlock(&spu_full_list_mutex);
+}
+
+static struct syscore_ops spu_syscore_ops = {
+       .shutdown = spu_shutdown,
+};
+
 static int __init init_spu_base(void)
 {
        int i, ret = 0;
@@ -830,6 +837,7 @@ static int __init init_spu_base(void)
        crash_register_spus(&spu_full_list);
        mutex_unlock(&spu_full_list_mutex);
        spu_add_sysdev_attr(&attr_stat);
+       register_syscore_ops(&spu_syscore_ops);
 
        spu_init_affinity();
 
index 023f24086a0ae08c9c1a3871a4ae24c754fe69ca..7c18a1607d1c872efbd640cdd3f14bcb756a8a9b 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/signal.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/module.h>
@@ -677,7 +677,7 @@ not_found:
        return viaint;
 }
 
-static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
+static int pmacpic_suspend(void)
 {
        int viaint = pmacpic_find_viaint();
 
@@ -698,7 +698,7 @@ static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
         return 0;
 }
 
-static int pmacpic_resume(struct sys_device *sysdev)
+static void pmacpic_resume(void)
 {
        int i;
 
@@ -709,39 +709,19 @@ static int pmacpic_resume(struct sys_device *sysdev)
        for (i = 0; i < max_real_irqs; ++i)
                if (test_bit(i, sleep_save_mask))
                        pmac_unmask_irq(irq_get_irq_data(i));
-
-       return 0;
 }
 
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-
-static struct sysdev_class pmacpic_sysclass = {
-       .name = "pmac_pic",
+static struct syscore_ops pmacpic_syscore_ops = {
+       .suspend        = pmacpic_suspend,
+       .resume         = pmacpic_resume,
 };
 
-static struct sys_device device_pmacpic = {
-       .id             = 0,
-       .cls            = &pmacpic_sysclass,
-};
-
-static struct sysdev_driver driver_pmacpic = {
-#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
-       .suspend        = &pmacpic_suspend,
-       .resume         = &pmacpic_resume,
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-};
-
-static int __init init_pmacpic_sysfs(void)
+static int __init init_pmacpic_syscore(void)
 {
-#ifdef CONFIG_PPC32
-       if (max_irqs == 0)
-               return -ENODEV;
-#endif
-       printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
-       sysdev_class_register(&pmacpic_sysclass);
-       sysdev_register(&device_pmacpic);
-       sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
+       register_syscore_ops(&pmacpic_syscore_ops);
        return 0;
 }
-machine_subsys_initcall(powermac, init_pmacpic_sysfs);
 
+machine_subsys_initcall(powermac, init_pmacpic_syscore);
+
+#endif /* CONFIG_PM && CONFIG_PPC32 */
index d5679dc1e20faddf7d5a20df6bc1374aee74e264..01cd2f089512149b7817199b7915677c6fa86b24 100644 (file)
@@ -304,8 +304,10 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
        return 0;
 }
 
+static const struct of_device_id fsl_of_msi_ids[];
 static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 {
+       const struct of_device_id *match;
        struct fsl_msi *msi;
        struct resource res;
        int err, i, j, irq_index, count;
@@ -316,9 +318,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
        u32 offset;
        static const u32 all_avail[] = { 0, NR_MSI_IRQS };
 
-       if (!dev->dev.of_match)
+       match = of_match_device(fsl_of_msi_ids, &dev->dev);
+       if (!match)
                return -EINVAL;
-       features = dev->dev.of_match->data;
+       features = match->data;
 
        printk(KERN_DEBUG "Setting up Freescale MSI support\n");
 
index fa438be962b71a2519fc00ff054698226a529b75..596554a8725e7de303485581dacce3f9ea5b9152 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/device.h>
 #include <linux/bootmem.h>
 #include <linux/spinlock.h>
@@ -902,7 +902,7 @@ static struct {
        u32 sercr;
 } ipic_saved_state;
 
-static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+static int ipic_suspend(void)
 {
        struct ipic *ipic = primary_ipic;
 
@@ -933,7 +933,7 @@ static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
        return 0;
 }
 
-static int ipic_resume(struct sys_device *sdev)
+static void ipic_resume(void)
 {
        struct ipic *ipic = primary_ipic;
 
@@ -949,44 +949,26 @@ static int ipic_resume(struct sys_device *sdev)
        ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
        ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
        ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
-
-       return 0;
 }
 #else
 #define ipic_suspend NULL
 #define ipic_resume NULL
 #endif
 
-static struct sysdev_class ipic_sysclass = {
-       .name = "ipic",
+static struct syscore_ops ipic_syscore_ops = {
        .suspend = ipic_suspend,
        .resume = ipic_resume,
 };
 
-static struct sys_device device_ipic = {
-       .id             = 0,
-       .cls            = &ipic_sysclass,
-};
-
-static int __init init_ipic_sysfs(void)
+static int __init init_ipic_syscore(void)
 {
-       int rc;
-
        if (!primary_ipic || !primary_ipic->regs)
                return -ENODEV;
-       printk(KERN_DEBUG "Registering ipic with sysfs...\n");
 
-       rc = sysdev_class_register(&ipic_sysclass);
-       if (rc) {
-               printk(KERN_ERR "Failed registering ipic sys class\n");
-               return -ENODEV;
-       }
-       rc = sysdev_register(&device_ipic);
-       if (rc) {
-               printk(KERN_ERR "Failed registering ipic sys device\n");
-               return -ENODEV;
-       }
+       printk(KERN_DEBUG "Registering ipic system core operations\n");
+       register_syscore_ops(&ipic_syscore_ops);
+
        return 0;
 }
 
-subsys_initcall(init_ipic_sysfs);
+subsys_initcall(init_ipic_syscore);
index f91c065bed5a21be3f1a7fd6e186a27d72b3e6de..7e5dc8f4984a61be8f7952a6f51de6283a38551a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/ptrace.h>
 #include <asm/signal.h>
@@ -1702,9 +1703,8 @@ void mpic_reset_core(int cpu)
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PM
-static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+static void mpic_suspend_one(struct mpic *mpic)
 {
-       struct mpic *mpic = container_of(dev, struct mpic, sysdev);
        int i;
 
        for (i = 0; i < mpic->num_sources; i++) {
@@ -1713,13 +1713,22 @@ static int mpic_suspend(struct sys_device *dev, pm_message_t state)
                mpic->save_data[i].dest =
                        mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
        }
+}
+
+static int mpic_suspend(void)
+{
+       struct mpic *mpic = mpics;
+
+       while (mpic) {
+               mpic_suspend_one(mpic);
+               mpic = mpic->next;
+       }
 
        return 0;
 }
 
-static int mpic_resume(struct sys_device *dev)
+static void mpic_resume_one(struct mpic *mpic)
 {
-       struct mpic *mpic = container_of(dev, struct mpic, sysdev);
        int i;
 
        for (i = 0; i < mpic->num_sources; i++) {
@@ -1746,33 +1755,28 @@ static int mpic_resume(struct sys_device *dev)
        }
 #endif
        } /* end for loop */
+}
 
-       return 0;
+static void mpic_resume(void)
+{
+       struct mpic *mpic = mpics;
+
+       while (mpic) {
+               mpic_resume_one(mpic);
+               mpic = mpic->next;
+       }
 }
-#endif
 
-static struct sysdev_class mpic_sysclass = {
-#ifdef CONFIG_PM
+static struct syscore_ops mpic_syscore_ops = {
        .resume = mpic_resume,
        .suspend = mpic_suspend,
-#endif
-       .name = "mpic",
 };
 
 static int mpic_init_sys(void)
 {
-       struct mpic *mpic = mpics;
-       int error, id = 0;
-
-       error = sysdev_class_register(&mpic_sysclass);
-
-       while (mpic && !error) {
-               mpic->sysdev.cls = &mpic_sysclass;
-               mpic->sysdev.id = id++;
-               error = sysdev_register(&mpic->sysdev);
-               mpic = mpic->next;
-       }
-       return error;
+       register_syscore_ops(&mpic_syscore_ops);
+       return 0;
 }
 
 device_initcall(mpic_init_sys);
+#endif
index 2508a6f3158862af5cee200d8254150d139f2c7c..4a7f14079e03b989bd4cd4b1a012b082e07447b3 100644 (file)
@@ -88,6 +88,7 @@ config S390
        select HAVE_KERNEL_XZ
        select HAVE_GET_USER_PAGES_FAST
        select HAVE_ARCH_MUTEX_CPU_RELAX
+       select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
        select ARCH_INLINE_SPIN_TRYLOCK
        select ARCH_INLINE_SPIN_TRYLOCK_BH
        select ARCH_INLINE_SPIN_LOCK
index 975e3ab13cb5477b29ac4ffd504d34e6cacd4325..8b16c479585b271db83330e68529634e5e5e4735 100644 (file)
@@ -76,7 +76,7 @@ static void prng_seed(int nbytes)
 
        /* Add the entropy */
        while (nbytes >= 8) {
-               *((__u64 *)parm_block) ^= *((__u64 *)buf+i*8);
+               *((__u64 *)parm_block) ^= *((__u64 *)(buf+i));
                prng_add_entropy();
                i += 8;
                nbytes -= 8;
index 43a5c78046db6cd918939607ae1cd6f7db0ee4e9..3e20383d09219f8bbbe26ddd731e362870e9676a 100644 (file)
@@ -11,5 +11,6 @@ void kernel_map_pages(struct page *page, int numpages, int enable);
 int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
 
 #endif /* _S390_CACHEFLUSH_H */
index 72b2e2f2d32d823d36f4135702d67bde05a05d30..7e91c58072e259345610c3b8a17a93b48dc5d297 100644 (file)
@@ -9,9 +9,22 @@
 #define _ASM_S390_DIAG_H
 
 /*
- * Diagnose 10: Release pages
+ * Diagnose 10: Release page range
  */
-extern void diag10(unsigned long addr);
+static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
+{
+       unsigned long start_addr, end_addr;
+
+       start_addr = start_pfn << PAGE_SHIFT;
+       end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT;
+
+       asm volatile(
+               "0:     diag    %0,%1,0x10\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               EX_TABLE(1b, 1b)
+               : : "a" (start_addr), "a" (end_addr));
+}
 
 /*
  * Diagnose 14: Input spool file manipulation
index 3c29be4836ed53db58af9f2b8eefefadfb3aa8fc..b7931faaef6d76add44dd3bcb5c461cec5237a94 100644 (file)
@@ -11,15 +11,13 @@ struct dyn_arch_ftrace { };
 
 #ifdef CONFIG_64BIT
 #define MCOUNT_INSN_SIZE  12
-#define MCOUNT_OFFSET     8
 #else
 #define MCOUNT_INSN_SIZE  20
-#define MCOUNT_OFFSET     4
 #endif
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
-       return addr - MCOUNT_OFFSET;
+       return addr;
 }
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..95a6cf2
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ASM_S390_JUMP_LABEL_H
+#define _ASM_S390_JUMP_LABEL_H
+
+#include <linux/types.h>
+
+#define JUMP_LABEL_NOP_SIZE 6
+
+#ifdef CONFIG_64BIT
+#define ASM_PTR ".quad"
+#define ASM_ALIGN ".balign 8"
+#else
+#define ASM_PTR ".long"
+#define ASM_ALIGN ".balign 4"
+#endif
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("0:    brcl 0,0\n"
+               ".pushsection __jump_table, \"aw\"\n"
+               ASM_ALIGN "\n"
+               ASM_PTR " 0b, %l[label], %0\n"
+               ".popsection\n"
+               : : "X" (key) : : label);
+       return false;
+label:
+       return true;
+}
+
+typedef unsigned long jump_label_t;
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+};
+
+#endif
index a6f0e7cc9cde2f341fba3fef347ea93240bb9372..8c277caa8d3aa81d0d8f14c28b2e71f12ec3e791 100644 (file)
@@ -23,7 +23,7 @@ static inline int init_new_context(struct task_struct *tsk,
 #ifdef CONFIG_64BIT
        mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
-       if (current->mm->context.alloc_pgste) {
+       if (current->mm && current->mm->context.alloc_pgste) {
                /*
                 * alloc_pgste indicates, that any NEW context will be created
                 * with extended page tables. The old context is unchanged. The
index 64230bc392fa39a26a61d5839ddb93f6bd4d0618..5ff15dacb5718c04973d4660c9a18478afd1c8f8 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o \
            processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
            s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
-           vdso.o vtime.o sysinfo.o nmi.o sclp.o
+           vdso.o vtime.o sysinfo.o nmi.o sclp.o jump_label.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
index c032d11da8a1e8df9a4556ee71fd333c7ae08b3b..8237fc07ac79ef27c2794c5367b9c0e05e37af6b 100644 (file)
@@ -8,27 +8,6 @@
 #include <linux/module.h>
 #include <asm/diag.h>
 
-/*
- * Diagnose 10: Release pages
- */
-void diag10(unsigned long addr)
-{
-       if (addr >= 0x7ff00000)
-               return;
-       asm volatile(
-#ifdef CONFIG_64BIT
-               "       sam31\n"
-               "       diag    %0,%0,0x10\n"
-               "0:     sam64\n"
-#else
-               "       diag    %0,%0,0x10\n"
-               "0:\n"
-#endif
-               EX_TABLE(0b, 0b)
-               : : "a" (addr));
-}
-EXPORT_SYMBOL(diag10);
-
 /*
  * Diagnose 14: Input spool file manipulation
  */
index c83726c9fe033d9f74ed9524c5a12e0722386142..3d4a78fc1adc3f6403eaf4ebc93f03211c5e1f86 100644 (file)
@@ -672,6 +672,7 @@ static struct insn opcode_b2[] = {
        { "rp", 0x77, INSTR_S_RD },
        { "stcke", 0x78, INSTR_S_RD },
        { "sacf", 0x79, INSTR_S_RD },
+       { "spp", 0x80, INSTR_S_RD },
        { "stsi", 0x7d, INSTR_S_RD },
        { "srnm", 0x99, INSTR_S_RD },
        { "stfpc", 0x9c, INSTR_S_RD },
index 648f64239a9d169d0f9f983d59a667f14fafea9d..1b67fc6ebdc25f1407e569f3114bc3cb4827fd72 100644 (file)
@@ -836,7 +836,7 @@ restart_base:
        stosm   __SF_EMPTY(%r15),0x04   # now we can turn dat on
        basr    %r14,0
        l       %r14,restart_addr-.(%r14)
-       br      %r14                    # branch to start_secondary
+       basr    %r14,%r14               # branch to start_secondary
 restart_addr:
        .long   start_secondary
        .align  8
index 9d3603d6c5118dac66f0c27f9bba3a9e1b305c7f..9fd864563499bb7e46f0cd85d4a03550b32a15ac 100644 (file)
@@ -841,7 +841,7 @@ restart_base:
        mvc     __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
        xc      __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
        stosm   __SF_EMPTY(%r15),0x04   # now we can turn dat on
-       jg      start_secondary
+       brasl   %r14,start_secondary
        .align  8
 restart_vtime:
        .long   0x7fffffff,0xffffffff
diff --git a/arch/s390/kernel/jump_label.c b/arch/s390/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..44cc06b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Jump label s390 support
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/stop_machine.h>
+#include <linux/jump_label.h>
+#include <asm/ipl.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+struct insn {
+       u16 opcode;
+       s32 offset;
+} __packed;
+
+struct insn_args {
+       unsigned long *target;
+       struct insn *insn;
+       ssize_t size;
+};
+
+static int __arch_jump_label_transform(void *data)
+{
+       struct insn_args *args = data;
+       int rc;
+
+       rc = probe_kernel_write(args->target, args->insn, args->size);
+       WARN_ON_ONCE(rc < 0);
+       return 0;
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       struct insn_args args;
+       struct insn insn;
+
+       if (type == JUMP_LABEL_ENABLE) {
+               /* brcl 15,offset */
+               insn.opcode = 0xc0f4;
+               insn.offset = (entry->target - entry->code) >> 1;
+       } else {
+               /* brcl 0,0 */
+               insn.opcode = 0xc004;
+               insn.offset = 0;
+       }
+
+       args.target = (void *) entry->code;
+       args.insn = &insn;
+       args.size = JUMP_LABEL_NOP_SIZE;
+
+       stop_machine(__arch_jump_label_transform, &args, NULL);
+}
+
+#endif
index 63a97db83f96337013bfeeaf7cb7369a58d2a60f..63c7d9ff220d1545dea5d3cded8e96a3216af3aa 100644 (file)
@@ -165,12 +165,12 @@ static void do_ext_call_interrupt(unsigned int ext_int_code,
        kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
        /*
         * handle bit signal external calls
-        *
-        * For the ec_schedule signal we have to do nothing. All the work
-        * is done automatically when we return from the interrupt.
         */
        bits = xchg(&S390_lowcore.ext_call_fast, 0);
 
+       if (test_bit(ec_schedule, &bits))
+               scheduler_ipi();
+
        if (test_bit(ec_call_function, &bits))
                generic_smp_call_function_interrupt();
 
index 7e9d30d567b0ab21265b669f1f343018d10de080..ab0e041ac54cf2b17fc0b631bf0ed6cd4f59fd53 100644 (file)
@@ -48,10 +48,10 @@ sie_irq_handler:
        tm      __TI_flags+7(%r2),_TIF_EXIT_SIE
        jz      0f
        larl    %r2,sie_exit                    # work pending, leave sie
-       stg     %r2,__LC_RETURN_PSW+8
+       stg     %r2,SPI_PSW+8(0,%r15)
        br      %r14
 0:     larl    %r2,sie_reenter                 # re-enter with guest id
-       stg     %r2,__LC_RETURN_PSW+8
+       stg     %r2,SPI_PSW+8(0,%r15)
 1:     br      %r14
 
 /*
index c66ffd8dbbb732416ad3d803d00ec02da6125555..1f1dba9dcf58f713211bbb6b3fc063171681ed70 100644 (file)
@@ -91,7 +91,7 @@ static long cmm_alloc_pages(long nr, long *counter,
                        } else
                                free_page((unsigned long) npa);
                }
-               diag10(addr);
+               diag10_range(addr >> PAGE_SHIFT, 1);
                pa->pages[pa->index++] = addr;
                (*counter)++;
                spin_unlock(&cmm_lock);
index 9217e332b1183a061fd5ca8423e811d8692627e3..ab988135e5c682a90370f998d5d72956fd40961c 100644 (file)
@@ -543,7 +543,6 @@ static void pfault_interrupt(unsigned int ext_int_code,
        struct task_struct *tsk;
        __u16 subcode;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
        /*
         * Get the external interruption subcode & pfault
         * initial/completion signal bit. VM stores this 
@@ -553,14 +552,15 @@ static void pfault_interrupt(unsigned int ext_int_code,
        subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != __SUBCODE_MASK)
                return;
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 
        /*
         * Get the token (= address of the task structure of the affected task).
         */
 #ifdef CONFIG_64BIT
-       tsk = *(struct task_struct **) param64;
+       tsk = (struct task_struct *) param64;
 #else
-       tsk = *(struct task_struct **) param32;
+       tsk = (struct task_struct *) param32;
 #endif
 
        if (subcode & 0x0080) {
index 122ffbd08ce016e4c87d744adcdf9b9cbf2c3c7f..f05edcc3beff42c53cae96eb1850001915ff5bbc 100644 (file)
@@ -24,12 +24,13 @@ static void change_page_attr(unsigned long addr, int numpages,
                        WARN_ON_ONCE(1);
                        continue;
                }
-               ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
+               ptep = pte_offset_kernel(pmdp, addr);
 
                pte = *ptep;
                pte = set(pte);
-               ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
+               ptep_invalidate(&init_mm, addr, ptep);
                *ptep = pte;
+               addr += PAGE_SIZE;
        }
 }
 
@@ -53,3 +54,8 @@ int set_memory_nx(unsigned long addr, int numpages)
        return 0;
 }
 EXPORT_SYMBOL_GPL(set_memory_nx);
+
+int set_memory_x(unsigned long addr, int numpages)
+{
+       return 0;
+}
index 4952872d6f0ae1c05c58bd7d046fe24029aef5ac..33cbd373cce4f39e1181299b9098c2334fc231ec 100644 (file)
@@ -1021,20 +1021,14 @@ deallocate_exit:
        return rc;
 }
 
-long hwsampler_query_min_interval(void)
+unsigned long hwsampler_query_min_interval(void)
 {
-       if (min_sampler_rate)
-               return min_sampler_rate;
-       else
-               return -EINVAL;
+       return min_sampler_rate;
 }
 
-long hwsampler_query_max_interval(void)
+unsigned long hwsampler_query_max_interval(void)
 {
-       if (max_sampler_rate)
-               return max_sampler_rate;
-       else
-               return -EINVAL;
+       return max_sampler_rate;
 }
 
 unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu)
index 8c72b59316b5de7b0f02b440404a057aaf768860..1912f3bb190cfbf9c7cf7218e84b2cd1555baf57 100644 (file)
@@ -102,8 +102,8 @@ int hwsampler_setup(void);
 int hwsampler_shutdown(void);
 int hwsampler_allocate(unsigned long sdbt, unsigned long sdb);
 int hwsampler_deallocate(void);
-long hwsampler_query_min_interval(void);
-long hwsampler_query_max_interval(void);
+unsigned long hwsampler_query_min_interval(void);
+unsigned long hwsampler_query_max_interval(void);
 int hwsampler_start_all(unsigned long interval);
 int hwsampler_stop_all(void);
 int hwsampler_deactivate(unsigned int cpu);
index c63d7e58352bb343db50a47bb0ea857fc5952f9b..5995e9bc72d9c291d57df38ab66c0a1929f43dd6 100644 (file)
@@ -145,15 +145,11 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops)
         * create hwsampler files only if hwsampler_setup() succeeds.
         */
        oprofile_min_interval = hwsampler_query_min_interval();
-       if (oprofile_min_interval < 0) {
-               oprofile_min_interval = 0;
+       if (oprofile_min_interval == 0)
                return -ENODEV;
-       }
        oprofile_max_interval = hwsampler_query_max_interval();
-       if (oprofile_max_interval < 0) {
-               oprofile_max_interval = 0;
+       if (oprofile_max_interval == 0)
                return -ENODEV;
-       }
 
        if (oprofile_timer_init(ops))
                return -ENODEV;
index 4b89da248d17acf77dc8355d96cef8c0bef79cea..bc439de48cd166f47137b73f9a390e11036349be 100644 (file)
@@ -24,7 +24,6 @@ config SUPERH
        select RTC_LIB
        select GENERIC_ATOMIC64
        select GENERIC_IRQ_SHOW
-       select ARCH_NO_SYSDEV_OPS
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
index e71a531f1e319f4e202e6fe940ff9616d7b4727e..77ec0e7b8ddf6c68b5fa2ad6226a6a03dc57845b 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_PREEMPT=y
 CONFIG_BINFMT_MISC=y
 CONFIG_PM=y
 CONFIG_PM_DEBUG=y
-CONFIG_PM_VERBOSE=y
 CONFIG_PM_RUNTIME=y
 CONFIG_CPU_IDLE=y
 CONFIG_NET=y
index dc4a2eb6a61673780034795994ba6a174068ef01..c41650572d7957584804e4b5a3f9c03403176113 100644 (file)
@@ -83,7 +83,6 @@ CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_BINFMT_MISC=y
 CONFIG_PM=y
 CONFIG_PM_DEBUG=y
-CONFIG_PM_VERBOSE=y
 CONFIG_PM_RUNTIME=y
 CONFIG_CPU_IDLE=y
 CONFIG_NET=y
index 6dcb8166a64dcf2b6fc7b613849bfb7ed4361144..22db127afa7b2bd7c68973dade04117785b876de 100644 (file)
@@ -139,7 +139,7 @@ void platform_pm_runtime_suspend_idle(void)
        queue_work(pm_wq, &hwblk_work);
 }
 
-int platform_pm_runtime_suspend(struct device *dev)
+static int default_platform_runtime_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct pdev_archdata *ad = &pdev->archdata;
@@ -147,7 +147,7 @@ int platform_pm_runtime_suspend(struct device *dev)
        int hwblk = ad->hwblk_id;
        int ret = 0;
 
-       dev_dbg(dev, "platform_pm_runtime_suspend() [%d]\n", hwblk);
+       dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
 
        /* ignore off-chip platform devices */
        if (!hwblk)
@@ -183,20 +183,20 @@ int platform_pm_runtime_suspend(struct device *dev)
        mutex_unlock(&ad->mutex);
 
 out:
-       dev_dbg(dev, "platform_pm_runtime_suspend() [%d] returns %d\n",
-               hwblk, ret);
+       dev_dbg(dev, "%s() [%d] returns %d\n",
+                __func__, hwblk, ret);
 
        return ret;
 }
 
-int platform_pm_runtime_resume(struct device *dev)
+static int default_platform_runtime_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct pdev_archdata *ad = &pdev->archdata;
        int hwblk = ad->hwblk_id;
        int ret = 0;
 
-       dev_dbg(dev, "platform_pm_runtime_resume() [%d]\n", hwblk);
+       dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
 
        /* ignore off-chip platform devices */
        if (!hwblk)
@@ -228,19 +228,19 @@ int platform_pm_runtime_resume(struct device *dev)
         */
        mutex_unlock(&ad->mutex);
 out:
-       dev_dbg(dev, "platform_pm_runtime_resume() [%d] returns %d\n",
-               hwblk, ret);
+       dev_dbg(dev, "%s() [%d] returns %d\n",
+               __func__, hwblk, ret);
 
        return ret;
 }
 
-int platform_pm_runtime_idle(struct device *dev)
+static int default_platform_runtime_idle(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        int hwblk = pdev->archdata.hwblk_id;
        int ret = 0;
 
-       dev_dbg(dev, "platform_pm_runtime_idle() [%d]\n", hwblk);
+       dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
 
        /* ignore off-chip platform devices */
        if (!hwblk)
@@ -252,10 +252,19 @@ int platform_pm_runtime_idle(struct device *dev)
        /* suspend synchronously to disable clocks immediately */
        ret = pm_runtime_suspend(dev);
 out:
-       dev_dbg(dev, "platform_pm_runtime_idle() [%d] done!\n", hwblk);
+       dev_dbg(dev, "%s() [%d] done!\n", __func__, hwblk);
        return ret;
 }
 
+static struct dev_power_domain default_power_domain = {
+       .ops = {
+               .runtime_suspend = default_platform_runtime_suspend,
+               .runtime_resume = default_platform_runtime_resume,
+               .runtime_idle = default_platform_runtime_idle,
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
+
 static int platform_bus_notify(struct notifier_block *nb,
                               unsigned long action, void *data)
 {
@@ -276,6 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
                hwblk_disable(hwblk_info, hwblk);
                /* make sure driver re-inits itself once */
                __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
+               dev->pwr_domain = &default_power_domain;
                break;
        /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
        case BUS_NOTIFY_BOUND_DRIVER:
@@ -289,6 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
                __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
                break;
        case BUS_NOTIFY_DEL_DEVICE:
+               dev->pwr_domain = NULL;
                break;
        }
        return 0;
index 2130ca674e9bdd1674a22d339011a7f364bf0ec5..3d7b209b2178cc63c520975a35d4146c99042ba4 100644 (file)
@@ -117,7 +117,11 @@ void user_enable_single_step(struct task_struct *child)
 
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
 
+       if (ptrace_get_breakpoints(child) < 0)
+               return;
+
        set_single_step(child, pc);
+       ptrace_put_breakpoints(child);
 }
 
 void user_disable_single_step(struct task_struct *child)
index 509b36b451155ee5a7174c1d43fc0259d66e8ccd..6207561ea34a93ca315589469b3a77257711254f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <asm/atomic.h>
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -323,6 +324,7 @@ void smp_message_recv(unsigned int msg)
                generic_smp_call_function_interrupt();
                break;
        case SMP_MSG_RESCHEDULE:
+               scheduler_ipi();
                break;
        case SMP_MSG_FUNCTION_SINGLE:
                generic_smp_call_function_single_interrupt();
index 427d4684e0d239bbafe9238a01a2713e423ff9b7..fc73a82366f847f6c9821b0a10da9a35901b9cf2 100644 (file)
@@ -7,17 +7,20 @@
 
 #define JUMP_LABEL_NOP_SIZE 4
 
-#define JUMP_LABEL(key, label)                                 \
-       do {                                                    \
-               asm goto("1:\n\t"                               \
-                        "nop\n\t"                              \
-                        "nop\n\t"                              \
-                        ".pushsection __jump_table,  \"a\"\n\t"\
-                        ".align 4\n\t"                         \
-                        ".word 1b, %l[" #label "], %c0\n\t"    \
-                        ".popsection \n\t"                     \
-                        : :  "i" (key) :  : label);\
-       } while (0)
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+               asm goto("1:\n\t"
+                        "nop\n\t"
+                        "nop\n\t"
+                        ".pushsection __jump_table,  \"aw\"\n\t"
+                        ".align 4\n\t"
+                        ".word 1b, %l[l_yes], %c0\n\t"
+                        ".popsection \n\t"
+                        : :  "i" (key) : : l_yes);
+       return false;
+l_yes:
+       return true;
+}
 
 #endif /* __KERNEL__ */
 
index 1c79f32734a05694a5297c7034ff0e6b93fe83f6..8b9c556d630b8731c76b16d1708d090dbd6d4cfc 100644 (file)
@@ -65,6 +65,10 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
 #define smt_capable()                          (sparc64_multi_core)
 #endif /* CONFIG_SMP */
 
-#define cpu_coregroup_mask(cpu)                        (&cpu_core_map[cpu])
+extern cpumask_t cpu_core_map[NR_CPUS];
+static inline const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+        return &cpu_core_map[cpu];
+}
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
index f679c57644d5f44b6bc710e060d86ace2c73b4ee..1e34f29e58bb723537429dd0aacb9e0fe7df11b9 100644 (file)
@@ -165,7 +165,7 @@ static int __devinit apc_probe(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id __initdata apc_match[] = {
+static struct of_device_id apc_match[] = {
        {
                .name = APC_OBPNAME,
        },
index 948068a083fca3eab756401d6fb30e00e295e352..d1840dbdaa2fef0179e55c06b24830246e397fc0 100644 (file)
@@ -452,8 +452,10 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
        sabre_scan_bus(pbm, &op->dev);
 }
 
+static const struct of_device_id sabre_match[];
 static int __devinit sabre_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        const struct linux_prom64_registers *pr_regs;
        struct device_node *dp = op->dev.of_node;
        struct pci_pbm_info *pbm;
@@ -463,7 +465,8 @@ static int __devinit sabre_probe(struct platform_device *op)
        const u32 *vdma;
        u64 clear_irq;
 
-       hummingbird_p = op->dev.of_match && (op->dev.of_match->data != NULL);
+       match = of_match_device(sabre_match, &op->dev);
+       hummingbird_p = match && (match->data != NULL);
        if (!hummingbird_p) {
                struct device_node *cpu_dp;
 
index fecfcb2063c805a11760e515d549b40d4c322b3a..283fbc329a4397c9d8ff9b159611fe1bf62d4e8b 100644 (file)
@@ -1458,11 +1458,15 @@ out_err:
        return err;
 }
 
+static const struct of_device_id schizo_match[];
 static int __devinit schizo_probe(struct platform_device *op)
 {
-       if (!op->dev.of_match)
+       const struct of_device_id *match;
+
+       match = of_match_device(schizo_match, &op->dev);
+       if (!match)
                return -EINVAL;
-       return __schizo_init(op, (unsigned long) op->dev.of_match->data);
+       return __schizo_init(op, (unsigned long)match->data);
 }
 
 /* The ordering of this table is very important.  Some Tomatillo
index 93d7b4465f8d2493dc542d0e836ac255182e25f2..6a585d393580d38d651f5053e08bded4081c6bba 100644 (file)
@@ -69,7 +69,7 @@ static int __devinit pmc_probe(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id __initdata pmc_match[] = {
+static struct of_device_id pmc_match[] = {
        {
                .name = PMC_OBPNAME,
        },
index 91c10fb7085849c1de8a5d1f2b58df90336af61e..442286d83435d115403ac71af53b7a6ce81c88fa 100644 (file)
@@ -53,6 +53,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE;
 void __cpuinit smp_store_cpu_info(int id)
 {
        int cpu_node;
+       int mid;
 
        cpu_data(id).udelay_val = loops_per_jiffy;
 
@@ -60,10 +61,13 @@ void __cpuinit smp_store_cpu_info(int id)
        cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
                                                     "clock-frequency", 0);
        cpu_data(id).prom_node = cpu_node;
-       cpu_data(id).mid = cpu_get_hwmid(cpu_node);
+       mid = cpu_get_hwmid(cpu_node);
 
-       if (cpu_data(id).mid < 0)
-               panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
+       if (mid < 0) {
+               printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node);
+               mid = 0;
+       }
+       cpu_data(id).mid = mid;
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
@@ -125,7 +129,9 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 };
 
 void smp_send_reschedule(int cpu)
 {
-       /* See sparc64 */
+       /*
+        * XXX missing reschedule IPI, see scheduler_ipi()
+        */
 }
 
 void smp_send_stop(void)
index 3e94a8c23238891da65dc84fcdb31acd8fa26cc9..9478da7fdb3e7017921259dfb664452be3f2e6ce 100644 (file)
@@ -1368,6 +1368,7 @@ void smp_send_reschedule(int cpu)
 void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
 {
        clear_softint(1 << irq);
+       scheduler_ipi();
 }
 
 /* This is a nop because we capture all other cpus
index 4e236391b6359ab59223034c61892c6b3fce7a28..96046a4024c23276e41769403a5155ec62ea2cd3 100644 (file)
@@ -168,7 +168,7 @@ static int __devinit clock_probe(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id __initdata clock_match[] = {
+static struct of_device_id clock_match[] = {
        {
                .name = "eeprom",
        },
index 3632cb34e914b241ed394b99092b6a5aa63601c0..0084c3361e15afa77530071ada7a6e30c3ece3b5 100644 (file)
@@ -289,10 +289,16 @@ cc_end_cruft:
 
        /* Also, handle the alignment code out of band. */
 cc_dword_align:
-       cmp     %g1, 6
-       bl,a    ccte
+       cmp     %g1, 16
+       bge     1f
+        srl    %g1, 1, %o3
+2:     cmp     %o3, 0
+       be,a    ccte
         andcc  %g1, 0xf, %o3
-       andcc   %o0, 0x1, %g0
+       andcc   %o3, %o0, %g0   ! Check %o0 only (%o1 has the same last 2 bits)
+       be,a    2b
+        srl    %o3, 1, %o3
+1:     andcc   %o0, 0x1, %g0
        bne     ccslow
         andcc  %o0, 0x2, %g0
        be      1f
index a4293102ef81b6eaaa52464f66ce7865801775e7..c52224d5ed45f06a38f4461e19f485a2bb4cadb3 100644 (file)
@@ -189,12 +189,8 @@ void flush_icache_range(unsigned long start, unsigned long end)
 /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
 static irqreturn_t handle_reschedule_ipi(int irq, void *token)
 {
-       /*
-        * Nothing to do here; when we return from interrupt, the
-        * rescheduling will occur there. But do bump the interrupt
-        * profiler count in the meantime.
-        */
        __get_cpu_var(irq_stat).irq_resched_count++;
+       scheduler_ipi();
 
        return IRQ_HANDLED;
 }
index 90a438acbfafcf00aa8281f03ca44228250189e4..b5e675e370c67203ef301ee0c0766d2babd5a330 100644 (file)
@@ -47,7 +47,7 @@ config HOSTFS
 
 config HPPFS
        tristate "HoneyPot ProcFS (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on EXPERIMENTAL && PROC_FS
        help
          hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
          entries to be overridden, removed, or fabricated from the host.
index e2cf786bda0a28c43a8173ab40ec62ee2ab8a6de..5bd1bad33fab65fdd8f8857c3452768377e88290 100644 (file)
@@ -49,7 +49,10 @@ static inline struct thread_info *current_thread_info(void)
 {
        struct thread_info *ti;
        unsigned long mask = THREAD_SIZE - 1;
-       ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
+       void *p;
+
+       asm volatile ("" : "=r" (p) : "0" (&ti));
+       ti = (struct thread_info *) (((unsigned long)p) & ~mask);
        return ti;
 }
 
index 106bf27e2a9a5fc96abf5056bfbe070a6e4f709f..eefb107d2d734856c376f973913a29ddf18acae7 100644 (file)
@@ -173,7 +173,7 @@ void IPI_handler(int cpu)
                        break;
 
                case 'R':
-                       set_tsk_need_resched(current);
+                       scheduler_ipi();
                        break;
 
                case 'S':
index 6ea77979531c95e1bf005eb0cc3e4a87fa6c913d..42827cafa6af3ac72f4c57d62e08968b81360faa 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
@@ -75,6 +76,26 @@ void setup_hostinfo(char *buf, int len)
                 host.release, host.version, host.machine);
 }
 
+/*
+ * We cannot use glibc's abort(). It makes use of tgkill() which
+ * has no effect within UML's kernel threads.
+ * After that glibc would execute an invalid instruction to kill
+ * the calling process and UML crashes with SIGSEGV.
+ */
+static inline void __attribute__ ((noreturn)) uml_abort(void)
+{
+       sigset_t sig;
+
+       fflush(NULL);
+
+       if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
+               sigprocmask(SIG_UNBLOCK, &sig, 0);
+
+       for (;;)
+               if (kill(getpid(), SIGABRT) < 0)
+                       exit(127);
+}
+
 void os_dump_core(void)
 {
        int pid;
@@ -116,5 +137,5 @@ void os_dump_core(void)
        while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
                os_kill_ptraced_process(pid, 0);
 
-       abort();
+       uml_abort();
 }
index 804b28dd0328a30088e122a1dcd984bf1464ba75..b1da91c1b200d4f14ff60fcbdbd3b203b595dbe4 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
        ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-       sys_call_table.o tls.o
+       sys_call_table.o tls.o atomic64_cx8_32.o
 
 obj-$(CONFIG_BINFMT_ELF) += elfcore.o
 
diff --git a/arch/um/sys-i386/atomic64_cx8_32.S b/arch/um/sys-i386/atomic64_cx8_32.S
new file mode 100644 (file)
index 0000000..1e901d3
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * atomic64_t for 586+
+ *
+ * Copied from arch/x86/lib/atomic64_cx8_32.S
+ *
+ * Copyright Â© 2010  Luca Barbieri
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+.macro SAVE reg
+       pushl_cfi %\reg
+       CFI_REL_OFFSET \reg, 0
+.endm
+
+.macro RESTORE reg
+       popl_cfi %\reg
+       CFI_RESTORE \reg
+.endm
+
+.macro read64 reg
+       movl %ebx, %eax
+       movl %ecx, %edx
+/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
+       LOCK_PREFIX
+       cmpxchg8b (\reg)
+.endm
+
+ENTRY(atomic64_read_cx8)
+       CFI_STARTPROC
+
+       read64 %ecx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_read_cx8)
+
+ENTRY(atomic64_set_cx8)
+       CFI_STARTPROC
+
+1:
+/* we don't need LOCK_PREFIX since aligned 64-bit writes
+ * are atomic on 586 and newer */
+       cmpxchg8b (%esi)
+       jne 1b
+
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_set_cx8)
+
+ENTRY(atomic64_xchg_cx8)
+       CFI_STARTPROC
+
+       movl %ebx, %eax
+       movl %ecx, %edx
+1:
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_xchg_cx8)
+
+.macro addsub_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+       CFI_STARTPROC
+       SAVE ebp
+       SAVE ebx
+       SAVE esi
+       SAVE edi
+
+       movl %eax, %esi
+       movl %edx, %edi
+       movl %ecx, %ebp
+
+       read64 %ebp
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       \ins\()l %esi, %ebx
+       \insc\()l %edi, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%ebp)
+       jne 1b
+
+10:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE edi
+       RESTORE esi
+       RESTORE ebx
+       RESTORE ebp
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+addsub_return add add adc
+addsub_return sub sub sbb
+
+.macro incdec_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       \ins\()l $1, %ebx
+       \insc\()l $0, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+10:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE ebx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+incdec_return inc add adc
+incdec_return dec sub sbb
+
+ENTRY(atomic64_dec_if_positive_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       subl $1, %ebx
+       sbb $0, %ecx
+       js 2f
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+2:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE ebx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_dec_if_positive_cx8)
+
+ENTRY(atomic64_add_unless_cx8)
+       CFI_STARTPROC
+       SAVE ebp
+       SAVE ebx
+/* these just push these two parameters on the stack */
+       SAVE edi
+       SAVE esi
+
+       movl %ecx, %ebp
+       movl %eax, %esi
+       movl %edx, %edi
+
+       read64 %ebp
+1:
+       cmpl %eax, 0(%esp)
+       je 4f
+2:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       addl %esi, %ebx
+       adcl %edi, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%ebp)
+       jne 1b
+
+       movl $1, %eax
+3:
+       addl $8, %esp
+       CFI_ADJUST_CFA_OFFSET -8
+       RESTORE ebx
+       RESTORE ebp
+       ret
+4:
+       cmpl %edx, 4(%esp)
+       jne 2b
+       xorl %eax, %eax
+       jmp 3b
+       CFI_ENDPROC
+ENDPROC(atomic64_add_unless_cx8)
+
+ENTRY(atomic64_inc_not_zero_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       testl %eax, %eax
+       je 4f
+2:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       addl $1, %ebx
+       adcl $0, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+       movl $1, %eax
+3:
+       RESTORE ebx
+       ret
+4:
+       testl %edx, %edx
+       jne 2b
+       jmp 3b
+       CFI_ENDPROC
+ENDPROC(atomic64_inc_not_zero_cx8)
index 2aa30a364bbe426e0749a758e26b11c000be0428..d4efa7d679ffe5e9d10d1ac09cfcfb83c52dcddb 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/gpio.h>
 
 #include <asm/system.h>
@@ -237,7 +237,7 @@ static struct puv3_irq_state {
        unsigned int    iccr;
 } puv3_irq_state;
 
-static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
+static int puv3_irq_suspend(void)
 {
        struct puv3_irq_state *st = &puv3_irq_state;
 
@@ -265,7 +265,7 @@ static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int puv3_irq_resume(struct sys_device *dev)
+static void puv3_irq_resume(void)
 {
        struct puv3_irq_state *st = &puv3_irq_state;
 
@@ -278,27 +278,20 @@ static int puv3_irq_resume(struct sys_device *dev)
 
                writel(st->icmr, INTC_ICMR);
        }
-       return 0;
 }
 
-static struct sysdev_class puv3_irq_sysclass = {
-       .name           = "pkunity-irq",
+static struct syscore_ops puv3_irq_syscore_ops = {
        .suspend        = puv3_irq_suspend,
        .resume         = puv3_irq_resume,
 };
 
-static struct sys_device puv3_irq_device = {
-       .id             = 0,
-       .cls            = &puv3_irq_sysclass,
-};
-
-static int __init puv3_irq_init_devicefs(void)
+static int __init puv3_irq_init_syscore(void)
 {
-       sysdev_class_register(&puv3_irq_sysclass);
-       return sysdev_register(&puv3_irq_device);
+       register_syscore_ops(&puv3_irq_syscore_ops);
+       return 0;
 }
 
-device_initcall(puv3_irq_init_devicefs);
+device_initcall(puv3_irq_init_syscore);
 
 void __init init_IRQ(void)
 {
index cc6c53a95bfdd7ca40d5836e25d2a24e23482f83..4168e5d8632af2f162504ea1b80fbf11c94b5264 100644 (file)
@@ -8,6 +8,7 @@ config 64BIT
 
 config X86_32
        def_bool !64BIT
+       select CLKSRC_I8253
 
 config X86_64
        def_bool 64BIT
@@ -71,7 +72,6 @@ config X86
        select GENERIC_IRQ_SHOW
        select IRQ_FORCED_THREADING
        select USE_GENERIC_SMP_HELPERS if SMP
-       select ARCH_NO_SYSDEV_OPS
 
 config INSTRUCTION_DECODER
        def_bool (KPROBES || PERF_EVENTS)
@@ -112,7 +112,14 @@ config MMU
        def_bool y
 
 config ZONE_DMA
-       def_bool y
+       bool "DMA memory allocation support" if EXPERT
+       default y
+       help
+         DMA memory allocation support allows devices with less than 32-bit
+         addressing to allocate within the first 16MB of address space.
+         Disable if no such devices will be used.
+
+         If unsure, say Y.
 
 config SBUS
        bool
@@ -365,17 +372,6 @@ config X86_UV
 # Following is an alphabetically sorted list of 32 bit extended platforms
 # Please maintain the alphabetic order if and when there are additions
 
-config X86_ELAN
-       bool "AMD Elan"
-       depends on X86_32
-       depends on X86_EXTENDED_PLATFORM
-       ---help---
-         Select this for an AMD Elan processor.
-
-         Do not use this option for K6/Athlon/Opteron processors!
-
-         If unsure, choose "PC-compatible" instead.
-
 config X86_INTEL_CE
        bool "CE4100 TV platform"
        depends on PCI
@@ -690,6 +686,7 @@ config AMD_IOMMU
        bool "AMD IOMMU support"
        select SWIOTLB
        select PCI_MSI
+       select PCI_IOV
        depends on X86_64 && PCI && ACPI
        ---help---
          With this option you can enable support for AMD IOMMU hardware in
@@ -1174,7 +1171,7 @@ comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
 config AMD_NUMA
        def_bool y
        prompt "Old style AMD Opteron NUMA detection"
-       depends on X86_64 && NUMA && PCI
+       depends on NUMA && PCI
        ---help---
          Enable AMD NUMA node topology detection.  You should say Y here if
          you have a multi processor AMD system. This uses an old method to
@@ -1201,7 +1198,7 @@ config NODES_SPAN_OTHER_NODES
 
 config NUMA_EMU
        bool "NUMA emulation"
-       depends on X86_64 && NUMA
+       depends on NUMA
        ---help---
          Enable NUMA emulation. A flat machine will be split
          into virtual nodes when booted with "numa=fake=N", where N is the
@@ -1223,6 +1220,10 @@ config HAVE_ARCH_BOOTMEM
        def_bool y
        depends on X86_32 && NUMA
 
+config HAVE_ARCH_ALLOC_REMAP
+       def_bool y
+       depends on X86_32 && NUMA
+
 config ARCH_HAVE_MEMORY_PRESENT
        def_bool y
        depends on X86_32 && DISCONTIGMEM
@@ -1231,13 +1232,9 @@ config NEED_NODE_MEMMAP_SIZE
        def_bool y
        depends on X86_32 && (DISCONTIGMEM || SPARSEMEM)
 
-config HAVE_ARCH_ALLOC_REMAP
-       def_bool y
-       depends on X86_32 && NUMA
-
 config ARCH_FLATMEM_ENABLE
        def_bool y
-       depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && !NUMA
+       depends on X86_32 && !NUMA
 
 config ARCH_DISCONTIGMEM_ENABLE
        def_bool y
@@ -1247,20 +1244,16 @@ config ARCH_DISCONTIGMEM_DEFAULT
        def_bool y
        depends on NUMA && X86_32
 
-config ARCH_PROC_KCORE_TEXT
-       def_bool y
-       depends on X86_64 && PROC_KCORE
-
-config ARCH_SPARSEMEM_DEFAULT
-       def_bool y
-       depends on X86_64
-
 config ARCH_SPARSEMEM_ENABLE
        def_bool y
        depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD
        select SPARSEMEM_STATIC if X86_32
        select SPARSEMEM_VMEMMAP_ENABLE if X86_64
 
+config ARCH_SPARSEMEM_DEFAULT
+       def_bool y
+       depends on X86_64
+
 config ARCH_SELECT_MEMORY_MODEL
        def_bool y
        depends on ARCH_SPARSEMEM_ENABLE
@@ -1269,6 +1262,10 @@ config ARCH_MEMORY_PROBE
        def_bool X86_64
        depends on MEMORY_HOTPLUG
 
+config ARCH_PROC_KCORE_TEXT
+       def_bool y
+       depends on X86_64 && PROC_KCORE
+
 config ILLEGAL_POINTER_VALUE
        hex
        default 0 if X86_32
@@ -1703,10 +1700,6 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
        def_bool y
        depends on MEMORY_HOTPLUG
 
-config HAVE_ARCH_EARLY_PFN_TO_NID
-       def_bool X86_64
-       depends on NUMA
-
 config USE_PERCPU_NUMA_NODE_ID
        def_bool y
        depends on NUMA
@@ -1848,7 +1841,7 @@ config APM_ALLOW_INTS
 
 endif # APM
 
-source "arch/x86/kernel/cpu/cpufreq/Kconfig"
+source "drivers/cpufreq/Kconfig"
 
 source "drivers/cpuidle/Kconfig"
 
@@ -2076,7 +2069,7 @@ config OLPC
        depends on !X86_PAE
        select GPIOLIB
        select OF
-       select OF_PROMTREE if PROC_DEVICETREE
+       select OF_PROMTREE
        ---help---
          Add support for detecting the unique features of the OLPC
          XO hardware.
index d161e939df6266566deb52f5e5752428bacf347f..6a7cfdf8ff6915c291e14e2167b54e7469503a34 100644 (file)
@@ -1,6 +1,4 @@
 # Put here option for CPU selection and depending optimization
-if !X86_ELAN
-
 choice
        prompt "Processor family"
        default M686 if X86_32
@@ -203,6 +201,14 @@ config MWINCHIP3D
          stores for this CPU, which can increase performance of some
          operations.
 
+config MELAN
+       bool "AMD Elan"
+       depends on X86_32
+       ---help---
+         Select this for an AMD Elan processor.
+
+         Do not use this option for K6/Athlon/Opteron processors!
+
 config MGEODEGX1
        bool "GeodeGX1"
        depends on X86_32
@@ -292,8 +298,6 @@ config X86_GENERIC
          This is really intended for distributors who need more
          generic optimizations.
 
-endif
-
 #
 # Define implied options from the CPU selection here
 config X86_INTERNODE_CACHE_SHIFT
@@ -312,7 +316,7 @@ config X86_L1_CACHE_SHIFT
        int
        default "7" if MPENTIUM4 || MPSC
        default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU
-       default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
+       default "4" if MELAN || M486 || M386 || MGEODEGX1
        default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
 
 config X86_XADD
@@ -358,7 +362,7 @@ config X86_POPAD_OK
 
 config X86_ALIGNMENT_16
        def_bool y
-       depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+       depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
 
 config X86_INTEL_USERCOPY
        def_bool y
index f2ee1abb1df9df8704c052c4d76ed22cbb6bd5bf..86cee7b749e1bc387522752ba2a5f200ccc172c0 100644 (file)
@@ -37,7 +37,7 @@ cflags-$(CONFIG_MATOM)                += $(call cc-option,-march=atom,$(call cc-option,-march=
        $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic))
 
 # AMD Elan support
-cflags-$(CONFIG_X86_ELAN)      += -march=i486
+cflags-$(CONFIG_MELAN)         += -march=i486
 
 # Geode GX1 support
 cflags-$(CONFIG_MGEODEGX1)     += -march=pentium-mmx
index cae3feb1035e3da73826b518de4d47c15ad4e58d..db75d07c3645c0375090596ae29d1085f0f8a38a 100644 (file)
@@ -91,7 +91,7 @@ static int detect_memory_e801(void)
        if (oreg.ax > 15*1024) {
                return -1;      /* Bogus! */
        } else if (oreg.ax == 15*1024) {
-               boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
+               boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
        } else {
                /*
                 * This ignores memory above 16MB if we have a memory
index 12e0e7dd869c6f966efd4415c740db2f39bd0eb7..416d865eae39bdb5eecb670aeaeffdc2a3f2bd21 100644 (file)
@@ -183,8 +183,6 @@ static inline void disable_acpi(void) { }
 
 #define ARCH_HAS_POWER_INIT    1
 
-struct bootnode;
-
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
 extern int x86_acpi_numa_init(void);
index a63a68be1cce2258daf9cadf0d465b291296c930..94d420b360d11cdfbbd4a39f13c19bd8d76fc7e0 100644 (file)
        .endm
 #endif
 
+.macro altinstruction_entry orig alt feature orig_len alt_len
+       .align 8
+       .quad \orig
+       .quad \alt
+       .word \feature
+       .byte \orig_len
+       .byte \alt_len
+.endm
+
 #endif  /*  __ASSEMBLY__  */
index 13009d1af99a33e2bbee39fbe80a194fac85ece4..bf535f947e8c359d1ff482420ca5fca0a8e70f19 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/stringify.h>
-#include <linux/jump_label.h>
 #include <asm/asm.h>
 
 /*
@@ -191,12 +190,4 @@ extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
 extern void text_poke_smp_batch(struct text_poke_param *params, int n);
 
-#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
-#define IDEAL_NOP_SIZE_5 5
-extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
-extern void arch_init_ideal_nop5(void);
-#else
-static inline void arch_init_ideal_nop5(void) {}
-#endif
-
 #endif /* _ASM_X86_ALTERNATIVE_H */
index 916bc8111a01fa5de3a5df9f35ce3b8b60113342..55d95eb789b3142efb38ddf7d31afc2bcf77cf44 100644 (file)
 #ifndef _ASM_X86_AMD_IOMMU_PROTO_H
 #define _ASM_X86_AMD_IOMMU_PROTO_H
 
-struct amd_iommu;
+#include <asm/amd_iommu_types.h>
 
 extern int amd_iommu_init_dma_ops(void);
 extern int amd_iommu_init_passthrough(void);
+extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
 extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
-extern void amd_iommu_flush_all_domains(void);
-extern void amd_iommu_flush_all_devices(void);
 extern void amd_iommu_apply_erratum_63(u16 devid);
 extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
 extern int amd_iommu_init_devices(void);
@@ -44,4 +43,12 @@ static inline bool is_rd890_iommu(struct pci_dev *pdev)
               (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
 }
 
+static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
+{
+       if (!(iommu->cap & (1 << IOMMU_CAP_EFR)))
+               return false;
+
+       return !!(iommu->features & f);
+}
+
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
index e3509fc303bf5a54069e5b9b6b6edbc9ec390a49..4c9982995414a3f84a06f7483733ddb7d9d160a7 100644 (file)
 #define MMIO_CONTROL_OFFSET     0x0018
 #define MMIO_EXCL_BASE_OFFSET   0x0020
 #define MMIO_EXCL_LIMIT_OFFSET  0x0028
+#define MMIO_EXT_FEATURES      0x0030
 #define MMIO_CMD_HEAD_OFFSET   0x2000
 #define MMIO_CMD_TAIL_OFFSET   0x2008
 #define MMIO_EVT_HEAD_OFFSET   0x2010
 #define MMIO_EVT_TAIL_OFFSET   0x2018
 #define MMIO_STATUS_OFFSET     0x2020
 
+
+/* Extended Feature Bits */
+#define FEATURE_PREFETCH       (1ULL<<0)
+#define FEATURE_PPR            (1ULL<<1)
+#define FEATURE_X2APIC         (1ULL<<2)
+#define FEATURE_NX             (1ULL<<3)
+#define FEATURE_GT             (1ULL<<4)
+#define FEATURE_IA             (1ULL<<6)
+#define FEATURE_GA             (1ULL<<7)
+#define FEATURE_HE             (1ULL<<8)
+#define FEATURE_PC             (1ULL<<9)
+
 /* MMIO status bits */
 #define MMIO_STATUS_COM_WAIT_INT_MASK  0x04
 
 /* command specific defines */
 #define CMD_COMPL_WAIT          0x01
 #define CMD_INV_DEV_ENTRY       0x02
-#define CMD_INV_IOMMU_PAGES     0x03
+#define CMD_INV_IOMMU_PAGES    0x03
+#define CMD_INV_IOTLB_PAGES    0x04
+#define CMD_INV_ALL            0x08
 
 #define CMD_COMPL_WAIT_STORE_MASK      0x01
 #define CMD_COMPL_WAIT_INT_MASK                0x02
 #define IOMMU_PTE_IR (1ULL << 61)
 #define IOMMU_PTE_IW (1ULL << 62)
 
+#define DTE_FLAG_IOTLB 0x01
+
 #define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
 #define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
 #define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
 /* IOMMU capabilities */
 #define IOMMU_CAP_IOTLB   24
 #define IOMMU_CAP_NPCACHE 26
+#define IOMMU_CAP_EFR     27
 
 #define MAX_DOMAIN_ID 65536
 
@@ -249,6 +267,8 @@ extern bool amd_iommu_dump;
 
 /* global flag if IOMMUs cache non-present entries */
 extern bool amd_iommu_np_cache;
+/* Only true if all IOMMUs support device IOTLBs */
+extern bool amd_iommu_iotlb_sup;
 
 /*
  * Make iterating over all IOMMUs easier
@@ -371,6 +391,9 @@ struct amd_iommu {
        /* flags read from acpi table */
        u8 acpi_flags;
 
+       /* Extended features */
+       u64 features;
+
        /*
         * Capability pointer. There could be more than one IOMMU per PCI
         * device function if there are more than one AMD IOMMU capability
@@ -409,9 +432,6 @@ struct amd_iommu {
        /* if one, we need to send a completion wait command */
        bool need_sync;
 
-       /* becomes true if a command buffer reset is running */
-       bool reset_in_progress;
-
        /* default dma_ops domain for that IOMMU */
        struct dma_ops_domain *default_dom;
 
index 331682231bb43c6a2a7ff7c40c1352cdeddd82f1..67f87f25761169a54e99795cecab98fed034aca7 100644 (file)
@@ -11,7 +11,6 @@ struct amd_nb_bus_dev_range {
 
 extern const struct pci_device_id amd_nb_misc_ids[];
 extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
-struct bootnode;
 
 extern bool early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
index 2b7d573be5496863572be6dc724af256e00f4cf7..a0c46f0612106a220cd01f4d6fe81df61eeecb70 100644 (file)
@@ -363,7 +363,12 @@ struct apic {
         */
        int (*x86_32_early_logical_apicid)(int cpu);
 
-       /* determine CPU -> NUMA node mapping */
+       /*
+        * Optional method called from setup_local_APIC() after logical
+        * apicid is guaranteed to be known to initialize apicid -> node
+        * mapping if NUMA initialization hasn't done so already.  Don't
+        * add new users.
+        */
        int (*x86_32_numa_cpu_node)(int cpu);
 #endif
 };
@@ -537,8 +542,6 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
        return cpuid_apic >> index_msb;
 }
 
-extern int default_x86_32_numa_cpu_node(int cpu);
-
 #endif
 
 static inline unsigned int
index d87988bacf3ec497a6a5db9ee1e2b54214b4cdf2..34595d5e1038615eeac0ac943a15e9bcf9f4e0d9 100644 (file)
@@ -78,6 +78,7 @@
 #define                APIC_DEST_LOGICAL       0x00800
 #define                APIC_DEST_PHYSICAL      0x00000
 #define                APIC_DM_FIXED           0x00000
+#define                APIC_DM_FIXED_MASK      0x00700
 #define                APIC_DM_LOWEST          0x00100
 #define                APIC_DM_SMI             0x00200
 #define                APIC_DM_REMRD           0x00300
index 91f3e087cf21817704c68f24379edc4cf31a6885..5dc6acc98dbde7a1bed021ead6386644d47f3ff3 100644 (file)
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
 #define X86_FEATURE_FSGSBASE   (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
+#define X86_FEATURE_SMEP       (9*32+ 7) /* Supervisor Mode Execution Protection */
+#define X86_FEATURE_ERMS       (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
@@ -207,8 +209,7 @@ extern const char * const x86_power_flags[32];
 #define test_cpu_cap(c, bit)                                           \
         test_bit(bit, (unsigned long *)((c)->x86_capability))
 
-#define cpu_has(c, bit)                                                        \
-       (__builtin_constant_p(bit) &&                                   \
+#define REQUIRED_MASK_BIT_SET(bit)                                     \
         ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||     \
           (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) ||     \
           (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) ||     \
@@ -218,10 +219,16 @@ extern const char * const x86_power_flags[32];
           (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||     \
           (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ||     \
           (((bit)>>5)==8 && (1UL<<((bit)&31) & REQUIRED_MASK8)) ||     \
-          (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9)) )      \
-         ? 1 :                                                         \
+          (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9)) )
+
+#define cpu_has(c, bit)                                                        \
+       (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
         test_cpu_cap(c, bit))
 
+#define this_cpu_has(bit)                                              \
+       (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
+        x86_this_cpu_test_bit(bit, (unsigned long *)&cpu_info.x86_capability))
+
 #define boot_cpu_has(bit)      cpu_has(&boot_cpu_data, bit)
 
 #define set_cpu_cap(c, bit)    set_bit(bit, (unsigned long *)((c)->x86_capability))
index 057099e5faba5fa4e82c33e8dfd54807b3062fec..0bdb0c54d9a15164a5bd1cf4bacde735bb1656bc 100644 (file)
 
 #define MAX_DMA_CHANNELS       8
 
-#ifdef CONFIG_X86_32
-
-/* The maximum address that we can perform a DMA transfer to on this platform */
-#define MAX_DMA_ADDRESS      (PAGE_OFFSET + 0x1000000)
-
-#else
-
 /* 16MB ISA DMA zone */
 #define MAX_DMA_PFN   ((16 * 1024 * 1024) >> PAGE_SHIFT)
 
 /* 4GB broken PCI/AGP hardware bus master zone */
 #define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
 
+#ifdef CONFIG_X86_32
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS      (PAGE_OFFSET + 0x1000000)
+#else
 /* Compat define for old dma zone */
 #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT))
-
 #endif
 
 /* 8237 DMA controllers */
index 8e4a16508d4e89641919cd39979c14532459af96..7093e4a6a0bc6dd5644b2b14cbef9ef5f4085eef 100644 (file)
@@ -90,6 +90,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
+extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern void efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
index db24c2278be04c7400f6f5057904d49642fa75e9..268c783ab1c0e5393db3339fee48b90381ff5bee 100644 (file)
@@ -38,11 +38,10 @@ extern void mcount(void);
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
        /*
-        * call mcount is "e8 <4 byte offset>"
-        * The addr points to the 4 byte offset and the caller of this
-        * function wants the pointer to e8. Simply subtract one.
+        * addr is the address of the mcount call instruction.
+        * recordmcount does the necessary offset calculation.
         */
-       return addr - 1;
+       return addr;
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 43085bfc99c30f963b929a9c7afdcff932ad9236..156cd5d18d2abeabb26a0587cfffd15c52aa6f13 100644 (file)
@@ -66,7 +66,7 @@ static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
         * Don't enable translation but enable GART IO and CPU accesses.
         * Also, set DISTLBWALKPRB since GART tables memory is UC.
         */
-       ctl = DISTLBWALKPRB | order << 1;
+       ctl = order << 1;
 
        pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
@@ -75,17 +75,17 @@ static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
 {
        u32 tmp, ctl;
 
-        /* address of the mappings table */
-        addr >>= 12;
-        tmp = (u32) addr<<4;
-        tmp &= ~0xf;
-        pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
-
-        /* Enable GART translation for this hammer. */
-        pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
-        ctl |= GARTEN;
-        ctl &= ~(DISGARTCPU | DISGARTIO);
-        pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+       /* address of the mappings table */
+       addr >>= 12;
+       tmp = (u32) addr<<4;
+       tmp &= ~0xf;
+       pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
+
+       /* Enable GART translation for this hammer. */
+       pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
+       ctl |= GARTEN | DISTLBWALKPRB;
+       ctl &= ~(DISGARTCPU | DISGARTIO);
+       pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
 
 static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
index fc1f579fb965157cec8ce23376a59ff5a23280e9..65aaa91d5850c03238ced9403da7c5ce5342a5ea 100644 (file)
@@ -6,6 +6,8 @@
 #define PIT_CH0                        0x40
 #define PIT_CH2                        0x42
 
+#define PIT_LATCH      LATCH
+
 extern raw_spinlock_t i8253_lock;
 
 extern struct clock_event_device *global_clock_event;
index c4bd267dfc50842e73ea02c562549717c47fb80a..a97a240f67f3158f79c112fffcd0b8dd1e3f4847 100644 (file)
@@ -150,7 +150,7 @@ void setup_IO_APIC_irq_extra(u32 gsi);
 extern void ioapic_and_gsi_init(void);
 extern void ioapic_insert_resources(void);
 
-int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
 
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
index 574dbc22893a9301914def19c5004b9ec1b851fe..a32b18ce6eadae461d712a6c49b172387cdbbfd1 100644 (file)
@@ -5,20 +5,25 @@
 
 #include <linux/types.h>
 #include <asm/nops.h>
+#include <asm/asm.h>
 
 #define JUMP_LABEL_NOP_SIZE 5
 
-# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"
-
-# define JUMP_LABEL(key, label)                                        \
-       do {                                                    \
-               asm goto("1:"                                   \
-                       JUMP_LABEL_INITIAL_NOP                  \
-                       ".pushsection __jump_table,  \"aw\" \n\t"\
-                       _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
-                       ".popsection \n\t"                      \
-                       : :  "i" (key) :  : label);             \
-       } while (0)
+#define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("1:"
+               JUMP_LABEL_INITIAL_NOP
+               ".pushsection __jump_table,  \"aw\" \n\t"
+               _ASM_ALIGN "\n\t"
+               _ASM_PTR "1b, %l[l_yes], %c0 \n\t"
+               ".popsection \n\t"
+               : :  "i" (key) : : l_yes);
+       return false;
+l_yes:
+       return true;
+}
 
 #endif /* __KERNEL__ */
 
index eb16e94ae04f79927eb2c5afbf7b6ecd849b1621..021979a6e23fe7074c6b0b44e09910682d0fcf0c 100644 (file)
@@ -142,8 +142,6 @@ static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
 static inline void enable_p5_mce(void) {}
 #endif
 
-extern void (*x86_mce_decode_callback)(struct mce *m);
-
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
 DECLARE_PER_CPU(struct sys_device, mce_dev);
index 91df7c51806cefc0820dbf13a49be0b51136676e..5e83a416eca8941410c0b93a99beff853831f433 100644 (file)
@@ -13,31 +13,11 @@ extern struct pglist_data *node_data[];
 #define NODE_DATA(nid) (node_data[nid])
 
 #include <asm/numaq.h>
-/* summit or generic arch */
-#include <asm/srat.h>
-
-extern int get_memcfg_numa_flat(void);
-/*
- * This allows any one NUMA architecture to be compiled
- * for, and still fall back to the flat function if it
- * fails.
- */
-static inline void get_memcfg_numa(void)
-{
-
-       if (get_memcfg_numaq())
-               return;
-       if (get_memcfg_from_srat())
-               return;
-       get_memcfg_numa_flat();
-}
 
 extern void resume_map_numa_kva(pgd_t *pgd);
 
 #else /* !CONFIG_NUMA */
 
-#define get_memcfg_numa get_memcfg_numa_flat
-
 static inline void resume_map_numa_kva(pgd_t *pgd) {}
 
 #endif /* CONFIG_NUMA */
index 288b96f815a6b53571b6b6192469276db283a8ac..b3f88d7867c79235372b5ad6f5cfc6edd254a083 100644 (file)
@@ -4,36 +4,13 @@
 #ifndef _ASM_X86_MMZONE_64_H
 #define _ASM_X86_MMZONE_64_H
 
-
 #ifdef CONFIG_NUMA
 
 #include <linux/mmdebug.h>
-
 #include <asm/smp.h>
 
-/* Simple perfect hash to map physical addresses to node numbers */
-struct memnode {
-       int shift;
-       unsigned int mapsize;
-       s16 *map;
-       s16 embedded_map[64 - 8];
-} ____cacheline_aligned; /* total size = 128 bytes */
-extern struct memnode memnode;
-#define memnode_shift memnode.shift
-#define memnodemap memnode.map
-#define memnodemapsize memnode.mapsize
-
 extern struct pglist_data *node_data[];
 
-static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
-{
-       unsigned nid;
-       VIRTUAL_BUG_ON(!memnodemap);
-       nid = memnodemap[addr >> memnode_shift];
-       VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]);
-       return nid;
-}
-
 #define NODE_DATA(nid)         (node_data[nid])
 
 #define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
index 67763c5d8b4ecc4f2e20541bcc73640ed03a8c12..9eae7752ae9b3dc80b970222d5606de302d07e6d 100644 (file)
@@ -35,7 +35,7 @@
 #define MODULE_PROC_FAMILY "K7 "
 #elif defined CONFIG_MK8
 #define MODULE_PROC_FAMILY "K8 "
-#elif defined CONFIG_X86_ELAN
+#elif defined CONFIG_MELAN
 #define MODULE_PROC_FAMILY "ELAN "
 #elif defined CONFIG_MCRUSOE
 #define MODULE_PROC_FAMILY "CRUSOE "
index af788496020b43918799c4f4691dda8c0ad44b96..405b4032a60b37200e2e2ecfae8289c792800755 100644 (file)
@@ -1,7 +1,13 @@
 #ifndef _ASM_X86_NOPS_H
 #define _ASM_X86_NOPS_H
 
-/* Define nops for use with alternative() */
+/*
+ * Define nops for use with alternative() and for tracing.
+ *
+ * *_NOP5_ATOMIC must be a single instruction.
+ */
+
+#define NOP_DS_PREFIX 0x3e
 
 /* generic versions from gas
    1: nop
    6: leal 0x00000000(%esi),%esi
    7: leal 0x00000000(,%esi,1),%esi
 */
-#define GENERIC_NOP1 ".byte 0x90\n"
-#define GENERIC_NOP2 ".byte 0x89,0xf6\n"
-#define GENERIC_NOP3 ".byte 0x8d,0x76,0x00\n"
-#define GENERIC_NOP4 ".byte 0x8d,0x74,0x26,0x00\n"
-#define GENERIC_NOP5 GENERIC_NOP1 GENERIC_NOP4
-#define GENERIC_NOP6 ".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
-#define GENERIC_NOP7 ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
-#define GENERIC_NOP8 GENERIC_NOP1 GENERIC_NOP7
+#define GENERIC_NOP1 0x90
+#define GENERIC_NOP2 0x89,0xf6
+#define GENERIC_NOP3 0x8d,0x76,0x00
+#define GENERIC_NOP4 0x8d,0x74,0x26,0x00
+#define GENERIC_NOP5 GENERIC_NOP1,GENERIC_NOP4
+#define GENERIC_NOP6 0x8d,0xb6,0x00,0x00,0x00,0x00
+#define GENERIC_NOP7 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00
+#define GENERIC_NOP8 GENERIC_NOP1,GENERIC_NOP7
+#define GENERIC_NOP5_ATOMIC NOP_DS_PREFIX,GENERIC_NOP4
 
 /* Opteron 64bit nops
    1: nop
    4: osp osp osp nop
 */
 #define K8_NOP1 GENERIC_NOP1
-#define K8_NOP2        ".byte 0x66,0x90\n"
-#define K8_NOP3        ".byte 0x66,0x66,0x90\n"
-#define K8_NOP4        ".byte 0x66,0x66,0x66,0x90\n"
-#define K8_NOP5        K8_NOP3 K8_NOP2
-#define K8_NOP6        K8_NOP3 K8_NOP3
-#define K8_NOP7        K8_NOP4 K8_NOP3
-#define K8_NOP8        K8_NOP4 K8_NOP4
+#define K8_NOP2        0x66,K8_NOP1
+#define K8_NOP3        0x66,K8_NOP2
+#define K8_NOP4        0x66,K8_NOP3
+#define K8_NOP5        K8_NOP3,K8_NOP2
+#define K8_NOP6        K8_NOP3,K8_NOP3
+#define K8_NOP7        K8_NOP4,K8_NOP3
+#define K8_NOP8        K8_NOP4,K8_NOP4
+#define K8_NOP5_ATOMIC 0x66,K8_NOP4
 
 /* K7 nops
    uses eax dependencies (arbitrary choice)
    7: leal 0x00000000(,%eax,1),%eax
 */
 #define K7_NOP1        GENERIC_NOP1
-#define K7_NOP2        ".byte 0x8b,0xc0\n"
-#define K7_NOP3        ".byte 0x8d,0x04,0x20\n"
-#define K7_NOP4        ".byte 0x8d,0x44,0x20,0x00\n"
-#define K7_NOP5        K7_NOP4 ASM_NOP1
-#define K7_NOP6        ".byte 0x8d,0x80,0,0,0,0\n"
-#define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
-#define K7_NOP8        K7_NOP7 ASM_NOP1
+#define K7_NOP2        0x8b,0xc0
+#define K7_NOP3        0x8d,0x04,0x20
+#define K7_NOP4        0x8d,0x44,0x20,0x00
+#define K7_NOP5        K7_NOP4,K7_NOP1
+#define K7_NOP6        0x8d,0x80,0,0,0,0
+#define K7_NOP7        0x8D,0x04,0x05,0,0,0,0
+#define K7_NOP8        K7_NOP7,K7_NOP1
+#define K7_NOP5_ATOMIC NOP_DS_PREFIX,K7_NOP4
 
 /* P6 nops
    uses eax dependencies (Intel-recommended choice)
        There is kernel code that depends on this.
 */
 #define P6_NOP1        GENERIC_NOP1
-#define P6_NOP2        ".byte 0x66,0x90\n"
-#define P6_NOP3        ".byte 0x0f,0x1f,0x00\n"
-#define P6_NOP4        ".byte 0x0f,0x1f,0x40,0\n"
-#define P6_NOP5        ".byte 0x0f,0x1f,0x44,0x00,0\n"
-#define P6_NOP6        ".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
-#define P6_NOP7        ".byte 0x0f,0x1f,0x80,0,0,0,0\n"
-#define P6_NOP8        ".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
+#define P6_NOP2        0x66,0x90
+#define P6_NOP3        0x0f,0x1f,0x00
+#define P6_NOP4        0x0f,0x1f,0x40,0
+#define P6_NOP5        0x0f,0x1f,0x44,0x00,0
+#define P6_NOP6        0x66,0x0f,0x1f,0x44,0x00,0
+#define P6_NOP7        0x0f,0x1f,0x80,0,0,0,0
+#define P6_NOP8        0x0f,0x1f,0x84,0x00,0,0,0,0
+#define P6_NOP5_ATOMIC P6_NOP5
+
+#define _ASM_MK_NOP(x) ".byte " __stringify(x) "\n"
 
 #if defined(CONFIG_MK7)
-#define ASM_NOP1 K7_NOP1
-#define ASM_NOP2 K7_NOP2
-#define ASM_NOP3 K7_NOP3
-#define ASM_NOP4 K7_NOP4
-#define ASM_NOP5 K7_NOP5
-#define ASM_NOP6 K7_NOP6
-#define ASM_NOP7 K7_NOP7
-#define ASM_NOP8 K7_NOP8
+#define ASM_NOP1 _ASM_MK_NOP(K7_NOP1)
+#define ASM_NOP2 _ASM_MK_NOP(K7_NOP2)
+#define ASM_NOP3 _ASM_MK_NOP(K7_NOP3)
+#define ASM_NOP4 _ASM_MK_NOP(K7_NOP4)
+#define ASM_NOP5 _ASM_MK_NOP(K7_NOP5)
+#define ASM_NOP6 _ASM_MK_NOP(K7_NOP6)
+#define ASM_NOP7 _ASM_MK_NOP(K7_NOP7)
+#define ASM_NOP8 _ASM_MK_NOP(K7_NOP8)
+#define ASM_NOP5_ATOMIC _ASM_MK_NOP(K7_NOP5_ATOMIC)
 #elif defined(CONFIG_X86_P6_NOP)
-#define ASM_NOP1 P6_NOP1
-#define ASM_NOP2 P6_NOP2
-#define ASM_NOP3 P6_NOP3
-#define ASM_NOP4 P6_NOP4
-#define ASM_NOP5 P6_NOP5
-#define ASM_NOP6 P6_NOP6
-#define ASM_NOP7 P6_NOP7
-#define ASM_NOP8 P6_NOP8
+#define ASM_NOP1 _ASM_MK_NOP(P6_NOP1)
+#define ASM_NOP2 _ASM_MK_NOP(P6_NOP2)
+#define ASM_NOP3 _ASM_MK_NOP(P6_NOP3)
+#define ASM_NOP4 _ASM_MK_NOP(P6_NOP4)
+#define ASM_NOP5 _ASM_MK_NOP(P6_NOP5)
+#define ASM_NOP6 _ASM_MK_NOP(P6_NOP6)
+#define ASM_NOP7 _ASM_MK_NOP(P6_NOP7)
+#define ASM_NOP8 _ASM_MK_NOP(P6_NOP8)
+#define ASM_NOP5_ATOMIC _ASM_MK_NOP(P6_NOP5_ATOMIC)
 #elif defined(CONFIG_X86_64)
-#define ASM_NOP1 K8_NOP1
-#define ASM_NOP2 K8_NOP2
-#define ASM_NOP3 K8_NOP3
-#define ASM_NOP4 K8_NOP4
-#define ASM_NOP5 K8_NOP5
-#define ASM_NOP6 K8_NOP6
-#define ASM_NOP7 K8_NOP7
-#define ASM_NOP8 K8_NOP8
+#define ASM_NOP1 _ASM_MK_NOP(K8_NOP1)
+#define ASM_NOP2 _ASM_MK_NOP(K8_NOP2)
+#define ASM_NOP3 _ASM_MK_NOP(K8_NOP3)
+#define ASM_NOP4 _ASM_MK_NOP(K8_NOP4)
+#define ASM_NOP5 _ASM_MK_NOP(K8_NOP5)
+#define ASM_NOP6 _ASM_MK_NOP(K8_NOP6)
+#define ASM_NOP7 _ASM_MK_NOP(K8_NOP7)
+#define ASM_NOP8 _ASM_MK_NOP(K8_NOP8)
+#define ASM_NOP5_ATOMIC _ASM_MK_NOP(K8_NOP5_ATOMIC)
 #else
-#define ASM_NOP1 GENERIC_NOP1
-#define ASM_NOP2 GENERIC_NOP2
-#define ASM_NOP3 GENERIC_NOP3
-#define ASM_NOP4 GENERIC_NOP4
-#define ASM_NOP5 GENERIC_NOP5
-#define ASM_NOP6 GENERIC_NOP6
-#define ASM_NOP7 GENERIC_NOP7
-#define ASM_NOP8 GENERIC_NOP8
+#define ASM_NOP1 _ASM_MK_NOP(GENERIC_NOP1)
+#define ASM_NOP2 _ASM_MK_NOP(GENERIC_NOP2)
+#define ASM_NOP3 _ASM_MK_NOP(GENERIC_NOP3)
+#define ASM_NOP4 _ASM_MK_NOP(GENERIC_NOP4)
+#define ASM_NOP5 _ASM_MK_NOP(GENERIC_NOP5)
+#define ASM_NOP6 _ASM_MK_NOP(GENERIC_NOP6)
+#define ASM_NOP7 _ASM_MK_NOP(GENERIC_NOP7)
+#define ASM_NOP8 _ASM_MK_NOP(GENERIC_NOP8)
+#define ASM_NOP5_ATOMIC _ASM_MK_NOP(GENERIC_NOP5_ATOMIC)
 #endif
 
 #define ASM_NOP_MAX 8
+#define NOP_ATOMIC5 (ASM_NOP_MAX+1)    /* Entry for the 5-byte atomic NOP */
+
+#ifndef __ASSEMBLY__
+extern const unsigned char * const *ideal_nops;
+extern void arch_init_ideal_nops(void);
+#endif
 
 #endif /* _ASM_X86_NOPS_H */
index 3d4dab43c99469b6d917f0ba4f4bebd7cdc25bb6..bfacd2ccf651cfd0346ff254ebfdc76de6791431 100644 (file)
@@ -1,12 +1,24 @@
 #ifndef _ASM_X86_NUMA_H
 #define _ASM_X86_NUMA_H
 
+#include <linux/nodemask.h>
+
 #include <asm/topology.h>
 #include <asm/apicdef.h>
 
 #ifdef CONFIG_NUMA
 
 #define NR_NODE_MEMBLKS                (MAX_NUMNODES*2)
+#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
+
+/*
+ * Too small node sizes may confuse the VM badly. Usually they
+ * result from BIOS bugs. So dont recognize nodes as standalone
+ * NUMA entities that have less than this amount of RAM listed:
+ */
+#define NODE_MIN_SIZE (4*1024*1024)
+
+extern int numa_off;
 
 /*
  * __apicid_to_node[] stores the raw mapping between physical apicid and
  * numa_cpu_node().
  */
 extern s16 __apicid_to_node[MAX_LOCAL_APIC];
+extern nodemask_t numa_nodes_parsed __initdata;
+
+extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+extern void __init numa_set_distance(int from, int to, int distance);
 
 static inline void set_apicid_to_node(int apicid, s16 node)
 {
        __apicid_to_node[apicid] = node;
 }
+
+extern int __cpuinit numa_cpu_node(int cpu);
+
 #else  /* CONFIG_NUMA */
 static inline void set_apicid_to_node(int apicid, s16 node)
 {
 }
+
+static inline int numa_cpu_node(int cpu)
+{
+       return NUMA_NO_NODE;
+}
 #endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_X86_32
@@ -37,21 +61,25 @@ static inline void set_apicid_to_node(int apicid, s16 node)
 #ifdef CONFIG_NUMA
 extern void __cpuinit numa_set_node(int cpu, int node);
 extern void __cpuinit numa_clear_node(int cpu);
-extern void __init numa_init_array(void);
 extern void __init init_cpu_to_node(void);
 extern void __cpuinit numa_add_cpu(int cpu);
 extern void __cpuinit numa_remove_cpu(int cpu);
 #else  /* CONFIG_NUMA */
 static inline void numa_set_node(int cpu, int node)    { }
 static inline void numa_clear_node(int cpu)            { }
-static inline void numa_init_array(void)               { }
 static inline void init_cpu_to_node(void)              { }
 static inline void numa_add_cpu(int cpu)               { }
 static inline void numa_remove_cpu(int cpu)            { }
 #endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_DEBUG_PER_CPU_MAPS
-struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable);
+void debug_cpumask_set_cpu(int cpu, int node, bool enable);
 #endif
 
+#ifdef CONFIG_NUMA_EMU
+#define FAKE_NODE_MIN_SIZE     ((u64)32 << 20)
+#define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1UL))
+void numa_emu_cmdline(char *);
+#endif /* CONFIG_NUMA_EMU */
+
 #endif /* _ASM_X86_NUMA_H */
index c6beed1ef10373f9be333a01fa8648cb499a1836..e7d6b82547429d470aa7679a602cc2788100aec8 100644 (file)
@@ -1,16 +1,6 @@
 #ifndef _ASM_X86_NUMA_32_H
 #define _ASM_X86_NUMA_32_H
 
-extern int numa_off;
-
-extern int pxm_to_nid(int pxm);
-
-#ifdef CONFIG_NUMA
-extern int __cpuinit numa_cpu_node(int cpu);
-#else  /* CONFIG_NUMA */
-static inline int numa_cpu_node(int cpu)               { return NUMA_NO_NODE; }
-#endif /* CONFIG_NUMA */
-
 #ifdef CONFIG_HIGHMEM
 extern void set_highmem_pages_init(void);
 #else
index 344eb1790b4646901f842786a8df9fb21f17bd63..0c05f7ae46e8cc8b12bbf374146310762c4fc424 100644 (file)
@@ -1,42 +1,6 @@
 #ifndef _ASM_X86_NUMA_64_H
 #define _ASM_X86_NUMA_64_H
 
-#include <linux/nodemask.h>
-
-struct bootnode {
-       u64 start;
-       u64 end;
-};
-
-#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
-
-extern int numa_off;
-
 extern unsigned long numa_free_all_bootmem(void);
-extern void setup_node_bootmem(int nodeid, unsigned long start,
-                              unsigned long end);
-
-#ifdef CONFIG_NUMA
-/*
- * Too small node sizes may confuse the VM badly. Usually they
- * result from BIOS bugs. So dont recognize nodes as standalone
- * NUMA entities that have less than this amount of RAM listed:
- */
-#define NODE_MIN_SIZE (4*1024*1024)
-
-extern nodemask_t numa_nodes_parsed __initdata;
-
-extern int __cpuinit numa_cpu_node(int cpu);
-extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
-extern void __init numa_set_distance(int from, int to, int distance);
-
-#ifdef CONFIG_NUMA_EMU
-#define FAKE_NODE_MIN_SIZE     ((u64)32 << 20)
-#define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1UL))
-void numa_emu_cmdline(char *);
-#endif /* CONFIG_NUMA_EMU */
-#else
-static inline int numa_cpu_node(int cpu)               { return NUMA_NO_NODE; }
-#endif
 
 #endif /* _ASM_X86_NUMA_64_H */
index 37c516545ec8c7a8b73b13e84c37756d1a6ac6e2..c3b3c322fd8773eb785de0839d5a240aeb92b942 100644 (file)
@@ -29,7 +29,7 @@
 #ifdef CONFIG_X86_NUMAQ
 
 extern int found_numaq;
-extern int get_memcfg_numaq(void);
+extern int numaq_numa_init(void);
 extern int pci_numaq_init(void);
 
 extern void *xquad_portio;
@@ -166,11 +166,6 @@ struct sys_cfg_data {
 
 void numaq_tsc_disable(void);
 
-#else
-static inline int get_memcfg_numaq(void)
-{
-       return 0;
-}
 #endif /* CONFIG_X86_NUMAQ */
 #endif /* _ASM_X86_NUMAQ_H */
 
index c5d3a5abbb9f4ec2757b468bc14459ce4d13d496..24487712e0b1915368f96a3a74ba362ff42fdbbd 100644 (file)
@@ -26,15 +26,12 @@ extern void setup_olpc_ofw_pgd(void);
 /* check if OFW was detected during boot */
 extern bool olpc_ofw_present(void);
 
+extern void olpc_dt_build_devicetree(void);
+
 #else /* !CONFIG_OLPC */
 static inline void olpc_ofw_detect(void) { }
 static inline void setup_olpc_ofw_pgd(void) { }
-#endif /* !CONFIG_OLPC */
-
-#ifdef CONFIG_OF_PROMTREE
-extern void olpc_dt_build_devicetree(void);
-#else
 static inline void olpc_dt_build_devicetree(void) { }
-#endif
+#endif /* !CONFIG_OLPC */
 
 #endif /* _ASM_X86_OLPC_OFW_H */
index d475b4398d8b858cadd87ad36514b79465dc795c..53278b0dfdf660103f8f9c234b0d97691ae48611 100644 (file)
@@ -517,7 +517,7 @@ do {                                                                        \
        typeof(o2) __o2 = o2;                                           \
        typeof(o2) __n2 = n2;                                           \
        typeof(o2) __dummy;                                             \
-       alternative_io("call this_cpu_cmpxchg16b_emu\n\t" P6_NOP4,      \
+       alternative_io("call this_cpu_cmpxchg16b_emu\n\t" ASM_NOP4,     \
                       "cmpxchg16b " __percpu_prefix "(%%rsi)\n\tsetz %0\n\t",  \
                       X86_FEATURE_CX16,                                \
                       ASM_OUTPUT2("=a"(__ret), "=d"(__dummy)),         \
@@ -542,6 +542,33 @@ do {                                                                       \
        old__;                                                          \
 })
 
+static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,
+                        const unsigned long __percpu *addr)
+{
+       unsigned long __percpu *a = (unsigned long *)addr + nr / BITS_PER_LONG;
+
+       return ((1UL << (nr % BITS_PER_LONG)) & percpu_read(*a)) != 0;
+}
+
+static inline int x86_this_cpu_variable_test_bit(int nr,
+                        const unsigned long __percpu *addr)
+{
+       int oldbit;
+
+       asm volatile("bt "__percpu_arg(2)",%1\n\t"
+                       "sbb %0,%0"
+                       : "=r" (oldbit)
+                       : "m" (*(unsigned long *)addr), "Ir" (nr));
+
+       return oldbit;
+}
+
+#define x86_this_cpu_test_bit(nr, addr)                        \
+       (__builtin_constant_p((nr))                     \
+        ? x86_this_cpu_constant_test_bit((nr), (addr)) \
+        : x86_this_cpu_variable_test_bit((nr), (addr)))
+
+
 #include <asm-generic/percpu.h>
 
 /* We can use this directly for local CPU (faster). */
index 7db7723d1f325f8016666806f790a015a4005c6b..d56187c6b8385425bb893f8d70003cb70290243a 100644 (file)
@@ -299,6 +299,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
 /* Install a pte for a particular vaddr in kernel space. */
 void set_pte_vaddr(unsigned long vaddr, pte_t pte);
 
+extern void native_pagetable_reserve(u64 start, u64 end);
 #ifdef CONFIG_X86_32
 extern void native_pagetable_setup_start(pgd_t *base);
 extern void native_pagetable_setup_done(pgd_t *base);
diff --git a/arch/x86/include/asm/probe_roms.h b/arch/x86/include/asm/probe_roms.h
new file mode 100644 (file)
index 0000000..4950a0b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _PROBE_ROMS_H_
+#define _PROBE_ROMS_H_
+struct pci_dev;
+
+extern void __iomem *pci_map_biosrom(struct pci_dev *pdev);
+extern void pci_unmap_biosrom(void __iomem *rom);
+extern size_t pci_biosrom_size(struct pci_dev *pdev);
+#endif
index a898a2b6e10c68ab0c82b11446d69d6b8452058b..59ab4dffa37794023f2dd5f29ab8dabd7325b0bb 100644 (file)
@@ -60,6 +60,7 @@
 #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE   0x00002000 /* enable VMX virtualization */
 #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
+#define X86_CR4_SMEP   0x00100000 /* enable SMEP support */
 
 /*
  * x86-64 Task Priority Register, CR8
index db8aa19a08a22d35e608625b251bcee7fa5fe1ee..9756551ec76024dba4dbf7a4f09f988219ca6f0b 100644 (file)
@@ -88,7 +88,7 @@ void *extend_brk(size_t size, size_t align);
  * executable.)
  */
 #define RESERVE_BRK(name,sz)                                           \
-       static void __section(.discard.text) __used                     \
+       static void __section(.discard.text) __used notrace             \
        __brk_reservation_fn_##name##__(void) {                         \
                asm volatile (                                          \
                        ".pushsection .brk_reservation,\"aw\",@nobits;" \
@@ -104,10 +104,10 @@ void *extend_brk(size_t size, size_t align);
        type *name;                                     \
        RESERVE_BRK(name, sizeof(type) * entries)
 
+extern void probe_roms(void);
 #ifdef __i386__
 
 void __init i386_start_kernel(void);
-extern void probe_roms(void);
 
 #else
 void __init x86_64_start_kernel(char *real_mode);
diff --git a/arch/x86/include/asm/srat.h b/arch/x86/include/asm/srat.h
deleted file mode 100644 (file)
index b508d63..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Some of the code in this file has been gleaned from the 64 bit
- * discontigmem support code base.
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to Pat Gaughen <gone@us.ibm.com>
- */
-
-#ifndef _ASM_X86_SRAT_H
-#define _ASM_X86_SRAT_H
-
-#ifdef CONFIG_ACPI_NUMA
-extern int get_memcfg_from_srat(void);
-#else
-static inline int get_memcfg_from_srat(void)
-{
-       return 0;
-}
-#endif
-
-#endif /* _ASM_X86_SRAT_H */
index d7e89c83645d275c3cc7b3677c05f28528cc771d..70bbe39043a9cda384e9afcd0a2f633cfde20931 100644 (file)
@@ -37,9 +37,6 @@ print_context_stack_bp(struct thread_info *tinfo,
 /* Generic stack tracer with callbacks */
 
 struct stacktrace_ops {
-       void (*warning)(void *data, char *msg);
-       /* msg must contain %s for the symbol */
-       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
        void (*address)(void *data, unsigned long address, int reliable);
        /* On negative return stop dumping */
        int (*stack)(void *data, char *name);
index 12569e691ce3aa139b745682fce86349918cee1a..c2ff2a1d845e402249e44a70e41459805c3faaa8 100644 (file)
@@ -303,24 +303,81 @@ static inline void native_wbinvd(void)
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
-#define read_cr0()     (native_read_cr0())
-#define write_cr0(x)   (native_write_cr0(x))
-#define read_cr2()     (native_read_cr2())
-#define write_cr2(x)   (native_write_cr2(x))
-#define read_cr3()     (native_read_cr3())
-#define write_cr3(x)   (native_write_cr3(x))
-#define read_cr4()     (native_read_cr4())
-#define read_cr4_safe()        (native_read_cr4_safe())
-#define write_cr4(x)   (native_write_cr4(x))
-#define wbinvd()       (native_wbinvd())
+
+static inline unsigned long read_cr0(void)
+{
+       return native_read_cr0();
+}
+
+static inline void write_cr0(unsigned long x)
+{
+       native_write_cr0(x);
+}
+
+static inline unsigned long read_cr2(void)
+{
+       return native_read_cr2();
+}
+
+static inline void write_cr2(unsigned long x)
+{
+       native_write_cr2(x);
+}
+
+static inline unsigned long read_cr3(void)
+{
+       return native_read_cr3();
+}
+
+static inline void write_cr3(unsigned long x)
+{
+       native_write_cr3(x);
+}
+
+static inline unsigned long read_cr4(void)
+{
+       return native_read_cr4();
+}
+
+static inline unsigned long read_cr4_safe(void)
+{
+       return native_read_cr4_safe();
+}
+
+static inline void write_cr4(unsigned long x)
+{
+       native_write_cr4(x);
+}
+
+static inline void wbinvd(void)
+{
+       native_wbinvd();
+}
+
 #ifdef CONFIG_X86_64
-#define read_cr8()     (native_read_cr8())
-#define write_cr8(x)   (native_write_cr8(x))
-#define load_gs_index   native_load_gs_index
+
+static inline unsigned long read_cr8(void)
+{
+       return native_read_cr8();
+}
+
+static inline void write_cr8(unsigned long x)
+{
+       native_write_cr8(x);
+}
+
+static inline void load_gs_index(unsigned selector)
+{
+       native_load_gs_index(selector);
+}
+
 #endif
 
 /* Clear the 'TS' bit */
-#define clts()         (native_clts())
+static inline void clts(void)
+{
+       native_clts();
+}
 
 #endif/* CONFIG_PARAVIRT */
 
index 910a7084f7f22dda7739d2b3d122d1c5be39ae33..c00692476e9fc6f824b77b0c420aadd18c1fae7e 100644 (file)
@@ -93,19 +93,11 @@ extern void setup_node_to_cpumask_map(void);
 #define pcibus_to_node(bus) __pcibus_to_node(bus)
 
 #ifdef CONFIG_X86_32
-extern unsigned long node_start_pfn[];
-extern unsigned long node_end_pfn[];
-extern unsigned long node_remap_size[];
-#define node_has_online_mem(nid) (node_start_pfn[nid] != node_end_pfn[nid])
-
 # define SD_CACHE_NICE_TRIES   1
 # define SD_IDLE_IDX           1
-
 #else
-
 # define SD_CACHE_NICE_TRIES   2
 # define SD_IDLE_IDX           2
-
 #endif
 
 /* sched_domains SD_NODE_INIT for NUMA machines */
index abd3e0ea762ac739b054ddd1922efba71017a742..99f0ad753f32c482f9f5b222c84cee881696b628 100644 (file)
@@ -42,7 +42,7 @@
  * 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)
+ * (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...
  */
index 3e094af443c396a6ccf9f08628ecafc2a5d974ab..130f1eeee5fed416bb41ed4fa54a97bdcc31a601 100644 (file)
@@ -94,6 +94,8 @@
 /* after this # consecutive successes, bump up the throttle if it was lowered */
 #define COMPLETE_THRESHOLD 5
 
+#define UV_LB_SUBNODEID 0x10
+
 /*
  * number of entries in the destination side payload queue
  */
  * The distribution specification (32 bytes) is interpreted as a 256-bit
  * distribution vector. Adjacent bits correspond to consecutive even numbered
  * nodeIDs. The result of adding the index of a given bit to the 15-bit
- * 'base_dest_nodeid' field of the header corresponds to the
+ * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
 struct bau_target_uvhubmask {
@@ -176,7 +178,7 @@ struct bau_msg_payload {
 struct bau_msg_header {
        unsigned int dest_subnodeid:6;  /* must be 0x10, for the LB */
        /* bits 5:0 */
-       unsigned int base_dest_nodeid:15; /* nasid of the */
+       unsigned int base_dest_nasid:15; /* nasid of the */
        /* bits 20:6 */                   /* first bit in uvhub map */
        unsigned int command:8; /* message type */
        /* bits 28:21 */
@@ -378,6 +380,10 @@ struct ptc_stats {
        unsigned long d_rcanceled; /* number of messages canceled by resets */
 };
 
+struct hub_and_pnode {
+       short uvhub;
+       short pnode;
+};
 /*
  * one per-cpu; to locate the software tables
  */
@@ -399,10 +405,12 @@ struct bau_control {
        int baudisabled;
        int set_bau_off;
        short cpu;
+       short osnode;
        short uvhub_cpu;
        short uvhub;
        short cpus_in_socket;
        short cpus_in_uvhub;
+       short partition_base_pnode;
        unsigned short message_number;
        unsigned short uvhub_quiesce;
        short socket_acknowledge_count[DEST_Q_SIZE];
@@ -422,15 +430,16 @@ struct bau_control {
        int congested_period;
        cycles_t period_time;
        long period_requests;
+       struct hub_and_pnode *target_hub_and_pnode;
 };
 
 static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
 {
        return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct bau_target_uvhubmask *dstp)
 {
-       __set_bit(uvhub, &dstp->bits[0]);
+       __set_bit(pnode, &dstp->bits[0]);
 }
 static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp,
                                    int nbits)
index a501741c2335a854fa43d14f73761d8bf8f9c82e..4298002d0c83a9c09c19c725c22a33e43921d128 100644 (file)
@@ -398,6 +398,8 @@ struct uv_blade_info {
        unsigned short  nr_online_cpus;
        unsigned short  pnode;
        short           memory_nid;
+       spinlock_t      nmi_lock;
+       unsigned long   nmi_count;
 };
 extern struct uv_blade_info *uv_blade_info;
 extern short *uv_node_to_blade;
index 20cafeac7455594d73a3bc6837da0a34fcdee3eb..f5bb64a823d77a1d3ebf97d40e80e913c83e0d31 100644 (file)
@@ -5,7 +5,7 @@
  *
  * SGI UV MMR definitions
  *
- * Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2011 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_MMRS_H
@@ -1099,5 +1099,19 @@ union uvh_rtc1_int_config_u {
     } s;
 };
 
+/* ========================================================================= */
+/*                               UVH_SCRATCH5                                */
+/* ========================================================================= */
+#define UVH_SCRATCH5 0x2d0200UL
+#define UVH_SCRATCH5_32 0x00778
+
+#define UVH_SCRATCH5_SCRATCH5_SHFT 0
+#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
+union uvh_scratch5_u {
+    unsigned long      v;
+    struct uvh_scratch5_s {
+       unsigned long   scratch5 : 64;  /* RW, W1CS */
+    } s;
+};
 
 #endif /* __ASM_UV_MMRS_X86_H__ */
index 643ebf2e2ad8733ddbec5ca884ee21bf405c0226..d3d859035af9e1968d0ad9d4a39000331c27c8f1 100644 (file)
@@ -67,6 +67,17 @@ struct x86_init_oem {
        void (*banner)(void);
 };
 
+/**
+ * struct x86_init_mapping - platform specific initial kernel pagetable setup
+ * @pagetable_reserve: reserve a range of addresses for kernel pagetable usage
+ *
+ * For more details on the purpose of this hook, look in
+ * init_memory_mapping and the commit that added it.
+ */
+struct x86_init_mapping {
+       void (*pagetable_reserve)(u64 start, u64 end);
+};
+
 /**
  * struct x86_init_paging - platform specific paging functions
  * @pagetable_setup_start:     platform specific pre paging_init() call
@@ -123,6 +134,7 @@ struct x86_init_ops {
        struct x86_init_mpparse         mpparse;
        struct x86_init_irqs            irqs;
        struct x86_init_oem             oem;
+       struct x86_init_mapping         mapping;
        struct x86_init_paging          paging;
        struct x86_init_timers          timers;
        struct x86_init_iommu           iommu;
index c61934fbf22a4f0d1b8de6c4ff5b514f40e3f0e3..64a619d47d341739ff34b5236e6bf85db0a79b06 100644 (file)
@@ -47,8 +47,9 @@ extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
 extern unsigned long set_phys_range_identity(unsigned long pfn_s,
                                             unsigned long pfn_e);
 
-extern int m2p_add_override(unsigned long mfn, struct page *page);
-extern int m2p_remove_override(struct page *page);
+extern int m2p_add_override(unsigned long mfn, struct page *page,
+                           bool clear_pte);
+extern int m2p_remove_override(struct page *page, bool clear_pte);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
index aa86209891622f1a871970cc758efc8ea28f935a..4fbda9a3f33905342a08c7819f247056228e1b9f 100644 (file)
@@ -15,10 +15,26 @@ static inline int pci_xen_hvm_init(void)
 #endif
 #if defined(CONFIG_XEN_DOM0)
 void __init xen_setup_pirqs(void);
+int xen_find_device_domain_owner(struct pci_dev *dev);
+int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
+int xen_unregister_device_domain_owner(struct pci_dev *dev);
 #else
 static inline void __init xen_setup_pirqs(void)
 {
 }
+static inline int xen_find_device_domain_owner(struct pci_dev *dev)
+{
+       return -1;
+}
+static inline int xen_register_device_domain_owner(struct pci_dev *dev,
+                                                  uint16_t domain)
+{
+       return -1;
+}
+static inline int xen_unregister_device_domain_owner(struct pci_dev *dev)
+{
+       return -1;
+}
 #endif
 
 #if defined(CONFIG_PCI_MSI)
index 7338ef2218bc0687f6bfc392ecfeca8a48ca0b56..250806472a7e07373c7bf5cd66acfc8bca81d032 100644 (file)
@@ -36,7 +36,7 @@ obj-y                 += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y                  += time.o ioport.o ldt.o dumpstack.o
 obj-y                  += setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
-obj-$(CONFIG_X86_32)   += probe_roms_32.o
+obj-y                  += probe_roms.o
 obj-$(CONFIG_X86_32)   += sys_i386_32.o i386_ksyms_32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o x8664_ksyms_64.o
 obj-$(CONFIG_X86_64)   += syscall_64.o vsyscall_64.o
@@ -117,7 +117,7 @@ obj-$(CONFIG_OF)                    += devicetree.o
 ifeq ($(CONFIG_X86_64),y)
        obj-$(CONFIG_AUDIT)             += audit_64.o
 
-       obj-$(CONFIG_GART_IOMMU)        += pci-gart_64.o aperture_64.o
+       obj-$(CONFIG_GART_IOMMU)        += amd_gart_64.o aperture_64.o
        obj-$(CONFIG_CALGARY_IOMMU)     += pci-calgary_64.o tce_64.o
        obj-$(CONFIG_AMD_IOMMU)         += amd_iommu_init.o amd_iommu.o
 
index ff93bc1b09c3aedd1a83a9e2e94952b56aef4fff..18a857ba7a25a920a1ad83f3acd477d587b28477 100644 (file)
@@ -112,11 +112,6 @@ static int __init acpi_sleep_setup(char *str)
 #ifdef CONFIG_HIBERNATION
                if (strncmp(str, "s4_nohwsig", 10) == 0)
                        acpi_no_s4_hw_signature();
-               if (strncmp(str, "s4_nonvs", 8) == 0) {
-                       pr_warning("ACPI: acpi_sleep=s4_nonvs is deprecated, "
-                                       "please use acpi_sleep=nonvs instead");
-                       acpi_nvs_nosave();
-               }
 #endif
                if (strncmp(str, "nonvs", 5) == 0)
                        acpi_nvs_nosave();
index 4a234677e21353017c5316b1056572f9acb48176..a81f2d52f869d842d9301d5f9aea5c23a74369a2 100644 (file)
@@ -67,17 +67,30 @@ __setup("noreplace-paravirt", setup_noreplace_paravirt);
 #define DPRINTK(fmt, args...) if (debug_alternative) \
        printk(KERN_DEBUG fmt, args)
 
+/*
+ * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes
+ * that correspond to that nop. Getting from one nop to the next, we
+ * add to the array the offset that is equal to the sum of all sizes of
+ * nops preceding the one we are after.
+ *
+ * Note: The GENERIC_NOP5_ATOMIC is at the end, as it breaks the
+ * nice symmetry of sizes of the previous nops.
+ */
 #if defined(GENERIC_NOP1) && !defined(CONFIG_X86_64)
-/* Use inline assembly to define this because the nops are defined
-   as inline assembly strings in the include files and we cannot
-   get them easily into strings. */
-asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nintelnops: "
-       GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
-       GENERIC_NOP7 GENERIC_NOP8
-    "\t.previous");
-extern const unsigned char intelnops[];
-static const unsigned char *const __initconst_or_module
-intel_nops[ASM_NOP_MAX+1] = {
+static const unsigned char intelnops[] =
+{
+       GENERIC_NOP1,
+       GENERIC_NOP2,
+       GENERIC_NOP3,
+       GENERIC_NOP4,
+       GENERIC_NOP5,
+       GENERIC_NOP6,
+       GENERIC_NOP7,
+       GENERIC_NOP8,
+       GENERIC_NOP5_ATOMIC
+};
+static const unsigned char * const intel_nops[ASM_NOP_MAX+2] =
+{
        NULL,
        intelnops,
        intelnops + 1,
@@ -87,17 +100,25 @@ intel_nops[ASM_NOP_MAX+1] = {
        intelnops + 1 + 2 + 3 + 4 + 5,
        intelnops + 1 + 2 + 3 + 4 + 5 + 6,
        intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
 };
 #endif
 
 #ifdef K8_NOP1
-asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk8nops: "
-       K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
-       K8_NOP7 K8_NOP8
-    "\t.previous");
-extern const unsigned char k8nops[];
-static const unsigned char *const __initconst_or_module
-k8_nops[ASM_NOP_MAX+1] = {
+static const unsigned char k8nops[] =
+{
+       K8_NOP1,
+       K8_NOP2,
+       K8_NOP3,
+       K8_NOP4,
+       K8_NOP5,
+       K8_NOP6,
+       K8_NOP7,
+       K8_NOP8,
+       K8_NOP5_ATOMIC
+};
+static const unsigned char * const k8_nops[ASM_NOP_MAX+2] =
+{
        NULL,
        k8nops,
        k8nops + 1,
@@ -107,17 +128,25 @@ k8_nops[ASM_NOP_MAX+1] = {
        k8nops + 1 + 2 + 3 + 4 + 5,
        k8nops + 1 + 2 + 3 + 4 + 5 + 6,
        k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
 };
 #endif
 
 #if defined(K7_NOP1) && !defined(CONFIG_X86_64)
-asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk7nops: "
-       K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
-       K7_NOP7 K7_NOP8
-    "\t.previous");
-extern const unsigned char k7nops[];
-static const unsigned char *const __initconst_or_module
-k7_nops[ASM_NOP_MAX+1] = {
+static const unsigned char k7nops[] =
+{
+       K7_NOP1,
+       K7_NOP2,
+       K7_NOP3,
+       K7_NOP4,
+       K7_NOP5,
+       K7_NOP6,
+       K7_NOP7,
+       K7_NOP8,
+       K7_NOP5_ATOMIC
+};
+static const unsigned char * const k7_nops[ASM_NOP_MAX+2] =
+{
        NULL,
        k7nops,
        k7nops + 1,
@@ -127,17 +156,25 @@ k7_nops[ASM_NOP_MAX+1] = {
        k7nops + 1 + 2 + 3 + 4 + 5,
        k7nops + 1 + 2 + 3 + 4 + 5 + 6,
        k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
 };
 #endif
 
 #ifdef P6_NOP1
-asm("\t" __stringify(__INITRODATA_OR_MODULE) "\np6nops: "
-       P6_NOP1 P6_NOP2 P6_NOP3 P6_NOP4 P6_NOP5 P6_NOP6
-       P6_NOP7 P6_NOP8
-    "\t.previous");
-extern const unsigned char p6nops[];
-static const unsigned char *const __initconst_or_module
-p6_nops[ASM_NOP_MAX+1] = {
+static const unsigned char  __initconst_or_module p6nops[] =
+{
+       P6_NOP1,
+       P6_NOP2,
+       P6_NOP3,
+       P6_NOP4,
+       P6_NOP5,
+       P6_NOP6,
+       P6_NOP7,
+       P6_NOP8,
+       P6_NOP5_ATOMIC
+};
+static const unsigned char * const p6_nops[ASM_NOP_MAX+2] =
+{
        NULL,
        p6nops,
        p6nops + 1,
@@ -147,47 +184,65 @@ p6_nops[ASM_NOP_MAX+1] = {
        p6nops + 1 + 2 + 3 + 4 + 5,
        p6nops + 1 + 2 + 3 + 4 + 5 + 6,
        p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
 };
 #endif
 
+/* Initialize these to a safe default */
 #ifdef CONFIG_X86_64
+const unsigned char * const *ideal_nops = p6_nops;
+#else
+const unsigned char * const *ideal_nops = intel_nops;
+#endif
 
-extern char __vsyscall_0;
-static const unsigned char *const *__init_or_module find_nop_table(void)
+void __init arch_init_ideal_nops(void)
 {
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-           boot_cpu_has(X86_FEATURE_NOPL))
-               return p6_nops;
-       else
-               return k8_nops;
-}
-
-#else /* CONFIG_X86_64 */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_INTEL:
+               /*
+                * Due to a decoder implementation quirk, some
+                * specific Intel CPUs actually perform better with
+                * the "k8_nops" than with the SDM-recommended NOPs.
+                */
+               if (boot_cpu_data.x86 == 6 &&
+                   boot_cpu_data.x86_model >= 0x0f &&
+                   boot_cpu_data.x86_model != 0x1c &&
+                   boot_cpu_data.x86_model != 0x26 &&
+                   boot_cpu_data.x86_model != 0x27 &&
+                   boot_cpu_data.x86_model < 0x30) {
+                       ideal_nops = k8_nops;
+               } else if (boot_cpu_has(X86_FEATURE_NOPL)) {
+                          ideal_nops = p6_nops;
+               } else {
+#ifdef CONFIG_X86_64
+                       ideal_nops = k8_nops;
+#else
+                       ideal_nops = intel_nops;
+#endif
+               }
 
-static const unsigned char *const *__init_or_module find_nop_table(void)
-{
-       if (boot_cpu_has(X86_FEATURE_K8))
-               return k8_nops;
-       else if (boot_cpu_has(X86_FEATURE_K7))
-               return k7_nops;
-       else if (boot_cpu_has(X86_FEATURE_NOPL))
-               return p6_nops;
-       else
-               return intel_nops;
+       default:
+#ifdef CONFIG_X86_64
+               ideal_nops = k8_nops;
+#else
+               if (boot_cpu_has(X86_FEATURE_K8))
+                       ideal_nops = k8_nops;
+               else if (boot_cpu_has(X86_FEATURE_K7))
+                       ideal_nops = k7_nops;
+               else
+                       ideal_nops = intel_nops;
+#endif
+       }
 }
 
-#endif /* CONFIG_X86_64 */
-
 /* Use this to add nops to a buffer, then text_poke the whole buffer. */
 static void __init_or_module add_nops(void *insns, unsigned int len)
 {
-       const unsigned char *const *noptable = find_nop_table();
-
        while (len > 0) {
                unsigned int noplen = len;
                if (noplen > ASM_NOP_MAX)
                        noplen = ASM_NOP_MAX;
-               memcpy(insns, noptable[noplen], noplen);
+               memcpy(insns, ideal_nops[noplen], noplen);
                insns += noplen;
                len -= noplen;
        }
@@ -195,6 +250,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern s32 __smp_locks[], __smp_locks_end[];
+extern char __vsyscall_0;
 void *text_poke_early(void *addr, const void *opcode, size_t len);
 
 /* Replace instructions with better alternatives for this CPU type.
@@ -210,6 +266,15 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
        u8 insnbuf[MAX_PATCH_LEN];
 
        DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
+       /*
+        * The scan order should be from start to end. A later scanned
+        * alternative code can overwrite a previous scanned alternative code.
+        * Some kernel functions (e.g. memcpy, memset, etc) use this order to
+        * patch code.
+        *
+        * So be careful if you want to change the scan order to any other
+        * order.
+        */
        for (a = start; a < end; a++) {
                u8 *instr = a->instr;
                BUG_ON(a->replacementlen > a->instrlen);
@@ -678,29 +743,3 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)
        wrote_text = 0;
        __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
 }
-
-#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
-
-#ifdef CONFIG_X86_64
-unsigned char ideal_nop5[5] = { 0x66, 0x66, 0x66, 0x66, 0x90 };
-#else
-unsigned char ideal_nop5[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
-#endif
-
-void __init arch_init_ideal_nop5(void)
-{
-       /*
-        * There is no good nop for all x86 archs.  This selection
-        * algorithm should be unified with the one in find_nop_table(),
-        * but this should be good enough for now.
-        *
-        * For cases other than the ones below, use the safe (as in
-        * always functional) defaults above.
-        */
-#ifdef CONFIG_X86_64
-       /* Don't use these on 32 bits due to broken virtualizers */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-               memcpy(ideal_nop5, p6_nops[5], 5);
-#endif
-}
-#endif
similarity index 98%
rename from arch/x86/kernel/pci-gart_64.c
rename to arch/x86/kernel/amd_gart_64.c
index 82ada01625b98c111a41fbecf72fdd026c08e5f1..b117efd24f71f589286aac56e0b50fb235dac0cc 100644 (file)
@@ -81,6 +81,9 @@ static u32 gart_unmapped_entry;
 #define AGPEXTERN
 #endif
 
+/* GART can only remap to physical addresses < 1TB */
+#define GART_MAX_PHYS_ADDR     (1ULL << 40)
+
 /* backdoor interface to AGP driver */
 AGPEXTERN int agp_memory_reserved;
 AGPEXTERN __u32 *agp_gatt_table;
@@ -212,9 +215,13 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
                                size_t size, int dir, unsigned long align_mask)
 {
        unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
-       unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
+       unsigned long iommu_page;
        int i;
 
+       if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR))
+               return bad_dma_addr;
+
+       iommu_page = alloc_iommu(dev, npages, align_mask);
        if (iommu_page == -1) {
                if (!nonforced_iommu(dev, phys_mem, size))
                        return phys_mem;
index 57ca777872206a7ab9df16158f769ee174ed5721..873e7e1ead7b6f233bd79a56ad646f217f233053 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/pci-ats.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
@@ -25,6 +26,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/iommu-helper.h>
 #include <linux/iommu.h>
+#include <linux/delay.h>
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
@@ -34,7 +36,7 @@
 
 #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
 
-#define EXIT_LOOP_COUNT 10000000
+#define LOOP_TIMEOUT   100000
 
 static DEFINE_RWLOCK(amd_iommu_devtable_lock);
 
@@ -57,7 +59,6 @@ struct iommu_cmd {
        u32 data[4];
 };
 
-static void reset_iommu_command_buffer(struct amd_iommu *iommu);
 static void update_domain(struct protection_domain *domain);
 
 /****************************************************************************
@@ -322,8 +323,6 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
                break;
        case EVENT_TYPE_ILL_CMD:
                printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
-               iommu->reset_in_progress = true;
-               reset_iommu_command_buffer(iommu);
                dump_command(address);
                break;
        case EVENT_TYPE_CMD_HARD_ERR:
@@ -367,7 +366,7 @@ static void iommu_poll_events(struct amd_iommu *iommu)
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-irqreturn_t amd_iommu_int_handler(int irq, void *data)
+irqreturn_t amd_iommu_int_thread(int irq, void *data)
 {
        struct amd_iommu *iommu;
 
@@ -377,192 +376,300 @@ irqreturn_t amd_iommu_int_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+irqreturn_t amd_iommu_int_handler(int irq, void *data)
+{
+       return IRQ_WAKE_THREAD;
+}
+
 /****************************************************************************
  *
  * IOMMU command queuing functions
  *
  ****************************************************************************/
 
-/*
- * Writes the command to the IOMMUs command buffer and informs the
- * hardware about the new command. Must be called with iommu->lock held.
- */
-static int __iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+static int wait_on_sem(volatile u64 *sem)
+{
+       int i = 0;
+
+       while (*sem == 0 && i < LOOP_TIMEOUT) {
+               udelay(1);
+               i += 1;
+       }
+
+       if (i == LOOP_TIMEOUT) {
+               pr_alert("AMD-Vi: Completion-Wait loop timed out\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void copy_cmd_to_buffer(struct amd_iommu *iommu,
+                              struct iommu_cmd *cmd,
+                              u32 tail)
 {
-       u32 tail, head;
        u8 *target;
 
-       WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
-       tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
        target = iommu->cmd_buf + tail;
-       memcpy_toio(target, cmd, sizeof(*cmd));
-       tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
-       head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
-       if (tail == head)
-               return -ENOMEM;
+       tail   = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
+
+       /* Copy command to buffer */
+       memcpy(target, cmd, sizeof(*cmd));
+
+       /* Tell the IOMMU about it */
        writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+}
 
-       return 0;
+static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
+{
+       WARN_ON(address & 0x7ULL);
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK;
+       cmd->data[1] = upper_32_bits(__pa(address));
+       cmd->data[2] = 1;
+       CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
+}
+
+static void build_inv_dte(struct iommu_cmd *cmd, u16 devid)
+{
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->data[0] = devid;
+       CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY);
+}
+
+static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
+                                 size_t size, u16 domid, int pde)
+{
+       u64 pages;
+       int s;
+
+       pages = iommu_num_pages(address, size, PAGE_SIZE);
+       s     = 0;
+
+       if (pages > 1) {
+               /*
+                * If we have to flush more than one page, flush all
+                * TLB entries for this domain
+                */
+               address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+               s = 1;
+       }
+
+       address &= PAGE_MASK;
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->data[1] |= domid;
+       cmd->data[2]  = lower_32_bits(address);
+       cmd->data[3]  = upper_32_bits(address);
+       CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
+       if (s) /* size bit - we flush more than one 4kb page */
+               cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+       if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
+               cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+}
+
+static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
+                                 u64 address, size_t size)
+{
+       u64 pages;
+       int s;
+
+       pages = iommu_num_pages(address, size, PAGE_SIZE);
+       s     = 0;
+
+       if (pages > 1) {
+               /*
+                * If we have to flush more than one page, flush all
+                * TLB entries for this domain
+                */
+               address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+               s = 1;
+       }
+
+       address &= PAGE_MASK;
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->data[0]  = devid;
+       cmd->data[0] |= (qdep & 0xff) << 24;
+       cmd->data[1]  = devid;
+       cmd->data[2]  = lower_32_bits(address);
+       cmd->data[3]  = upper_32_bits(address);
+       CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
+       if (s)
+               cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+}
+
+static void build_inv_all(struct iommu_cmd *cmd)
+{
+       memset(cmd, 0, sizeof(*cmd));
+       CMD_SET_TYPE(cmd, CMD_INV_ALL);
 }
 
 /*
- * General queuing function for commands. Takes iommu->lock and calls
- * __iommu_queue_command().
+ * Writes the command to the IOMMUs command buffer and informs the
+ * hardware about the new command.
  */
 static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
 {
+       u32 left, tail, head, next_tail;
        unsigned long flags;
-       int ret;
 
+       WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
+
+again:
        spin_lock_irqsave(&iommu->lock, flags);
-       ret = __iommu_queue_command(iommu, cmd);
-       if (!ret)
-               iommu->need_sync = true;
-       spin_unlock_irqrestore(&iommu->lock, flags);
 
-       return ret;
-}
+       head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
+       tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+       next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
+       left      = (head - next_tail) % iommu->cmd_buf_size;
 
-/*
- * This function waits until an IOMMU has completed a completion
- * wait command
- */
-static void __iommu_wait_for_completion(struct amd_iommu *iommu)
-{
-       int ready = 0;
-       unsigned status = 0;
-       unsigned long i = 0;
+       if (left <= 2) {
+               struct iommu_cmd sync_cmd;
+               volatile u64 sem = 0;
+               int ret;
 
-       INC_STATS_COUNTER(compl_wait);
+               build_completion_wait(&sync_cmd, (u64)&sem);
+               copy_cmd_to_buffer(iommu, &sync_cmd, tail);
 
-       while (!ready && (i < EXIT_LOOP_COUNT)) {
-               ++i;
-               /* wait for the bit to become one */
-               status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
-               ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
+               spin_unlock_irqrestore(&iommu->lock, flags);
+
+               if ((ret = wait_on_sem(&sem)) != 0)
+                       return ret;
+
+               goto again;
        }
 
-       /* set bit back to zero */
-       status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
-       writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
+       copy_cmd_to_buffer(iommu, cmd, tail);
+
+       /* We need to sync now to make sure all commands are processed */
+       iommu->need_sync = true;
+
+       spin_unlock_irqrestore(&iommu->lock, flags);
 
-       if (unlikely(i == EXIT_LOOP_COUNT))
-               iommu->reset_in_progress = true;
+       return 0;
 }
 
 /*
  * This function queues a completion wait command into the command
  * buffer of an IOMMU
  */
-static int __iommu_completion_wait(struct amd_iommu *iommu)
+static int iommu_completion_wait(struct amd_iommu *iommu)
 {
        struct iommu_cmd cmd;
+       volatile u64 sem = 0;
+       int ret;
 
-        memset(&cmd, 0, sizeof(cmd));
-        cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
-        CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
+       if (!iommu->need_sync)
+               return 0;
 
-        return __iommu_queue_command(iommu, &cmd);
+       build_completion_wait(&cmd, (u64)&sem);
+
+       ret = iommu_queue_command(iommu, &cmd);
+       if (ret)
+               return ret;
+
+       return wait_on_sem(&sem);
 }
 
-/*
- * This function is called whenever we need to ensure that the IOMMU has
- * completed execution of all commands we sent. It sends a
- * COMPLETION_WAIT command and waits for it to finish. The IOMMU informs
- * us about that by writing a value to a physical address we pass with
- * the command.
- */
-static int iommu_completion_wait(struct amd_iommu *iommu)
+static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
 {
-       int ret = 0;
-       unsigned long flags;
+       struct iommu_cmd cmd;
 
-       spin_lock_irqsave(&iommu->lock, flags);
+       build_inv_dte(&cmd, devid);
 
-       if (!iommu->need_sync)
-               goto out;
+       return iommu_queue_command(iommu, &cmd);
+}
 
-       ret = __iommu_completion_wait(iommu);
+static void iommu_flush_dte_all(struct amd_iommu *iommu)
+{
+       u32 devid;
 
-       iommu->need_sync = false;
+       for (devid = 0; devid <= 0xffff; ++devid)
+               iommu_flush_dte(iommu, devid);
 
-       if (ret)
-               goto out;
-
-       __iommu_wait_for_completion(iommu);
+       iommu_completion_wait(iommu);
+}
 
-out:
-       spin_unlock_irqrestore(&iommu->lock, flags);
+/*
+ * This function uses heavy locking and may disable irqs for some time. But
+ * this is no issue because it is only called during resume.
+ */
+static void iommu_flush_tlb_all(struct amd_iommu *iommu)
+{
+       u32 dom_id;
 
-       if (iommu->reset_in_progress)
-               reset_iommu_command_buffer(iommu);
+       for (dom_id = 0; dom_id <= 0xffff; ++dom_id) {
+               struct iommu_cmd cmd;
+               build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+                                     dom_id, 1);
+               iommu_queue_command(iommu, &cmd);
+       }
 
-       return 0;
+       iommu_completion_wait(iommu);
 }
 
-static void iommu_flush_complete(struct protection_domain *domain)
+static void iommu_flush_all(struct amd_iommu *iommu)
 {
-       int i;
+       struct iommu_cmd cmd;
 
-       for (i = 0; i < amd_iommus_present; ++i) {
-               if (!domain->dev_iommu[i])
-                       continue;
+       build_inv_all(&cmd);
 
-               /*
-                * Devices of this domain are behind this IOMMU
-                * We need to wait for completion of all commands.
-                */
-               iommu_completion_wait(amd_iommus[i]);
+       iommu_queue_command(iommu, &cmd);
+       iommu_completion_wait(iommu);
+}
+
+void iommu_flush_all_caches(struct amd_iommu *iommu)
+{
+       if (iommu_feature(iommu, FEATURE_IA)) {
+               iommu_flush_all(iommu);
+       } else {
+               iommu_flush_dte_all(iommu);
+               iommu_flush_tlb_all(iommu);
        }
 }
 
 /*
- * Command send function for invalidating a device table entry
+ * Command send function for flushing on-device TLB
  */
-static int iommu_flush_device(struct device *dev)
+static int device_flush_iotlb(struct device *dev, u64 address, size_t size)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct amd_iommu *iommu;
        struct iommu_cmd cmd;
        u16 devid;
+       int qdep;
 
+       qdep  = pci_ats_queue_depth(pdev);
        devid = get_device_id(dev);
        iommu = amd_iommu_rlookup_table[devid];
 
-       /* Build command */
-       memset(&cmd, 0, sizeof(cmd));
-       CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);
-       cmd.data[0] = devid;
+       build_inv_iotlb_pages(&cmd, devid, qdep, address, size);
 
        return iommu_queue_command(iommu, &cmd);
 }
 
-static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
-                                         u16 domid, int pde, int s)
-{
-       memset(cmd, 0, sizeof(*cmd));
-       address &= PAGE_MASK;
-       CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
-       cmd->data[1] |= domid;
-       cmd->data[2] = lower_32_bits(address);
-       cmd->data[3] = upper_32_bits(address);
-       if (s) /* size bit - we flush more than one 4kb page */
-               cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-       if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
-               cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
-}
-
 /*
- * Generic command send function for invalidaing TLB entries
+ * Command send function for invalidating a device table entry
  */
-static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
-               u64 address, u16 domid, int pde, int s)
+static int device_flush_dte(struct device *dev)
 {
-       struct iommu_cmd cmd;
+       struct amd_iommu *iommu;
+       struct pci_dev *pdev;
+       u16 devid;
        int ret;
 
-       __iommu_build_inv_iommu_pages(&cmd, address, domid, pde, s);
+       pdev  = to_pci_dev(dev);
+       devid = get_device_id(dev);
+       iommu = amd_iommu_rlookup_table[devid];
 
-       ret = iommu_queue_command(iommu, &cmd);
+       ret = iommu_flush_dte(iommu, devid);
+       if (ret)
+               return ret;
+
+       if (pci_ats_enabled(pdev))
+               ret = device_flush_iotlb(dev, 0, ~0UL);
 
        return ret;
 }
@@ -572,23 +679,14 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
  * It invalidates a single PTE if the range to flush is within a single
  * page. Otherwise it flushes the whole TLB of the IOMMU.
  */
-static void __iommu_flush_pages(struct protection_domain *domain,
-                               u64 address, size_t size, int pde)
+static void __domain_flush_pages(struct protection_domain *domain,
+                                u64 address, size_t size, int pde)
 {
-       int s = 0, i;
-       unsigned long pages = iommu_num_pages(address, size, PAGE_SIZE);
-
-       address &= PAGE_MASK;
-
-       if (pages > 1) {
-               /*
-                * If we have to flush more than one page, flush all
-                * TLB entries for this domain
-                */
-               address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-               s = 1;
-       }
+       struct iommu_dev_data *dev_data;
+       struct iommu_cmd cmd;
+       int ret = 0, i;
 
+       build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
 
        for (i = 0; i < amd_iommus_present; ++i) {
                if (!domain->dev_iommu[i])
@@ -598,101 +696,70 @@ static void __iommu_flush_pages(struct protection_domain *domain,
                 * Devices of this domain are behind this IOMMU
                 * We need a TLB flush
                 */
-               iommu_queue_inv_iommu_pages(amd_iommus[i], address,
-                                           domain->id, pde, s);
+               ret |= iommu_queue_command(amd_iommus[i], &cmd);
+       }
+
+       list_for_each_entry(dev_data, &domain->dev_list, list) {
+               struct pci_dev *pdev = to_pci_dev(dev_data->dev);
+
+               if (!pci_ats_enabled(pdev))
+                       continue;
+
+               ret |= device_flush_iotlb(dev_data->dev, address, size);
        }
 
-       return;
+       WARN_ON(ret);
 }
 
-static void iommu_flush_pages(struct protection_domain *domain,
-                            u64 address, size_t size)
+static void domain_flush_pages(struct protection_domain *domain,
+                              u64 address, size_t size)
 {
-       __iommu_flush_pages(domain, address, size, 0);
+       __domain_flush_pages(domain, address, size, 0);
 }
 
 /* Flush the whole IO/TLB for a given protection domain */
-static void iommu_flush_tlb(struct protection_domain *domain)
+static void domain_flush_tlb(struct protection_domain *domain)
 {
-       __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
+       __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
 }
 
 /* Flush the whole IO/TLB for a given protection domain - including PDE */
-static void iommu_flush_tlb_pde(struct protection_domain *domain)
+static void domain_flush_tlb_pde(struct protection_domain *domain)
 {
-       __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
-}
-
-
-/*
- * This function flushes the DTEs for all devices in domain
- */
-static void iommu_flush_domain_devices(struct protection_domain *domain)
-{
-       struct iommu_dev_data *dev_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&domain->lock, flags);
-
-       list_for_each_entry(dev_data, &domain->dev_list, list)
-               iommu_flush_device(dev_data->dev);
-
-       spin_unlock_irqrestore(&domain->lock, flags);
+       __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
 }
 
-static void iommu_flush_all_domain_devices(void)
+static void domain_flush_complete(struct protection_domain *domain)
 {
-       struct protection_domain *domain;
-       unsigned long flags;
+       int i;
 
-       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+       for (i = 0; i < amd_iommus_present; ++i) {
+               if (!domain->dev_iommu[i])
+                       continue;
 
-       list_for_each_entry(domain, &amd_iommu_pd_list, list) {
-               iommu_flush_domain_devices(domain);
-               iommu_flush_complete(domain);
+               /*
+                * Devices of this domain are behind this IOMMU
+                * We need to wait for completion of all commands.
+                */
+               iommu_completion_wait(amd_iommus[i]);
        }
-
-       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
-void amd_iommu_flush_all_devices(void)
-{
-       iommu_flush_all_domain_devices();
-}
 
 /*
- * This function uses heavy locking and may disable irqs for some time. But
- * this is no issue because it is only called during resume.
+ * This function flushes the DTEs for all devices in domain
  */
-void amd_iommu_flush_all_domains(void)
+static void domain_flush_devices(struct protection_domain *domain)
 {
-       struct protection_domain *domain;
+       struct iommu_dev_data *dev_data;
        unsigned long flags;
 
-       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
-
-       list_for_each_entry(domain, &amd_iommu_pd_list, list) {
-               spin_lock(&domain->lock);
-               iommu_flush_tlb_pde(domain);
-               iommu_flush_complete(domain);
-               spin_unlock(&domain->lock);
-       }
-
-       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
-}
-
-static void reset_iommu_command_buffer(struct amd_iommu *iommu)
-{
-       pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
-
-       if (iommu->reset_in_progress)
-               panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n");
+       spin_lock_irqsave(&domain->lock, flags);
 
-       amd_iommu_reset_cmd_buffer(iommu);
-       amd_iommu_flush_all_devices();
-       amd_iommu_flush_all_domains();
+       list_for_each_entry(dev_data, &domain->dev_list, list)
+               device_flush_dte(dev_data->dev);
 
-       iommu->reset_in_progress = false;
+       spin_unlock_irqrestore(&domain->lock, flags);
 }
 
 /****************************************************************************
@@ -1410,17 +1477,22 @@ static bool dma_ops_domain(struct protection_domain *domain)
        return domain->flags & PD_DMA_OPS_MASK;
 }
 
-static void set_dte_entry(u16 devid, struct protection_domain *domain)
+static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 {
        u64 pte_root = virt_to_phys(domain->pt_root);
+       u32 flags = 0;
 
        pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
                    << DEV_ENTRY_MODE_SHIFT;
        pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
 
-       amd_iommu_dev_table[devid].data[2] = domain->id;
-       amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root);
-       amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root);
+       if (ats)
+               flags |= DTE_FLAG_IOTLB;
+
+       amd_iommu_dev_table[devid].data[3] |= flags;
+       amd_iommu_dev_table[devid].data[2]  = domain->id;
+       amd_iommu_dev_table[devid].data[1]  = upper_32_bits(pte_root);
+       amd_iommu_dev_table[devid].data[0]  = lower_32_bits(pte_root);
 }
 
 static void clear_dte_entry(u16 devid)
@@ -1437,34 +1509,42 @@ static void do_attach(struct device *dev, struct protection_domain *domain)
 {
        struct iommu_dev_data *dev_data;
        struct amd_iommu *iommu;
+       struct pci_dev *pdev;
+       bool ats = false;
        u16 devid;
 
        devid    = get_device_id(dev);
        iommu    = amd_iommu_rlookup_table[devid];
        dev_data = get_dev_data(dev);
+       pdev     = to_pci_dev(dev);
+
+       if (amd_iommu_iotlb_sup)
+               ats = pci_ats_enabled(pdev);
 
        /* Update data structures */
        dev_data->domain = domain;
        list_add(&dev_data->list, &domain->dev_list);
-       set_dte_entry(devid, domain);
+       set_dte_entry(devid, domain, ats);
 
        /* Do reference counting */
        domain->dev_iommu[iommu->index] += 1;
        domain->dev_cnt                 += 1;
 
        /* Flush the DTE entry */
-       iommu_flush_device(dev);
+       device_flush_dte(dev);
 }
 
 static void do_detach(struct device *dev)
 {
        struct iommu_dev_data *dev_data;
        struct amd_iommu *iommu;
+       struct pci_dev *pdev;
        u16 devid;
 
        devid    = get_device_id(dev);
        iommu    = amd_iommu_rlookup_table[devid];
        dev_data = get_dev_data(dev);
+       pdev     = to_pci_dev(dev);
 
        /* decrease reference counters */
        dev_data->domain->dev_iommu[iommu->index] -= 1;
@@ -1476,7 +1556,7 @@ static void do_detach(struct device *dev)
        clear_dte_entry(devid);
 
        /* Flush the DTE entry */
-       iommu_flush_device(dev);
+       device_flush_dte(dev);
 }
 
 /*
@@ -1539,9 +1619,13 @@ out_unlock:
 static int attach_device(struct device *dev,
                         struct protection_domain *domain)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        unsigned long flags;
        int ret;
 
+       if (amd_iommu_iotlb_sup)
+               pci_enable_ats(pdev, PAGE_SHIFT);
+
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
        ret = __attach_device(dev, domain);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
@@ -1551,7 +1635,7 @@ static int attach_device(struct device *dev,
         * left the caches in the IOMMU dirty. So we have to flush
         * here to evict all dirty stuff.
         */
-       iommu_flush_tlb_pde(domain);
+       domain_flush_tlb_pde(domain);
 
        return ret;
 }
@@ -1598,12 +1682,16 @@ static void __detach_device(struct device *dev)
  */
 static void detach_device(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        unsigned long flags;
 
        /* lock device table */
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
        __detach_device(dev);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+       if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev))
+               pci_disable_ats(pdev);
 }
 
 /*
@@ -1692,7 +1780,7 @@ static int device_change_notifier(struct notifier_block *nb,
                goto out;
        }
 
-       iommu_flush_device(dev);
+       device_flush_dte(dev);
        iommu_completion_wait(iommu);
 
 out:
@@ -1753,8 +1841,9 @@ static void update_device_table(struct protection_domain *domain)
        struct iommu_dev_data *dev_data;
 
        list_for_each_entry(dev_data, &domain->dev_list, list) {
+               struct pci_dev *pdev = to_pci_dev(dev_data->dev);
                u16 devid = get_device_id(dev_data->dev);
-               set_dte_entry(devid, domain);
+               set_dte_entry(devid, domain, pci_ats_enabled(pdev));
        }
 }
 
@@ -1764,8 +1853,9 @@ static void update_domain(struct protection_domain *domain)
                return;
 
        update_device_table(domain);
-       iommu_flush_domain_devices(domain);
-       iommu_flush_tlb_pde(domain);
+
+       domain_flush_devices(domain);
+       domain_flush_tlb_pde(domain);
 
        domain->updated = false;
 }
@@ -1924,10 +2014,10 @@ retry:
        ADD_STATS_COUNTER(alloced_io_mem, size);
 
        if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
-               iommu_flush_tlb(&dma_dom->domain);
+               domain_flush_tlb(&dma_dom->domain);
                dma_dom->need_flush = false;
        } else if (unlikely(amd_iommu_np_cache))
-               iommu_flush_pages(&dma_dom->domain, address, size);
+               domain_flush_pages(&dma_dom->domain, address, size);
 
 out:
        return address;
@@ -1976,7 +2066,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-               iommu_flush_pages(&dma_dom->domain, flush_addr, size);
+               domain_flush_pages(&dma_dom->domain, flush_addr, size);
                dma_dom->need_flush = false;
        }
 }
@@ -2012,7 +2102,7 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
        if (addr == DMA_ERROR_CODE)
                goto out;
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
 out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@ -2039,7 +2129,7 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        __unmap_single(domain->priv, dma_addr, size, dir);
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -2104,7 +2194,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
                        goto unmap;
        }
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
 out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@ -2150,7 +2240,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
                s->dma_address = s->dma_length = 0;
        }
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -2200,7 +2290,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
                goto out_free;
        }
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -2232,7 +2322,7 @@ static void free_coherent(struct device *dev, size_t size,
 
        __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
 
-       iommu_flush_complete(domain);
+       domain_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -2476,7 +2566,7 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
        if (!iommu)
                return;
 
-       iommu_flush_device(dev);
+       device_flush_dte(dev);
        iommu_completion_wait(iommu);
 }
 
@@ -2542,7 +2632,7 @@ static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
        unmap_size = iommu_unmap_page(domain, iova, page_size);
        mutex_unlock(&domain->api_lock);
 
-       iommu_flush_tlb_pde(domain);
+       domain_flush_tlb_pde(domain);
 
        return get_order(unmap_size);
 }
index 246d727b65b7987babfaf64dc71dd5f78271a64b..9179c21120a88ea5e764297fc5c91c6a488fb51c 100644 (file)
@@ -137,6 +137,7 @@ int amd_iommus_present;
 
 /* IOMMUs have a non-present cache? */
 bool amd_iommu_np_cache __read_mostly;
+bool amd_iommu_iotlb_sup __read_mostly = true;
 
 /*
  * The ACPI table parsing functions set this variable on an error
@@ -180,6 +181,12 @@ static u32 dev_table_size; /* size of the device table */
 static u32 alias_table_size;   /* size of the alias table */
 static u32 rlookup_table_size; /* size if the rlookup table */
 
+/*
+ * This function flushes all internal caches of
+ * the IOMMU used by this driver.
+ */
+extern void iommu_flush_all_caches(struct amd_iommu *iommu);
+
 static inline void update_last_devid(u16 devid)
 {
        if (devid > amd_iommu_last_bdf)
@@ -293,9 +300,23 @@ static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
 /* Function to enable the hardware */
 static void iommu_enable(struct amd_iommu *iommu)
 {
-       printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n",
+       static const char * const feat_str[] = {
+               "PreF", "PPR", "X2APIC", "NX", "GT", "[5]",
+               "IA", "GA", "HE", "PC", NULL
+       };
+       int i;
+
+       printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx",
               dev_name(&iommu->dev->dev), iommu->cap_ptr);
 
+       if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
+               printk(KERN_CONT " extended features: ");
+               for (i = 0; feat_str[i]; ++i)
+                       if (iommu_feature(iommu, (1ULL << i)))
+                               printk(KERN_CONT " %s", feat_str[i]);
+       }
+       printk(KERN_CONT "\n");
+
        iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
 }
 
@@ -651,7 +672,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
 static void __init init_iommu_from_pci(struct amd_iommu *iommu)
 {
        int cap_ptr = iommu->cap_ptr;
-       u32 range, misc;
+       u32 range, misc, low, high;
        int i, j;
 
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
@@ -667,6 +688,15 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
                                        MMIO_GET_LD(range));
        iommu->evt_msi_num = MMIO_MSI_NUM(misc);
 
+       if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
+               amd_iommu_iotlb_sup = false;
+
+       /* read extended feature bits */
+       low  = readl(iommu->mmio_base + MMIO_EXT_FEATURES);
+       high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4);
+
+       iommu->features = ((u64)high << 32) | low;
+
        if (!is_rd890_iommu(iommu->dev))
                return;
 
@@ -1004,10 +1034,11 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
        if (pci_enable_msi(iommu->dev))
                return 1;
 
-       r = request_irq(iommu->dev->irq, amd_iommu_int_handler,
-                       IRQF_SAMPLE_RANDOM,
-                       "AMD-Vi",
-                       NULL);
+       r = request_threaded_irq(iommu->dev->irq,
+                                amd_iommu_int_handler,
+                                amd_iommu_int_thread,
+                                0, "AMD-Vi",
+                                iommu->dev);
 
        if (r) {
                pci_disable_msi(iommu->dev);
@@ -1244,6 +1275,7 @@ static void enable_iommus(void)
                iommu_set_exclusion_range(iommu);
                iommu_init_msi(iommu);
                iommu_enable(iommu);
+               iommu_flush_all_caches(iommu);
        }
 }
 
@@ -1274,8 +1306,8 @@ static void amd_iommu_resume(void)
         * we have to flush after the IOMMUs are enabled because a
         * disabled IOMMU will never execute the commands we send
         */
-       amd_iommu_flush_all_devices();
-       amd_iommu_flush_all_domains();
+       for_each_iommu(iommu)
+               iommu_flush_all_caches(iommu);
 }
 
 static int amd_iommu_suspend(void)
index cd1ffed4ee2226bd2ec6381c7c5de67bc7c13348..289e92862fd97aac3534eca0048cd646abb60860 100644 (file)
@@ -177,7 +177,6 @@ static struct clocksource clocksource_apbt = {
        .rating         = APBT_CLOCKSOURCE_RATING,
        .read           = apbt_read_clocksource,
        .mask           = APBT_MASK,
-       .shift          = APBT_SHIFT,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
        .resume         = apbt_restart_clocksource,
 };
@@ -543,14 +542,7 @@ static int apbt_clocksource_register(void)
        if (t1 == apbt_read_clocksource(&clocksource_apbt))
                panic("APBT counter not counting. APBT disabled\n");
 
-       /*
-        * initialize and register APBT clocksource
-        * convert that to ns/clock cycle
-        * mult = (ns/c) * 2^APBT_SHIFT
-        */
-       clocksource_apbt.mult = div_sc(MSEC_PER_SEC,
-                                      (unsigned long) apbt_freq, APBT_SHIFT);
-       clocksource_register(&clocksource_apbt);
+       clocksource_register_khz(&clocksource_apbt, (u32)apbt_freq*1000);
 
        return 0;
 }
index 86d1ad4962a73a352ec22625658bec7deca21d7c..3d2661ca6542f3527fc24b3841e04de8d8437522 100644 (file)
 #include <asm/amd_nb.h>
 #include <asm/x86_init.h>
 
+/*
+ * Using 512M as goal, in case kexec will load kernel_big
+ * that will do the on-position decompress, and could overlap with
+ * with the gart aperture that is used.
+ * Sequence:
+ * kernel_small
+ * ==> kexec (with kdump trigger path or gart still enabled)
+ * ==> kernel_small (gart area become e820_reserved)
+ * ==> kexec (with kdump trigger path or gart still enabled)
+ * ==> kerne_big (uncompressed size will be big than 64M or 128M)
+ * So don't use 512M below as gart iommu, leave the space for kernel
+ * code for safe.
+ */
+#define GART_MIN_ADDR  (512ULL << 20)
+#define GART_MAX_ADDR  (1ULL   << 32)
+
 int gart_iommu_aperture;
 int gart_iommu_aperture_disabled __initdata;
 int gart_iommu_aperture_allowed __initdata;
@@ -70,21 +86,9 @@ static u32 __init allocate_aperture(void)
         * memory. Unfortunately we cannot move it up because that would
         * make the IOMMU useless.
         */
-       /*
-        * using 512M as goal, in case kexec will load kernel_big
-        * that will do the on position decompress, and  could overlap with
-        * that position with gart that is used.
-        * sequende:
-        * kernel_small
-        * ==> kexec (with kdump trigger path or previous doesn't shutdown gart)
-        * ==> kernel_small(gart area become e820_reserved)
-        * ==> kexec (with kdump trigger path or previous doesn't shutdown gart)
-        * ==> kerne_big (uncompressed size will be big than 64M or 128M)
-        * so don't use 512M below as gart iommu, leave the space for kernel
-        * code for safe
-        */
-       addr = memblock_find_in_range(0, 1ULL<<32, aper_size, 512ULL<<20);
-       if (addr == MEMBLOCK_ERROR || addr + aper_size > 0xffffffff) {
+       addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR,
+                                     aper_size, aper_size);
+       if (addr == MEMBLOCK_ERROR || addr + aper_size > GART_MAX_ADDR) {
                printk(KERN_ERR
                        "Cannot allocate aperture memory hole (%lx,%uK)\n",
                                addr, aper_size>>10);
@@ -499,7 +503,7 @@ out:
                 * Don't enable translation yet but enable GART IO and CPU
                 * accesses and set DISTLBWALKPRB since GART table memory is UC.
                 */
-               u32 ctl = DISTLBWALKPRB | aper_order << 1;
+               u32 ctl = aper_order << 1;
 
                bus = amd_nb_bus_dev_ranges[i].bus;
                dev_base = amd_nb_bus_dev_ranges[i].dev_base;
index fabf01eff771856d0ee2bd1026b3475c88c9cd40..f92a8e5d1e21fd132479068028241405818aa04a 100644 (file)
@@ -505,7 +505,7 @@ static void __cpuinit setup_APIC_timer(void)
 {
        struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
-       if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_ARAT)) {
+       if (this_cpu_has(X86_FEATURE_ARAT)) {
                lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
                /* Make LAPIC timer preferrable over percpu HPET */
                lapic_clockevent.rating = 150;
@@ -1237,6 +1237,17 @@ void __cpuinit setup_local_APIC(void)
        /* always use the value from LDR */
        early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
                logical_smp_processor_id();
+
+       /*
+        * Some NUMA implementations (NUMAQ) don't initialize apicid to
+        * node mapping during NUMA init.  Now that logical apicid is
+        * guaranteed to be known, give it another chance.  This is already
+        * a bit too late - percpu allocation has already happened without
+        * proper NUMA affinity.
+        */
+       if (apic->x86_32_numa_cpu_node)
+               set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu),
+                                  apic->x86_32_numa_cpu_node(cpu));
 #endif
 
        /*
@@ -1812,30 +1823,41 @@ void smp_spurious_interrupt(struct pt_regs *regs)
  */
 void smp_error_interrupt(struct pt_regs *regs)
 {
-       u32 v, v1;
+       u32 v0, v1;
+       u32 i = 0;
+       static const char * const error_interrupt_reason[] = {
+               "Send CS error",                /* APIC Error Bit 0 */
+               "Receive CS error",             /* APIC Error Bit 1 */
+               "Send accept error",            /* APIC Error Bit 2 */
+               "Receive accept error",         /* APIC Error Bit 3 */
+               "Redirectable IPI",             /* APIC Error Bit 4 */
+               "Send illegal vector",          /* APIC Error Bit 5 */
+               "Received illegal vector",      /* APIC Error Bit 6 */
+               "Illegal register address",     /* APIC Error Bit 7 */
+       };
 
        exit_idle();
        irq_enter();
        /* First tickle the hardware, only then report what went on. -- REW */
-       v = apic_read(APIC_ESR);
+       v0 = apic_read(APIC_ESR);
        apic_write(APIC_ESR, 0);
        v1 = apic_read(APIC_ESR);
        ack_APIC_irq();
        atomic_inc(&irq_err_count);
 
-       /*
-        * Here is what the APIC error bits mean:
-        * 0: Send CS error
-        * 1: Receive CS error
-        * 2: Send accept error
-        * 3: Receive accept error
-        * 4: Reserved
-        * 5: Send illegal vector
-        * 6: Received illegal vector
-        * 7: Illegal register address
-        */
-       pr_debug("APIC error on CPU%d: %02x(%02x)\n",
-               smp_processor_id(), v , v1);
+       apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)",
+                   smp_processor_id(), v0 , v1);
+
+       v1 = v1 & 0xff;
+       while (v1) {
+               if (v1 & 0x1)
+                       apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
+               i++;
+               v1 >>= 1;
+       };
+
+       apic_printk(APIC_DEBUG, KERN_CONT "\n");
+
        irq_exit();
 }
 
@@ -2003,21 +2025,6 @@ void default_init_apic_ldr(void)
        apic_write(APIC_LDR, val);
 }
 
-#ifdef CONFIG_X86_32
-int default_x86_32_numa_cpu_node(int cpu)
-{
-#ifdef CONFIG_NUMA
-       int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
-
-       if (apicid != BAD_APICID)
-               return __apicid_to_node[apicid];
-       return NUMA_NO_NODE;
-#else
-       return 0;
-#endif
-}
-#endif
-
 /*
  * Power management
  */
index f1baa2dc087ac1b6b880c60c896fb05fb099be69..775b82bc655cbe49ba16afdc6aa03cdd0395990c 100644 (file)
@@ -119,14 +119,6 @@ static void noop_apic_write(u32 reg, u32 v)
        WARN_ON_ONCE(cpu_has_apic && !disable_apic);
 }
 
-#ifdef CONFIG_X86_32
-static int noop_x86_32_numa_cpu_node(int cpu)
-{
-       /* we're always on node 0 */
-       return 0;
-}
-#endif
-
 struct apic apic_noop = {
        .name                           = "noop",
        .probe                          = noop_probe,
@@ -195,6 +187,5 @@ struct apic apic_noop = {
 
 #ifdef CONFIG_X86_32
        .x86_32_early_logical_apicid    = noop_x86_32_early_logical_apicid,
-       .x86_32_numa_cpu_node           = noop_x86_32_numa_cpu_node,
 #endif
 };
index 541a2e43165942490453aa315eb6bbf9f7accbae..d84ac5a584b511291e7677bca5f11caf457435b7 100644 (file)
@@ -253,5 +253,4 @@ struct apic apic_bigsmp = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 
        .x86_32_early_logical_apicid    = bigsmp_early_logical_apicid,
-       .x86_32_numa_cpu_node           = default_x86_32_numa_cpu_node,
 };
index 3e9de4854c5b5253bf041ef60dbc3d594b665b80..70533de5bd29741c41b03b1cc8c989740c4ff15c 100644 (file)
@@ -510,11 +510,6 @@ static void es7000_setup_apic_routing(void)
                nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
 }
 
-static int es7000_numa_cpu_node(int cpu)
-{
-       return 0;
-}
-
 static int es7000_cpu_present_to_apicid(int mps_cpu)
 {
        if (!mps_cpu)
@@ -688,7 +683,6 @@ struct apic __refdata apic_es7000_cluster = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 
        .x86_32_early_logical_apicid    = es7000_early_logical_apicid,
-       .x86_32_numa_cpu_node           = es7000_numa_cpu_node,
 };
 
 struct apic __refdata apic_es7000 = {
@@ -752,5 +746,4 @@ struct apic __refdata apic_es7000 = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 
        .x86_32_early_logical_apicid    = es7000_early_logical_apicid,
-       .x86_32_numa_cpu_node           = es7000_numa_cpu_node,
 };
index 68df09bba92ee902dabdd2e37acdd29d9ae67007..45fd33d1fd3a01951184feca64ed476178d34922 100644 (file)
@@ -128,8 +128,8 @@ static int __init parse_noapic(char *str)
 }
 early_param("noapic", parse_noapic);
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr);
+static int io_apic_setup_irq_pin(unsigned int irq, int node,
+                                struct io_apic_irq_attr *attr);
 
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
@@ -3570,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 }
 #endif /* CONFIG_HT_IRQ */
 
-int
+static int
 io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 {
        struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
@@ -3585,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
        return ret;
 }
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr)
+int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+                              struct io_apic_irq_attr *attr)
 {
        unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
        int ret;
index 6273eee5134b7d81c8dea080886d150a3adca14f..30f13319e24b82f81a85d9de989a24024083af8c 100644 (file)
@@ -48,8 +48,6 @@
 #include <asm/e820.h>
 #include <asm/ipi.h>
 
-#define        MB_TO_PAGES(addr)               ((addr) << (20 - PAGE_SHIFT))
-
 int found_numaq;
 
 /*
@@ -79,31 +77,20 @@ int                                 quad_local_to_mp_bus_id[NR_CPUS/4][4];
 static inline void numaq_register_node(int node, struct sys_cfg_data *scd)
 {
        struct eachquadmem *eq = scd->eq + node;
+       u64 start = (u64)(eq->hi_shrd_mem_start - eq->priv_mem_size) << 20;
+       u64 end = (u64)(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size) << 20;
+       int ret;
 
-       node_set_online(node);
-
-       /* Convert to pages */
-       node_start_pfn[node] =
-                MB_TO_PAGES(eq->hi_shrd_mem_start - eq->priv_mem_size);
-
-       node_end_pfn[node] =
-                MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
-
-       memblock_x86_register_active_regions(node, node_start_pfn[node],
-                                               node_end_pfn[node]);
-
-       memory_present(node, node_start_pfn[node], node_end_pfn[node]);
-
-       node_remap_size[node] = node_memmap_size_bytes(node,
-                                       node_start_pfn[node],
-                                       node_end_pfn[node]);
+       node_set(node, numa_nodes_parsed);
+       ret = numa_add_memblk(node, start, end);
+       BUG_ON(ret < 0);
 }
 
 /*
  * Function: smp_dump_qct()
  *
  * Description: gets memory layout from the quad config table.  This
- * function also updates node_online_map with the nodes (quads) present.
+ * function also updates numa_nodes_parsed with the nodes (quads) present.
  */
 static void __init smp_dump_qct(void)
 {
@@ -112,7 +99,6 @@ static void __init smp_dump_qct(void)
 
        scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR);
 
-       nodes_clear(node_online_map);
        for_each_node(node) {
                if (scd->quads_present31_0 & (1 << node))
                        numaq_register_node(node, scd);
@@ -282,14 +268,14 @@ static __init void early_check_numaq(void)
        }
 }
 
-int __init get_memcfg_numaq(void)
+int __init numaq_numa_init(void)
 {
        early_check_numaq();
        if (!found_numaq)
-               return 0;
+               return -ENOENT;
        smp_dump_qct();
 
-       return 1;
+       return 0;
 }
 
 #define NUMAQ_APIC_DFR_VALUE   (APIC_DFR_CLUSTER)
index fc84c7b61108086448295821abfc2daca5d0c391..6541e471fd9195535a6198efa87d738ee25afbba 100644 (file)
@@ -172,7 +172,6 @@ struct apic apic_default = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 
        .x86_32_early_logical_apicid    = default_x86_32_early_logical_apicid,
-       .x86_32_numa_cpu_node           = default_x86_32_numa_cpu_node,
 };
 
 extern struct apic apic_numaq;
index e4b8059b414a800627c95eb9269d9c7f4fbd1774..35bcd7d995a137ecd98cb30c510418b725bf001c 100644 (file)
@@ -551,5 +551,4 @@ struct apic apic_summit = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 
        .x86_32_early_logical_apicid    = summit_early_logical_apicid,
-       .x86_32_numa_cpu_node           = default_x86_32_numa_cpu_node,
 };
index 33b10a0fc095b9d458f851b20e4c5dda37cfc9ed..7acd2d2ac965f9932f39986ab1fe23361c6de90e 100644 (file)
 #include <asm/smp.h>
 #include <asm/x86_init.h>
 #include <asm/emergency-restart.h>
+#include <asm/nmi.h>
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR                            UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR                      (UVH_NMI_MMR + 8)
+#define UV_NMI_PENDING_MASK                    (1UL << 63)
+DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
 
 DEFINE_PER_CPU(int, x2apic_extra_bits);
 
@@ -642,18 +649,46 @@ void __cpuinit uv_cpu_init(void)
  */
 int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
 {
+       unsigned long real_uv_nmi;
+       int bid;
+
        if (reason != DIE_NMIUNKNOWN)
                return NOTIFY_OK;
 
        if (in_crash_kexec)
                /* do nothing if entering the crash kernel */
                return NOTIFY_OK;
+
        /*
-        * Use a lock so only one cpu prints at a time
-        * to prevent intermixed output.
+        * Each blade has an MMR that indicates when an NMI has been sent
+        * to cpus on the blade. If an NMI is detected, atomically
+        * clear the MMR and update a per-blade NMI count used to
+        * cause each cpu on the blade to notice a new NMI.
+        */
+       bid = uv_numa_blade_id();
+       real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+
+       if (unlikely(real_uv_nmi)) {
+               spin_lock(&uv_blade_info[bid].nmi_lock);
+               real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+               if (real_uv_nmi) {
+                       uv_blade_info[bid].nmi_count++;
+                       uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
+               }
+               spin_unlock(&uv_blade_info[bid].nmi_lock);
+       }
+
+       if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
+               return NOTIFY_DONE;
+
+       __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
+
+       /*
+        * Use a lock so only one cpu prints at a time.
+        * This prevents intermixed output.
         */
        spin_lock(&uv_nmi_lock);
-       pr_info("NMI stack dump cpu %u:\n", smp_processor_id());
+       pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
        dump_stack();
        spin_unlock(&uv_nmi_lock);
 
@@ -661,7 +696,8 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
 }
 
 static struct notifier_block uv_dump_stack_nmi_nb = {
-       .notifier_call  = uv_handle_nmi
+       .notifier_call  = uv_handle_nmi,
+       .priority = NMI_LOCAL_LOW_PRIOR - 1,
 };
 
 void uv_register_nmi_notifier(void)
@@ -720,8 +756,9 @@ void __init uv_system_init(void)
        printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
 
        bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
-       uv_blade_info = kmalloc(bytes, GFP_KERNEL);
+       uv_blade_info = kzalloc(bytes, GFP_KERNEL);
        BUG_ON(!uv_blade_info);
+
        for (blade = 0; blade < uv_num_possible_blades(); blade++)
                uv_blade_info[blade].memory_nid = -1;
 
@@ -747,6 +784,7 @@ void __init uv_system_init(void)
                        uv_blade_info[blade].pnode = pnode;
                        uv_blade_info[blade].nr_possible_cpus = 0;
                        uv_blade_info[blade].nr_online_cpus = 0;
+                       spin_lock_init(&uv_blade_info[blade].nmi_lock);
                        max_pnode = max(pnode, max_pnode);
                        blade++;
                }
index 0b4be431c620ab30ac0bd348888fdf3e9dd3a5b8..3bfa022359659d26a609cc4c951ea8e3865609b7 100644 (file)
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
 #include <linux/acpi.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -1237,7 +1238,7 @@ static int suspend(int vetoable)
        dpm_suspend_noirq(PMSG_SUSPEND);
 
        local_irq_disable();
-       sysdev_suspend(PMSG_SUSPEND);
+       syscore_suspend();
 
        local_irq_enable();
 
@@ -1255,7 +1256,7 @@ static int suspend(int vetoable)
                apm_error("suspend", err);
        err = (err == APM_SUCCESS) ? 0 : -EIO;
 
-       sysdev_resume();
+       syscore_resume();
        local_irq_enable();
 
        dpm_resume_noirq(PMSG_RESUME);
@@ -1279,7 +1280,7 @@ static void standby(void)
        dpm_suspend_noirq(PMSG_SUSPEND);
 
        local_irq_disable();
-       sysdev_suspend(PMSG_SUSPEND);
+       syscore_suspend();
        local_irq_enable();
 
        err = set_system_power_state(APM_STATE_STANDBY);
@@ -1287,7 +1288,7 @@ static void standby(void)
                apm_error("standby", err);
 
        local_irq_disable();
-       sysdev_resume();
+       syscore_resume();
        local_irq_enable();
 
        dpm_resume_noirq(PMSG_RESUME);
index 3f0ebe429a01c14e67d252e475f34252fcf0f105..6042981d0309c492bdfb5032312a8e4f7cb0a5d1 100644 (file)
@@ -30,7 +30,6 @@ obj-$(CONFIG_PERF_EVENTS)             += perf_event.o
 
 obj-$(CONFIG_X86_MCE)                  += mcheck/
 obj-$(CONFIG_MTRR)                     += mtrr/
-obj-$(CONFIG_CPU_FREQ)                 += cpufreq/
 
 obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o
 
index 3532d3bf81050ef145a861b09c294980bf1674c3..6f9d1f6063e9c62841d1a3148d015ed009ef02f3 100644 (file)
@@ -613,7 +613,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 #endif
 
        /* As a rule processors have APIC timer running in deep C states */
-       if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400))
+       if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400))
                set_cpu_cap(c, X86_FEATURE_ARAT);
 
        /*
index e2ced0074a45c1ffee1eeb1a7e8d56657824847f..cbc70a27430ce3dc7010fbf07909ed886674c5e0 100644 (file)
@@ -254,6 +254,25 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
 }
 #endif
 
+static int disable_smep __initdata;
+static __init int setup_disable_smep(char *arg)
+{
+       disable_smep = 1;
+       return 1;
+}
+__setup("nosmep", setup_disable_smep);
+
+static __init void setup_smep(struct cpuinfo_x86 *c)
+{
+       if (cpu_has(c, X86_FEATURE_SMEP)) {
+               if (unlikely(disable_smep)) {
+                       setup_clear_cpu_cap(X86_FEATURE_SMEP);
+                       clear_in_cr4(X86_CR4_SMEP);
+               } else
+                       set_in_cr4(X86_CR4_SMEP);
+       }
+}
+
 /*
  * Some CPU features depend on higher CPUID levels, which may not always
  * be available due to CPUID level capping or broken virtualization
@@ -565,8 +584,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
 
                cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
 
-               if (eax > 0)
-                       c->x86_capability[9] = ebx;
+               c->x86_capability[9] = ebx;
        }
 
        /* AMD-defined flags: level 0x80000001 */
@@ -668,6 +686,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
        c->cpu_index = 0;
 #endif
        filter_cpuid_features(c, false);
+
+       setup_smep(c);
 }
 
 void __init early_cpu_init(void)
@@ -753,6 +773,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
 #endif
        }
 
+       setup_smep(c);
+
        get_model_name(c); /* Default name */
 
        detect_nopl(c);
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile
deleted file mode 100644 (file)
index bd54bf6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# Link order matters. K8 is preferred to ACPI because of firmware bugs in early
-# K8 systems. ACPI is preferred to all other hardware-specific drivers.
-# speedstep-* is preferred over p4-clockmod.
-
-obj-$(CONFIG_X86_POWERNOW_K8)          += powernow-k8.o mperf.o
-obj-$(CONFIG_X86_ACPI_CPUFREQ)         += acpi-cpufreq.o mperf.o
-obj-$(CONFIG_X86_PCC_CPUFREQ)          += pcc-cpufreq.o
-obj-$(CONFIG_X86_POWERNOW_K6)          += powernow-k6.o
-obj-$(CONFIG_X86_POWERNOW_K7)          += powernow-k7.o
-obj-$(CONFIG_X86_LONGHAUL)             += longhaul.o
-obj-$(CONFIG_X86_E_POWERSAVER)         += e_powersaver.o
-obj-$(CONFIG_ELAN_CPUFREQ)             += elanfreq.o
-obj-$(CONFIG_SC520_CPUFREQ)            += sc520_freq.o
-obj-$(CONFIG_X86_LONGRUN)              += longrun.o  
-obj-$(CONFIG_X86_GX_SUSPMOD)           += gx-suspmod.o
-obj-$(CONFIG_X86_SPEEDSTEP_ICH)                += speedstep-ich.o
-obj-$(CONFIG_X86_SPEEDSTEP_LIB)                += speedstep-lib.o
-obj-$(CONFIG_X86_SPEEDSTEP_SMI)                += speedstep-smi.o
-obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)   += speedstep-centrino.o
-obj-$(CONFIG_X86_P4_CLOCKMOD)          += p4-clockmod.o
-obj-$(CONFIG_X86_CPUFREQ_NFORCE2)      += cpufreq-nforce2.o
index df86bc8c859d6ff8596759e7a54258fd9764d7d6..1edf5ba4fb2b76076f448db70d01587c71a96d3d 100644 (file)
 
 static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
 {
+       u64 misc_enable;
+
        /* Unmask CPUID levels if masked: */
        if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
-               u64 misc_enable;
-
                rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 
                if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
@@ -118,8 +118,6 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
         * (model 2) with the same problem.
         */
        if (c->x86 == 15) {
-               u64 misc_enable;
-
                rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 
                if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) {
@@ -130,6 +128,19 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
                }
        }
 #endif
+
+       /*
+        * If fast string is not enabled in IA32_MISC_ENABLE for any reason,
+        * clear the fast string and enhanced fast string CPU capabilities.
+        */
+       if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
+               rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+               if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
+                       printk(KERN_INFO "Disabled fast string operations\n");
+                       setup_clear_cpu_cap(X86_FEATURE_REP_GOOD);
+                       setup_clear_cpu_cap(X86_FEATURE_ERMS);
+               }
+       }
 }
 
 #ifdef CONFIG_X86_32
@@ -400,12 +411,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 
                switch (c->x86_model) {
                case 5:
-                       if (c->x86_mask == 0) {
-                               if (l2 == 0)
-                                       p = "Celeron (Covington)";
-                               else if (l2 == 256)
-                                       p = "Mobile Pentium II (Dixon)";
-                       }
+                       if (l2 == 0)
+                               p = "Celeron (Covington)";
+                       else if (l2 == 256)
+                               p = "Mobile Pentium II (Dixon)";
                        break;
 
                case 6:
index 1ce1af2899df24d2f7c5a23091e5173c56f88918..c105c533ed94575e54b047ab131ff4a9170282b8 100644 (file)
@@ -327,7 +327,6 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
        l3->subcaches[2] = sc2 = !(val & BIT(8))  + !(val & BIT(9));
        l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
-       l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
        l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
@@ -454,27 +453,16 @@ int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
 {
        int ret = 0;
 
-#define SUBCACHE_MASK  (3UL << 20)
-#define SUBCACHE_INDEX 0xfff
-
-       /*
-        * check whether this slot is already used or
-        * the index is already disabled
-        */
+       /*  check if @slot is already used or the index is already disabled */
        ret = amd_get_l3_disable_slot(l3, slot);
        if (ret >= 0)
                return -EINVAL;
 
-       /*
-        * check whether the other slot has disabled the
-        * same index already
-        */
-       if (index == amd_get_l3_disable_slot(l3, !slot))
+       if (index > l3->indices)
                return -EINVAL;
 
-       /* do not allow writes outside of allowed bits */
-       if ((index & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
-           ((index & SUBCACHE_INDEX) > l3->indices))
+       /* check whether the other slot has disabled the same index already */
+       if (index == amd_get_l3_disable_slot(l3, !slot))
                return -EINVAL;
 
        amd_l3_disable_index(l3, cpu, slot, index);
index 3385ea26f6841bea370faa9ea7baa08b3fda90f2..ff1ae9b6464d80d4663b8bc09124edbe6992ea7f 100644 (file)
@@ -105,20 +105,6 @@ static int                 cpu_missing;
 ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain);
 EXPORT_SYMBOL_GPL(x86_mce_decoder_chain);
 
-static int default_decode_mce(struct notifier_block *nb, unsigned long val,
-                              void *data)
-{
-       pr_emerg(HW_ERR "No human readable MCE decoding support on this CPU type.\n");
-       pr_emerg(HW_ERR "Run the message through 'mcelog --ascii' to decode.\n");
-
-       return NOTIFY_STOP;
-}
-
-static struct notifier_block mce_dec_nb = {
-       .notifier_call = default_decode_mce,
-       .priority      = -1,
-};
-
 /* MCA banks polled by the period polling timer for corrected events */
 DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
        [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
@@ -212,6 +198,8 @@ void mce_log(struct mce *mce)
 
 static void print_mce(struct mce *m)
 {
+       int ret = 0;
+
        pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
               m->extcpu, m->mcgstatus, m->bank, m->status);
 
@@ -239,7 +227,11 @@ static void print_mce(struct mce *m)
         * Print out human-readable details about the MCE error,
         * (if the CPU has an implementation for that)
         */
-       atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
+       ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
+       if (ret == NOTIFY_STOP)
+               return;
+
+       pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n");
 }
 
 #define PANIC_TIMEOUT 5 /* 5 seconds */
@@ -590,7 +582,6 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
                        mce_log(&m);
                        atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
-                       add_taint(TAINT_MACHINE_CHECK);
                }
 
                /*
@@ -1722,8 +1713,6 @@ __setup("mce", mcheck_enable);
 
 int __init mcheck_init(void)
 {
-       atomic_notifier_chain_register(&x86_mce_decoder_chain, &mce_dec_nb);
-
        mcheck_intel_therm_init();
 
        return 0;
index 167f97b5596e2f6e6e01df1f0b1096cff3392b2f..bb0adad3514339d5a2f25d471af5f568f9b4d03e 100644 (file)
@@ -509,6 +509,7 @@ recurse:
 out_free:
        if (b) {
                kobject_put(&b->kobj);
+               list_del(&b->miscj);
                kfree(b);
        }
        return err;
index 6f8c5e9da97f0f3e4c0ac89557a3b2f1c3a5f01e..27c625178bf11dd8a8e7f3bab162ed611515059d 100644 (file)
@@ -187,8 +187,6 @@ static int therm_throt_process(bool new_event, int event, int level)
                                this_cpu,
                                level == CORE_LEVEL ? "Core" : "Package",
                                state->count);
-
-               add_taint(TAINT_MACHINE_CHECK);
                return 1;
        }
        if (old_event) {
@@ -355,7 +353,6 @@ static void notify_thresholds(__u64 msr_val)
 static void intel_thermal_interrupt(void)
 {
        __u64 msr_val;
-       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
 
        rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 
@@ -367,19 +364,19 @@ static void intel_thermal_interrupt(void)
                                CORE_LEVEL) != 0)
                mce_log_therm_throt_event(CORE_THROTTLED | msr_val);
 
-       if (cpu_has(c, X86_FEATURE_PLN))
+       if (this_cpu_has(X86_FEATURE_PLN))
                if (therm_throt_process(msr_val & THERM_STATUS_POWER_LIMIT,
                                        POWER_LIMIT_EVENT,
                                        CORE_LEVEL) != 0)
                        mce_log_therm_throt_event(CORE_POWER_LIMIT | msr_val);
 
-       if (cpu_has(c, X86_FEATURE_PTS)) {
+       if (this_cpu_has(X86_FEATURE_PTS)) {
                rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
                if (therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
                                        THERMAL_THROTTLING_EVENT,
                                        PACKAGE_LEVEL) != 0)
                        mce_log_therm_throt_event(PACKAGE_THROTTLED | msr_val);
-               if (cpu_has(c, X86_FEATURE_PLN))
+               if (this_cpu_has(X86_FEATURE_PLN))
                        if (therm_throt_process(msr_val &
                                        PACKAGE_THERM_STATUS_POWER_LIMIT,
                                        POWER_LIMIT_EVENT,
@@ -393,7 +390,6 @@ static void unexpected_thermal_interrupt(void)
 {
        printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n",
                        smp_processor_id());
-       add_taint(TAINT_MACHINE_CHECK);
 }
 
 static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
@@ -446,18 +442,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
         */
        rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 
+       h = lvtthmr_init;
        /*
         * The initial value of thermal LVT entries on all APs always reads
         * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
         * sequence to them and LVT registers are reset to 0s except for
         * the mask bits which are set to 1s when APs receive INIT IPI.
-        * Always restore the value that BIOS has programmed on AP based on
-        * BSP's info we saved since BIOS is always setting the same value
-        * for all threads/cores
+        * If BIOS takes over the thermal interrupt and sets its interrupt
+        * delivery mode to SMI (not fixed), it restores the value that the
+        * BIOS has programmed on AP based on BSP's info we saved since BIOS
+        * is always setting the same value for all threads/cores.
         */
-       apic_write(APIC_LVTTHMR, lvtthmr_init);
+       if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
+               apic_write(APIC_LVTTHMR, lvtthmr_init);
 
-       h = lvtthmr_init;
 
        if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
                printk(KERN_DEBUG
index eed3673a8656f5688d54f6b4d72fd9774c831fcb..3a0338b4b1790714293dbe213342fba56f13373c 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/nmi.h>
 #include <asm/compat.h>
 #include <asm/smp.h>
+#include <asm/alternative.h>
 
 #if 0
 #undef wrmsrl
@@ -363,12 +364,18 @@ again:
        return new_raw_count;
 }
 
-/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */
 static inline int x86_pmu_addr_offset(int index)
 {
-       if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
-               return index << 1;
-       return index;
+       int offset;
+
+       /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
+       alternative_io(ASM_NOP2,
+                      "shll $1, %%eax",
+                      X86_FEATURE_PERFCTR_CORE,
+                      "=a" (offset),
+                      "a"  (index));
+
+       return offset;
 }
 
 static inline unsigned int x86_pmu_config_addr(int index)
@@ -586,8 +593,12 @@ static int x86_setup_perfctr(struct perf_event *event)
                        return -EOPNOTSUPP;
        }
 
+       /*
+        * Do not allow config1 (extended registers) to propagate,
+        * there's no sane user-space generalization yet:
+        */
        if (attr->type == PERF_TYPE_RAW)
-               return x86_pmu_extra_regs(event->attr.config, event);
+               return 0;
 
        if (attr->type == PERF_TYPE_HW_CACHE)
                return set_ext_hw_attr(hwc, event);
@@ -609,8 +620,8 @@ static int x86_setup_perfctr(struct perf_event *event)
        /*
         * Branch tracing:
         */
-       if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
-           (hwc->sample_period == 1)) {
+       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+           !attr->freq && hwc->sample_period == 1) {
                /* BTS is not supported by this architecture. */
                if (!x86_pmu.bts_active)
                        return -EOPNOTSUPP;
@@ -1284,6 +1295,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
+       /*
+        * Some chipsets need to unmask the LVTPC in a particular spot
+        * inside the nmi handler.  As a result, the unmasking was pushed
+        * into all the nmi handlers.
+        *
+        * This generic handler doesn't seem to have any issues where the
+        * unmasking occurs so it was left at the top.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
                if (!test_bit(idx, cpuc->active_mask)) {
                        /*
@@ -1370,8 +1391,6 @@ perf_event_nmi_handler(struct notifier_block *self,
                return NOTIFY_DONE;
        }
 
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-
        handled = x86_pmu.handle_irq(args->regs);
        if (!handled)
                return NOTIFY_DONE;
@@ -1754,17 +1773,6 @@ static struct pmu pmu = {
  * callchain support
  */
 
-static void
-backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
-{
-       /* Ignore warnings */
-}
-
-static void backtrace_warning(void *data, char *msg)
-{
-       /* Ignore warnings */
-}
-
 static int backtrace_stack(void *data, char *name)
 {
        return 0;
@@ -1778,8 +1786,6 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops backtrace_ops = {
-       .warning                = backtrace_warning,
-       .warning_symbol         = backtrace_warning_symbol,
        .stack                  = backtrace_stack,
        .address                = backtrace_address,
        .walk_stack             = print_context_stack_bp,
index 461f62bbd774a0adec028334f8c723e5a33bea1d..fe29c1d2219ecfa80d325d856a5db56241213150 100644 (file)
@@ -8,7 +8,7 @@ static __initconst const u64 amd_hw_cache_event_ids
  [ C(L1D) ] = {
        [ C(OP_READ) ] = {
                [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-               [ C(RESULT_MISS)   ] = 0x0041, /* Data Cache Misses          */
+               [ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
        },
        [ C(OP_WRITE) ] = {
                [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
@@ -96,12 +96,14 @@ static __initconst const u64 amd_hw_cache_event_ids
  */
 static const u64 amd_perfmon_event_map[] =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0076,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0080,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x0081,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c2,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c3,
+  [PERF_COUNT_HW_CPU_CYCLES]                   = 0x0076,
+  [PERF_COUNT_HW_INSTRUCTIONS]                 = 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]             = 0x0080,
+  [PERF_COUNT_HW_CACHE_MISSES]                 = 0x0081,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]          = 0x00c2,
+  [PERF_COUNT_HW_BRANCH_MISSES]                        = 0x00c3,
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]      = 0x00d0, /* "Decoder empty" event */
+  [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]       = 0x00d1, /* "Dispatch stalls" event */
 };
 
 static u64 amd_pmu_event_map(int hw_event)
@@ -427,7 +429,9 @@ static __initconst const struct x86_pmu amd_pmu = {
  *
  * Exceptions:
  *
+ * 0x000       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
  * 0x003       FP      PERF_CTL[3]
+ * 0x004       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
  * 0x00B       FP      PERF_CTL[3]
  * 0x00D       FP      PERF_CTL[3]
  * 0x023       DE      PERF_CTL[2:0]
@@ -448,6 +452,8 @@ static __initconst const struct x86_pmu amd_pmu = {
  * 0x0DF       LS      PERF_CTL[5:0]
  * 0x1D6       EX      PERF_CTL[5:0]
  * 0x1D8       EX      PERF_CTL[5:0]
+ *
+ * (*) depending on the umask all FPU counters may be used
  */
 
 static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
@@ -460,18 +466,28 @@ static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
 static struct event_constraint *
 amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
-       unsigned int event_code = amd_get_event_code(&event->hw);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int event_code = amd_get_event_code(hwc);
 
        switch (event_code & AMD_EVENT_TYPE_MASK) {
        case AMD_EVENT_FP:
                switch (event_code) {
+               case 0x000:
+                       if (!(hwc->config & 0x0000F000ULL))
+                               break;
+                       if (!(hwc->config & 0x00000F00ULL))
+                               break;
+                       return &amd_f15_PMC3;
+               case 0x004:
+                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+                               break;
+                       return &amd_f15_PMC3;
                case 0x003:
                case 0x00B:
                case 0x00D:
                        return &amd_f15_PMC3;
-               default:
-                       return &amd_f15_PMC53;
                }
+               return &amd_f15_PMC53;
        case AMD_EVENT_LS:
        case AMD_EVENT_DC:
        case AMD_EVENT_EX_LS:
index 8fc2b2cee1da32713746cc7e871aab075deaee41..41178c826c48507cac37d32f234b0f66a4c99708 100644 (file)
@@ -25,7 +25,7 @@ struct intel_percore {
 /*
  * Intel PerfMon, used on Core and later.
  */
-static const u64 intel_perfmon_event_map[] =
+static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
   [PERF_COUNT_HW_CPU_CYCLES]           = 0x003c,
   [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
@@ -36,7 +36,7 @@ static const u64 intel_perfmon_event_map[] =
   [PERF_COUNT_HW_BUS_CYCLES]           = 0x013c,
 };
 
-static struct event_constraint intel_core_event_constraints[] =
+static struct event_constraint intel_core_event_constraints[] __read_mostly =
 {
        INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
@@ -47,7 +47,7 @@ static struct event_constraint intel_core_event_constraints[] =
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_core2_event_constraints[] =
+static struct event_constraint intel_core2_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -70,7 +70,7 @@ static struct event_constraint intel_core2_event_constraints[] =
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_nehalem_event_constraints[] =
+static struct event_constraint intel_nehalem_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -86,19 +86,19 @@ static struct event_constraint intel_nehalem_event_constraints[] =
        EVENT_CONSTRAINT_END
 };
 
-static struct extra_reg intel_nehalem_extra_regs[] =
+static struct extra_reg intel_nehalem_extra_regs[] __read_mostly =
 {
        INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
        EVENT_EXTRA_END
 };
 
-static struct event_constraint intel_nehalem_percore_constraints[] =
+static struct event_constraint intel_nehalem_percore_constraints[] __read_mostly =
 {
        INTEL_EVENT_CONSTRAINT(0xb7, 0),
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_westmere_event_constraints[] =
+static struct event_constraint intel_westmere_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -110,7 +110,7 @@ static struct event_constraint intel_westmere_event_constraints[] =
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_snb_event_constraints[] =
+static struct event_constraint intel_snb_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -123,21 +123,21 @@ static struct event_constraint intel_snb_event_constraints[] =
        EVENT_CONSTRAINT_END
 };
 
-static struct extra_reg intel_westmere_extra_regs[] =
+static struct extra_reg intel_westmere_extra_regs[] __read_mostly =
 {
        INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
        INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
        EVENT_EXTRA_END
 };
 
-static struct event_constraint intel_westmere_percore_constraints[] =
+static struct event_constraint intel_westmere_percore_constraints[] __read_mostly =
 {
        INTEL_EVENT_CONSTRAINT(0xb7, 0),
        INTEL_EVENT_CONSTRAINT(0xbb, 0),
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_gen_event_constraints[] =
+static struct event_constraint intel_gen_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -184,26 +184,23 @@ static __initconst const u64 snb_hw_cache_event_ids
        },
  },
  [ C(LL  ) ] = {
-       /*
-        * TBD: Need Off-core Response Performance Monitoring support
-        */
        [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
                [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01bb,
+               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
        },
        [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE_0.ANY_RFO.LOCAL_CACHE */
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
                [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE_1.ANY_RFO.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01bb,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
        },
        [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
                [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01bb,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
        },
  },
  [ C(DTLB) ] = {
@@ -285,26 +282,26 @@ static __initconst const u64 westmere_hw_cache_event_ids
  },
  [ C(LL  ) ] = {
        [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
                [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01bb,
+               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
        },
        /*
         * Use RFO, not WRITEBACK, because a write miss would typically occur
         * on RFO.
         */
        [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE_1.ANY_RFO.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01bb,
-               /* OFFCORE_RESPONSE_0.ANY_RFO.ANY_LLC_MISS */
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
                [ C(RESULT_MISS)   ] = 0x01b7,
        },
        [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
                [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01bb,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
        },
  },
  [ C(DTLB) ] = {
@@ -352,16 +349,36 @@ static __initconst const u64 westmere_hw_cache_event_ids
 };
 
 /*
- * OFFCORE_RESPONSE MSR bits (subset), See IA32 SDM Vol 3 30.6.1.3
+ * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits;
+ * See IA32 SDM Vol 3B 30.6.1.3
  */
 
-#define DMND_DATA_RD     (1 << 0)
-#define DMND_RFO         (1 << 1)
-#define DMND_WB          (1 << 3)
-#define PF_DATA_RD       (1 << 4)
-#define PF_DATA_RFO      (1 << 5)
-#define RESP_UNCORE_HIT  (1 << 8)
-#define RESP_MISS        (0xf600) /* non uncore hit */
+#define NHM_DMND_DATA_RD       (1 << 0)
+#define NHM_DMND_RFO           (1 << 1)
+#define NHM_DMND_IFETCH                (1 << 2)
+#define NHM_DMND_WB            (1 << 3)
+#define NHM_PF_DATA_RD         (1 << 4)
+#define NHM_PF_DATA_RFO                (1 << 5)
+#define NHM_PF_IFETCH          (1 << 6)
+#define NHM_OFFCORE_OTHER      (1 << 7)
+#define NHM_UNCORE_HIT         (1 << 8)
+#define NHM_OTHER_CORE_HIT_SNP (1 << 9)
+#define NHM_OTHER_CORE_HITM    (1 << 10)
+                               /* reserved */
+#define NHM_REMOTE_CACHE_FWD   (1 << 12)
+#define NHM_REMOTE_DRAM                (1 << 13)
+#define NHM_LOCAL_DRAM         (1 << 14)
+#define NHM_NON_DRAM           (1 << 15)
+
+#define NHM_ALL_DRAM           (NHM_REMOTE_DRAM|NHM_LOCAL_DRAM)
+
+#define NHM_DMND_READ          (NHM_DMND_DATA_RD)
+#define NHM_DMND_WRITE         (NHM_DMND_RFO|NHM_DMND_WB)
+#define NHM_DMND_PREFETCH      (NHM_PF_DATA_RD|NHM_PF_DATA_RFO)
+
+#define NHM_L3_HIT     (NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM)
+#define NHM_L3_MISS    (NHM_NON_DRAM|NHM_ALL_DRAM|NHM_REMOTE_CACHE_FWD)
+#define NHM_L3_ACCESS  (NHM_L3_HIT|NHM_L3_MISS)
 
 static __initconst const u64 nehalem_hw_cache_extra_regs
                                [PERF_COUNT_HW_CACHE_MAX]
@@ -370,16 +387,16 @@ static __initconst const u64 nehalem_hw_cache_extra_regs
 {
  [ C(LL  ) ] = {
        [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = DMND_DATA_RD|RESP_UNCORE_HIT,
-               [ C(RESULT_MISS)   ] = DMND_DATA_RD|RESP_MISS,
+               [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_L3_MISS,
        },
        [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = DMND_RFO|DMND_WB|RESP_UNCORE_HIT,
-               [ C(RESULT_MISS)   ] = DMND_RFO|DMND_WB|RESP_MISS,
+               [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_L3_MISS,
        },
        [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_UNCORE_HIT,
-               [ C(RESULT_MISS)   ] = PF_DATA_RD|PF_DATA_RFO|RESP_MISS,
+               [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
        },
  }
 };
@@ -391,12 +408,12 @@ static __initconst const u64 nehalem_hw_cache_event_ids
 {
  [ C(L1D) ] = {
        [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI            */
-               [ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE         */
+               [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
        },
        [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI            */
-               [ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE         */
+               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+               [ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
        },
        [ C(OP_PREFETCH) ] = {
                [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
@@ -933,6 +950,16 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
+       /*
+        * Some chipsets need to unmask the LVTPC in a particular spot
+        * inside the nmi handler.  As a result, the unmasking was pushed
+        * into all the nmi handlers.
+        *
+        * This handler doesn't seem to have any issues with the unmasking
+        * so it was left at the top.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
        intel_pmu_disable_all();
        handled = intel_pmu_drain_bts_buffer();
        status = intel_pmu_get_status();
@@ -998,6 +1025,9 @@ intel_bts_constraints(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        unsigned int hw_event, bts_event;
 
+       if (event->attr.freq)
+               return NULL;
+
        hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
        bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
@@ -1305,7 +1335,7 @@ static void intel_clovertown_quirks(void)
         * AJ106 could possibly be worked around by not allowing LBR
         *       usage from PEBS, including the fixup.
         * AJ68  could possibly be worked around by always programming
-        *       a pebs_event_reset[0] value and coping with the lost events.
+        *       a pebs_event_reset[0] value and coping with the lost events.
         *
         * But taken together it might just make sense to not enable PEBS on
         * these chips.
@@ -1409,6 +1439,23 @@ static __init int intel_pmu_init(void)
                x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
                x86_pmu.enable_all = intel_pmu_nhm_enable_all;
                x86_pmu.extra_regs = intel_nehalem_extra_regs;
+
+               /* UOPS_ISSUED.STALLED_CYCLES */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
+               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1;
+
+               if (ebx & 0x40) {
+                       /*
+                        * Erratum AAJ80 detected, we work it around by using
+                        * the BR_MISP_EXEC.ANY event. This will over-count
+                        * branch-misses, but it's still much better than the
+                        * architectural event which is often completely bogus:
+                        */
+                       intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
+
+                       pr_cont("erratum AAJ80 worked around, ");
+               }
                pr_cont("Nehalem events, ");
                break;
 
@@ -1425,6 +1472,7 @@ static __init int intel_pmu_init(void)
 
        case 37: /* 32 nm nehalem, "Clarkdale" */
        case 44: /* 32 nm nehalem, "Gulftown" */
+       case 47: /* 32 nm Xeon E7 */
                memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
@@ -1437,6 +1485,12 @@ static __init int intel_pmu_init(void)
                x86_pmu.enable_all = intel_pmu_nhm_enable_all;
                x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
                x86_pmu.extra_regs = intel_westmere_extra_regs;
+
+               /* UOPS_ISSUED.STALLED_CYCLES */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
+               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1;
+
                pr_cont("Westmere events, ");
                break;
 
@@ -1448,6 +1502,12 @@ static __init int intel_pmu_init(void)
 
                x86_pmu.event_constraints = intel_snb_event_constraints;
                x86_pmu.pebs_constraints = intel_snb_pebs_events;
+
+               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
+               /* UOPS_DISPATCHED.THREAD,c=1,i=1 to count stall cycles*/
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x18001b1;
+
                pr_cont("SandyBridge events, ");
                break;
 
index c2520e178d32147fd9e2acd954d59e4217115add..ead584fb6a7d4870a606b4dace503c8c63763293 100644 (file)
@@ -468,7 +468,7 @@ static struct p4_event_bind p4_event_bind_map[] = {
                .opcode         = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
                .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
                .escr_emask     =
-               P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_X87_ASSIST] = {
@@ -912,8 +912,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
        int idx, handled = 0;
        u64 val;
 
-       data.addr = 0;
-       data.raw = NULL;
+       perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -947,14 +946,23 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
                if (!x86_perf_event_set_period(event))
                        continue;
                if (perf_event_overflow(event, 1, &data, regs))
-                       p4_pmu_disable_event(event);
+                       x86_pmu_stop(event, 0);
        }
 
-       if (handled) {
-               /* p4 quirk: unmask it again */
-               apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
+       if (handled)
                inc_irq_stat(apic_perf_irqs);
-       }
+
+       /*
+        * When dealing with the unmasking of the LVTPC on P4 perf hw, it has
+        * been observed that the OVF bit flag has to be cleared first _before_
+        * the LVTPC can be unmasked.
+        *
+        * The reason is the NMI line will continue to be asserted while the OVF
+        * bit is set.  This causes a second NMI to generate if the LVTPC is
+        * unmasked before the OVF bit is cleared, leading to unknown NMI
+        * messages.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
 
        return handled;
 }
@@ -1188,7 +1196,7 @@ static __init int p4_pmu_init(void)
 {
        unsigned int low, high;
 
-       /* If we get stripped -- indexig fails */
+       /* If we get stripped -- indexing fails */
        BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC);
 
        rdmsr(MSR_IA32_MISC_ENABLE, low, high);
index 706a9fb46a58785edef3632d2dcfc5d02ac6404f..e90f08458e6ba5879c033388945fbec7963f677c 100644 (file)
@@ -391,7 +391,7 @@ static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
 
        set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
 
-       return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+       return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
 }
 
 static void __init ioapic_add_ofnode(struct device_node *np)
index f72e7193acc55c56f4e5b4c3e74e671faeae9fcc..1aae78f775fc18e4f01b2ed568a1934e2de6dd31 100644 (file)
@@ -135,20 +135,6 @@ print_context_stack_bp(struct thread_info *tinfo,
 }
 EXPORT_SYMBOL_GPL(print_context_stack_bp);
 
-
-static void
-print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
-{
-       printk(data);
-       print_symbol(msg, symbol);
-       printk("\n");
-}
-
-static void print_trace_warning(void *data, char *msg)
-{
-       printk("%s%s\n", (char *)data, msg);
-}
-
 static int print_trace_stack(void *data, char *name)
 {
        printk("%s <%s> ", (char *)data, name);
@@ -166,8 +152,6 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops print_trace_ops = {
-       .warning                = print_trace_warning,
-       .warning_symbol         = print_trace_warning_symbol,
        .stack                  = print_trace_stack,
        .address                = print_trace_address,
        .walk_stack             = print_context_stack,
index a93742a57468770bd7f8be02dae04fc4765fe306..0ba15a6cc57eeacc3944c09f8e894b3a9348a54f 100644 (file)
@@ -260,9 +260,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code)
        return mod_code_status;
 }
 
-static unsigned char *ftrace_nop_replace(void)
+static const unsigned char *ftrace_nop_replace(void)
 {
-       return ideal_nop5;
+       return ideal_nops[NOP_ATOMIC5];
 }
 
 static int
index d6d6bb36193126885f4de35964fd6d07c7e3325b..3bb08509a7a151725182e5cf64d7dd636958e239 100644 (file)
@@ -23,7 +23,6 @@
 static void __init i386_default_early_setup(void)
 {
        /* Initialize 32bit specific setup functions */
-       x86_init.resources.probe_roms = probe_roms;
        x86_init.resources.reserve_resources = i386_reserve_resources;
        x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
 
index bfe8f729e0861a9edf636e2acfddcaec46261ca5..6781765b3a0df0317fc67a0051fb459aa3c15d01 100644 (file)
@@ -217,7 +217,7 @@ static void hpet_reserve_platform_timers(unsigned int id) { }
 /*
  * Common hpet info
  */
-static unsigned long hpet_period;
+static unsigned long hpet_freq;
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
                          struct clock_event_device *evt);
@@ -232,7 +232,6 @@ static struct clock_event_device hpet_clockevent = {
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode       = hpet_legacy_set_mode,
        .set_next_event = hpet_legacy_next_event,
-       .shift          = 32,
        .irq            = 0,
        .rating         = 50,
 };
@@ -289,29 +288,13 @@ static void hpet_legacy_clockevent_register(void)
        /* Start HPET legacy interrupts */
        hpet_enable_legacy_int();
 
-       /*
-        * The mult factor is defined as (include/linux/clockchips.h)
-        *  mult/2^shift = cyc/ns (in contrast to ns/cyc in clocksource.h)
-        * hpet_period is in units of femtoseconds (per cycle), so
-        *  mult/2^shift = cyc/ns = 10^6/hpet_period
-        *  mult = (10^6 * 2^shift)/hpet_period
-        *  mult = (FSEC_PER_NSEC << hpet_clockevent.shift)/hpet_period
-        */
-       hpet_clockevent.mult = div_sc((unsigned long) FSEC_PER_NSEC,
-                                     hpet_period, hpet_clockevent.shift);
-       /* Calculate the min / max delta */
-       hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
-                                                          &hpet_clockevent);
-       /* Setup minimum reprogramming delta. */
-       hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
-                                                          &hpet_clockevent);
-
        /*
         * Start hpet with the boot cpu mask and make it
         * global after the IO_APIC has been initialized.
         */
        hpet_clockevent.cpumask = cpumask_of(smp_processor_id());
-       clockevents_register_device(&hpet_clockevent);
+       clockevents_config_and_register(&hpet_clockevent, hpet_freq,
+                                       HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
        global_clock_event = &hpet_clockevent;
        printk(KERN_DEBUG "hpet clockevent registered\n");
 }
@@ -549,7 +532,6 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 {
        struct clock_event_device *evt = &hdev->evt;
-       uint64_t hpet_freq;
 
        WARN_ON(cpu != smp_processor_id());
        if (!(hdev->flags & HPET_DEV_VALID))
@@ -571,24 +553,10 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 
        evt->set_mode = hpet_msi_set_mode;
        evt->set_next_event = hpet_msi_next_event;
-       evt->shift = 32;
-
-       /*
-        * The period is a femto seconds value. We need to calculate the
-        * scaled math multiplication factor for nanosecond to hpet tick
-        * conversion.
-        */
-       hpet_freq = FSEC_PER_SEC;
-       do_div(hpet_freq, hpet_period);
-       evt->mult = div_sc((unsigned long) hpet_freq,
-                                     NSEC_PER_SEC, evt->shift);
-       /* Calculate the max delta */
-       evt->max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, evt);
-       /* 5 usec minimum reprogramming delta. */
-       evt->min_delta_ns = 5000;
-
        evt->cpumask = cpumask_of(hdev->cpu);
-       clockevents_register_device(evt);
+
+       clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
+                                       0x7FFFFFFF);
 }
 
 #ifdef CONFIG_HPET
@@ -792,7 +760,6 @@ static struct clocksource clocksource_hpet = {
 static int hpet_clocksource_register(void)
 {
        u64 start, now;
-       u64 hpet_freq;
        cycle_t t1;
 
        /* Start the counter */
@@ -819,24 +786,7 @@ static int hpet_clocksource_register(void)
                return -ENODEV;
        }
 
-       /*
-        * The definition of mult is (include/linux/clocksource.h)
-        * mult/2^shift = ns/cyc and hpet_period is in units of fsec/cyc
-        * so we first need to convert hpet_period to ns/cyc units:
-        *  mult/2^shift = ns/cyc = hpet_period/10^6
-        *  mult = (hpet_period * 2^shift)/10^6
-        *  mult = (hpet_period << shift)/FSEC_PER_NSEC
-        */
-
-       /* Need to convert hpet_period (fsec/cyc) to cyc/sec:
-        *
-        * cyc/sec = FSEC_PER_SEC/hpet_period(fsec/cyc)
-        * cyc/sec = (FSEC_PER_NSEC * NSEC_PER_SEC)/hpet_period
-        */
-       hpet_freq = FSEC_PER_SEC;
-       do_div(hpet_freq, hpet_period);
        clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
-
        return 0;
 }
 
@@ -845,7 +795,9 @@ static int hpet_clocksource_register(void)
  */
 int __init hpet_enable(void)
 {
+       unsigned long hpet_period;
        unsigned int id;
+       u64 freq;
        int i;
 
        if (!is_hpet_capable())
@@ -883,6 +835,14 @@ int __init hpet_enable(void)
        if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
                goto out_nohpet;
 
+       /*
+        * The period is a femto seconds value. Convert it to a
+        * frequency.
+        */
+       freq = FSEC_PER_SEC;
+       do_div(freq, hpet_period);
+       hpet_freq = freq;
+
        /*
         * Read the HPET ID register to retrieve the IRQ routing
         * information and the number of channels
index 2dfd315974436bf8f4f63e32c7efd3390018cfe5..fb66dc9e36cba31bb190a0a47fb120eaf4cc863e 100644 (file)
@@ -93,7 +93,6 @@ static struct clock_event_device pit_ce = {
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode       = init_pit_timer,
        .set_next_event = pit_next_event,
-       .shift          = 32,
        .irq            = 0,
 };
 
@@ -108,90 +107,12 @@ void __init setup_pit_timer(void)
         * IO_APIC has been initialized.
         */
        pit_ce.cpumask = cpumask_of(smp_processor_id());
-       pit_ce.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
-       pit_ce.max_delta_ns = clockevent_delta2ns(0x7FFF, &pit_ce);
-       pit_ce.min_delta_ns = clockevent_delta2ns(0xF, &pit_ce);
 
-       clockevents_register_device(&pit_ce);
+       clockevents_config_and_register(&pit_ce, CLOCK_TICK_RATE, 0xF, 0x7FFF);
        global_clock_event = &pit_ce;
 }
 
 #ifndef CONFIG_X86_64
-/*
- * Since the PIT overflows every tick, its not very useful
- * to just read by itself. So use jiffies to emulate a free
- * running counter:
- */
-static cycle_t pit_read(struct clocksource *cs)
-{
-       static int old_count;
-       static u32 old_jifs;
-       unsigned long flags;
-       int count;
-       u32 jifs;
-
-       raw_spin_lock_irqsave(&i8253_lock, flags);
-       /*
-        * Although our caller may have the read side of xtime_lock,
-        * this is now a seqlock, and we are cheating in this routine
-        * by having side effects on state that we cannot undo if
-        * there is a collision on the seqlock and our caller has to
-        * retry.  (Namely, old_jifs and old_count.)  So we must treat
-        * jiffies as volatile despite the lock.  We read jiffies
-        * before latching the timer count to guarantee that although
-        * the jiffies value might be older than the count (that is,
-        * the counter may underflow between the last point where
-        * jiffies was incremented and the point where we latch the
-        * count), it cannot be newer.
-        */
-       jifs = jiffies;
-       outb_pit(0x00, PIT_MODE);       /* latch the count ASAP */
-       count = inb_pit(PIT_CH0);       /* read the latched count */
-       count |= inb_pit(PIT_CH0) << 8;
-
-       /* VIA686a test code... reset the latch if count > max + 1 */
-       if (count > LATCH) {
-               outb_pit(0x34, PIT_MODE);
-               outb_pit(LATCH & 0xff, PIT_CH0);
-               outb_pit(LATCH >> 8, PIT_CH0);
-               count = LATCH - 1;
-       }
-
-       /*
-        * It's possible for count to appear to go the wrong way for a
-        * couple of reasons:
-        *
-        *  1. The timer counter underflows, but we haven't handled the
-        *     resulting interrupt and incremented jiffies yet.
-        *  2. Hardware problem with the timer, not giving us continuous time,
-        *     the counter does small "jumps" upwards on some Pentium systems,
-        *     (see c't 95/10 page 335 for Neptun bug.)
-        *
-        * Previous attempts to handle these cases intelligently were
-        * buggy, so we just do the simple thing now.
-        */
-       if (count > old_count && jifs == old_jifs)
-               count = old_count;
-
-       old_count = count;
-       old_jifs = jifs;
-
-       raw_spin_unlock_irqrestore(&i8253_lock, flags);
-
-       count = (LATCH - 1) - count;
-
-       return (cycle_t)(jifs * LATCH) + count;
-}
-
-static struct clocksource pit_cs = {
-       .name           = "pit",
-       .rating         = 110,
-       .read           = pit_read,
-       .mask           = CLOCKSOURCE_MASK(32),
-       .mult           = 0,
-       .shift          = 20,
-};
-
 static int __init init_pit_clocksource(void)
 {
         /*
@@ -205,10 +126,7 @@ static int __init init_pit_clocksource(void)
            pit_ce.mode != CLOCK_EVT_MODE_PERIODIC)
                return 0;
 
-       pit_cs.mult = clocksource_hz2mult(CLOCK_TICK_RATE, pit_cs.shift);
-
-       return clocksource_register(&pit_cs);
+       return clocksource_i8253_init();
 }
 arch_initcall(init_pit_clocksource);
-
 #endif /* !CONFIG_X86_64 */
index 1cb0b9fc78dccffd68a1c571e873043e0d28d007..6c0802eb2f7f7efdc79c9a51d160ac92c70e43c2 100644 (file)
@@ -249,7 +249,7 @@ void fixup_irqs(void)
 
                data = irq_desc_get_irq_data(desc);
                affinity = data->affinity;
-               if (!irq_has_action(irq) ||
+               if (!irq_has_action(irq) || irqd_is_per_cpu(data) ||
                    cpumask_subset(affinity, cpu_online_mask)) {
                        raw_spin_unlock(&desc->lock);
                        continue;
@@ -276,7 +276,8 @@ void fixup_irqs(void)
                else if (!(warned++))
                        set_affinity = 0;
 
-               if (!irqd_can_move_in_process_context(data) && chip->irq_unmask)
+               if (!irqd_can_move_in_process_context(data) &&
+                   !irqd_irq_disabled(data) && chip->irq_unmask)
                        chip->irq_unmask(data);
 
                raw_spin_unlock(&desc->lock);
index 961b6b30ba90df9754f94fe13a83e0d6b8d19134..3fee346ef5454e257e927f901da982e4bea83141 100644 (file)
@@ -34,7 +34,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
                code.offset = entry->target -
                                (entry->code + JUMP_LABEL_NOP_SIZE);
        } else
-               memcpy(&code, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+               memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
        get_online_cpus();
        mutex_lock(&text_mutex);
        text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
@@ -44,7 +44,8 @@ void arch_jump_label_transform(struct jump_entry *entry,
 
 void arch_jump_label_text_poke_early(jump_label_t addr)
 {
-       text_poke_early((void *)addr, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+       text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5],
+                       JUMP_LABEL_NOP_SIZE);
 }
 
 #endif
index c969fd9d156651c9d0cc6dae1a606bb091cbcde6..f1a6244d7d93769c35d219b79de6358d8a4096e3 100644 (file)
@@ -1183,12 +1183,13 @@ static void __kprobes optimized_callback(struct optimized_kprobe *op,
                                         struct pt_regs *regs)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       unsigned long flags;
 
        /* This is possible if op is under delayed unoptimizing */
        if (kprobe_disabled(&op->kp))
                return;
 
-       preempt_disable();
+       local_irq_save(flags);
        if (kprobe_running()) {
                kprobes_inc_nmissed_count(&op->kp);
        } else {
@@ -1207,7 +1208,7 @@ static void __kprobes optimized_callback(struct optimized_kprobe *op,
                opt_pre_handler(&op->kp, regs);
                __this_cpu_write(current_kprobe, NULL);
        }
-       preempt_enable_no_resched();
+       local_irq_restore(flags);
 }
 
 static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
index f98d3eafe07a6f98884ad55dce00c74d3dd91967..6389a6bca11b8159e47eab9feff42b828f666fc2 100644 (file)
@@ -26,8 +26,6 @@
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
 
-#define KVM_SCALE 22
-
 static int kvmclock = 1;
 static int msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
 static int msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
@@ -120,8 +118,6 @@ static struct clocksource kvm_clock = {
        .read = kvm_clock_get_cycles,
        .rating = 400,
        .mask = CLOCKSOURCE_MASK(64),
-       .mult = 1 << KVM_SCALE,
-       .shift = KVM_SCALE,
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -203,7 +199,7 @@ void __init kvmclock_init(void)
        machine_ops.crash_shutdown  = kvm_crash_shutdown;
 #endif
        kvm_get_preset_lpj();
-       clocksource_register(&kvm_clock);
+       clocksource_register_hz(&kvm_clock, NSEC_PER_SEC);
        pv_info.paravirt_enabled = 1;
        pv_info.name = "KVM";
 
index ab23f1ad4bf1054fd069132ef750f2d88a7f6852..52f256f2cc81323f20579c02253befc2b1cf4845 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/mm.h>
 #include <linux/gfp.h>
+#include <linux/jump_label.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
index 5a532ce646bf5c08988e108c9e859fc77e8a0b57..6f9bfffb27204976ca6b1ff3393b01072e028b22 100644 (file)
@@ -715,17 +715,15 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
        }
 }
 
-static int
+static int __init
 check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
 {
-       int ret = 0;
-
        if (!mpc_new_phys || count <= mpc_new_length) {
                WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
                return -1;
        }
 
-       return ret;
+       return 0;
 }
 #else /* CONFIG_X86_IO_APIC */
 static
index 55d745ec11818d958bacebef0940d33b7e508e70..35ccf75696eb8ab22af0e94e6246b5cb3f655b4f 100644 (file)
@@ -50,20 +50,14 @@ void __init check_iommu_entries(struct iommu_table_entry *start,
                                struct iommu_table_entry *finish)
 {
        struct iommu_table_entry *p, *q, *x;
-       char sym_p[KSYM_SYMBOL_LEN];
-       char sym_q[KSYM_SYMBOL_LEN];
 
        /* Simple cyclic dependency checker. */
        for (p = start; p < finish; p++) {
                q = find_dependents_of(start, finish, p);
                x = find_dependents_of(start, finish, q);
                if (p == x) {
-                       sprint_symbol(sym_p, (unsigned long)p->detect);
-                       sprint_symbol(sym_q, (unsigned long)q->detect);
-
-                       printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %s depends" \
-                                       " on %s and vice-versa. BREAKING IT.\n",
-                                       sym_p, sym_q);
+                       printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %pS depends on %pS and vice-versa. BREAKING IT.\n",
+                              p->detect, q->detect);
                        /* Heavy handed way..*/
                        x->depend = 0;
                }
@@ -72,12 +66,8 @@ void __init check_iommu_entries(struct iommu_table_entry *start,
        for (p = start; p < finish; p++) {
                q = find_dependents_of(p, finish, p);
                if (q && q > p) {
-                       sprint_symbol(sym_p, (unsigned long)p->detect);
-                       sprint_symbol(sym_q, (unsigned long)q->detect);
-
-                       printk(KERN_ERR "EXECUTION ORDER INVALID! %s "\
-                                       "should be called before %s!\n",
-                                       sym_p, sym_q);
+                       printk(KERN_ERR "EXECUTION ORDER INVALID! %pS should be called before %pS!\n",
+                              p->detect, q->detect);
                }
        }
 }
similarity index 65%
rename from arch/x86/kernel/probe_roms_32.c
rename to arch/x86/kernel/probe_roms.c
index 071e7fea42e5b3fd07bb16a7a953f4d4145f9110..ba0a4cce53be2d70cf4b14c07e39d9756907d110 100644 (file)
@@ -73,6 +73,107 @@ static struct resource video_rom_resource = {
        .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
 };
 
+/* does this oprom support the given pci device, or any of the devices
+ * that the driver supports?
+ */
+static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short device)
+{
+       struct pci_driver *drv = pdev->driver;
+       const struct pci_device_id *id;
+
+       if (pdev->vendor == vendor && pdev->device == device)
+               return true;
+
+       for (id = drv ? drv->id_table : NULL; id && id->vendor; id++)
+               if (id->vendor == vendor && id->device == device)
+                       break;
+
+       return id && id->vendor;
+}
+
+static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
+                      const unsigned char *rom_list)
+{
+       unsigned short device;
+
+       do {
+               if (probe_kernel_address(rom_list, device) != 0)
+                       device = 0;
+
+               if (device && match_id(pdev, vendor, device))
+                       break;
+
+               rom_list += 2;
+       } while (device);
+
+       return !!device;
+}
+
+static struct resource *find_oprom(struct pci_dev *pdev)
+{
+       struct resource *oprom = NULL;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
+               struct resource *res = &adapter_rom_resources[i];
+               unsigned short offset, vendor, device, list, rev;
+               const unsigned char *rom;
+
+               if (res->end == 0)
+                       break;
+
+               rom = isa_bus_to_virt(res->start);
+               if (probe_kernel_address(rom + 0x18, offset) != 0)
+                       continue;
+
+               if (probe_kernel_address(rom + offset + 0x4, vendor) != 0)
+                       continue;
+
+               if (probe_kernel_address(rom + offset + 0x6, device) != 0)
+                       continue;
+
+               if (match_id(pdev, vendor, device)) {
+                       oprom = res;
+                       break;
+               }
+
+               if (probe_kernel_address(rom + offset + 0x8, list) == 0 &&
+                   probe_kernel_address(rom + offset + 0xc, rev) == 0 &&
+                   rev >= 3 && list &&
+                   probe_list(pdev, vendor, rom + offset + list)) {
+                       oprom = res;
+                       break;
+               }
+       }
+
+       return oprom;
+}
+
+void *pci_map_biosrom(struct pci_dev *pdev)
+{
+       struct resource *oprom = find_oprom(pdev);
+
+       if (!oprom)
+               return NULL;
+
+       return ioremap(oprom->start, resource_size(oprom));
+}
+EXPORT_SYMBOL(pci_map_biosrom);
+
+void pci_unmap_biosrom(void __iomem *image)
+{
+       iounmap(image);
+}
+EXPORT_SYMBOL(pci_unmap_biosrom);
+
+size_t pci_biosrom_size(struct pci_dev *pdev)
+{
+       struct resource *oprom = find_oprom(pdev);
+
+       return oprom ? resource_size(oprom) : 0;
+}
+EXPORT_SYMBOL(pci_biosrom_size);
+
 #define ROMSIGNATURE 0xaa55
 
 static int __init romsignature(const unsigned char *rom)
index d46cbe46b7aba845ab1a2261a569f0178ec954b0..88a90a977f8ee58d58b5bf14546b66a82f85aabf 100644 (file)
@@ -449,7 +449,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
 void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
 {
        if (!need_resched()) {
-               if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR))
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
                        clflush((void *)&current_thread_info()->flags);
 
                __monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -465,7 +465,7 @@ static void mwait_idle(void)
        if (!need_resched()) {
                trace_power_start(POWER_CSTATE, 1, smp_processor_id());
                trace_cpu_idle(1, smp_processor_id());
-               if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR))
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
                        clflush((void *)&current_thread_info()->flags);
 
                __monitor((void *)&current_thread_info()->flags, 0, 0);
index 45892dc4b72a37f01627725db2654591fc4dad6b..f65e5b521dbd4b3d28c8dc30faecec02073e56fb 100644 (file)
@@ -608,6 +608,9 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
        unsigned len, type;
        struct perf_event *bp;
 
+       if (ptrace_get_breakpoints(tsk) < 0)
+               return -ESRCH;
+
        data &= ~DR_CONTROL_RESERVED;
        old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
 restore:
@@ -655,6 +658,9 @@ restore:
                }
                goto restore;
        }
+
+       ptrace_put_breakpoints(tsk);
+
        return ((orig_ret < 0) ? orig_ret : rc);
 }
 
@@ -668,10 +674,17 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)
 
        if (n < HBP_NUM) {
                struct perf_event *bp;
+
+               if (ptrace_get_breakpoints(tsk) < 0)
+                       return -ESRCH;
+
                bp = thread->ptrace_bps[n];
                if (!bp)
-                       return 0;
-               val = bp->hw.info.address;
+                       val = 0;
+               else
+                       val = bp->hw.info.address;
+
+               ptrace_put_breakpoints(tsk);
        } else if (n == 6) {
                val = thread->debugreg6;
         } else if (n == 7) {
@@ -686,6 +699,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
        struct perf_event *bp;
        struct thread_struct *t = &tsk->thread;
        struct perf_event_attr attr;
+       int err = 0;
+
+       if (ptrace_get_breakpoints(tsk) < 0)
+               return -ESRCH;
 
        if (!t->ptrace_bps[nr]) {
                ptrace_breakpoint_init(&attr);
@@ -709,24 +726,23 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
                 * writing for the user. And anyway this is the previous
                 * behaviour.
                 */
-               if (IS_ERR(bp))
-                       return PTR_ERR(bp);
+               if (IS_ERR(bp)) {
+                       err = PTR_ERR(bp);
+                       goto put;
+               }
 
                t->ptrace_bps[nr] = bp;
        } else {
-               int err;
-
                bp = t->ptrace_bps[nr];
 
                attr = bp->attr;
                attr.bp_addr = addr;
                err = modify_user_hw_breakpoint(bp, &attr);
-               if (err)
-                       return err;
        }
 
-
-       return 0;
+put:
+       ptrace_put_breakpoints(tsk);
+       return err;
 }
 
 /*
index 08c44b08bf5bda05e227a2c8b2a55bfa36964836..0c016f727695e9ab1a4544e845fa698a8c540737 100644 (file)
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(pm_power_off);
 
 static const struct desc_ptr no_idt = {};
 static int reboot_mode;
-enum reboot_type reboot_type = BOOT_KBD;
+enum reboot_type reboot_type = BOOT_ACPI;
 int reboot_force;
 
 #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
@@ -478,9 +478,24 @@ void __attribute__((weak)) mach_reboot_fixups(void)
 {
 }
 
+/*
+ * Windows compatible x86 hardware expects the following on reboot:
+ *
+ * 1) If the FADT has the ACPI reboot register flag set, try it
+ * 2) If still alive, write to the keyboard controller
+ * 3) If still alive, write to the ACPI reboot register again
+ * 4) If still alive, write to the keyboard controller again
+ *
+ * If the machine is still alive at this stage, it gives up. We default to
+ * following the same pattern, except that if we're still alive after (4) we'll
+ * try to force a triple fault and then cycle between hitting the keyboard
+ * controller and doing that
+ */
 static void native_machine_emergency_restart(void)
 {
        int i;
+       int attempt = 0;
+       int orig_reboot_type = reboot_type;
 
        if (reboot_emergency)
                emergency_vmx_disable_all();
@@ -502,6 +517,13 @@ static void native_machine_emergency_restart(void)
                                outb(0xfe, 0x64); /* pulse reset low */
                                udelay(50);
                        }
+                       if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
+                               attempt = 1;
+                               reboot_type = BOOT_ACPI;
+                       } else {
+                               reboot_type = BOOT_TRIPLE;
+                       }
+                       break;
 
                case BOOT_TRIPLE:
                        load_idt(&no_idt);
index 29092b38d816ee2577e5e89fb74cc023dbafc411..1d5c46df0d787abc497a1d025a9a8fd2cd347026 100644 (file)
@@ -21,26 +21,26 @@ r_base = .
        /* Get our own relocated address */
        call    1f
 1:     popl    %ebx
-       subl    $1b, %ebx
+       subl    $(1b - r_base), %ebx
 
        /* Compute the equivalent real-mode segment */
        movl    %ebx, %ecx
        shrl    $4, %ecx
        
        /* Patch post-real-mode segment jump */
-       movw    dispatch_table(%ebx,%eax,2),%ax
-       movw    %ax, 101f(%ebx)
-       movw    %cx, 102f(%ebx)
+       movw    (dispatch_table - r_base)(%ebx,%eax,2),%ax
+       movw    %ax, (101f - r_base)(%ebx)
+       movw    %cx, (102f - r_base)(%ebx)
 
        /* Set up the IDT for real mode. */
-       lidtl   machine_real_restart_idt(%ebx)
+       lidtl   (machine_real_restart_idt - r_base)(%ebx)
 
        /*
         * Set up a GDT from which we can load segment descriptors for real
         * mode.  The GDT is not used in real mode; it is just needed here to
         * prepare the descriptors.
         */
-       lgdtl   machine_real_restart_gdt(%ebx)
+       lgdtl   (machine_real_restart_gdt - r_base)(%ebx)
 
        /*
         * Load the data segment registers with 16-bit compatible values
index 4be9b398470ea7ed399fcd72d39c67681ae98e3f..c3050af9306d2337e19d06d6841f5c1af422902c 100644 (file)
@@ -691,8 +691,6 @@ early_param("reservelow", parse_reservelow);
 
 void __init setup_arch(char **cmdline_p)
 {
-       unsigned long flags;
-
 #ifdef CONFIG_X86_32
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
        visws_early_detect();
@@ -1041,9 +1039,7 @@ void __init setup_arch(char **cmdline_p)
 
        mcheck_init();
 
-       local_irq_save(flags);
-       arch_init_ideal_nop5();
-       local_irq_restore(flags);
+       arch_init_ideal_nops();
 }
 
 #ifdef CONFIG_X86_32
index 513deac7228d2262b3e07c2915c042a791abb7f8..013e7eba83bbd400fa099df067e71fbddc44b34d 100644 (file)
@@ -194,14 +194,13 @@ static void native_stop_other_cpus(int wait)
 }
 
 /*
- * Reschedule call back. Nothing to do,
- * all the work is done automatically when
- * we return from the interrupt.
+ * Reschedule call back.
  */
 void smp_reschedule_interrupt(struct pt_regs *regs)
 {
        ack_APIC_irq();
        inc_irq_stat(irq_resched_count);
+       scheduler_ipi();
        /*
         * KVM uses this interrupt to force a cpu out of guest mode
         */
index 8ed8908cc9f79ab06d828d181555255fa9f65c82..a3c430bdfb6020aaefd4a7c97717f30c627d0a85 100644 (file)
@@ -312,26 +312,6 @@ void __cpuinit smp_store_cpu_info(int id)
                identify_secondary_cpu(c);
 }
 
-static void __cpuinit check_cpu_siblings_on_same_node(int cpu1, int cpu2)
-{
-       int node1 = early_cpu_to_node(cpu1);
-       int node2 = early_cpu_to_node(cpu2);
-
-       /*
-        * Our CPU scheduler assumes all logical cpus in the same physical cpu
-        * share the same node. But, buggy ACPI or NUMA emulation might assign
-        * them to different node. Fix it.
-        */
-       if (node1 != node2) {
-               pr_warning("CPU %d in node %d and CPU %d in node %d are in the same physical CPU. forcing same node %d\n",
-                          cpu1, node1, cpu2, node2, node2);
-
-               numa_remove_cpu(cpu1);
-               numa_set_node(cpu1, node2);
-               numa_add_cpu(cpu1);
-       }
-}
-
 static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
 {
        cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
@@ -340,7 +320,6 @@ static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
        cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
        cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2));
        cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1));
-       check_cpu_siblings_on_same_node(cpu1, cpu2);
 }
 
 
@@ -382,12 +361,10 @@ void __cpuinit set_cpu_sibling_map(int cpu)
                    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
                        cpumask_set_cpu(i, cpu_llc_shared_mask(cpu));
                        cpumask_set_cpu(cpu, cpu_llc_shared_mask(i));
-                       check_cpu_siblings_on_same_node(cpu, i);
                }
                if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
                        cpumask_set_cpu(i, cpu_core_mask(cpu));
                        cpumask_set_cpu(cpu, cpu_core_mask(i));
-                       check_cpu_siblings_on_same_node(cpu, i);
                        /*
                         *  Does this new cpu bringup a new core?
                         */
@@ -1355,9 +1332,9 @@ static inline void mwait_play_dead(void)
        void *mwait_ptr;
        struct cpuinfo_x86 *c = __this_cpu_ptr(&cpu_info);
 
-       if (!(cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)))
+       if (!this_cpu_has(X86_FEATURE_MWAIT) && mwait_usable(c))
                return;
-       if (!cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLSH))
+       if (!this_cpu_has(X86_FEATURE_CLFLSH))
                return;
        if (__this_cpu_read(cpu_info.cpuid_level) < CPUID_MWAIT_LEAF)
                return;
index 6515733a289d858fde792d8db8f35bca3cad503d..55d9bc03f696c1d37638575bd504fbf8bc2e1444 100644 (file)
@@ -9,15 +9,6 @@
 #include <linux/uaccess.h>
 #include <asm/stacktrace.h>
 
-static void save_stack_warning(void *data, char *msg)
-{
-}
-
-static void
-save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
-{
-}
-
 static int save_stack_stack(void *data, char *name)
 {
        return 0;
@@ -53,16 +44,12 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops save_stack_ops = {
-       .warning        = save_stack_warning,
-       .warning_symbol = save_stack_warning_symbol,
        .stack          = save_stack_stack,
        .address        = save_stack_address,
        .walk_stack     = print_context_stack,
 };
 
 static const struct stacktrace_ops save_stack_ops_nosched = {
-       .warning        = save_stack_warning,
-       .warning_symbol = save_stack_warning_symbol,
        .stack          = save_stack_stack,
        .address        = save_stack_address_nosched,
        .walk_stack     = print_context_stack,
index c11514e9128b53cf0b6ad66d844c7703a6a8523a..6f164bd5e14d167d417b2f86e5fc8580047ed371 100644 (file)
@@ -35,7 +35,7 @@ void iommu_shutdown_noop(void) { }
 struct x86_init_ops x86_init __initdata = {
 
        .resources = {
-               .probe_roms             = x86_init_noop,
+               .probe_roms             = probe_roms,
                .reserve_resources      = reserve_standard_io_resources,
                .memory_setup           = default_machine_specific_memory_setup,
        },
@@ -61,6 +61,10 @@ struct x86_init_ops x86_init __initdata = {
                .banner                 = default_banner,
        },
 
+       .mapping = {
+               .pagetable_reserve              = native_pagetable_reserve,
+       },
+
        .paging = {
                .pagetable_setup_start  = native_pagetable_setup_start,
                .pagetable_setup_done   = native_pagetable_setup_done,
index 1cd608973ce594f6e0853170ef3e7abc84425c82..e191c096ab90363228965e746a0f898d6f8a9451 100644 (file)
@@ -7,7 +7,7 @@
  * kernel and insert a module (lg.ko) which allows us to run other Linux
  * kernels the same way we'd run processes.  We call the first kernel the Host,
  * and the others the Guests.  The program which sets up and configures Guests
- * (such as the example in Documentation/lguest/lguest.c) is called the
+ * (such as the example in Documentation/virtual/lguest/lguest.c) is called the
  * Launcher.
  *
  * Secondly, we only run specially modified Guests, not normal kernels: setting
@@ -913,8 +913,6 @@ static struct clocksource lguest_clock = {
        .rating         = 200,
        .read           = lguest_clock_read,
        .mask           = CLOCKSOURCE_MASK(64),
-       .mult           = 1 << 22,
-       .shift          = 22,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -997,7 +995,7 @@ static void lguest_time_init(void)
        /* Set up the timer interrupt (0) to go to our simple timer routine */
        irq_set_handler(0, lguest_time_irq);
 
-       clocksource_register(&lguest_clock);
+       clocksource_register_hz(&lguest_clock, NSEC_PER_SEC);
 
        /* We can't set cpumask in the initializer: damn C limitations!  Set it
         * here and register our timer device. */
index aa4326bfb24a1dc6dbe2b131dd7c7c19bb58d58d..f2145cfa12a66830e834718340c4cc88e64a731a 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/alternative-asm.h>
 
 /*
  * Zero a page.        
@@ -14,6 +15,15 @@ ENTRY(clear_page_c)
        CFI_ENDPROC
 ENDPROC(clear_page_c)
 
+ENTRY(clear_page_c_e)
+       CFI_STARTPROC
+       movl $4096,%ecx
+       xorl %eax,%eax
+       rep stosb
+       ret
+       CFI_ENDPROC
+ENDPROC(clear_page_c_e)
+
 ENTRY(clear_page)
        CFI_STARTPROC
        xorl   %eax,%eax
@@ -38,21 +48,26 @@ ENTRY(clear_page)
 .Lclear_page_end:
 ENDPROC(clear_page)
 
-       /* Some CPUs run faster using the string instructions.
-          It is also a lot simpler. Use this when possible */
+       /*
+        * Some CPUs support enhanced REP MOVSB/STOSB instructions.
+        * It is recommended to use this when possible.
+        * If enhanced REP MOVSB/STOSB is not available, try to use fast string.
+        * Otherwise, use original function.
+        *
+        */
 
 #include <asm/cpufeature.h>
 
        .section .altinstr_replacement,"ax"
 1:     .byte 0xeb                                      /* jmp <disp8> */
        .byte (clear_page_c - clear_page) - (2f - 1b)   /* offset */
-2:
+2:     .byte 0xeb                                      /* jmp <disp8> */
+       .byte (clear_page_c_e - clear_page) - (3f - 2b) /* offset */
+3:
        .previous
        .section .altinstructions,"a"
-       .align 8
-       .quad clear_page
-       .quad 1b
-       .word X86_FEATURE_REP_GOOD
-       .byte .Lclear_page_end - clear_page
-       .byte 2b - 1b
+       altinstruction_entry clear_page,1b,X86_FEATURE_REP_GOOD,\
+                            .Lclear_page_end-clear_page, 2b-1b
+       altinstruction_entry clear_page,2b,X86_FEATURE_ERMS,   \
+                            .Lclear_page_end-clear_page,3b-2b
        .previous
index 99e482615195484e9da7c6152ee0fb1969488067..024840266ba0d94144697de13194417d0427d22f 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
 
-       .macro ALTERNATIVE_JUMP feature,orig,alt
+/*
+ * By placing feature2 after feature1 in altinstructions section, we logically
+ * implement:
+ * If CPU has feature2, jmp to alt2 is used
+ * else if CPU has feature1, jmp to alt1 is used
+ * else jmp to orig is used.
+ */
+       .macro ALTERNATIVE_JUMP feature1,feature2,orig,alt1,alt2
 0:
        .byte 0xe9      /* 32bit jump */
        .long \orig-1f  /* by default jump to orig */
 1:
        .section .altinstr_replacement,"ax"
 2:     .byte 0xe9                      /* near jump with 32bit immediate */
-       .long \alt-1b /* offset */   /* or alternatively to alt */
+       .long \alt1-1b /* offset */   /* or alternatively to alt1 */
+3:     .byte 0xe9                      /* near jump with 32bit immediate */
+       .long \alt2-1b /* offset */   /* or alternatively to alt2 */
        .previous
+
        .section .altinstructions,"a"
-       .align 8
-       .quad  0b
-       .quad  2b
-       .word  \feature                 /* when feature is set */
-       .byte  5
-       .byte  5
+       altinstruction_entry 0b,2b,\feature1,5,5
+       altinstruction_entry 0b,3b,\feature2,5,5
        .previous
        .endm
 
@@ -72,8 +79,10 @@ ENTRY(_copy_to_user)
        addq %rdx,%rcx
        jc bad_to_user
        cmpq TI_addr_limit(%rax),%rcx
-       jae bad_to_user
-       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       ja bad_to_user
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \
+               copy_user_generic_unrolled,copy_user_generic_string,    \
+               copy_user_enhanced_fast_string
        CFI_ENDPROC
 ENDPROC(_copy_to_user)
 
@@ -85,8 +94,10 @@ ENTRY(_copy_from_user)
        addq %rdx,%rcx
        jc bad_from_user
        cmpq TI_addr_limit(%rax),%rcx
-       jae bad_from_user
-       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       ja bad_from_user
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \
+               copy_user_generic_unrolled,copy_user_generic_string,    \
+               copy_user_enhanced_fast_string
        CFI_ENDPROC
 ENDPROC(_copy_from_user)
 
@@ -255,3 +266,37 @@ ENTRY(copy_user_generic_string)
        .previous
        CFI_ENDPROC
 ENDPROC(copy_user_generic_string)
+
+/*
+ * Some CPUs are adding enhanced REP MOVSB/STOSB instructions.
+ * It's recommended to use enhanced REP MOVSB/STOSB if it's enabled.
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
+ *
+ * Output:
+ * eax uncopied bytes or 0 if successful.
+ */
+ENTRY(copy_user_enhanced_fast_string)
+       CFI_STARTPROC
+       andl %edx,%edx
+       jz 2f
+       movl %edx,%ecx
+1:     rep
+       movsb
+2:     xorl %eax,%eax
+       ret
+
+       .section .fixup,"ax"
+12:    movl %ecx,%edx          /* ecx is zerorest also */
+       jmp copy_user_handle_tail
+       .previous
+
+       .section __ex_table,"a"
+       .align 8
+       .quad 1b,12b
+       .previous
+       CFI_ENDPROC
+ENDPROC(copy_user_enhanced_fast_string)
index 75ef61e35e38aee1cf62b05a48f1add62b148f98..efbf2a0ecdea85a41566f01d05d14e14177e7145 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/cpufeature.h>
 #include <asm/dwarf2.h>
+#include <asm/alternative-asm.h>
 
 /*
  * memcpy - Copy a memory block.
 .Lmemcpy_e:
        .previous
 
+/*
+ * memcpy_c_e() - enhanced fast string memcpy. This is faster and simpler than
+ * memcpy_c. Use memcpy_c_e when possible.
+ *
+ * This gets patched over the unrolled variant (below) via the
+ * alternative instructions framework:
+ */
+       .section .altinstr_replacement, "ax", @progbits
+.Lmemcpy_c_e:
+       movq %rdi, %rax
+
+       movl %edx, %ecx
+       rep movsb
+       ret
+.Lmemcpy_e_e:
+       .previous
+
 ENTRY(__memcpy)
 ENTRY(memcpy)
        CFI_STARTPROC
@@ -49,7 +67,7 @@ ENTRY(memcpy)
        jb .Lhandle_tail
 
        /*
-        * We check whether memory false dependece could occur,
+        * We check whether memory false dependence could occur,
         * then jump to corresponding copy mode.
         */
        cmp  %dil, %sil
@@ -171,21 +189,22 @@ ENDPROC(memcpy)
 ENDPROC(__memcpy)
 
        /*
-        * Some CPUs run faster using the string copy instructions.
-        * It is also a lot simpler. Use this when possible:
-        */
-
-       .section .altinstructions, "a"
-       .align 8
-       .quad memcpy
-       .quad .Lmemcpy_c
-       .word X86_FEATURE_REP_GOOD
-
-       /*
+        * Some CPUs are adding enhanced REP MOVSB/STOSB feature
+        * If the feature is supported, memcpy_c_e() is the first choice.
+        * If enhanced rep movsb copy is not available, use fast string copy
+        * memcpy_c() when possible. This is faster and code is simpler than
+        * original memcpy().
+        * Otherwise, original memcpy() is used.
+        * In .altinstructions section, ERMS feature is placed after REG_GOOD
+         * feature to implement the right patch order.
+        *
         * Replace only beginning, memcpy is used to apply alternatives,
         * so it is silly to overwrite itself with nops - reboot is the
         * only outcome...
         */
-       .byte .Lmemcpy_e - .Lmemcpy_c
-       .byte .Lmemcpy_e - .Lmemcpy_c
+       .section .altinstructions, "a"
+       altinstruction_entry memcpy,.Lmemcpy_c,X86_FEATURE_REP_GOOD,\
+                            .Lmemcpy_e-.Lmemcpy_c,.Lmemcpy_e-.Lmemcpy_c
+       altinstruction_entry memcpy,.Lmemcpy_c_e,X86_FEATURE_ERMS, \
+                            .Lmemcpy_e_e-.Lmemcpy_c_e,.Lmemcpy_e_e-.Lmemcpy_c_e
        .previous
index 0ecb8433e5a8e2f62c0a678da69ccd16f233b304..d0ec9c2936d75fb6e7c908c00f2359fd0c366dd5 100644 (file)
@@ -8,6 +8,7 @@
 #define _STRING_C
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
 
 #undef memmove
 
@@ -24,6 +25,7 @@
  */
 ENTRY(memmove)
        CFI_STARTPROC
+
        /* Handle more 32bytes in loop */
        mov %rdi, %rax
        cmp $0x20, %rdx
@@ -31,8 +33,13 @@ ENTRY(memmove)
 
        /* Decide forward/backward copy mode */
        cmp %rdi, %rsi
-       jb      2f
+       jge .Lmemmove_begin_forward
+       mov %rsi, %r8
+       add %rdx, %r8
+       cmp %rdi, %r8
+       jg 2f
 
+.Lmemmove_begin_forward:
        /*
         * movsq instruction have many startup latency
         * so we handle small size by general register.
@@ -78,6 +85,8 @@ ENTRY(memmove)
        rep movsq
        movq %r11, (%r10)
        jmp 13f
+.Lmemmove_end_forward:
+
        /*
         * Handle data backward by movsq.
         */
@@ -194,4 +203,22 @@ ENTRY(memmove)
 13:
        retq
        CFI_ENDPROC
+
+       .section .altinstr_replacement,"ax"
+.Lmemmove_begin_forward_efs:
+       /* Forward moving data. */
+       movq %rdx, %rcx
+       rep movsb
+       retq
+.Lmemmove_end_forward_efs:
+       .previous
+
+       .section .altinstructions,"a"
+       .align 8
+       .quad .Lmemmove_begin_forward
+       .quad .Lmemmove_begin_forward_efs
+       .word X86_FEATURE_ERMS
+       .byte .Lmemmove_end_forward-.Lmemmove_begin_forward
+       .byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
+       .previous
 ENDPROC(memmove)
index 09d3442696522e19aea8adb9efdbfd051d8d57aa..79bd454b78a36fa91498d71e57018e7c949223d5 100644 (file)
@@ -2,9 +2,13 @@
 
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
 
 /*
- * ISO C memset - set a memory block to a byte value.
+ * ISO C memset - set a memory block to a byte value. This function uses fast
+ * string to get better performance than the original function. The code is
+ * simpler and shorter than the orignal function as well.
  *     
  * rdi   destination
  * rsi   value (char) 
 .Lmemset_e:
        .previous
 
+/*
+ * ISO C memset - set a memory block to a byte value. This function uses
+ * enhanced rep stosb to override the fast string function.
+ * The code is simpler and shorter than the fast string function as well.
+ *
+ * rdi   destination
+ * rsi   value (char)
+ * rdx   count (bytes)
+ *
+ * rax   original destination
+ */
+       .section .altinstr_replacement, "ax", @progbits
+.Lmemset_c_e:
+       movq %rdi,%r9
+       movb %sil,%al
+       movl %edx,%ecx
+       rep stosb
+       movq %r9,%rax
+       ret
+.Lmemset_e_e:
+       .previous
+
 ENTRY(memset)
 ENTRY(__memset)
        CFI_STARTPROC
@@ -112,16 +138,20 @@ ENTRY(__memset)
 ENDPROC(memset)
 ENDPROC(__memset)
 
-       /* Some CPUs run faster using the string instructions.
-          It is also a lot simpler. Use this when possible */
-
-#include <asm/cpufeature.h>
-
+       /* Some CPUs support enhanced REP MOVSB/STOSB feature.
+        * It is recommended to use this when possible.
+        *
+        * If enhanced REP MOVSB/STOSB feature is not available, use fast string
+        * instructions.
+        *
+        * Otherwise, use original memset function.
+        *
+        * In .altinstructions section, ERMS feature is placed after REG_GOOD
+         * feature to implement the right patch order.
+        */
        .section .altinstructions,"a"
-       .align 8
-       .quad memset
-       .quad .Lmemset_c
-       .word X86_FEATURE_REP_GOOD
-       .byte .Lfinal - memset
-       .byte .Lmemset_e - .Lmemset_c
+       altinstruction_entry memset,.Lmemset_c,X86_FEATURE_REP_GOOD,\
+                            .Lfinal-memset,.Lmemset_e-.Lmemset_c
+       altinstruction_entry memset,.Lmemset_c_e,X86_FEATURE_ERMS, \
+                            .Lfinal-memset,.Lmemset_e_e-.Lmemset_c_e
        .previous
index 3e608edf99586608235fe366e10171b68a6a01fa..3d11327c9ab4630cd0aa687dcf7118bc3efb4d25 100644 (file)
@@ -23,8 +23,8 @@ mmiotrace-y                   := kmmio.o pf_in.o mmio-mod.o
 obj-$(CONFIG_MMIOTRACE_TEST)   += testmmiotrace.o
 
 obj-$(CONFIG_NUMA)             += numa.o numa_$(BITS).o
-obj-$(CONFIG_AMD_NUMA)         += amdtopology_64.o
-obj-$(CONFIG_ACPI_NUMA)                += srat_$(BITS).o
+obj-$(CONFIG_AMD_NUMA)         += amdtopology.o
+obj-$(CONFIG_ACPI_NUMA)                += srat.o
 obj-$(CONFIG_NUMA_EMU)         += numa_emulation.o
 
 obj-$(CONFIG_HAVE_MEMBLOCK)            += memblock.o
similarity index 90%
rename from arch/x86/mm/amdtopology_64.c
rename to arch/x86/mm/amdtopology.c
index 0919c26820d429e3d9660e0a1ec8852ae0910d27..5247d01329ca96de7e9eacbb3f2511ff8f9c3a59 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <linux/memblock.h>
+#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <linux/pci_ids.h>
@@ -69,10 +70,10 @@ static __init void early_get_boot_cpu_id(void)
 
 int __init amd_numa_init(void)
 {
-       unsigned long start = PFN_PHYS(0);
-       unsigned long end = PFN_PHYS(max_pfn);
+       u64 start = PFN_PHYS(0);
+       u64 end = PFN_PHYS(max_pfn);
        unsigned numnodes;
-       unsigned long prevbase;
+       u64 prevbase;
        int i, j, nb;
        u32 nodeid, reg;
        unsigned int bits, cores, apicid_base;
@@ -95,7 +96,7 @@ int __init amd_numa_init(void)
 
        prevbase = 0;
        for (i = 0; i < 8; i++) {
-               unsigned long base, limit;
+               u64 base, limit;
 
                base = read_pci_config(0, nb, 1, 0x40 + i*8);
                limit = read_pci_config(0, nb, 1, 0x44 + i*8);
@@ -107,18 +108,18 @@ int __init amd_numa_init(void)
                        continue;
                }
                if (nodeid >= numnodes) {
-                       pr_info("Ignoring excess node %d (%lx:%lx)\n", nodeid,
+                       pr_info("Ignoring excess node %d (%Lx:%Lx)\n", nodeid,
                                base, limit);
                        continue;
                }
 
                if (!limit) {
-                       pr_info("Skipping node entry %d (base %lx)\n",
+                       pr_info("Skipping node entry %d (base %Lx)\n",
                                i, base);
                        continue;
                }
                if ((base >> 8) & 3 || (limit >> 8) & 3) {
-                       pr_err("Node %d using interleaving mode %lx/%lx\n",
+                       pr_err("Node %d using interleaving mode %Lx/%Lx\n",
                               nodeid, (base >> 8) & 3, (limit >> 8) & 3);
                        return -EINVAL;
                }
@@ -150,19 +151,19 @@ int __init amd_numa_init(void)
                        continue;
                }
                if (limit < base) {
-                       pr_err("Node %d bogus settings %lx-%lx.\n",
+                       pr_err("Node %d bogus settings %Lx-%Lx.\n",
                               nodeid, base, limit);
                        continue;
                }
 
                /* Could sort here, but pun for now. Should not happen anyroads. */
                if (prevbase > base) {
-                       pr_err("Node map not sorted %lx,%lx\n",
+                       pr_err("Node map not sorted %Lx,%Lx\n",
                               prevbase, base);
                        return -EINVAL;
                }
 
-               pr_info("Node %d MemBase %016lx Limit %016lx\n",
+               pr_info("Node %d MemBase %016Lx Limit %016Lx\n",
                        nodeid, base, limit);
 
                prevbase = base;
index 286d289b039b876ef046565d29552827d76f243c..37b8b0fe8320952c89158d29a508568affbd8c8e 100644 (file)
@@ -81,6 +81,11 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
                end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
 }
 
+void __init native_pagetable_reserve(u64 start, u64 end)
+{
+       memblock_x86_reserve_range(start, end, "PGTABLE");
+}
+
 struct map_range {
        unsigned long start;
        unsigned long end;
@@ -272,9 +277,24 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
 
        __flush_tlb_all();
 
+       /*
+        * Reserve the kernel pagetable pages we used (pgt_buf_start -
+        * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top)
+        * so that they can be reused for other purposes.
+        *
+        * On native it just means calling memblock_x86_reserve_range, on Xen it
+        * also means marking RW the pagetable pages that we allocated before
+        * but that haven't been used.
+        *
+        * In fact on xen we mark RO the whole range pgt_buf_start -
+        * pgt_buf_top, because we have to make sure that when
+        * init_memory_mapping reaches the pagetable pages area, it maps
+        * RO all the pagetable pages, including the ones that are beyond
+        * pgt_buf_end at that time.
+        */
        if (!after_bootmem && pgt_buf_end > pgt_buf_start)
-               memblock_x86_reserve_range(pgt_buf_start << PAGE_SHIFT,
-                                pgt_buf_end << PAGE_SHIFT, "PGTABLE");
+               x86_init.mapping.pagetable_reserve(PFN_PHYS(pgt_buf_start),
+                               PFN_PHYS(pgt_buf_end));
 
        if (!after_bootmem)
                early_memtest(start, end);
index 80088f994193681f169c75f2757b7bfb723bc679..29f7c6d981790cea29114c1b20d7cb54904a702e 100644 (file)
@@ -678,8 +678,10 @@ static void __init zone_sizes_init(void)
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES];
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
        max_zone_pfns[ZONE_DMA] =
                virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+#endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 #ifdef CONFIG_HIGHMEM
        max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
@@ -716,6 +718,7 @@ void __init paging_init(void)
         * NOTE: at this point the bootmem allocator is fully available.
         */
        olpc_dt_build_devicetree();
+       sparse_memory_present_with_active_regions(MAX_NUMNODES);
        sparse_init();
        zone_sizes_init();
 }
index 7942335872874c35a213fd6a45c1af326eb7c01c..d865c4aeec55fb6c57638006c0a05e8fec30aed1 100644 (file)
@@ -616,7 +616,9 @@ void __init paging_init(void)
        unsigned long max_zone_pfns[MAX_NR_ZONES];
 
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
        max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+#endif
        max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
        max_zone_pfns[ZONE_NORMAL] = max_pfn;
 
@@ -679,14 +681,6 @@ int arch_add_memory(int nid, u64 start, u64 size)
 }
 EXPORT_SYMBOL_GPL(arch_add_memory);
 
-#if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA)
-int memory_add_physaddr_to_nid(u64 start)
-{
-       return 0;
-}
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-#endif
-
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
 static struct kcore_list kcore_vsyscall;
index 0369843511dc34292b6b0e944fc53bcab7396f8d..be1ef574ce9a7a933c22133be78f6a24bac6a80c 100644 (file)
@@ -90,13 +90,6 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        if (is_ISA_range(phys_addr, last_addr))
                return (__force void __iomem *)phys_to_virt(phys_addr);
 
-       /*
-        * Check if the request spans more than any BAR in the iomem resource
-        * tree.
-        */
-       WARN_ONCE(iomem_map_sanity_check(phys_addr, size),
-                 KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
-
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
@@ -170,6 +163,13 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        ret_addr = (void __iomem *) (vaddr + offset);
        mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
 
+       /*
+        * Check if the request spans more than any BAR in the iomem resource
+        * tree.
+        */
+       WARN_ONCE(iomem_map_sanity_check(unaligned_phys_addr, unaligned_size),
+                 KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
+
        return ret_addr;
 err_free_area:
        free_vm_area(area);
index 9559d360fde79b8373d042fb48e24c98b836684d..f5510d889a226d4d38bbf529330fcc829beb8e51 100644 (file)
@@ -1,11 +1,39 @@
 /* Common code for 32 and 64-bit NUMA */
-#include <linux/topology.h>
-#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/init.h>
 #include <linux/bootmem.h>
-#include <asm/numa.h>
+#include <linux/memblock.h>
+#include <linux/mmzone.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+#include <linux/topology.h>
+
+#include <asm/e820.h>
+#include <asm/proto.h>
+#include <asm/dma.h>
 #include <asm/acpi.h>
+#include <asm/amd_nb.h>
+
+#include "numa_internal.h"
 
 int __initdata numa_off;
+nodemask_t numa_nodes_parsed __initdata;
+
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_data);
+
+static struct numa_meminfo numa_meminfo
+#ifndef CONFIG_MEMORY_HOTPLUG
+__initdata
+#endif
+;
+
+static int numa_distance_cnt;
+static u8 *numa_distance;
 
 static __init int numa_setup(char *opt)
 {
@@ -32,6 +60,15 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
        [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
 };
 
+int __cpuinit numa_cpu_node(int cpu)
+{
+       int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
+
+       if (apicid != BAD_APICID)
+               return __apicid_to_node[apicid];
+       return NUMA_NO_NODE;
+}
+
 cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 EXPORT_SYMBOL(node_to_cpumask_map);
 
@@ -95,6 +132,407 @@ void __init setup_node_to_cpumask_map(void)
        pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
 }
 
+static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
+                                    struct numa_meminfo *mi)
+{
+       /* ignore zero length blks */
+       if (start == end)
+               return 0;
+
+       /* whine about and ignore invalid blks */
+       if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
+               pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
+                          nid, start, end);
+               return 0;
+       }
+
+       if (mi->nr_blks >= NR_NODE_MEMBLKS) {
+               pr_err("NUMA: too many memblk ranges\n");
+               return -EINVAL;
+       }
+
+       mi->blk[mi->nr_blks].start = start;
+       mi->blk[mi->nr_blks].end = end;
+       mi->blk[mi->nr_blks].nid = nid;
+       mi->nr_blks++;
+       return 0;
+}
+
+/**
+ * numa_remove_memblk_from - Remove one numa_memblk from a numa_meminfo
+ * @idx: Index of memblk to remove
+ * @mi: numa_meminfo to remove memblk from
+ *
+ * Remove @idx'th numa_memblk from @mi by shifting @mi->blk[] and
+ * decrementing @mi->nr_blks.
+ */
+void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
+{
+       mi->nr_blks--;
+       memmove(&mi->blk[idx], &mi->blk[idx + 1],
+               (mi->nr_blks - idx) * sizeof(mi->blk[0]));
+}
+
+/**
+ * numa_add_memblk - Add one numa_memblk to numa_meminfo
+ * @nid: NUMA node ID of the new memblk
+ * @start: Start address of the new memblk
+ * @end: End address of the new memblk
+ *
+ * Add a new memblk to the default numa_meminfo.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init numa_add_memblk(int nid, u64 start, u64 end)
+{
+       return numa_add_memblk_to(nid, start, end, &numa_meminfo);
+}
+
+/* Initialize NODE_DATA for a node on the local memory */
+static void __init setup_node_data(int nid, u64 start, u64 end)
+{
+       const u64 nd_low = PFN_PHYS(MAX_DMA_PFN);
+       const u64 nd_high = PFN_PHYS(max_pfn_mapped);
+       const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
+       bool remapped = false;
+       u64 nd_pa;
+       void *nd;
+       int tnid;
+
+       /*
+        * Don't confuse VM with a node that doesn't have the
+        * minimum amount of memory:
+        */
+       if (end && (end - start) < NODE_MIN_SIZE)
+               return;
+
+       /* initialize remap allocator before aligning to ZONE_ALIGN */
+       init_alloc_remap(nid, start, end);
+
+       start = roundup(start, ZONE_ALIGN);
+
+       printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n",
+              nid, start, end);
+
+       /*
+        * Allocate node data.  Try remap allocator first, node-local
+        * memory and then any node.  Never allocate in DMA zone.
+        */
+       nd = alloc_remap(nid, nd_size);
+       if (nd) {
+               nd_pa = __pa(nd);
+               remapped = true;
+       } else {
+               nd_pa = memblock_x86_find_in_range_node(nid, nd_low, nd_high,
+                                               nd_size, SMP_CACHE_BYTES);
+               if (nd_pa == MEMBLOCK_ERROR)
+                       nd_pa = memblock_find_in_range(nd_low, nd_high,
+                                               nd_size, SMP_CACHE_BYTES);
+               if (nd_pa == MEMBLOCK_ERROR) {
+                       pr_err("Cannot find %zu bytes in node %d\n",
+                              nd_size, nid);
+                       return;
+               }
+               memblock_x86_reserve_range(nd_pa, nd_pa + nd_size, "NODE_DATA");
+               nd = __va(nd_pa);
+       }
+
+       /* report and initialize */
+       printk(KERN_INFO "  NODE_DATA [%016Lx - %016Lx]%s\n",
+              nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : "");
+       tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
+       if (!remapped && tnid != nid)
+               printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nid, tnid);
+
+       node_data[nid] = nd;
+       memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
+       NODE_DATA(nid)->node_id = nid;
+       NODE_DATA(nid)->node_start_pfn = start >> PAGE_SHIFT;
+       NODE_DATA(nid)->node_spanned_pages = (end - start) >> PAGE_SHIFT;
+
+       node_set_online(nid);
+}
+
+/**
+ * numa_cleanup_meminfo - Cleanup a numa_meminfo
+ * @mi: numa_meminfo to clean up
+ *
+ * Sanitize @mi by merging and removing unncessary memblks.  Also check for
+ * conflicts and clear unused memblks.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
+{
+       const u64 low = 0;
+       const u64 high = PFN_PHYS(max_pfn);
+       int i, j, k;
+
+       /* first, trim all entries */
+       for (i = 0; i < mi->nr_blks; i++) {
+               struct numa_memblk *bi = &mi->blk[i];
+
+               /* make sure all blocks are inside the limits */
+               bi->start = max(bi->start, low);
+               bi->end = min(bi->end, high);
+
+               /* and there's no empty block */
+               if (bi->start >= bi->end)
+                       numa_remove_memblk_from(i--, mi);
+       }
+
+       /* merge neighboring / overlapping entries */
+       for (i = 0; i < mi->nr_blks; i++) {
+               struct numa_memblk *bi = &mi->blk[i];
+
+               for (j = i + 1; j < mi->nr_blks; j++) {
+                       struct numa_memblk *bj = &mi->blk[j];
+                       u64 start, end;
+
+                       /*
+                        * See whether there are overlapping blocks.  Whine
+                        * about but allow overlaps of the same nid.  They
+                        * will be merged below.
+                        */
+                       if (bi->end > bj->start && bi->start < bj->end) {
+                               if (bi->nid != bj->nid) {
+                                       pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
+                                              bi->nid, bi->start, bi->end,
+                                              bj->nid, bj->start, bj->end);
+                                       return -EINVAL;
+                               }
+                               pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
+                                          bi->nid, bi->start, bi->end,
+                                          bj->start, bj->end);
+                       }
+
+                       /*
+                        * Join together blocks on the same node, holes
+                        * between which don't overlap with memory on other
+                        * nodes.
+                        */
+                       if (bi->nid != bj->nid)
+                               continue;
+                       start = min(bi->start, bj->start);
+                       end = max(bi->end, bj->end);
+                       for (k = 0; k < mi->nr_blks; k++) {
+                               struct numa_memblk *bk = &mi->blk[k];
+
+                               if (bi->nid == bk->nid)
+                                       continue;
+                               if (start < bk->end && end > bk->start)
+                                       break;
+                       }
+                       if (k < mi->nr_blks)
+                               continue;
+                       printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%Lx,%Lx)\n",
+                              bi->nid, bi->start, bi->end, bj->start, bj->end,
+                              start, end);
+                       bi->start = start;
+                       bi->end = end;
+                       numa_remove_memblk_from(j--, mi);
+               }
+       }
+
+       /* clear unused ones */
+       for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) {
+               mi->blk[i].start = mi->blk[i].end = 0;
+               mi->blk[i].nid = NUMA_NO_NODE;
+       }
+
+       return 0;
+}
+
+/*
+ * Set nodes, which have memory in @mi, in *@nodemask.
+ */
+static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
+                                             const struct numa_meminfo *mi)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mi->blk); i++)
+               if (mi->blk[i].start != mi->blk[i].end &&
+                   mi->blk[i].nid != NUMA_NO_NODE)
+                       node_set(mi->blk[i].nid, *nodemask);
+}
+
+/**
+ * numa_reset_distance - Reset NUMA distance table
+ *
+ * The current table is freed.  The next numa_set_distance() call will
+ * create a new one.
+ */
+void __init numa_reset_distance(void)
+{
+       size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]);
+
+       /* numa_distance could be 1LU marking allocation failure, test cnt */
+       if (numa_distance_cnt)
+               memblock_x86_free_range(__pa(numa_distance),
+                                       __pa(numa_distance) + size);
+       numa_distance_cnt = 0;
+       numa_distance = NULL;   /* enable table creation */
+}
+
+static int __init numa_alloc_distance(void)
+{
+       nodemask_t nodes_parsed;
+       size_t size;
+       int i, j, cnt = 0;
+       u64 phys;
+
+       /* size the new table and allocate it */
+       nodes_parsed = numa_nodes_parsed;
+       numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo);
+
+       for_each_node_mask(i, nodes_parsed)
+               cnt = i;
+       cnt++;
+       size = cnt * cnt * sizeof(numa_distance[0]);
+
+       phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
+                                     size, PAGE_SIZE);
+       if (phys == MEMBLOCK_ERROR) {
+               pr_warning("NUMA: Warning: can't allocate distance table!\n");
+               /* don't retry until explicitly reset */
+               numa_distance = (void *)1LU;
+               return -ENOMEM;
+       }
+       memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
+
+       numa_distance = __va(phys);
+       numa_distance_cnt = cnt;
+
+       /* fill with the default distances */
+       for (i = 0; i < cnt; i++)
+               for (j = 0; j < cnt; j++)
+                       numa_distance[i * cnt + j] = i == j ?
+                               LOCAL_DISTANCE : REMOTE_DISTANCE;
+       printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt);
+
+       return 0;
+}
+
+/**
+ * numa_set_distance - Set NUMA distance from one NUMA to another
+ * @from: the 'from' node to set distance
+ * @to: the 'to'  node to set distance
+ * @distance: NUMA distance
+ *
+ * Set the distance from node @from to @to to @distance.  If distance table
+ * doesn't exist, one which is large enough to accommodate all the currently
+ * known nodes will be created.
+ *
+ * If such table cannot be allocated, a warning is printed and further
+ * calls are ignored until the distance table is reset with
+ * numa_reset_distance().
+ *
+ * If @from or @to is higher than the highest known node at the time of
+ * table creation or @distance doesn't make sense, the call is ignored.
+ * This is to allow simplification of specific NUMA config implementations.
+ */
+void __init numa_set_distance(int from, int to, int distance)
+{
+       if (!numa_distance && numa_alloc_distance() < 0)
+               return;
+
+       if (from >= numa_distance_cnt || to >= numa_distance_cnt) {
+               printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n",
+                           from, to, distance);
+               return;
+       }
+
+       if ((u8)distance != distance ||
+           (from == to && distance != LOCAL_DISTANCE)) {
+               pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
+                            from, to, distance);
+               return;
+       }
+
+       numa_distance[from * numa_distance_cnt + to] = distance;
+}
+
+int __node_distance(int from, int to)
+{
+       if (from >= numa_distance_cnt || to >= numa_distance_cnt)
+               return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+       return numa_distance[from * numa_distance_cnt + to];
+}
+EXPORT_SYMBOL(__node_distance);
+
+/*
+ * Sanity check to catch more bad NUMA configurations (they are amazingly
+ * common).  Make sure the nodes cover all memory.
+ */
+static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
+{
+       u64 numaram, e820ram;
+       int i;
+
+       numaram = 0;
+       for (i = 0; i < mi->nr_blks; i++) {
+               u64 s = mi->blk[i].start >> PAGE_SHIFT;
+               u64 e = mi->blk[i].end >> PAGE_SHIFT;
+               numaram += e - s;
+               numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
+               if ((s64)numaram < 0)
+                       numaram = 0;
+       }
+
+       e820ram = max_pfn - (memblock_x86_hole_size(0,
+                                       PFN_PHYS(max_pfn)) >> PAGE_SHIFT);
+       /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+       if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
+               printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n",
+                      (numaram << PAGE_SHIFT) >> 20,
+                      (e820ram << PAGE_SHIFT) >> 20);
+               return false;
+       }
+       return true;
+}
+
+static int __init numa_register_memblks(struct numa_meminfo *mi)
+{
+       int i, nid;
+
+       /* Account for nodes with cpus and no memory */
+       node_possible_map = numa_nodes_parsed;
+       numa_nodemask_from_meminfo(&node_possible_map, mi);
+       if (WARN_ON(nodes_empty(node_possible_map)))
+               return -EINVAL;
+
+       for (i = 0; i < mi->nr_blks; i++)
+               memblock_x86_register_active_regions(mi->blk[i].nid,
+                                       mi->blk[i].start >> PAGE_SHIFT,
+                                       mi->blk[i].end >> PAGE_SHIFT);
+
+       /* for out of order entries */
+       sort_node_map();
+       if (!numa_meminfo_cover_memory(mi))
+               return -EINVAL;
+
+       /* Finally register nodes. */
+       for_each_node_mask(nid, node_possible_map) {
+               u64 start = PFN_PHYS(max_pfn);
+               u64 end = 0;
+
+               for (i = 0; i < mi->nr_blks; i++) {
+                       if (nid != mi->blk[i].nid)
+                               continue;
+                       start = min(mi->blk[i].start, start);
+                       end = max(mi->blk[i].end, end);
+               }
+
+               if (start < end)
+                       setup_node_data(nid, start, end);
+       }
+
+       return 0;
+}
+
 /*
  * There are unfortunately some poorly designed mainboards around that
  * only connect memory to a single CPU. This breaks the 1:1 cpu->node
@@ -102,7 +540,7 @@ void __init setup_node_to_cpumask_map(void)
  * as the number of CPUs is not known yet. We round robin the existing
  * nodes.
  */
-void __init numa_init_array(void)
+static void __init numa_init_array(void)
 {
        int rr, i;
 
@@ -117,6 +555,95 @@ void __init numa_init_array(void)
        }
 }
 
+static int __init numa_init(int (*init_func)(void))
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < MAX_LOCAL_APIC; i++)
+               set_apicid_to_node(i, NUMA_NO_NODE);
+
+       nodes_clear(numa_nodes_parsed);
+       nodes_clear(node_possible_map);
+       nodes_clear(node_online_map);
+       memset(&numa_meminfo, 0, sizeof(numa_meminfo));
+       remove_all_active_ranges();
+       numa_reset_distance();
+
+       ret = init_func();
+       if (ret < 0)
+               return ret;
+       ret = numa_cleanup_meminfo(&numa_meminfo);
+       if (ret < 0)
+               return ret;
+
+       numa_emulation(&numa_meminfo, numa_distance_cnt);
+
+       ret = numa_register_memblks(&numa_meminfo);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < nr_cpu_ids; i++) {
+               int nid = early_cpu_to_node(i);
+
+               if (nid == NUMA_NO_NODE)
+                       continue;
+               if (!node_online(nid))
+                       numa_clear_node(i);
+       }
+       numa_init_array();
+       return 0;
+}
+
+/**
+ * dummy_numa_init - Fallback dummy NUMA init
+ *
+ * Used if there's no underlying NUMA architecture, NUMA initialization
+ * fails, or NUMA is disabled on the command line.
+ *
+ * Must online at least one node and add memory blocks that cover all
+ * allowed memory.  This function must not fail.
+ */
+static int __init dummy_numa_init(void)
+{
+       printk(KERN_INFO "%s\n",
+              numa_off ? "NUMA turned off" : "No NUMA configuration found");
+       printk(KERN_INFO "Faking a node at %016Lx-%016Lx\n",
+              0LLU, PFN_PHYS(max_pfn));
+
+       node_set(0, numa_nodes_parsed);
+       numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
+
+       return 0;
+}
+
+/**
+ * x86_numa_init - Initialize NUMA
+ *
+ * Try each configured NUMA initialization method until one succeeds.  The
+ * last fallback is dummy single node config encomapssing whole memory and
+ * never fails.
+ */
+void __init x86_numa_init(void)
+{
+       if (!numa_off) {
+#ifdef CONFIG_X86_NUMAQ
+               if (!numa_init(numaq_numa_init))
+                       return;
+#endif
+#ifdef CONFIG_ACPI_NUMA
+               if (!numa_init(x86_acpi_numa_init))
+                       return;
+#endif
+#ifdef CONFIG_AMD_NUMA
+               if (!numa_init(amd_numa_init))
+                       return;
+#endif
+       }
+
+       numa_init(dummy_numa_init);
+}
+
 static __init int find_near_online_node(int node)
 {
        int n, val;
@@ -213,53 +740,48 @@ int early_cpu_to_node(int cpu)
        return per_cpu(x86_cpu_to_node_map, cpu);
 }
 
-struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable)
+void debug_cpumask_set_cpu(int cpu, int node, bool enable)
 {
-       int node = early_cpu_to_node(cpu);
        struct cpumask *mask;
        char buf[64];
 
        if (node == NUMA_NO_NODE) {
                /* early_cpu_to_node() already emits a warning and trace */
-               return NULL;
+               return;
        }
        mask = node_to_cpumask_map[node];
        if (!mask) {
                pr_err("node_to_cpumask_map[%i] NULL\n", node);
                dump_stack();
-               return NULL;
+               return;
        }
 
+       if (enable)
+               cpumask_set_cpu(cpu, mask);
+       else
+               cpumask_clear_cpu(cpu, mask);
+
        cpulist_scnprintf(buf, sizeof(buf), mask);
        printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
                enable ? "numa_add_cpu" : "numa_remove_cpu",
                cpu, node, buf);
-       return mask;
+       return;
 }
 
 # ifndef CONFIG_NUMA_EMU
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
+static void __cpuinit numa_set_cpumask(int cpu, bool enable)
 {
-       struct cpumask *mask;
-
-       mask = debug_cpumask_set_cpu(cpu, enable);
-       if (!mask)
-               return;
-
-       if (enable)
-               cpumask_set_cpu(cpu, mask);
-       else
-               cpumask_clear_cpu(cpu, mask);
+       debug_cpumask_set_cpu(cpu, early_cpu_to_node(cpu), enable);
 }
 
 void __cpuinit numa_add_cpu(int cpu)
 {
-       numa_set_cpumask(cpu, 1);
+       numa_set_cpumask(cpu, true);
 }
 
 void __cpuinit numa_remove_cpu(int cpu)
 {
-       numa_set_cpumask(cpu, 0);
+       numa_set_cpumask(cpu, false);
 }
 # endif        /* !CONFIG_NUMA_EMU */
 
@@ -287,3 +809,18 @@ const struct cpumask *cpumask_of_node(int node)
 EXPORT_SYMBOL(cpumask_of_node);
 
 #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int memory_add_physaddr_to_nid(u64 start)
+{
+       struct numa_meminfo *mi = &numa_meminfo;
+       int nid = mi->blk[0].nid;
+       int i;
+
+       for (i = 0; i < mi->nr_blks; i++)
+               if (mi->blk[i].start <= start && mi->blk[i].end > start)
+                       nid = mi->blk[i].nid;
+       return nid;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
index bde3906420df74559bd49a52aad171216be52108..849a975d3fa07231f98a247b847f5a482954b72a 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
-#include <linux/mmzone.h>
-#include <linux/highmem.h>
-#include <linux/initrd.h>
-#include <linux/nodemask.h>
 #include <linux/module.h>
-#include <linux/kexec.h>
-#include <linux/pfn.h>
-#include <linux/swap.h>
-#include <linux/acpi.h>
-
-#include <asm/e820.h>
-#include <asm/setup.h>
-#include <asm/mmzone.h>
-#include <asm/bios_ebda.h>
-#include <asm/proto.h>
-
-struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
-EXPORT_SYMBOL(node_data);
-
-/*
- * numa interface - we expect the numa architecture specific code to have
- *                  populated the following initialisation.
- *
- * 1) node_online_map  - the map of all nodes configured (online) in the system
- * 2) node_start_pfn   - the starting page frame number for a node
- * 3) node_end_pfn     - the ending page fram number for a node
- */
-unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
-unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
 
+#include "numa_internal.h"
 
 #ifdef CONFIG_DISCONTIGMEM
 /*
@@ -99,108 +71,46 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
 }
 #endif
 
-extern unsigned long find_max_low_pfn(void);
 extern unsigned long highend_pfn, highstart_pfn;
 
 #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
 
-unsigned long node_remap_size[MAX_NUMNODES];
 static void *node_remap_start_vaddr[MAX_NUMNODES];
 void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
 
-static unsigned long kva_start_pfn;
-static unsigned long kva_pages;
-
-int __cpuinit numa_cpu_node(int cpu)
-{
-       return apic->x86_32_numa_cpu_node(cpu);
-}
-
-/*
- * FLAT - support for basic PC memory model with discontig enabled, essentially
- *        a single node with all available processors in it with a flat
- *        memory map.
- */
-int __init get_memcfg_numa_flat(void)
-{
-       printk(KERN_DEBUG "NUMA - single node, flat memory mode\n");
-
-       node_start_pfn[0] = 0;
-       node_end_pfn[0] = max_pfn;
-       memblock_x86_register_active_regions(0, 0, max_pfn);
-       memory_present(0, 0, max_pfn);
-       node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
-
-        /* Indicate there is one node available. */
-       nodes_clear(node_online_map);
-       node_set_online(0);
-       return 1;
-}
-
-/*
- * Find the highest page frame number we have available for the node
- */
-static void __init propagate_e820_map_node(int nid)
-{
-       if (node_end_pfn[nid] > max_pfn)
-               node_end_pfn[nid] = max_pfn;
-       /*
-        * if a user has given mem=XXXX, then we need to make sure 
-        * that the node _starts_ before that, too, not just ends
-        */
-       if (node_start_pfn[nid] > max_pfn)
-               node_start_pfn[nid] = max_pfn;
-       BUG_ON(node_start_pfn[nid] > node_end_pfn[nid]);
-}
-
-/* 
- * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
- * method.  For node zero take this from the bottom of memory, for
- * subsequent nodes place them at node_remap_start_vaddr which contains
- * node local data in physically node local memory.  See setup_memory()
- * for details.
- */
-static void __init allocate_pgdat(int nid)
-{
-       char buf[16];
-
-       if (node_has_online_mem(nid) && node_remap_start_vaddr[nid])
-               NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
-       else {
-               unsigned long pgdat_phys;
-               pgdat_phys = memblock_find_in_range(min_low_pfn<<PAGE_SHIFT,
-                                max_pfn_mapped<<PAGE_SHIFT,
-                                sizeof(pg_data_t),
-                                PAGE_SIZE);
-               NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
-               memset(buf, 0, sizeof(buf));
-               sprintf(buf, "NODE_DATA %d",  nid);
-               memblock_x86_reserve_range(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
-       }
-       printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
-               nid, (unsigned long)NODE_DATA(nid));
-}
-
 /*
- * In the DISCONTIGMEM and SPARSEMEM memory model, a portion of the kernel
- * virtual address space (KVA) is reserved and portions of nodes are mapped
- * using it. This is to allow node-local memory to be allocated for
- * structures that would normally require ZONE_NORMAL. The memory is
- * allocated with alloc_remap() and callers should be prepared to allocate
- * from the bootmem allocator instead.
+ * Remap memory allocator
  */
 static unsigned long node_remap_start_pfn[MAX_NUMNODES];
 static void *node_remap_end_vaddr[MAX_NUMNODES];
 static void *node_remap_alloc_vaddr[MAX_NUMNODES];
-static unsigned long node_remap_offset[MAX_NUMNODES];
 
+/**
+ * alloc_remap - Allocate remapped memory
+ * @nid: NUMA node to allocate memory from
+ * @size: The size of allocation
+ *
+ * Allocate @size bytes from the remap area of NUMA node @nid.  The
+ * size of the remap area is predetermined by init_alloc_remap() and
+ * only the callers considered there should call this function.  For
+ * more info, please read the comment on top of init_alloc_remap().
+ *
+ * The caller must be ready to handle allocation failure from this
+ * function and fall back to regular memory allocator in such cases.
+ *
+ * CONTEXT:
+ * Single CPU early boot context.
+ *
+ * RETURNS:
+ * Pointer to the allocated memory on success, %NULL on failure.
+ */
 void *alloc_remap(int nid, unsigned long size)
 {
        void *allocation = node_remap_alloc_vaddr[nid];
 
        size = ALIGN(size, L1_CACHE_BYTES);
 
-       if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
+       if (!allocation || (allocation + size) > node_remap_end_vaddr[nid])
                return NULL;
 
        node_remap_alloc_vaddr[nid] += size;
@@ -209,26 +119,6 @@ void *alloc_remap(int nid, unsigned long size)
        return allocation;
 }
 
-static void __init remap_numa_kva(void)
-{
-       void *vaddr;
-       unsigned long pfn;
-       int node;
-
-       for_each_online_node(node) {
-               printk(KERN_DEBUG "remap_numa_kva: node %d\n", node);
-               for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
-                       vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
-                       printk(KERN_DEBUG "remap_numa_kva: %08lx to pfn %08lx\n",
-                               (unsigned long)vaddr,
-                               node_remap_start_pfn[node] + pfn);
-                       set_pmd_pfn((ulong) vaddr, 
-                               node_remap_start_pfn[node] + pfn, 
-                               PAGE_KERNEL_LARGE);
-               }
-       }
-}
-
 #ifdef CONFIG_HIBERNATION
 /**
  * resume_map_numa_kva - add KVA mapping to the temporary page tables created
@@ -240,15 +130,16 @@ void resume_map_numa_kva(pgd_t *pgd_base)
        int node;
 
        for_each_online_node(node) {
-               unsigned long start_va, start_pfn, size, pfn;
+               unsigned long start_va, start_pfn, nr_pages, pfn;
 
                start_va = (unsigned long)node_remap_start_vaddr[node];
                start_pfn = node_remap_start_pfn[node];
-               size = node_remap_size[node];
+               nr_pages = (node_remap_end_vaddr[node] -
+                           node_remap_start_vaddr[node]) >> PAGE_SHIFT;
 
                printk(KERN_DEBUG "%s: node %d\n", __func__, node);
 
-               for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) {
+               for (pfn = 0; pfn < nr_pages; pfn += PTRS_PER_PTE) {
                        unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
                        pgd_t *pgd = pgd_base + pgd_index(vaddr);
                        pud_t *pud = pud_offset(pgd, vaddr);
@@ -264,132 +155,89 @@ void resume_map_numa_kva(pgd_t *pgd_base)
 }
 #endif
 
-static __init unsigned long calculate_numa_remap_pages(void)
+/**
+ * init_alloc_remap - Initialize remap allocator for a NUMA node
+ * @nid: NUMA node to initizlie remap allocator for
+ *
+ * NUMA nodes may end up without any lowmem.  As allocating pgdat and
+ * memmap on a different node with lowmem is inefficient, a special
+ * remap allocator is implemented which can be used by alloc_remap().
+ *
+ * For each node, the amount of memory which will be necessary for
+ * pgdat and memmap is calculated and two memory areas of the size are
+ * allocated - one in the node and the other in lowmem; then, the area
+ * in the node is remapped to the lowmem area.
+ *
+ * As pgdat and memmap must be allocated in lowmem anyway, this
+ * doesn't waste lowmem address space; however, the actual lowmem
+ * which gets remapped over is wasted.  The amount shouldn't be
+ * problematic on machines this feature will be used.
+ *
+ * Initialization failure isn't fatal.  alloc_remap() is used
+ * opportunistically and the callers will fall back to other memory
+ * allocation mechanisms on failure.
+ */
+void __init init_alloc_remap(int nid, u64 start, u64 end)
 {
-       int nid;
-       unsigned long size, reserve_pages = 0;
-
-       for_each_online_node(nid) {
-               u64 node_kva_target;
-               u64 node_kva_final;
-
-               /*
-                * The acpi/srat node info can show hot-add memroy zones
-                * where memory could be added but not currently present.
-                */
-               printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
-                       nid, node_start_pfn[nid], node_end_pfn[nid]);
-               if (node_start_pfn[nid] > max_pfn)
-                       continue;
-               if (!node_end_pfn[nid])
-                       continue;
-               if (node_end_pfn[nid] > max_pfn)
-                       node_end_pfn[nid] = max_pfn;
-
-               /* ensure the remap includes space for the pgdat. */
-               size = node_remap_size[nid] + sizeof(pg_data_t);
-
-               /* convert size to large (pmd size) pages, rounding up */
-               size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
-               /* now the roundup is correct, convert to PAGE_SIZE pages */
-               size = size * PTRS_PER_PTE;
-
-               node_kva_target = round_down(node_end_pfn[nid] - size,
-                                                PTRS_PER_PTE);
-               node_kva_target <<= PAGE_SHIFT;
-               do {
-                       node_kva_final = memblock_find_in_range(node_kva_target,
-                                       ((u64)node_end_pfn[nid])<<PAGE_SHIFT,
-                                               ((u64)size)<<PAGE_SHIFT,
-                                               LARGE_PAGE_BYTES);
-                       node_kva_target -= LARGE_PAGE_BYTES;
-               } while (node_kva_final == MEMBLOCK_ERROR &&
-                        (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
-
-               if (node_kva_final == MEMBLOCK_ERROR)
-                       panic("Can not get kva ram\n");
-
-               node_remap_size[nid] = size;
-               node_remap_offset[nid] = reserve_pages;
-               reserve_pages += size;
-               printk(KERN_DEBUG "Reserving %ld pages of KVA for lmem_map of"
-                                 " node %d at %llx\n",
-                               size, nid, node_kva_final>>PAGE_SHIFT);
-
-               /*
-                *  prevent kva address below max_low_pfn want it on system
-                *  with less memory later.
-                *  layout will be: KVA address , KVA RAM
-                *
-                *  we are supposed to only record the one less then max_low_pfn
-                *  but we could have some hole in high memory, and it will only
-                *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
-                *  to use it as free.
-                *  So memblock_x86_reserve_range here, hope we don't run out of that array
-                */
-               memblock_x86_reserve_range(node_kva_final,
-                             node_kva_final+(((u64)size)<<PAGE_SHIFT),
-                             "KVA RAM");
-
-               node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
-       }
-       printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
-                       reserve_pages);
-       return reserve_pages;
-}
+       unsigned long start_pfn = start >> PAGE_SHIFT;
+       unsigned long end_pfn = end >> PAGE_SHIFT;
+       unsigned long size, pfn;
+       u64 node_pa, remap_pa;
+       void *remap_va;
 
-static void init_remap_allocator(int nid)
-{
-       node_remap_start_vaddr[nid] = pfn_to_kaddr(
-                       kva_start_pfn + node_remap_offset[nid]);
-       node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
-               (node_remap_size[nid] * PAGE_SIZE);
-       node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
-               ALIGN(sizeof(pg_data_t), PAGE_SIZE);
-
-       printk(KERN_DEBUG "node %d will remap to vaddr %08lx - %08lx\n", nid,
-               (ulong) node_remap_start_vaddr[nid],
-               (ulong) node_remap_end_vaddr[nid]);
+       /*
+        * The acpi/srat node info can show hot-add memroy zones where
+        * memory could be added but not currently present.
+        */
+       printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
+              nid, start_pfn, end_pfn);
+
+       /* calculate the necessary space aligned to large page size */
+       size = node_memmap_size_bytes(nid, start_pfn, end_pfn);
+       size += ALIGN(sizeof(pg_data_t), PAGE_SIZE);
+       size = ALIGN(size, LARGE_PAGE_BYTES);
+
+       /* allocate node memory and the lowmem remap area */
+       node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES);
+       if (node_pa == MEMBLOCK_ERROR) {
+               pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n",
+                          size, nid);
+               return;
+       }
+       memblock_x86_reserve_range(node_pa, node_pa + size, "KVA RAM");
+
+       remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT,
+                                         max_low_pfn << PAGE_SHIFT,
+                                         size, LARGE_PAGE_BYTES);
+       if (remap_pa == MEMBLOCK_ERROR) {
+               pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n",
+                          size, nid);
+               memblock_x86_free_range(node_pa, node_pa + size);
+               return;
+       }
+       memblock_x86_reserve_range(remap_pa, remap_pa + size, "KVA PG");
+       remap_va = phys_to_virt(remap_pa);
+
+       /* perform actual remap */
+       for (pfn = 0; pfn < size >> PAGE_SHIFT; pfn += PTRS_PER_PTE)
+               set_pmd_pfn((unsigned long)remap_va + (pfn << PAGE_SHIFT),
+                           (node_pa >> PAGE_SHIFT) + pfn,
+                           PAGE_KERNEL_LARGE);
+
+       /* initialize remap allocator parameters */
+       node_remap_start_pfn[nid] = node_pa >> PAGE_SHIFT;
+       node_remap_start_vaddr[nid] = remap_va;
+       node_remap_end_vaddr[nid] = remap_va + size;
+       node_remap_alloc_vaddr[nid] = remap_va;
+
+       printk(KERN_DEBUG "remap_alloc: node %d [%08llx-%08llx) -> [%p-%p)\n",
+              nid, node_pa, node_pa + size, remap_va, remap_va + size);
 }
 
 void __init initmem_init(void)
 {
-       int nid;
-       long kva_target_pfn;
-
-       /*
-        * When mapping a NUMA machine we allocate the node_mem_map arrays
-        * from node local memory.  They are then mapped directly into KVA
-        * between zone normal and vmalloc space.  Calculate the size of
-        * this space and use it to adjust the boundary between ZONE_NORMAL
-        * and ZONE_HIGHMEM.
-        */
-
-       get_memcfg_numa();
-       numa_init_array();
-
-       kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
+       x86_numa_init();
 
-       kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
-       do {
-               kva_start_pfn = memblock_find_in_range(kva_target_pfn<<PAGE_SHIFT,
-                                       max_low_pfn<<PAGE_SHIFT,
-                                       kva_pages<<PAGE_SHIFT,
-                                       PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
-               kva_target_pfn -= PTRS_PER_PTE;
-       } while (kva_start_pfn == MEMBLOCK_ERROR && kva_target_pfn > min_low_pfn);
-
-       if (kva_start_pfn == MEMBLOCK_ERROR)
-               panic("Can not get kva space\n");
-
-       printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
-               kva_start_pfn, max_low_pfn);
-       printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
-
-       /* avoid clash with initrd */
-       memblock_x86_reserve_range(kva_start_pfn<<PAGE_SHIFT,
-                     (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
-                    "KVA PG");
 #ifdef CONFIG_HIGHMEM
        highstart_pfn = highend_pfn = max_pfn;
        if (max_pfn > max_low_pfn)
@@ -409,51 +257,9 @@ void __init initmem_init(void)
 
        printk(KERN_DEBUG "Low memory ends at vaddr %08lx\n",
                        (ulong) pfn_to_kaddr(max_low_pfn));
-       for_each_online_node(nid) {
-               init_remap_allocator(nid);
-
-               allocate_pgdat(nid);
-       }
-       remap_numa_kva();
 
        printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
                        (ulong) pfn_to_kaddr(highstart_pfn));
-       for_each_online_node(nid)
-               propagate_e820_map_node(nid);
-
-       for_each_online_node(nid) {
-               memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
-               NODE_DATA(nid)->node_id = nid;
-       }
 
        setup_bootmem_allocator();
 }
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static int paddr_to_nid(u64 addr)
-{
-       int nid;
-       unsigned long pfn = PFN_DOWN(addr);
-
-       for_each_node(nid)
-               if (node_start_pfn[nid] <= pfn &&
-                   pfn < node_end_pfn[nid])
-                       return nid;
-
-       return -1;
-}
-
-/*
- * This function is used to ask node id BEFORE memmap and mem_section's
- * initialization (pfn_to_nid() can't be used yet).
- * If _PXM is not defined on ACPI's DSDT, node id must be found by this.
- */
-int memory_add_physaddr_to_nid(u64 addr)
-{
-       int nid = paddr_to_nid(addr);
-       return (nid >= 0) ? nid : 0;
-}
-
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-#endif
-
index e8c00cc72033cbf4ee5e4f44a3a59a10386596fe..dd27f401f0a03a3c62268c2097f363178767d795 100644 (file)
  * Generic VM initialization for x86-64 NUMA setups.
  * Copyright 2002,2003 Andi Kleen, SuSE Labs.
  */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/init.h>
 #include <linux/bootmem.h>
-#include <linux/memblock.h>
-#include <linux/mmzone.h>
-#include <linux/ctype.h>
-#include <linux/module.h>
-#include <linux/nodemask.h>
-#include <linux/sched.h>
-#include <linux/acpi.h>
-
-#include <asm/e820.h>
-#include <asm/proto.h>
-#include <asm/dma.h>
-#include <asm/acpi.h>
-#include <asm/amd_nb.h>
 
 #include "numa_internal.h"
 
-struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
-EXPORT_SYMBOL(node_data);
-
-nodemask_t numa_nodes_parsed __initdata;
-
-struct memnode memnode;
-
-static unsigned long __initdata nodemap_addr;
-static unsigned long __initdata nodemap_size;
-
-static struct numa_meminfo numa_meminfo __initdata;
-
-static int numa_distance_cnt;
-static u8 *numa_distance;
-
-/*
- * Given a shift value, try to populate memnodemap[]
- * Returns :
- * 1 if OK
- * 0 if memnodmap[] too small (of shift too small)
- * -1 if node overlap or lost ram (shift too big)
- */
-static int __init populate_memnodemap(const struct numa_meminfo *mi, int shift)
-{
-       unsigned long addr, end;
-       int i, res = -1;
-
-       memset(memnodemap, 0xff, sizeof(s16)*memnodemapsize);
-       for (i = 0; i < mi->nr_blks; i++) {
-               addr = mi->blk[i].start;
-               end = mi->blk[i].end;
-               if (addr >= end)
-                       continue;
-               if ((end >> shift) >= memnodemapsize)
-                       return 0;
-               do {
-                       if (memnodemap[addr >> shift] != NUMA_NO_NODE)
-                               return -1;
-                       memnodemap[addr >> shift] = mi->blk[i].nid;
-                       addr += (1UL << shift);
-               } while (addr < end);
-               res = 1;
-       }
-       return res;
-}
-
-static int __init allocate_cachealigned_memnodemap(void)
-{
-       unsigned long addr;
-
-       memnodemap = memnode.embedded_map;
-       if (memnodemapsize <= ARRAY_SIZE(memnode.embedded_map))
-               return 0;
-
-       addr = 0x8000;
-       nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
-       nodemap_addr = memblock_find_in_range(addr, get_max_mapped(),
-                                     nodemap_size, L1_CACHE_BYTES);
-       if (nodemap_addr == MEMBLOCK_ERROR) {
-               printk(KERN_ERR
-                      "NUMA: Unable to allocate Memory to Node hash map\n");
-               nodemap_addr = nodemap_size = 0;
-               return -1;
-       }
-       memnodemap = phys_to_virt(nodemap_addr);
-       memblock_x86_reserve_range(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
-
-       printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
-              nodemap_addr, nodemap_addr + nodemap_size);
-       return 0;
-}
-
-/*
- * The LSB of all start and end addresses in the node map is the value of the
- * maximum possible shift.
- */
-static int __init extract_lsb_from_nodes(const struct numa_meminfo *mi)
-{
-       int i, nodes_used = 0;
-       unsigned long start, end;
-       unsigned long bitfield = 0, memtop = 0;
-
-       for (i = 0; i < mi->nr_blks; i++) {
-               start = mi->blk[i].start;
-               end = mi->blk[i].end;
-               if (start >= end)
-                       continue;
-               bitfield |= start;
-               nodes_used++;
-               if (end > memtop)
-                       memtop = end;
-       }
-       if (nodes_used <= 1)
-               i = 63;
-       else
-               i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
-       memnodemapsize = (memtop >> i)+1;
-       return i;
-}
-
-static int __init compute_hash_shift(const struct numa_meminfo *mi)
-{
-       int shift;
-
-       shift = extract_lsb_from_nodes(mi);
-       if (allocate_cachealigned_memnodemap())
-               return -1;
-       printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
-               shift);
-
-       if (populate_memnodemap(mi, shift) != 1) {
-               printk(KERN_INFO "Your memory is not aligned you need to "
-                      "rebuild your kernel with a bigger NODEMAPSIZE "
-                      "shift=%d\n", shift);
-               return -1;
-       }
-       return shift;
-}
-
-int __meminit  __early_pfn_to_nid(unsigned long pfn)
-{
-       return phys_to_nid(pfn << PAGE_SHIFT);
-}
-
-static void * __init early_node_mem(int nodeid, unsigned long start,
-                                   unsigned long end, unsigned long size,
-                                   unsigned long align)
-{
-       unsigned long mem;
-
-       /*
-        * put it on high as possible
-        * something will go with NODE_DATA
-        */
-       if (start < (MAX_DMA_PFN<<PAGE_SHIFT))
-               start = MAX_DMA_PFN<<PAGE_SHIFT;
-       if (start < (MAX_DMA32_PFN<<PAGE_SHIFT) &&
-           end > (MAX_DMA32_PFN<<PAGE_SHIFT))
-               start = MAX_DMA32_PFN<<PAGE_SHIFT;
-       mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
-       if (mem != MEMBLOCK_ERROR)
-               return __va(mem);
-
-       /* extend the search scope */
-       end = max_pfn_mapped << PAGE_SHIFT;
-       start = MAX_DMA_PFN << PAGE_SHIFT;
-       mem = memblock_find_in_range(start, end, size, align);
-       if (mem != MEMBLOCK_ERROR)
-               return __va(mem);
-
-       printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
-                      size, nodeid);
-
-       return NULL;
-}
-
-static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
-                                    struct numa_meminfo *mi)
-{
-       /* ignore zero length blks */
-       if (start == end)
-               return 0;
-
-       /* whine about and ignore invalid blks */
-       if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
-               pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
-                          nid, start, end);
-               return 0;
-       }
-
-       if (mi->nr_blks >= NR_NODE_MEMBLKS) {
-               pr_err("NUMA: too many memblk ranges\n");
-               return -EINVAL;
-       }
-
-       mi->blk[mi->nr_blks].start = start;
-       mi->blk[mi->nr_blks].end = end;
-       mi->blk[mi->nr_blks].nid = nid;
-       mi->nr_blks++;
-       return 0;
-}
-
-/**
- * numa_remove_memblk_from - Remove one numa_memblk from a numa_meminfo
- * @idx: Index of memblk to remove
- * @mi: numa_meminfo to remove memblk from
- *
- * Remove @idx'th numa_memblk from @mi by shifting @mi->blk[] and
- * decrementing @mi->nr_blks.
- */
-void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
-{
-       mi->nr_blks--;
-       memmove(&mi->blk[idx], &mi->blk[idx + 1],
-               (mi->nr_blks - idx) * sizeof(mi->blk[0]));
-}
-
-/**
- * numa_add_memblk - Add one numa_memblk to numa_meminfo
- * @nid: NUMA node ID of the new memblk
- * @start: Start address of the new memblk
- * @end: End address of the new memblk
- *
- * Add a new memblk to the default numa_meminfo.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-int __init numa_add_memblk(int nid, u64 start, u64 end)
-{
-       return numa_add_memblk_to(nid, start, end, &numa_meminfo);
-}
-
-/* Initialize bootmem allocator for a node */
-void __init
-setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
-{
-       unsigned long start_pfn, last_pfn, nodedata_phys;
-       const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
-       int nid;
-
-       if (!end)
-               return;
-
-       /*
-        * Don't confuse VM with a node that doesn't have the
-        * minimum amount of memory:
-        */
-       if (end && (end - start) < NODE_MIN_SIZE)
-               return;
-
-       start = roundup(start, ZONE_ALIGN);
-
-       printk(KERN_INFO "Initmem setup node %d %016lx-%016lx\n", nodeid,
-              start, end);
-
-       start_pfn = start >> PAGE_SHIFT;
-       last_pfn = end >> PAGE_SHIFT;
-
-       node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size,
-                                          SMP_CACHE_BYTES);
-       if (node_data[nodeid] == NULL)
-               return;
-       nodedata_phys = __pa(node_data[nodeid]);
-       memblock_x86_reserve_range(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
-       printk(KERN_INFO "  NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
-               nodedata_phys + pgdat_size - 1);
-       nid = phys_to_nid(nodedata_phys);
-       if (nid != nodeid)
-               printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nodeid, nid);
-
-       memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
-       NODE_DATA(nodeid)->node_id = nodeid;
-       NODE_DATA(nodeid)->node_start_pfn = start_pfn;
-       NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
-
-       node_set_online(nodeid);
-}
-
-/**
- * numa_cleanup_meminfo - Cleanup a numa_meminfo
- * @mi: numa_meminfo to clean up
- *
- * Sanitize @mi by merging and removing unncessary memblks.  Also check for
- * conflicts and clear unused memblks.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
-{
-       const u64 low = 0;
-       const u64 high = (u64)max_pfn << PAGE_SHIFT;
-       int i, j, k;
-
-       for (i = 0; i < mi->nr_blks; i++) {
-               struct numa_memblk *bi = &mi->blk[i];
-
-               /* make sure all blocks are inside the limits */
-               bi->start = max(bi->start, low);
-               bi->end = min(bi->end, high);
-
-               /* and there's no empty block */
-               if (bi->start == bi->end) {
-                       numa_remove_memblk_from(i--, mi);
-                       continue;
-               }
-
-               for (j = i + 1; j < mi->nr_blks; j++) {
-                       struct numa_memblk *bj = &mi->blk[j];
-                       unsigned long start, end;
-
-                       /*
-                        * See whether there are overlapping blocks.  Whine
-                        * about but allow overlaps of the same nid.  They
-                        * will be merged below.
-                        */
-                       if (bi->end > bj->start && bi->start < bj->end) {
-                               if (bi->nid != bj->nid) {
-                                       pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
-                                              bi->nid, bi->start, bi->end,
-                                              bj->nid, bj->start, bj->end);
-                                       return -EINVAL;
-                               }
-                               pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
-                                          bi->nid, bi->start, bi->end,
-                                          bj->start, bj->end);
-                       }
-
-                       /*
-                        * Join together blocks on the same node, holes
-                        * between which don't overlap with memory on other
-                        * nodes.
-                        */
-                       if (bi->nid != bj->nid)
-                               continue;
-                       start = max(min(bi->start, bj->start), low);
-                       end = min(max(bi->end, bj->end), high);
-                       for (k = 0; k < mi->nr_blks; k++) {
-                               struct numa_memblk *bk = &mi->blk[k];
-
-                               if (bi->nid == bk->nid)
-                                       continue;
-                               if (start < bk->end && end > bk->start)
-                                       break;
-                       }
-                       if (k < mi->nr_blks)
-                               continue;
-                       printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
-                              bi->nid, bi->start, bi->end, bj->start, bj->end,
-                              start, end);
-                       bi->start = start;
-                       bi->end = end;
-                       numa_remove_memblk_from(j--, mi);
-               }
-       }
-
-       for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) {
-               mi->blk[i].start = mi->blk[i].end = 0;
-               mi->blk[i].nid = NUMA_NO_NODE;
-       }
-
-       return 0;
-}
-
-/*
- * Set nodes, which have memory in @mi, in *@nodemask.
- */
-static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
-                                             const struct numa_meminfo *mi)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(mi->blk); i++)
-               if (mi->blk[i].start != mi->blk[i].end &&
-                   mi->blk[i].nid != NUMA_NO_NODE)
-                       node_set(mi->blk[i].nid, *nodemask);
-}
-
-/**
- * numa_reset_distance - Reset NUMA distance table
- *
- * The current table is freed.  The next numa_set_distance() call will
- * create a new one.
- */
-void __init numa_reset_distance(void)
-{
-       size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]);
-
-       /* numa_distance could be 1LU marking allocation failure, test cnt */
-       if (numa_distance_cnt)
-               memblock_x86_free_range(__pa(numa_distance),
-                                       __pa(numa_distance) + size);
-       numa_distance_cnt = 0;
-       numa_distance = NULL;   /* enable table creation */
-}
-
-static int __init numa_alloc_distance(void)
-{
-       nodemask_t nodes_parsed;
-       size_t size;
-       int i, j, cnt = 0;
-       u64 phys;
-
-       /* size the new table and allocate it */
-       nodes_parsed = numa_nodes_parsed;
-       numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo);
-
-       for_each_node_mask(i, nodes_parsed)
-               cnt = i;
-       cnt++;
-       size = cnt * cnt * sizeof(numa_distance[0]);
-
-       phys = memblock_find_in_range(0, (u64)max_pfn_mapped << PAGE_SHIFT,
-                                     size, PAGE_SIZE);
-       if (phys == MEMBLOCK_ERROR) {
-               pr_warning("NUMA: Warning: can't allocate distance table!\n");
-               /* don't retry until explicitly reset */
-               numa_distance = (void *)1LU;
-               return -ENOMEM;
-       }
-       memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
-
-       numa_distance = __va(phys);
-       numa_distance_cnt = cnt;
-
-       /* fill with the default distances */
-       for (i = 0; i < cnt; i++)
-               for (j = 0; j < cnt; j++)
-                       numa_distance[i * cnt + j] = i == j ?
-                               LOCAL_DISTANCE : REMOTE_DISTANCE;
-       printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt);
-
-       return 0;
-}
-
-/**
- * numa_set_distance - Set NUMA distance from one NUMA to another
- * @from: the 'from' node to set distance
- * @to: the 'to'  node to set distance
- * @distance: NUMA distance
- *
- * Set the distance from node @from to @to to @distance.  If distance table
- * doesn't exist, one which is large enough to accommodate all the currently
- * known nodes will be created.
- *
- * If such table cannot be allocated, a warning is printed and further
- * calls are ignored until the distance table is reset with
- * numa_reset_distance().
- *
- * If @from or @to is higher than the highest known node at the time of
- * table creation or @distance doesn't make sense, the call is ignored.
- * This is to allow simplification of specific NUMA config implementations.
- */
-void __init numa_set_distance(int from, int to, int distance)
-{
-       if (!numa_distance && numa_alloc_distance() < 0)
-               return;
-
-       if (from >= numa_distance_cnt || to >= numa_distance_cnt) {
-               printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n",
-                           from, to, distance);
-               return;
-       }
-
-       if ((u8)distance != distance ||
-           (from == to && distance != LOCAL_DISTANCE)) {
-               pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
-                            from, to, distance);
-               return;
-       }
-
-       numa_distance[from * numa_distance_cnt + to] = distance;
-}
-
-int __node_distance(int from, int to)
-{
-       if (from >= numa_distance_cnt || to >= numa_distance_cnt)
-               return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
-       return numa_distance[from * numa_distance_cnt + to];
-}
-EXPORT_SYMBOL(__node_distance);
-
-/*
- * Sanity check to catch more bad NUMA configurations (they are amazingly
- * common).  Make sure the nodes cover all memory.
- */
-static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
-{
-       unsigned long numaram, e820ram;
-       int i;
-
-       numaram = 0;
-       for (i = 0; i < mi->nr_blks; i++) {
-               unsigned long s = mi->blk[i].start >> PAGE_SHIFT;
-               unsigned long e = mi->blk[i].end >> PAGE_SHIFT;
-               numaram += e - s;
-               numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
-               if ((long)numaram < 0)
-                       numaram = 0;
-       }
-
-       e820ram = max_pfn - (memblock_x86_hole_size(0,
-                                       max_pfn << PAGE_SHIFT) >> PAGE_SHIFT);
-       /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
-       if ((long)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
-               printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
-                      (numaram << PAGE_SHIFT) >> 20,
-                      (e820ram << PAGE_SHIFT) >> 20);
-               return false;
-       }
-       return true;
-}
-
-static int __init numa_register_memblks(struct numa_meminfo *mi)
-{
-       int i, nid;
-
-       /* Account for nodes with cpus and no memory */
-       node_possible_map = numa_nodes_parsed;
-       numa_nodemask_from_meminfo(&node_possible_map, mi);
-       if (WARN_ON(nodes_empty(node_possible_map)))
-               return -EINVAL;
-
-       memnode_shift = compute_hash_shift(mi);
-       if (memnode_shift < 0) {
-               printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < mi->nr_blks; i++)
-               memblock_x86_register_active_regions(mi->blk[i].nid,
-                                       mi->blk[i].start >> PAGE_SHIFT,
-                                       mi->blk[i].end >> PAGE_SHIFT);
-
-       /* for out of order entries */
-       sort_node_map();
-       if (!numa_meminfo_cover_memory(mi))
-               return -EINVAL;
-
-       /* Finally register nodes. */
-       for_each_node_mask(nid, node_possible_map) {
-               u64 start = (u64)max_pfn << PAGE_SHIFT;
-               u64 end = 0;
-
-               for (i = 0; i < mi->nr_blks; i++) {
-                       if (nid != mi->blk[i].nid)
-                               continue;
-                       start = min(mi->blk[i].start, start);
-                       end = max(mi->blk[i].end, end);
-               }
-
-               if (start < end)
-                       setup_node_bootmem(nid, start, end);
-       }
-
-       return 0;
-}
-
-/**
- * dummy_numma_init - Fallback dummy NUMA init
- *
- * Used if there's no underlying NUMA architecture, NUMA initialization
- * fails, or NUMA is disabled on the command line.
- *
- * Must online at least one node and add memory blocks that cover all
- * allowed memory.  This function must not fail.
- */
-static int __init dummy_numa_init(void)
-{
-       printk(KERN_INFO "%s\n",
-              numa_off ? "NUMA turned off" : "No NUMA configuration found");
-       printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
-              0LU, max_pfn << PAGE_SHIFT);
-
-       node_set(0, numa_nodes_parsed);
-       numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
-
-       return 0;
-}
-
-static int __init numa_init(int (*init_func)(void))
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < MAX_LOCAL_APIC; i++)
-               set_apicid_to_node(i, NUMA_NO_NODE);
-
-       nodes_clear(numa_nodes_parsed);
-       nodes_clear(node_possible_map);
-       nodes_clear(node_online_map);
-       memset(&numa_meminfo, 0, sizeof(numa_meminfo));
-       remove_all_active_ranges();
-       numa_reset_distance();
-
-       ret = init_func();
-       if (ret < 0)
-               return ret;
-       ret = numa_cleanup_meminfo(&numa_meminfo);
-       if (ret < 0)
-               return ret;
-
-       numa_emulation(&numa_meminfo, numa_distance_cnt);
-
-       ret = numa_register_memblks(&numa_meminfo);
-       if (ret < 0)
-               return ret;
-
-       for (i = 0; i < nr_cpu_ids; i++) {
-               int nid = early_cpu_to_node(i);
-
-               if (nid == NUMA_NO_NODE)
-                       continue;
-               if (!node_online(nid))
-                       numa_clear_node(i);
-       }
-       numa_init_array();
-       return 0;
-}
-
 void __init initmem_init(void)
 {
-       int ret;
-
-       if (!numa_off) {
-#ifdef CONFIG_ACPI_NUMA
-               ret = numa_init(x86_acpi_numa_init);
-               if (!ret)
-                       return;
-#endif
-#ifdef CONFIG_AMD_NUMA
-               ret = numa_init(amd_numa_init);
-               if (!ret)
-                       return;
-#endif
-       }
-
-       numa_init(dummy_numa_init);
+       x86_numa_init();
 }
 
 unsigned long __init numa_free_all_bootmem(void)
@@ -656,12 +23,3 @@ unsigned long __init numa_free_all_bootmem(void)
 
        return pages;
 }
-
-int __cpuinit numa_cpu_node(int cpu)
-{
-       int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
-
-       if (apicid != BAD_APICID)
-               return __apicid_to_node[apicid];
-       return NUMA_NO_NODE;
-}
index ad091e4cff17f01a598c7a2c1b3a5a541e9d96a1..d0ed086b6247d35fb986d98dfe35a1711d901876 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/errno.h>
 #include <linux/topology.h>
 #include <linux/memblock.h>
+#include <linux/bootmem.h>
 #include <asm/dma.h>
 
 #include "numa_internal.h"
@@ -84,7 +85,13 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
                nr_nodes = MAX_NUMNODES;
        }
 
-       size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
+       /*
+        * Calculate target node size.  x86_32 freaks on __udivdi3() so do
+        * the division in ulong number of pages and convert back.
+        */
+       size = max_addr - addr - memblock_x86_hole_size(addr, max_addr);
+       size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes);
+
        /*
         * Calculate the number of big nodes that can be allocated as a result
         * of consolidating the remainder.
@@ -226,7 +233,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
         */
        while (nodes_weight(physnode_mask)) {
                for_each_node_mask(i, physnode_mask) {
-                       u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT;
+                       u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
                        u64 start, limit, end;
                        int phys_blk;
 
@@ -298,7 +305,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
 {
        static struct numa_meminfo ei __initdata;
        static struct numa_meminfo pi __initdata;
-       const u64 max_addr = max_pfn << PAGE_SHIFT;
+       const u64 max_addr = PFN_PHYS(max_pfn);
        u8 *phys_dist = NULL;
        size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]);
        int max_emu_nid, dfl_phys_nid;
@@ -342,8 +349,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
        if (numa_dist_cnt) {
                u64 phys;
 
-               phys = memblock_find_in_range(0,
-                                             (u64)max_pfn_mapped << PAGE_SHIFT,
+               phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
                                              phys_size, PAGE_SIZE);
                if (phys == MEMBLOCK_ERROR) {
                        pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
@@ -454,10 +460,9 @@ void __cpuinit numa_remove_cpu(int cpu)
                cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
 }
 #else  /* !CONFIG_DEBUG_PER_CPU_MAPS */
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
+static void __cpuinit numa_set_cpumask(int cpu, bool enable)
 {
-       struct cpumask *mask;
-       int nid, physnid, i;
+       int nid, physnid;
 
        nid = early_cpu_to_node(cpu);
        if (nid == NUMA_NO_NODE) {
@@ -467,28 +472,21 @@ static void __cpuinit numa_set_cpumask(int cpu, int enable)
 
        physnid = emu_nid_to_phys[nid];
 
-       for_each_online_node(i) {
+       for_each_online_node(nid) {
                if (emu_nid_to_phys[nid] != physnid)
                        continue;
 
-               mask = debug_cpumask_set_cpu(cpu, enable);
-               if (!mask)
-                       return;
-
-               if (enable)
-                       cpumask_set_cpu(cpu, mask);
-               else
-                       cpumask_clear_cpu(cpu, mask);
+               debug_cpumask_set_cpu(cpu, nid, enable);
        }
 }
 
 void __cpuinit numa_add_cpu(int cpu)
 {
-       numa_set_cpumask(cpu, 1);
+       numa_set_cpumask(cpu, true);
 }
 
 void __cpuinit numa_remove_cpu(int cpu)
 {
-       numa_set_cpumask(cpu, 0);
+       numa_set_cpumask(cpu, false);
 }
 #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
index ef2d97377d7c7d222378942d628c9415e228be22..7178c3afe05e1ff2280c5d8a46e03ddb7c8f52de 100644 (file)
@@ -19,6 +19,14 @@ void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi);
 int __init numa_cleanup_meminfo(struct numa_meminfo *mi);
 void __init numa_reset_distance(void);
 
+void __init x86_numa_init(void);
+
+#ifdef CONFIG_X86_64
+static inline void init_alloc_remap(int nid, u64 start, u64 end)       { }
+#else
+void __init init_alloc_remap(int nid, u64 start, u64 end);
+#endif
+
 #ifdef CONFIG_NUMA_EMU
 void __init numa_emulation(struct numa_meminfo *numa_meminfo,
                           int numa_dist_cnt);
similarity index 67%
rename from arch/x86/mm/srat_64.c
rename to arch/x86/mm/srat.c
index 8e9d3394f6d452d97703f2e639e2d0b8f409d473..81dbfdeb080db2e42ff61cd16a3fb63de23085db 100644 (file)
@@ -26,8 +26,6 @@
 
 int acpi_numa __initdata;
 
-static struct bootnode nodes_add[MAX_NUMNODES];
-
 static __init int setup_node(int pxm)
 {
        return acpi_map_pxm_to_node(pxm);
@@ -37,7 +35,6 @@ static __init void bad_srat(void)
 {
        printk(KERN_ERR "SRAT: SRAT not used.\n");
        acpi_numa = -1;
-       memset(nodes_add, 0, sizeof(nodes_add));
 }
 
 static __init inline int srat_disabled(void)
@@ -131,73 +128,17 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
               pxm, apic_id, node);
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+#ifdef CONFIG_MEMORY_HOTPLUG
 static inline int save_add_info(void) {return 1;}
 #else
 static inline int save_add_info(void) {return 0;}
 #endif
-/*
- * Update nodes_add[]
- * This code supports one contiguous hot add area per node
- */
-static void __init
-update_nodes_add(int node, unsigned long start, unsigned long end)
-{
-       unsigned long s_pfn = start >> PAGE_SHIFT;
-       unsigned long e_pfn = end >> PAGE_SHIFT;
-       int changed = 0;
-       struct bootnode *nd = &nodes_add[node];
-
-       /* I had some trouble with strange memory hotadd regions breaking
-          the boot. Be very strict here and reject anything unexpected.
-          If you want working memory hotadd write correct SRATs.
-
-          The node size check is a basic sanity check to guard against
-          mistakes */
-       if ((signed long)(end - start) < NODE_MIN_SIZE) {
-               printk(KERN_ERR "SRAT: Hotplug area too small\n");
-               return;
-       }
-
-       /* This check might be a bit too strict, but I'm keeping it for now. */
-       if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
-               printk(KERN_ERR
-                       "SRAT: Hotplug area %lu -> %lu has existing memory\n",
-                       s_pfn, e_pfn);
-               return;
-       }
-
-       /* Looks good */
-
-       if (nd->start == nd->end) {
-               nd->start = start;
-               nd->end = end;
-               changed = 1;
-       } else {
-               if (nd->start == end) {
-                       nd->start = start;
-                       changed = 1;
-               }
-               if (nd->end == start) {
-                       nd->end = end;
-                       changed = 1;
-               }
-               if (!changed)
-                       printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
-       }
-
-       if (changed) {
-               node_set(node, numa_nodes_parsed);
-               printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
-                                nd->start, nd->end);
-       }
-}
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-       unsigned long start, end;
+       u64 start, end;
        int node, pxm;
 
        if (srat_disabled())
@@ -226,11 +167,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
                return;
        }
 
-       printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
+       printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
               start, end);
-
-       if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
-               update_nodes_add(node, start, end);
 }
 
 void __init acpi_numa_arch_fixup(void) {}
@@ -244,17 +182,3 @@ int __init x86_acpi_numa_init(void)
                return ret;
        return srat_disabled() ? -EINVAL : 0;
 }
-
-#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
-int memory_add_physaddr_to_nid(u64 start)
-{
-       int i, ret = 0;
-
-       for_each_node(i)
-               if (nodes_add[i].start <= start && nodes_add[i].end > start)
-                       ret = i;
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-#endif
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
deleted file mode 100644 (file)
index 364f36b..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Some of the code in this file has been gleaned from the 64 bit 
- * discontigmem support code base.
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * All rights reserved.          
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to Pat Gaughen <gone@us.ibm.com>
- */
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/memblock.h>
-#include <linux/mmzone.h>
-#include <linux/acpi.h>
-#include <linux/nodemask.h>
-#include <asm/srat.h>
-#include <asm/topology.h>
-#include <asm/smp.h>
-#include <asm/e820.h>
-
-/*
- * proximity macros and definitions
- */
-#define NODE_ARRAY_INDEX(x)    ((x) / 8)       /* 8 bits/char */
-#define NODE_ARRAY_OFFSET(x)   ((x) % 8)       /* 8 bits/char */
-#define BMAP_SET(bmap, bit)    ((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit))
-#define BMAP_TEST(bmap, bit)   ((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit)))
-/* bitmap length; _PXM is at most 255 */
-#define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) 
-static u8 __initdata pxm_bitmap[PXM_BITMAP_LEN];       /* bitmap of proximity domains */
-
-#define MAX_CHUNKS_PER_NODE    3
-#define MAXCHUNKS              (MAX_CHUNKS_PER_NODE * MAX_NUMNODES)
-struct node_memory_chunk_s {
-       unsigned long   start_pfn;
-       unsigned long   end_pfn;
-       u8      pxm;            // proximity domain of node
-       u8      nid;            // which cnode contains this chunk?
-       u8      bank;           // which mem bank on this node
-};
-static struct node_memory_chunk_s __initdata node_memory_chunk[MAXCHUNKS];
-
-static int __initdata num_memory_chunks; /* total number of memory chunks */
-static u8 __initdata apicid_to_pxm[MAX_LOCAL_APIC];
-
-int acpi_numa __initdata;
-
-static __init void bad_srat(void)
-{
-        printk(KERN_ERR "SRAT: SRAT not used.\n");
-        acpi_numa = -1;
-       num_memory_chunks = 0;
-}
-
-static __init inline int srat_disabled(void)
-{
-       return numa_off || acpi_numa < 0;
-}
-
-/* Identify CPU proximity domains */
-void __init
-acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *cpu_affinity)
-{
-       if (srat_disabled())
-               return;
-       if (cpu_affinity->header.length !=
-            sizeof(struct acpi_srat_cpu_affinity)) {
-               bad_srat();
-               return;
-       }
-
-       if ((cpu_affinity->flags & ACPI_SRAT_CPU_ENABLED) == 0)
-               return;         /* empty entry */
-
-       /* mark this node as "seen" in node bitmap */
-       BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo);
-
-       /* don't need to check apic_id here, because it is always 8 bits */
-       apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo;
-
-       printk(KERN_DEBUG "CPU %02x in proximity domain %02x\n",
-               cpu_affinity->apic_id, cpu_affinity->proximity_domain_lo);
-}
-
-/*
- * Identify memory proximity domains and hot-remove capabilities.
- * Fill node memory chunk list structure.
- */
-void __init
-acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity)
-{
-       unsigned long long paddr, size;
-       unsigned long start_pfn, end_pfn;
-       u8 pxm;
-       struct node_memory_chunk_s *p, *q, *pend;
-
-       if (srat_disabled())
-               return;
-       if (memory_affinity->header.length !=
-            sizeof(struct acpi_srat_mem_affinity)) {
-               bad_srat();
-               return;
-       }
-
-       if ((memory_affinity->flags & ACPI_SRAT_MEM_ENABLED) == 0)
-               return;         /* empty entry */
-
-       pxm = memory_affinity->proximity_domain & 0xff;
-
-       /* mark this node as "seen" in node bitmap */
-       BMAP_SET(pxm_bitmap, pxm);
-
-       /* calculate info for memory chunk structure */
-       paddr = memory_affinity->base_address;
-       size = memory_affinity->length;
-
-       start_pfn = paddr >> PAGE_SHIFT;
-       end_pfn = (paddr + size) >> PAGE_SHIFT;
-
-
-       if (num_memory_chunks >= MAXCHUNKS) {
-               printk(KERN_WARNING "Too many mem chunks in SRAT."
-                       " Ignoring %lld MBytes at %llx\n",
-                       size/(1024*1024), paddr);
-               return;
-       }
-
-       /* Insertion sort based on base address */
-       pend = &node_memory_chunk[num_memory_chunks];
-       for (p = &node_memory_chunk[0]; p < pend; p++) {
-               if (start_pfn < p->start_pfn)
-                       break;
-       }
-       if (p < pend) {
-               for (q = pend; q >= p; q--)
-                       *(q + 1) = *q;
-       }
-       p->start_pfn = start_pfn;
-       p->end_pfn = end_pfn;
-       p->pxm = pxm;
-
-       num_memory_chunks++;
-
-       printk(KERN_DEBUG "Memory range %08lx to %08lx"
-                         " in proximity domain %02x %s\n",
-               start_pfn, end_pfn,
-               pxm,
-               ((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
-                "enabled and removable" : "enabled" ) );
-}
-
-/* Callback for SLIT parsing */
-void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
-{
-}
-
-void acpi_numa_arch_fixup(void)
-{
-}
-/*
- * The SRAT table always lists ascending addresses, so can always
- * assume that the first "start" address that you see is the real
- * start of the node, and that the current "end" address is after
- * the previous one.
- */
-static __init int node_read_chunk(int nid, struct node_memory_chunk_s *memory_chunk)
-{
-       /*
-        * Only add present memory as told by the e820.
-        * There is no guarantee from the SRAT that the memory it
-        * enumerates is present at boot time because it represents
-        * *possible* memory hotplug areas the same as normal RAM.
-        */
-       if (memory_chunk->start_pfn >= max_pfn) {
-               printk(KERN_INFO "Ignoring SRAT pfns: %08lx - %08lx\n",
-                       memory_chunk->start_pfn, memory_chunk->end_pfn);
-               return -1;
-       }
-       if (memory_chunk->nid != nid)
-               return -1;
-
-       if (!node_has_online_mem(nid))
-               node_start_pfn[nid] = memory_chunk->start_pfn;
-
-       if (node_start_pfn[nid] > memory_chunk->start_pfn)
-               node_start_pfn[nid] = memory_chunk->start_pfn;
-
-       if (node_end_pfn[nid] < memory_chunk->end_pfn)
-               node_end_pfn[nid] = memory_chunk->end_pfn;
-
-       return 0;
-}
-
-int __init get_memcfg_from_srat(void)
-{
-       int i, j, nid;
-
-       if (srat_disabled())
-               goto out_fail;
-
-       if (acpi_numa_init() < 0)
-               goto out_fail;
-
-       if (num_memory_chunks == 0) {
-               printk(KERN_DEBUG
-                        "could not find any ACPI SRAT memory areas.\n");
-               goto out_fail;
-       }
-
-       /* Calculate total number of nodes in system from PXM bitmap and create
-        * a set of sequential node IDs starting at zero.  (ACPI doesn't seem
-        * to specify the range of _PXM values.)
-        */
-       /*
-        * MCD - we no longer HAVE to number nodes sequentially.  PXM domain
-        * numbers could go as high as 256, and MAX_NUMNODES for i386 is typically
-        * 32, so we will continue numbering them in this manner until MAX_NUMNODES
-        * approaches MAX_PXM_DOMAINS for i386.
-        */
-       nodes_clear(node_online_map);
-       for (i = 0; i < MAX_PXM_DOMAINS; i++) {
-               if (BMAP_TEST(pxm_bitmap, i)) {
-                       int nid = acpi_map_pxm_to_node(i);
-                       node_set_online(nid);
-               }
-       }
-       BUG_ON(num_online_nodes() == 0);
-
-       /* set cnode id in memory chunk structure */
-       for (i = 0; i < num_memory_chunks; i++)
-               node_memory_chunk[i].nid = pxm_to_node(node_memory_chunk[i].pxm);
-
-       printk(KERN_DEBUG "pxm bitmap: ");
-       for (i = 0; i < sizeof(pxm_bitmap); i++) {
-               printk(KERN_CONT "%02x ", pxm_bitmap[i]);
-       }
-       printk(KERN_CONT "\n");
-       printk(KERN_DEBUG "Number of logical nodes in system = %d\n",
-                        num_online_nodes());
-       printk(KERN_DEBUG "Number of memory chunks in system = %d\n",
-                        num_memory_chunks);
-
-       for (i = 0; i < MAX_LOCAL_APIC; i++)
-               set_apicid_to_node(i, pxm_to_node(apicid_to_pxm[i]));
-
-       for (j = 0; j < num_memory_chunks; j++){
-               struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
-               printk(KERN_DEBUG
-                       "chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
-                      j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
-               if (node_read_chunk(chunk->nid, chunk))
-                       continue;
-
-               memblock_x86_register_active_regions(chunk->nid, chunk->start_pfn,
-                                            min(chunk->end_pfn, max_pfn));
-       }
-       /* for out of order entries in SRAT */
-       sort_node_map();
-
-       for_each_online_node(nid) {
-               unsigned long start = node_start_pfn[nid];
-               unsigned long end = min(node_end_pfn[nid], max_pfn);
-
-               memory_present(nid, start, end);
-               node_remap_size[nid] = node_memmap_size_bytes(nid, start, end);
-       }
-       return 1;
-out_fail:
-       printk(KERN_DEBUG "failed to get NUMA memory information from SRAT"
-                       " table\n");
-       return 0;
-}
index 2d49d4e19a3619c0be2c7d17a892b8aea582048f..a5b64ab4cd6e3ef34be5beda88100e72091437c8 100644 (file)
 #include <asm/stacktrace.h>
 #include <linux/compat.h>
 
-static void backtrace_warning_symbol(void *data, char *msg,
-                                    unsigned long symbol)
-{
-       /* Ignore warnings */
-}
-
-static void backtrace_warning(void *data, char *msg)
-{
-       /* Ignore warnings */
-}
-
 static int backtrace_stack(void *data, char *name)
 {
        /* Yes, we want all stacks */
@@ -42,8 +31,6 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
 }
 
 static struct stacktrace_ops backtrace_ops = {
-       .warning        = backtrace_warning,
-       .warning_symbol = backtrace_warning_symbol,
        .stack          = backtrace_stack,
        .address        = backtrace_address,
        .walk_stack     = print_context_stack,
index e37b407a0ee8d4d6e4d8c7b2c4cece5f315da66c..8214724ce54dafeef19290199e4a9657a6468766 100644 (file)
@@ -108,7 +108,8 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                }
                irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
                                               (type == PCI_CAP_ID_MSIX) ?
-                                              "msi-x" : "msi");
+                                              "msi-x" : "msi",
+                                              DOMID_SELF);
                if (irq < 0)
                        goto error;
                dev_dbg(&dev->dev,
@@ -148,7 +149,8 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
                                               (type == PCI_CAP_ID_MSIX) ?
                                               "pcifront-msi-x" :
-                                              "pcifront-msi");
+                                              "pcifront-msi",
+                                               DOMID_SELF);
                if (irq < 0)
                        goto free;
                i++;
@@ -190,9 +192,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
        list_for_each_entry(msidesc, &dev->msi_list, list) {
                struct physdev_map_pirq map_irq;
+               domid_t domid;
+
+               domid = ret = xen_find_device_domain_owner(dev);
+               /* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED,
+                * hence check ret value for < 0. */
+               if (ret < 0)
+                       domid = DOMID_SELF;
 
                memset(&map_irq, 0, sizeof(map_irq));
-               map_irq.domid = DOMID_SELF;
+               map_irq.domid = domid;
                map_irq.type = MAP_PIRQ_TYPE_MSI;
                map_irq.index = -1;
                map_irq.pirq = -1;
@@ -215,14 +224,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
                ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
                if (ret) {
-                       dev_warn(&dev->dev, "xen map irq failed %d\n", ret);
+                       dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
+                                ret, domid);
                        goto out;
                }
 
                ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
                                               map_irq.pirq, map_irq.index,
                                               (type == PCI_CAP_ID_MSIX) ?
-                                              "msi-x" : "msi");
+                                              "msi-x" : "msi",
+                                               domid);
                if (ret < 0)
                        goto out;
        }
@@ -461,3 +472,78 @@ void __init xen_setup_pirqs(void)
        }
 }
 #endif
+
+#ifdef CONFIG_XEN_DOM0
+struct xen_device_domain_owner {
+       domid_t domain;
+       struct pci_dev *dev;
+       struct list_head list;
+};
+
+static DEFINE_SPINLOCK(dev_domain_list_spinlock);
+static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
+
+static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
+{
+       struct xen_device_domain_owner *owner;
+
+       list_for_each_entry(owner, &dev_domain_list, list) {
+               if (owner->dev == dev)
+                       return owner;
+       }
+       return NULL;
+}
+
+int xen_find_device_domain_owner(struct pci_dev *dev)
+{
+       struct xen_device_domain_owner *owner;
+       int domain = -ENODEV;
+
+       spin_lock(&dev_domain_list_spinlock);
+       owner = find_device(dev);
+       if (owner)
+               domain = owner->domain;
+       spin_unlock(&dev_domain_list_spinlock);
+       return domain;
+}
+EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
+
+int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
+{
+       struct xen_device_domain_owner *owner;
+
+       owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
+       if (!owner)
+               return -ENODEV;
+
+       spin_lock(&dev_domain_list_spinlock);
+       if (find_device(dev)) {
+               spin_unlock(&dev_domain_list_spinlock);
+               kfree(owner);
+               return -EEXIST;
+       }
+       owner->domain = domain;
+       owner->dev = dev;
+       list_add_tail(&owner->list, &dev_domain_list);
+       spin_unlock(&dev_domain_list_spinlock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
+
+int xen_unregister_device_domain_owner(struct pci_dev *dev)
+{
+       struct xen_device_domain_owner *owner;
+
+       spin_lock(&dev_domain_list_spinlock);
+       owner = find_device(dev);
+       if (!owner) {
+               spin_unlock(&dev_domain_list_spinlock);
+               return -ENODEV;
+       }
+       list_del(&owner->list);
+       spin_unlock(&dev_domain_list_spinlock);
+       kfree(owner);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
+#endif
index 2d6d226f2b10fc511897bd484d25f15c6eef22c1..e70be38ce03920d4d8210a98ef1038c9ec471745 100644 (file)
                                                   "pciclass0c03";
 
                                        reg = <0x16800 0x0 0x0 0x0 0x0>;
-                                       interrupts = <22 3>;
+                                       interrupts = <22 1>;
                                };
 
                                usb@d,1 {
                                                   "pciclass0c03";
 
                                        reg = <0x16900 0x0 0x0 0x0 0x0>;
-                                       interrupts = <22 3>;
+                                       interrupts = <22 1>;
                                };
 
                                sata@e,0 {
                                                   "pciclass0106";
 
                                        reg = <0x17000 0x0 0x0 0x0 0x0>;
-                                       interrupts = <23 3>;
+                                       interrupts = <23 1>;
                                };
 
                                flash@f,0 {
index 0fe27d7c6258e8e22b8918c0fbf14d088ecd9380..b30aa26a8df25304b1aa798be441a84c27ce7afc 100644 (file)
@@ -145,17 +145,6 @@ static void virt_efi_reset_system(int reset_type,
                       data_size, data);
 }
 
-static efi_status_t virt_efi_set_virtual_address_map(
-       unsigned long memory_map_size,
-       unsigned long descriptor_size,
-       u32 descriptor_version,
-       efi_memory_desc_t *virtual_map)
-{
-       return efi_call_virt4(set_virtual_address_map,
-                             memory_map_size, descriptor_size,
-                             descriptor_version, virtual_map);
-}
-
 static efi_status_t __init phys_efi_set_virtual_address_map(
        unsigned long memory_map_size,
        unsigned long descriptor_size,
@@ -468,11 +457,25 @@ void __init efi_init(void)
 #endif
 }
 
+void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
+{
+       u64 addr, npages;
+
+       addr = md->virt_addr;
+       npages = md->num_pages;
+
+       memrange_efi_to_native(&addr, &npages);
+
+       if (executable)
+               set_memory_x(addr, npages);
+       else
+               set_memory_nx(addr, npages);
+}
+
 static void __init runtime_code_page_mkexec(void)
 {
        efi_memory_desc_t *md;
        void *p;
-       u64 addr, npages;
 
        /* Make EFI runtime service code area executable */
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -481,10 +484,7 @@ static void __init runtime_code_page_mkexec(void)
                if (md->type != EFI_RUNTIME_SERVICES_CODE)
                        continue;
 
-               addr = md->virt_addr;
-               npages = md->num_pages;
-               memrange_efi_to_native(&addr, &npages);
-               set_memory_x(addr, npages);
+               efi_set_executable(md, true);
        }
 }
 
@@ -498,13 +498,42 @@ static void __init runtime_code_page_mkexec(void)
  */
 void __init efi_enter_virtual_mode(void)
 {
-       efi_memory_desc_t *md;
+       efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
        u64 end, systab, addr, npages, end_pfn;
-       void *p, *va;
+       void *p, *va, *new_memmap = NULL;
+       int count = 0;
 
        efi.systab = 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;
+
+               if (!prev_md) {
+                       prev_md = md;
+                       continue;
+               }
+
+               if (prev_md->type != md->type ||
+                   prev_md->attribute != md->attribute) {
+                       prev_md = md;
+                       continue;
+               }
+
+               prev_size = prev_md->num_pages << EFI_PAGE_SHIFT;
+
+               if (md->phys_addr == (prev_md->phys_addr + prev_size)) {
+                       prev_md->num_pages += md->num_pages;
+                       md->type = EFI_RESERVED_TYPE;
+                       md->attribute = 0;
+                       continue;
+               }
+               prev_md = md;
+       }
+
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
                if (!(md->attribute & EFI_MEMORY_RUNTIME))
@@ -541,15 +570,21 @@ void __init efi_enter_virtual_mode(void)
                        systab += md->virt_addr - md->phys_addr;
                        efi.systab = (efi_system_table_t *) (unsigned long) systab;
                }
+               new_memmap = krealloc(new_memmap,
+                                     (count + 1) * memmap.desc_size,
+                                     GFP_KERNEL);
+               memcpy(new_memmap + (count * memmap.desc_size), md,
+                      memmap.desc_size);
+               count++;
        }
 
        BUG_ON(!efi.systab);
 
        status = phys_efi_set_virtual_address_map(
-               memmap.desc_size * memmap.nr_map,
+               memmap.desc_size * count,
                memmap.desc_size,
                memmap.desc_version,
-               memmap.phys_map);
+               (efi_memory_desc_t *)__pa(new_memmap));
 
        if (status != EFI_SUCCESS) {
                printk(KERN_ALERT "Unable to switch EFI into virtual mode "
@@ -572,11 +607,12 @@ void __init efi_enter_virtual_mode(void)
        efi.set_variable = virt_efi_set_variable;
        efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
        efi.reset_system = virt_efi_reset_system;
-       efi.set_virtual_address_map = virt_efi_set_virtual_address_map;
+       efi.set_virtual_address_map = NULL;
        if (__supported_pte_mask & _PAGE_NX)
                runtime_code_page_mkexec();
        early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
        memmap.map = NULL;
+       kfree(new_memmap);
 }
 
 /*
index ac0621a7ac3d23383ed6f284451c5bb7d960f977..2649426a79055f5449c68e6e986baf6a0b150d43 100644 (file)
 static pgd_t save_pgd __initdata;
 static unsigned long efi_flags __initdata;
 
-static void __init early_mapping_set_exec(unsigned long start,
-                                         unsigned long end,
-                                         int executable)
-{
-       unsigned long num_pages;
-
-       start &= PMD_MASK;
-       end = (end + PMD_SIZE - 1) & PMD_MASK;
-       num_pages = (end - start) >> PAGE_SHIFT;
-       if (executable)
-               set_memory_x((unsigned long)__va(start), num_pages);
-       else
-               set_memory_nx((unsigned long)__va(start), num_pages);
-}
-
-static void __init early_runtime_code_mapping_set_exec(int executable)
+static void __init early_code_mapping_set_exec(int executable)
 {
        efi_memory_desc_t *md;
        void *p;
@@ -67,11 +52,8 @@ static void __init early_runtime_code_mapping_set_exec(int executable)
        /* Make EFI runtime service code area executable */
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
-               if (md->type == EFI_RUNTIME_SERVICES_CODE) {
-                       unsigned long end;
-                       end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-                       early_mapping_set_exec(md->phys_addr, end, executable);
-               }
+               if (md->type == EFI_RUNTIME_SERVICES_CODE)
+                       efi_set_executable(md, executable);
        }
 }
 
@@ -79,7 +61,7 @@ void __init efi_call_phys_prelog(void)
 {
        unsigned long vaddress;
 
-       early_runtime_code_mapping_set_exec(1);
+       early_code_mapping_set_exec(1);
        local_irq_save(efi_flags);
        vaddress = (unsigned long)__va(0x0UL);
        save_pgd = *pgd_offset_k(0x0UL);
@@ -95,7 +77,7 @@ void __init efi_call_phys_epilog(void)
        set_pgd(pgd_offset_k(0x0UL), save_pgd);
        __flush_tlb_all();
        local_irq_restore(efi_flags);
-       early_runtime_code_mapping_set_exec(0);
+       early_code_mapping_set_exec(0);
 }
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
@@ -107,8 +89,10 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
                return ioremap(phys_addr, size);
 
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
-       if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size)
-               return NULL;
+       if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {
+               unsigned long top = last_map_pfn << PAGE_SHIFT;
+               efi_ioremap(top, size - (top - phys_addr), type);
+       }
 
        return (void __iomem *)__va(phys_addr);
 }
index 275dbc19e2cf55f2e7cb55f1c3ad861cb976c8a6..7000e74b30877bea018f46946f8d99b1275e7624 100644 (file)
@@ -194,7 +194,7 @@ static unsigned long __init mrst_calibrate_tsc(void)
        return 0;
 }
 
-void __init mrst_time_init(void)
+static void __init mrst_time_init(void)
 {
        sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
        switch (mrst_timer_options) {
@@ -216,7 +216,7 @@ void __init mrst_time_init(void)
        apbt_time_init();
 }
 
-void __cpuinit mrst_arch_setup(void)
+static void __cpuinit mrst_arch_setup(void)
 {
        if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
                __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
index c2a8cab65e5d71f82404a9b6b118dc6556c79489..81c5e2165c2416be638675f83f887e1f8f52d218 100644 (file)
@@ -1,4 +1,2 @@
-obj-$(CONFIG_OLPC)             += olpc.o
+obj-$(CONFIG_OLPC)             += olpc.o olpc_ofw.o olpc_dt.o
 obj-$(CONFIG_OLPC_XO1)         += olpc-xo1.o
-obj-$(CONFIG_OLPC)             += olpc_ofw.o
-obj-$(CONFIG_OF_PROMTREE)      += olpc_dt.o
index edaf3fe8dc5e4b0326c0280042b868cd3400bf4c..0060fd59ea001baaf1b31769bb1bbe6c490709ca 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -187,41 +188,43 @@ err:
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
-static bool __init check_ofw_architecture(void)
+static bool __init check_ofw_architecture(struct device_node *root)
 {
-       size_t propsize;
-       char olpc_arch[5];
-       const void *args[] = { NULL, "architecture", olpc_arch, (void *)5 };
-       void *res[] = { &propsize };
+       const char *olpc_arch;
+       int propsize;
 
-       if (olpc_ofw("getprop", args, res)) {
-               printk(KERN_ERR "ofw: getprop call failed!\n");
-               return false;
-       }
+       olpc_arch = of_get_property(root, "architecture", &propsize);
        return propsize == 5 && strncmp("OLPC", olpc_arch, 5) == 0;
 }
 
-static u32 __init get_board_revision(void)
+static u32 __init get_board_revision(struct device_node *root)
 {
-       size_t propsize;
-       __be32 rev;
-       const void *args[] = { NULL, "board-revision-int", &rev, (void *)4 };
-       void *res[] = { &propsize };
-
-       if (olpc_ofw("getprop", args, res) || propsize != 4) {
-               printk(KERN_ERR "ofw: getprop call failed!\n");
-               return cpu_to_be32(0);
-       }
-       return be32_to_cpu(rev);
+       int propsize;
+       const __be32 *rev;
+
+       rev = of_get_property(root, "board-revision-int", &propsize);
+       if (propsize != 4)
+               return 0;
+
+       return be32_to_cpu(*rev);
 }
 
 static bool __init platform_detect(void)
 {
-       if (!check_ofw_architecture())
+       struct device_node *root = of_find_node_by_path("/");
+       bool success;
+
+       if (!root)
                return false;
-       olpc_platform_info.flags |= OLPC_F_PRESENT;
-       olpc_platform_info.boardrev = get_board_revision();
-       return true;
+
+       success = check_ofw_architecture(root);
+       if (success) {
+               olpc_platform_info.boardrev = get_board_revision(root);
+               olpc_platform_info.flags |= OLPC_F_PRESENT;
+       }
+
+       of_node_put(root);
+       return success;
 }
 
 static int __init add_xo1_platform_devices(void)
index 044bda5b3174f19c07a0fe9cb8b1ab1d77ca1b60..d39f63d017d2860aecc2f8b0237a56da5c3ca4c7 100644 (file)
@@ -19,7 +19,9 @@
 #include <linux/kernel.h>
 #include <linux/bootmem.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/of_pdt.h>
+#include <asm/olpc.h>
 #include <asm/olpc_ofw.h>
 
 static phandle __init olpc_dt_getsibling(phandle node)
@@ -180,3 +182,20 @@ void __init olpc_dt_build_devicetree(void)
        pr_info("PROM DT: Built device tree with %u bytes of memory.\n",
                        prom_early_allocated);
 }
+
+/* A list of DT node/bus matches that we want to expose as platform devices */
+static struct of_device_id __initdata of_ids[] = {
+       { .compatible = "olpc,xo1-battery" },
+       { .compatible = "olpc,xo1-dcon" },
+       { .compatible = "olpc,xo1-rtc" },
+       {},
+};
+
+static int __init olpc_create_platform_devices(void)
+{
+       if (machine_is_olpc())
+               return of_platform_bus_probe(NULL, of_ids, NULL);
+       else
+               return 0;
+}
+device_initcall(olpc_create_platform_devices);
index 7cb6424317f642bcbb44caabdd6c92cf0fbfa605..c58e0ea39ef5facdaa630fa8138cb77fb530aa06 100644 (file)
@@ -699,16 +699,17 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                                          struct mm_struct *mm,
                                          unsigned long va, unsigned int cpu)
 {
-       int tcpu;
-       int uvhub;
        int locals = 0;
        int remotes = 0;
        int hubs = 0;
+       int tcpu;
+       int tpnode;
        struct bau_desc *bau_desc;
        struct cpumask *flush_mask;
        struct ptc_stats *stat;
        struct bau_control *bcp;
        struct bau_control *tbcp;
+       struct hub_and_pnode *hpp;
 
        /* kernel was booted 'nobau' */
        if (nobau)
@@ -750,11 +751,18 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
        bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
 
-       /* cpu statistics */
        for_each_cpu(tcpu, flush_mask) {
-               uvhub = uv_cpu_to_blade_id(tcpu);
-               bau_uvhub_set(uvhub, &bau_desc->distribution);
-               if (uvhub == bcp->uvhub)
+               /*
+                * The distribution vector is a bit map of pnodes, relative
+                * to the partition base pnode (and the partition base nasid
+                * in the header).
+                * Translate cpu to pnode and hub using an array stored
+                * in local memory.
+                */
+               hpp = &bcp->socket_master->target_hub_and_pnode[tcpu];
+               tpnode = hpp->pnode - bcp->partition_base_pnode;
+               bau_uvhub_set(tpnode, &bau_desc->distribution);
+               if (hpp->uvhub == bcp->uvhub)
                        locals++;
                else
                        remotes++;
@@ -855,7 +863,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
  * an interrupt, but causes an error message to be returned to
  * the sender.
  */
-static void uv_enable_timeouts(void)
+static void __init uv_enable_timeouts(void)
 {
        int uvhub;
        int nuvhubs;
@@ -1326,10 +1334,10 @@ static int __init uv_ptc_init(void)
 }
 
 /*
- * initialize the sending side's sending buffers
+ * Initialize the sending side's sending buffers.
  */
 static void
-uv_activation_descriptor_init(int node, int pnode)
+uv_activation_descriptor_init(int node, int pnode, int base_pnode)
 {
        int i;
        int cpu;
@@ -1352,11 +1360,11 @@ uv_activation_descriptor_init(int node, int pnode)
        n = pa >> uv_nshift;
        m = pa & uv_mmask;
 
+       /* the 14-bit pnode */
        uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
                              (n << UV_DESC_BASE_PNODE_SHIFT | m));
-
        /*
-        * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
+        * Initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
         * cpu even though we only use the first one; one descriptor can
         * describe a broadcast to 256 uv hubs.
         */
@@ -1365,12 +1373,13 @@ uv_activation_descriptor_init(int node, int pnode)
                memset(bd2, 0, sizeof(struct bau_desc));
                bd2->header.sw_ack_flag = 1;
                /*
-                * base_dest_nodeid is the nasid of the first uvhub
-                * in the partition. The bit map will indicate uvhub numbers,
-                * which are 0-N in a partition. Pnodes are unique system-wide.
+                * The base_dest_nasid set in the message header is the nasid
+                * of the first uvhub in the partition. The bit map will
+                * indicate destination pnode numbers relative to that base.
+                * They may not be consecutive if nasid striding is being used.
                 */
-               bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode);
-               bd2->header.dest_subnodeid = 0x10; /* the LB */
+               bd2->header.base_dest_nasid = UV_PNODE_TO_NASID(base_pnode);
+               bd2->header.dest_subnodeid = UV_LB_SUBNODEID;
                bd2->header.command = UV_NET_ENDPOINT_INTD;
                bd2->header.int_both = 1;
                /*
@@ -1442,7 +1451,7 @@ uv_payload_queue_init(int node, int pnode)
 /*
  * Initialization of each UV hub's structures
  */
-static void __init uv_init_uvhub(int uvhub, int vector)
+static void __init uv_init_uvhub(int uvhub, int vector, int base_pnode)
 {
        int node;
        int pnode;
@@ -1450,11 +1459,11 @@ static void __init uv_init_uvhub(int uvhub, int vector)
 
        node = uvhub_to_first_node(uvhub);
        pnode = uv_blade_to_pnode(uvhub);
-       uv_activation_descriptor_init(node, pnode);
+       uv_activation_descriptor_init(node, pnode, base_pnode);
        uv_payload_queue_init(node, pnode);
        /*
-        * the below initialization can't be in firmware because the
-        * messaging IRQ will be determined by the OS
+        * The below initialization can't be in firmware because the
+        * messaging IRQ will be determined by the OS.
         */
        apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
        uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
@@ -1491,10 +1500,11 @@ calculate_destination_timeout(void)
 /*
  * initialize the bau_control structure for each cpu
  */
-static int __init uv_init_per_cpu(int nuvhubs)
+static int __init uv_init_per_cpu(int nuvhubs, int base_part_pnode)
 {
        int i;
        int cpu;
+       int tcpu;
        int pnode;
        int uvhub;
        int have_hmaster;
@@ -1528,6 +1538,15 @@ static int __init uv_init_per_cpu(int nuvhubs)
                bcp = &per_cpu(bau_control, cpu);
                memset(bcp, 0, sizeof(struct bau_control));
                pnode = uv_cpu_hub_info(cpu)->pnode;
+               if ((pnode - base_part_pnode) >= UV_DISTRIBUTION_SIZE) {
+                       printk(KERN_EMERG
+                               "cpu %d pnode %d-%d beyond %d; BAU disabled\n",
+                               cpu, pnode, base_part_pnode,
+                               UV_DISTRIBUTION_SIZE);
+                       return 1;
+               }
+               bcp->osnode = cpu_to_node(cpu);
+               bcp->partition_base_pnode = uv_partition_base_pnode;
                uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
                *(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8));
                bdp = &uvhub_descs[uvhub];
@@ -1536,7 +1555,7 @@ static int __init uv_init_per_cpu(int nuvhubs)
                bdp->pnode = pnode;
                /* kludge: 'assuming' one node per socket, and assuming that
                   disabling a socket just leaves a gap in node numbers */
-               socket = (cpu_to_node(cpu) & 1);
+               socket = bcp->osnode & 1;
                bdp->socket_mask |= (1 << socket);
                sdp = &bdp->socket[socket];
                sdp->cpu_number[sdp->num_cpus] = cpu;
@@ -1585,6 +1604,20 @@ static int __init uv_init_per_cpu(int nuvhubs)
 nextsocket:
                        socket++;
                        socket_mask = (socket_mask >> 1);
+                       /* each socket gets a local array of pnodes/hubs */
+                       bcp = smaster;
+                       bcp->target_hub_and_pnode = kmalloc_node(
+                               sizeof(struct hub_and_pnode) *
+                               num_possible_cpus(), GFP_KERNEL, bcp->osnode);
+                       memset(bcp->target_hub_and_pnode, 0,
+                               sizeof(struct hub_and_pnode) *
+                               num_possible_cpus());
+                       for_each_present_cpu(tcpu) {
+                               bcp->target_hub_and_pnode[tcpu].pnode =
+                                       uv_cpu_hub_info(tcpu)->pnode;
+                               bcp->target_hub_and_pnode[tcpu].uvhub =
+                                       uv_cpu_hub_info(tcpu)->numa_blade_id;
+                       }
                }
        }
        kfree(uvhub_descs);
@@ -1637,21 +1670,22 @@ static int __init uv_bau_init(void)
        spin_lock_init(&disable_lock);
        congested_cycles = microsec_2_cycles(congested_response_us);
 
-       if (uv_init_per_cpu(nuvhubs)) {
-               nobau = 1;
-               return 0;
-       }
-
        uv_partition_base_pnode = 0x7fffffff;
-       for (uvhub = 0; uvhub < nuvhubs; uvhub++)
+       for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
                if (uv_blade_nr_possible_cpus(uvhub) &&
                        (uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
                        uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
+       }
+
+       if (uv_init_per_cpu(nuvhubs, uv_partition_base_pnode)) {
+               nobau = 1;
+               return 0;
+       }
 
        vector = UV_BAU_MESSAGE;
        for_each_possible_blade(uvhub)
                if (uv_blade_nr_possible_cpus(uvhub))
-                       uv_init_uvhub(uvhub, vector);
+                       uv_init_uvhub(uvhub, vector, uv_partition_base_pnode);
 
        uv_enable_timeouts();
        alloc_intr_gate(vector, uv_bau_message_intr1);
index 9daf5d1af9f190015b8b9be646aac14cbe6c2c44..0eb90184515fe132c42b3fb8459f55671c71bd8d 100644 (file)
@@ -40,7 +40,6 @@ static struct clocksource clocksource_uv = {
        .rating         = 400,
        .read           = uv_read_rtc,
        .mask           = (cycle_t)UVH_RTC_REAL_TIME_CLOCK_MASK,
-       .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -372,14 +371,11 @@ static __init int uv_rtc_setup_clock(void)
        if (!is_uv_system())
                return -ENODEV;
 
-       clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
-                               clocksource_uv.shift);
-
        /* If single blade, prefer tsc */
        if (uv_num_possible_blades() == 1)
                clocksource_uv.rating = 250;
 
-       rc = clocksource_register(&clocksource_uv);
+       rc = clocksource_register_hz(&clocksource_uv, sn_rtc_cycles_per_second);
        if (rc)
                printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
        else
index e3c6a06cf725ef08b87a5961b33043bbf493acf3..dd7b88f2ec7a6f30bf4ec628fc7f59112cf4d65e 100644 (file)
@@ -235,7 +235,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
        *dx &= maskedx;
 }
 
-static __init void xen_init_cpuid_mask(void)
+static void __init xen_init_cpuid_mask(void)
 {
        unsigned int ax, bx, cx, dx;
        unsigned int xsave_mask;
@@ -400,7 +400,7 @@ static void xen_load_gdt(const struct desc_ptr *dtr)
 /*
  * load_gdt for early boot, when the gdt is only mapped once
  */
-static __init void xen_load_gdt_boot(const struct desc_ptr *dtr)
+static void __init xen_load_gdt_boot(const struct desc_ptr *dtr)
 {
        unsigned long va = dtr->address;
        unsigned int size = dtr->size + 1;
@@ -662,7 +662,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
  * Version of write_gdt_entry for use at early boot-time needed to
  * update an entry as simply as possible.
  */
-static __init void xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
+static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
                                            const void *desc, int type)
 {
        switch (type) {
@@ -933,18 +933,18 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
        return ret;
 }
 
-static const struct pv_info xen_info __initdata = {
+static const struct pv_info xen_info __initconst = {
        .paravirt_enabled = 1,
        .shared_kernel_pmd = 0,
 
        .name = "Xen",
 };
 
-static const struct pv_init_ops xen_init_ops __initdata = {
+static const struct pv_init_ops xen_init_ops __initconst = {
        .patch = xen_patch,
 };
 
-static const struct pv_cpu_ops xen_cpu_ops __initdata = {
+static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .cpuid = xen_cpuid,
 
        .set_debugreg = xen_set_debugreg,
@@ -1004,7 +1004,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
        .end_context_switch = xen_end_context_switch,
 };
 
-static const struct pv_apic_ops xen_apic_ops __initdata = {
+static const struct pv_apic_ops xen_apic_ops __initconst = {
 #ifdef CONFIG_X86_LOCAL_APIC
        .startup_ipi_hook = paravirt_nop,
 #endif
@@ -1055,7 +1055,7 @@ int xen_panic_handler_init(void)
        return 0;
 }
 
-static const struct machine_ops __initdata xen_machine_ops = {
+static const struct machine_ops xen_machine_ops __initconst = {
        .restart = xen_restart,
        .halt = xen_machine_halt,
        .power_off = xen_machine_halt,
@@ -1332,7 +1332,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
+static struct notifier_block xen_hvm_cpu_notifier __cpuinitdata = {
        .notifier_call  = xen_hvm_cpu_notify,
 };
 
@@ -1381,7 +1381,7 @@ bool xen_hvm_need_lapic(void)
 }
 EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
 
-const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
+const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
        .name                   = "Xen HVM",
        .detect                 = xen_hvm_platform,
        .init_platform          = xen_hvm_guest_init,
index 6a6fe8939645f948e248cbaf21933675899b5c62..8bbb465b6f0aa32ebff23cc9d4a883b44a8da4fe 100644 (file)
@@ -113,7 +113,7 @@ static void xen_halt(void)
                xen_safe_halt();
 }
 
-static const struct pv_irq_ops xen_irq_ops __initdata = {
+static const struct pv_irq_ops xen_irq_ops __initconst = {
        .save_fl = PV_CALLEE_SAVE(xen_save_fl),
        .restore_fl = PV_CALLEE_SAVE(xen_restore_fl),
        .irq_disable = PV_CALLEE_SAVE(xen_irq_disable),
index a991b57f91fe26ae944bdd11a5f03db9307bbf5b..02d7524603710bf1afed949598645f6ebab2413b 100644 (file)
@@ -1054,7 +1054,7 @@ void xen_mm_pin_all(void)
  * that's before we have page structures to store the bits.  So do all
  * the book-keeping now.
  */
-static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page,
+static int __init xen_mark_pinned(struct mm_struct *mm, struct page *page,
                                  enum pt_level level)
 {
        SetPagePinned(page);
@@ -1187,7 +1187,7 @@ static void drop_other_mm_ref(void *info)
 
        active_mm = percpu_read(cpu_tlbstate.active_mm);
 
-       if (active_mm == mm)
+       if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK)
                leave_mm(smp_processor_id());
 
        /* If this cpu still has a stale cr3 reference, then make sure
@@ -1271,13 +1271,27 @@ void xen_exit_mmap(struct mm_struct *mm)
        spin_unlock(&mm->page_table_lock);
 }
 
-static __init void xen_pagetable_setup_start(pgd_t *base)
+static void __init xen_pagetable_setup_start(pgd_t *base)
 {
 }
 
+static __init void xen_mapping_pagetable_reserve(u64 start, u64 end)
+{
+       /* reserve the range used */
+       native_pagetable_reserve(start, end);
+
+       /* set as RW the rest */
+       printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n", end,
+                       PFN_PHYS(pgt_buf_top));
+       while (end < PFN_PHYS(pgt_buf_top)) {
+               make_lowmem_page_readwrite(__va(end));
+               end += PAGE_SIZE;
+       }
+}
+
 static void xen_post_allocator_init(void);
 
-static __init void xen_pagetable_setup_done(pgd_t *base)
+static void __init xen_pagetable_setup_done(pgd_t *base)
 {
        xen_setup_shared_info();
        xen_post_allocator_init();
@@ -1473,16 +1487,20 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #endif
 }
 
-static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
-{
-       unsigned long pfn = pte_pfn(pte);
-
 #ifdef CONFIG_X86_32
+static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
+{
        /* If there's an existing pte, then don't allow _PAGE_RW to be set */
        if (pte_val_ma(*ptep) & _PAGE_PRESENT)
                pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
                               pte_val_ma(pte));
-#endif
+
+       return pte;
+}
+#else /* CONFIG_X86_64 */
+static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
+{
+       unsigned long pfn = pte_pfn(pte);
 
        /*
         * If the new pfn is within the range of the newly allocated
@@ -1491,16 +1509,17 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
         * it is RO.
         */
        if (((!is_early_ioremap_ptep(ptep) &&
-                       pfn >= pgt_buf_start && pfn < pgt_buf_end)) ||
+                       pfn >= pgt_buf_start && pfn < pgt_buf_top)) ||
                        (is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1)))
                pte = pte_wrprotect(pte);
 
        return pte;
 }
+#endif /* CONFIG_X86_64 */
 
 /* Init-time set_pte while constructing initial pagetables, which
    doesn't allow RO pagetable pages to be remapped RW */
-static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
+static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
 {
        pte = mask_rw_pte(ptep, pte);
 
@@ -1518,7 +1537,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
 
 /* Early in boot, while setting up the initial pagetable, assume
    everything is pinned. */
-static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
+static void __init xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
 {
 #ifdef CONFIG_FLATMEM
        BUG_ON(mem_map);        /* should only be used early */
@@ -1528,7 +1547,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
 }
 
 /* Used for pmd and pud */
-static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn)
+static void __init xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn)
 {
 #ifdef CONFIG_FLATMEM
        BUG_ON(mem_map);        /* should only be used early */
@@ -1538,13 +1557,13 @@ static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn)
 
 /* Early release_pte assumes that all pts are pinned, since there's
    only init_mm and anything attached to that is pinned. */
-static __init void xen_release_pte_init(unsigned long pfn)
+static void __init xen_release_pte_init(unsigned long pfn)
 {
        pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
        make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
 }
 
-static __init void xen_release_pmd_init(unsigned long pfn)
+static void __init xen_release_pmd_init(unsigned long pfn)
 {
        make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
 }
@@ -1670,7 +1689,7 @@ static void set_page_prot(void *addr, pgprot_t prot)
                BUG();
 }
 
-static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
+static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 {
        unsigned pmdidx, pteidx;
        unsigned ident_pte;
@@ -1753,7 +1772,7 @@ static void convert_pfn_mfn(void *v)
  * of the physical mapping once some sort of allocator has been set
  * up.
  */
-__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
+pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
                                         unsigned long max_pfn)
 {
        pud_t *l3;
@@ -1824,7 +1843,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
 static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
 static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
 
-static __init void xen_write_cr3_init(unsigned long cr3)
+static void __init xen_write_cr3_init(unsigned long cr3)
 {
        unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
 
@@ -1861,7 +1880,7 @@ static __init void xen_write_cr3_init(unsigned long cr3)
        pv_mmu_ops.write_cr3 = &xen_write_cr3;
 }
 
-__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
+pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
                                         unsigned long max_pfn)
 {
        pmd_t *kernel_pmd;
@@ -1967,7 +1986,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 #endif
 }
 
-__init void xen_ident_map_ISA(void)
+void __init xen_ident_map_ISA(void)
 {
        unsigned long pa;
 
@@ -1990,7 +2009,7 @@ __init void xen_ident_map_ISA(void)
        xen_flush_tlb();
 }
 
-static __init void xen_post_allocator_init(void)
+static void __init xen_post_allocator_init(void)
 {
 #ifdef CONFIG_XEN_DEBUG
        pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
@@ -2027,7 +2046,7 @@ static void xen_leave_lazy_mmu(void)
        preempt_enable();
 }
 
-static const struct pv_mmu_ops xen_mmu_ops __initdata = {
+static const struct pv_mmu_ops xen_mmu_ops __initconst = {
        .read_cr2 = xen_read_cr2,
        .write_cr2 = xen_write_cr2,
 
@@ -2100,6 +2119,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
 
 void __init xen_init_mmu_ops(void)
 {
+       x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
        x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start;
        x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
        pv_mmu_ops = xen_mmu_ops;
index 141eb0de8b06f82d2fb9f42eb2e2af18d3969f0e..58efeb9d5440b75d2fd6d3cb5880f4ddd2729130 100644 (file)
@@ -522,11 +522,20 @@ static bool __init __early_alloc_p2m(unsigned long pfn)
        /* Boundary cross-over for the edges: */
        if (idx) {
                unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               unsigned long *mid_mfn_p;
 
                p2m_init(p2m);
 
                p2m_top[topidx][mididx] = p2m;
 
+               /* For save/restore we need to MFN of the P2M saved */
+               
+               mid_mfn_p = p2m_top_mfn_p[topidx];
+               WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing),
+                       "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n",
+                       topidx, mididx);
+               mid_mfn_p[mididx] = virt_to_mfn(p2m);
+
        }
        return idx != 0;
 }
@@ -549,12 +558,29 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
                pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
        {
                unsigned topidx = p2m_top_index(pfn);
-               if (p2m_top[topidx] == p2m_mid_missing) {
-                       unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               unsigned long *mid_mfn_p;
+               unsigned long **mid;
+
+               mid = p2m_top[topidx];
+               mid_mfn_p = p2m_top_mfn_p[topidx];
+               if (mid == p2m_mid_missing) {
+                       mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
 
                        p2m_mid_init(mid);
 
                        p2m_top[topidx] = mid;
+
+                       BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
+               }
+               /* And the save/restore P2M tables.. */
+               if (mid_mfn_p == p2m_mid_missing_mfn) {
+                       mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+                       p2m_mid_mfn_init(mid_mfn_p);
+
+                       p2m_top_mfn_p[topidx] = mid_mfn_p;
+                       p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
+                       /* Note: we don't set mid_mfn_p[midix] here,
+                        * look in __early_alloc_p2m */
                }
        }
 
@@ -650,7 +676,7 @@ static unsigned long mfn_hash(unsigned long mfn)
 }
 
 /* Add an MFN override for a particular page */
-int m2p_add_override(unsigned long mfn, struct page *page)
+int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
 {
        unsigned long flags;
        unsigned long pfn;
@@ -662,7 +688,6 @@ int m2p_add_override(unsigned long mfn, struct page *page)
        if (!PageHighMem(page)) {
                address = (unsigned long)__va(pfn << PAGE_SHIFT);
                ptep = lookup_address(address, &level);
-
                if (WARN(ptep == NULL || level != PG_LEVEL_4K,
                                        "m2p_add_override: pfn %lx not mapped", pfn))
                        return -EINVAL;
@@ -674,18 +699,17 @@ int m2p_add_override(unsigned long mfn, struct page *page)
        if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
                return -ENOMEM;
 
-       if (!PageHighMem(page))
+       if (clear_pte && !PageHighMem(page))
                /* Just zap old mapping for now */
                pte_clear(&init_mm, address, ptep);
-
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
 
        return 0;
 }
-
-int m2p_remove_override(struct page *page)
+EXPORT_SYMBOL_GPL(m2p_add_override);
+int m2p_remove_override(struct page *page, bool clear_pte)
 {
        unsigned long flags;
        unsigned long mfn;
@@ -713,7 +737,7 @@ int m2p_remove_override(struct page *page)
        spin_unlock_irqrestore(&m2p_override_lock, flags);
        set_phys_to_machine(pfn, page->index);
 
-       if (!PageHighMem(page))
+       if (clear_pte && !PageHighMem(page))
                set_pte_at(&init_mm, address, ptep,
                                pfn_pte(pfn, PAGE_KERNEL));
                /* No tlb flush necessary because the caller already
@@ -721,6 +745,7 @@ int m2p_remove_override(struct page *page)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(m2p_remove_override);
 
 struct page *m2p_find_override(unsigned long mfn)
 {
index fa0269a993773f8488f765c3a1e255ba59fd4e3f..be1a464f6d66eac7f6d24ae74894b321dc1cd4b5 100644 (file)
@@ -50,7 +50,7 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
  */
 #define EXTRA_MEM_RATIO                (10)
 
-static __init void xen_add_extra_mem(unsigned long pages)
+static void __init xen_add_extra_mem(unsigned long pages)
 {
        unsigned long pfn;
 
@@ -166,7 +166,7 @@ static unsigned long __init xen_set_identity(const struct e820entry *list,
                if (last > end)
                        continue;
 
-               if (entry->type == E820_RAM) {
+               if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) {
                        if (start > start_pci)
                                identity += set_phys_range_identity(
                                                PFN_UP(start_pci), PFN_DOWN(start));
@@ -227,7 +227,11 @@ char * __init xen_memory_setup(void)
 
        memcpy(map_raw, map, sizeof(map));
        e820.nr_map = 0;
+#ifdef CONFIG_X86_32
        xen_extra_mem_start = mem_end;
+#else
+       xen_extra_mem_start = max((1ULL << 32), mem_end);
+#endif
        for (i = 0; i < memmap.nr_entries; i++) {
                unsigned long long end;
 
@@ -336,7 +340,7 @@ static void __init fiddle_vdso(void)
 #endif
 }
 
-static __cpuinit int register_callback(unsigned type, const void *func)
+static int __cpuinit register_callback(unsigned type, const void *func)
 {
        struct callback_register callback = {
                .type = type,
index 30612441ed9991b7e34c64a97c513d65e8061826..41038c01de403e48c71052ab615dcf7f647f2653 100644 (file)
@@ -46,18 +46,17 @@ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
 static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
 
 /*
- * Reschedule call back. Nothing to do,
- * all the work is done automatically when
- * we return from the interrupt.
+ * Reschedule call back.
  */
 static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
 {
        inc_irq_stat(irq_resched_count);
+       scheduler_ipi();
 
        return IRQ_HANDLED;
 }
 
-static __cpuinit void cpu_bringup(void)
+static void __cpuinit cpu_bringup(void)
 {
        int cpu = smp_processor_id();
 
@@ -85,7 +84,7 @@ static __cpuinit void cpu_bringup(void)
        wmb();                  /* make sure everything is out */
 }
 
-static __cpuinit void cpu_bringup_and_idle(void)
+static void __cpuinit cpu_bringup_and_idle(void)
 {
        cpu_bringup();
        cpu_idle();
@@ -242,7 +241,7 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
        }
 }
 
-static __cpuinit int
+static int __cpuinit
 cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 {
        struct vcpu_guest_context *ctxt;
@@ -486,7 +485,7 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static const struct smp_ops xen_smp_ops __initdata = {
+static const struct smp_ops xen_smp_ops __initconst = {
        .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
        .smp_prepare_cpus = xen_smp_prepare_cpus,
        .smp_cpus_done = xen_smp_cpus_done,
index 2e2d370a47b1517bf1caa2503c04a96e1fa3b79a..5158c505bef9772400d263c3e895178820f5b305 100644 (file)
@@ -26,8 +26,6 @@
 
 #include "xen-ops.h"
 
-#define XEN_SHIFT 22
-
 /* Xen may fire a timer up to this many ns early */
 #define TIMER_SLOP     100000
 #define NS_PER_TICK    (1000000000LL / HZ)
@@ -211,8 +209,6 @@ static struct clocksource xen_clocksource __read_mostly = {
        .rating = 400,
        .read = xen_clocksource_get_cycles,
        .mask = ~0,
-       .mult = 1<<XEN_SHIFT,           /* time directly in nanoseconds */
-       .shift = XEN_SHIFT,
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -439,16 +435,16 @@ void xen_timer_resume(void)
        }
 }
 
-static const struct pv_time_ops xen_time_ops __initdata = {
+static const struct pv_time_ops xen_time_ops __initconst = {
        .sched_clock = xen_clocksource_read,
 };
 
-static __init void xen_time_init(void)
+static void __init xen_time_init(void)
 {
        int cpu = smp_processor_id();
        struct timespec tp;
 
-       clocksource_register(&xen_clocksource);
+       clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
 
        if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) {
                /* Successfully turned off 100Hz tick, so we have the
@@ -468,7 +464,7 @@ static __init void xen_time_init(void)
        xen_setup_cpu_clockevents();
 }
 
-__init void xen_init_time_ops(void)
+void __init xen_init_time_ops(void)
 {
        pv_time_ops = xen_time_ops;
 
@@ -490,7 +486,7 @@ static void xen_hvm_setup_cpu_clockevents(void)
        xen_setup_cpu_clockevents();
 }
 
-__init void xen_hvm_init_time_ops(void)
+void __init xen_hvm_init_time_ops(void)
 {
        /* vector callback is needed otherwise we cannot receive interrupts
         * on cpu > 0 and at this point we don't know how many cpus are
index 3112f55638c4ae67106c8964bfc9eb90e332145a..97dfdc8757b3303cb86a0b28f9d1b497c640f68f 100644 (file)
@@ -74,7 +74,7 @@ static inline void xen_hvm_smp_init(void) {}
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
 void __init xen_init_spinlocks(void);
-__cpuinit void xen_init_lock_cpu(int cpu);
+void __cpuinit xen_init_lock_cpu(int cpu);
 void xen_uninit_lock_cpu(int cpu);
 #else
 static inline void xen_init_spinlocks(void)
index d77089df412e156fb4784f7d3913af0b21d68980..4340ee076bd522f88229aae7f474ce4a59493a40 100644 (file)
@@ -64,47 +64,41 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
-       int j;
-
-       seq_printf(p, "%*s: ", prec, "NMI");
-       for_each_online_cpu(j)
-               seq_printf(p, "%10u ", nmi_count(j));
-       seq_putc(p, '\n');
        seq_printf(p, "%*s: ", prec, "ERR");
        seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
        return 0;
 }
 
-static void xtensa_irq_mask(struct irq_chip *d)
+static void xtensa_irq_mask(struct irq_data *d)
 {
        cached_irq_mask &= ~(1 << d->irq);
        set_sr (cached_irq_mask, INTENABLE);
 }
 
-static void xtensa_irq_unmask(struct irq_chip *d)
+static void xtensa_irq_unmask(struct irq_data *d)
 {
        cached_irq_mask |= 1 << d->irq;
        set_sr (cached_irq_mask, INTENABLE);
 }
 
-static void xtensa_irq_enable(struct irq_chip *d)
+static void xtensa_irq_enable(struct irq_data *d)
 {
        variant_irq_enable(d->irq);
        xtensa_irq_unmask(d->irq);
 }
 
-static void xtensa_irq_disable(struct irq_chip *d)
+static void xtensa_irq_disable(struct irq_data *d)
 {
        xtensa_irq_mask(d->irq);
        variant_irq_disable(d->irq);
 }
 
-static void xtensa_irq_ack(struct irq_chip *d)
+static void xtensa_irq_ack(struct irq_data *d)
 {
        set_sr(1 << d->irq, INTCLEAR);
 }
 
-static int xtensa_irq_retrigger(struct irq_chip *d)
+static int xtensa_irq_retrigger(struct irq_data *d)
 {
        set_sr (1 << d->irq, INTSET);
        return 1;
index f0605ab2a76119dd94bccd5809ad881443c25fd7..471fdcc5df85e3135dfefac29aa81a889d0ed567 100644 (file)
@@ -114,6 +114,13 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
 }
 EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
 
+struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk)
+{
+       return container_of(task_subsys_state(tsk, blkio_subsys_id),
+                           struct blkio_cgroup, css);
+}
+EXPORT_SYMBOL_GPL(task_blkio_cgroup);
+
 static inline void
 blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
 {
index 10919fae2d3aa2e6ebc1e3cdc2d1636939c997ad..c774930cc20659de992ccebc21d35ffd1e80e234 100644 (file)
@@ -291,6 +291,7 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 extern struct blkio_cgroup blkio_root_cgroup;
 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
+extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk);
 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
        struct blkio_group *blkg, void *key, dev_t dev,
        enum blkio_policy_id plid);
@@ -314,6 +315,8 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg,
 struct cgroup;
 static inline struct blkio_cgroup *
 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
+static inline struct blkio_cgroup *
+task_blkio_cgroup(struct task_struct *tsk) { return NULL; }
 
 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
                struct blkio_group *blkg, void *key, dev_t dev,
index 5fa3dd2705c61f88fd2315974d8081881f0f860e..3fe00a14822a203cacc0529ad0610cf5ce7dae06 100644 (file)
@@ -292,7 +292,6 @@ EXPORT_SYMBOL(blk_sync_queue);
 /**
  * __blk_run_queue - run a single device queue
  * @q: The queue to run
- * @force_kblockd: Don't run @q->request_fn directly.  Use kblockd.
  *
  * Description:
  *    See @blk_run_queue. This variant must be called with the queue lock
@@ -303,15 +302,7 @@ void __blk_run_queue(struct request_queue *q)
        if (unlikely(blk_queue_stopped(q)))
                return;
 
-       /*
-        * Only recurse once to avoid overrunning the stack, let the unplug
-        * handling reinvoke the handler shortly if we already got there.
-        */
-       if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
-               q->request_fn(q);
-               queue_flag_clear(QUEUE_FLAG_REENTER, q);
-       } else
-               queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
+       q->request_fn(q);
 }
 EXPORT_SYMBOL(__blk_run_queue);
 
@@ -325,9 +316,12 @@ EXPORT_SYMBOL(__blk_run_queue);
  */
 void blk_run_queue_async(struct request_queue *q)
 {
-       if (likely(!blk_queue_stopped(q)))
+       if (likely(!blk_queue_stopped(q))) {
+               __cancel_delayed_work(&q->delay_work);
                queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
+       }
 }
+EXPORT_SYMBOL(blk_run_queue_async);
 
 /**
  * blk_run_queue - run a single device queue
@@ -2787,7 +2781,6 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 
        local_irq_restore(flags);
 }
-EXPORT_SYMBOL(blk_flush_plug_list);
 
 void blk_finish_plug(struct blk_plug *plug)
 {
index 6d735122bc59499693d8682d4730c92ff63c91be..bd236313f35d59bd08da5a3d375cc29eed6fd86f 100644 (file)
@@ -66,14 +66,14 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 
        if (rl->count[BLK_RW_SYNC] >= q->nr_requests) {
                blk_set_queue_full(q, BLK_RW_SYNC);
-       } else if (rl->count[BLK_RW_SYNC]+1 <= q->nr_requests) {
+       } else {
                blk_clear_queue_full(q, BLK_RW_SYNC);
                wake_up(&rl->wait[BLK_RW_SYNC]);
        }
 
        if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) {
                blk_set_queue_full(q, BLK_RW_ASYNC);
-       } else if (rl->count[BLK_RW_ASYNC]+1 <= q->nr_requests) {
+       } else {
                blk_clear_queue_full(q, BLK_RW_ASYNC);
                wake_up(&rl->wait[BLK_RW_ASYNC]);
        }
@@ -508,8 +508,10 @@ int blk_register_queue(struct gendisk *disk)
                return ret;
 
        ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
-       if (ret < 0)
+       if (ret < 0) {
+               blk_trace_remove_sysfs(dev);
                return ret;
+       }
 
        kobject_uevent(&q->kobj, KOBJ_ADD);
 
index 0475a22a420dfb09d34ba51698e8b2a07f391b32..252a81a306f7bef0179f953ab1535a4a06a40798 100644 (file)
@@ -160,9 +160,8 @@ static void throtl_put_tg(struct throtl_grp *tg)
 }
 
 static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
-                       struct cgroup *cgroup)
+                       struct blkio_cgroup *blkcg)
 {
-       struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
        struct throtl_grp *tg = NULL;
        void *key = td;
        struct backing_dev_info *bdi = &td->queue->backing_dev_info;
@@ -229,12 +228,12 @@ done:
 
 static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
 {
-       struct cgroup *cgroup;
        struct throtl_grp *tg = NULL;
+       struct blkio_cgroup *blkcg;
 
        rcu_read_lock();
-       cgroup = task_cgroup(current, blkio_subsys_id);
-       tg = throtl_find_alloc_tg(td, cgroup);
+       blkcg = task_blkio_cgroup(current);
+       tg = throtl_find_alloc_tg(td, blkcg);
        if (!tg)
                tg = &td->root_tg;
        rcu_read_unlock();
index c9df8fc3c99979de8fe21f439b82989d1361e859..61263463e38e17be7c7f742f0bbe9233eec2ecd2 100644 (file)
@@ -22,7 +22,6 @@ void blk_rq_timed_out_timer(unsigned long data);
 void blk_delete_timer(struct request *);
 void blk_add_timer(struct request *);
 void __generic_unplug_device(struct request_queue *);
-void blk_run_queue_async(struct request_queue *q);
 
 /*
  * Internal atomic flags for request handling
index 46b0a1d1d925703d32d5f796ea400f43542e0b3d..ab7a9e6a9b1cb12c1952f5fd725ca2ea0dd20fd1 100644 (file)
@@ -1014,10 +1014,9 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
        cfqg->needs_update = true;
 }
 
-static struct cfq_group *
-cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
+static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd,
+               struct blkio_cgroup *blkcg, int create)
 {
-       struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
        struct cfq_group *cfqg = NULL;
        void *key = cfqd;
        int i, j;
@@ -1079,12 +1078,12 @@ done:
  */
 static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
 {
-       struct cgroup *cgroup;
+       struct blkio_cgroup *blkcg;
        struct cfq_group *cfqg = NULL;
 
        rcu_read_lock();
-       cgroup = task_cgroup(current, blkio_subsys_id);
-       cfqg = cfq_find_alloc_cfqg(cfqd, cgroup, create);
+       blkcg = task_blkio_cgroup(current);
+       cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create);
        if (!cfqg && create)
                cfqg = &cfqd->root_group;
        rcu_read_unlock();
@@ -2582,28 +2581,20 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
 }
 
 /*
- * Must always be called with the rcu_read_lock() held
+ * Call func for each cic attached to this ioc.
  */
 static void
-__call_for_each_cic(struct io_context *ioc,
-                   void (*func)(struct io_context *, struct cfq_io_context *))
+call_for_each_cic(struct io_context *ioc,
+                 void (*func)(struct io_context *, struct cfq_io_context *))
 {
        struct cfq_io_context *cic;
        struct hlist_node *n;
 
+       rcu_read_lock();
+
        hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
                func(ioc, cic);
-}
 
-/*
- * Call func for each cic attached to this ioc.
- */
-static void
-call_for_each_cic(struct io_context *ioc,
-                 void (*func)(struct io_context *, struct cfq_io_context *))
-{
-       rcu_read_lock();
-       __call_for_each_cic(ioc, func);
        rcu_read_unlock();
 }
 
@@ -2664,7 +2655,7 @@ static void cfq_free_io_context(struct io_context *ioc)
         * should be ok to iterate over the known list, we will see all cic's
         * since no new ones are added.
         */
-       __call_for_each_cic(ioc, cic_free_func);
+       call_for_each_cic(ioc, cic_free_func);
 }
 
 static void cfq_put_cooperator(struct cfq_queue *cfqq)
index 6f6abc08bb565e61d63294e1a14f66ac6cda6a3d..45ca1e34f58249ff5b3838c0ec89fbc1c6ea2bb7 100644 (file)
@@ -671,7 +671,8 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
                        q->boundary_rq = rq;
                }
        } else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
-                   where == ELEVATOR_INSERT_SORT)
+                   (where == ELEVATOR_INSERT_SORT ||
+                    where == ELEVATOR_INSERT_SORT_MERGE))
                where = ELEVATOR_INSERT_BACK;
 
        switch (where) {
index b364bd038a18f76fc5461d5f9c7e1186d696fb31..2dd988723d73e98880d271b84dc77ef36b49a0a9 100644 (file)
@@ -1588,9 +1588,13 @@ static void disk_events_workfn(struct work_struct *work)
 
        spin_unlock_irq(&ev->lock);
 
-       /* tell userland about new events */
+       /*
+        * Tell userland about new events.  Only the events listed in
+        * @disk->events are reported.  Unlisted events are processed the
+        * same internally but never get reported to userland.
+        */
        for (i = 0; i < ARRAY_SIZE(disk_uevents); i++)
-               if (events & (1 << i))
+               if (events & disk->events & (1 << i))
                        envp[nr_events++] = disk_uevents[i];
 
        if (nr_events)
index 177c7d15693309fe6d00a6a51db79cb25d26cf5b..557a469c7aa61bbd7905d0805521dc4cb38b5bcf 100644 (file)
@@ -119,4 +119,7 @@ source "drivers/platform/Kconfig"
 source "drivers/clk/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
+
+source "drivers/clocksource/Kconfig"
+
 endmenu
index 3a73a93596e88a29c1e66fabec91dd2d0db96f6c..85b32376dad7e7d133b68515a1c0baba5f96ffa0 100644 (file)
@@ -49,10 +49,6 @@ ACPI_MODULE_NAME("processor_perflib");
 
 static DEFINE_MUTEX(performance_mutex);
 
-/* Use cpufreq debug layer for _PPC changes. */
-#define cpufreq_printk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
-                                               "cpufreq-core", msg)
-
 /*
  * _PPC support is implemented as a CPUfreq policy notifier:
  * This means each time a CPUfreq driver registered also with
@@ -145,7 +141,7 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
                return -ENODEV;
        }
 
-       cpufreq_printk("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
+       pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
                       (int)ppc, ppc ? "" : "not");
 
        pr->performance_platform_limit = (int)ppc;
index ad350173956338cc75ece02f3159b5f1b150b8e4..605a2954ef175e563db7d212d2184c924b7b5013 100644 (file)
@@ -710,20 +710,14 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
 }
 
 #ifdef CONFIG_X86
-static int acpi_throttling_rdmsr(struct acpi_processor *pr,
-                                       u64 *value)
+static int acpi_throttling_rdmsr(u64 *value)
 {
-       struct cpuinfo_x86 *c;
        u64 msr_high, msr_low;
-       unsigned int cpu;
        u64 msr = 0;
        int ret = -1;
 
-       cpu = pr->id;
-       c = &cpu_data(cpu);
-
-       if ((c->x86_vendor != X86_VENDOR_INTEL) ||
-               !cpu_has(c, X86_FEATURE_ACPI)) {
+       if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
+               !this_cpu_has(X86_FEATURE_ACPI)) {
                printk(KERN_ERR PREFIX
                        "HARDWARE addr space,NOT supported yet\n");
        } else {
@@ -738,18 +732,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr,
        return ret;
 }
 
-static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value)
+static int acpi_throttling_wrmsr(u64 value)
 {
-       struct cpuinfo_x86 *c;
-       unsigned int cpu;
        int ret = -1;
        u64 msr;
 
-       cpu = pr->id;
-       c = &cpu_data(cpu);
-
-       if ((c->x86_vendor != X86_VENDOR_INTEL) ||
-               !cpu_has(c, X86_FEATURE_ACPI)) {
+       if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
+               !this_cpu_has(X86_FEATURE_ACPI)) {
                printk(KERN_ERR PREFIX
                        "HARDWARE addr space,NOT supported yet\n");
        } else {
@@ -761,15 +750,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value)
        return ret;
 }
 #else
-static int acpi_throttling_rdmsr(struct acpi_processor *pr,
-                               u64 *value)
+static int acpi_throttling_rdmsr(u64 *value)
 {
        printk(KERN_ERR PREFIX
                "HARDWARE addr space,NOT supported yet\n");
        return -1;
 }
 
-static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value)
+static int acpi_throttling_wrmsr(u64 value)
 {
        printk(KERN_ERR PREFIX
                "HARDWARE addr space,NOT supported yet\n");
@@ -801,7 +789,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
                ret = 0;
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
-               ret = acpi_throttling_rdmsr(pr, value);
+               ret = acpi_throttling_rdmsr(value);
                break;
        default:
                printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -834,7 +822,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr,
                ret = 0;
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
-               ret = acpi_throttling_wrmsr(pr, value);
+               ret = acpi_throttling_wrmsr(value);
                break;
        default:
                printk(KERN_ERR PREFIX "Unknown addr space %d\n",
index b136c9c1e531954dc27cc4bed422e1618e7681ee..449c556274c052cf4c9fd221c577b7735bcdca0f 100644 (file)
@@ -943,6 +943,10 @@ static int acpi_bus_get_flags(struct acpi_device *device)
        if (ACPI_SUCCESS(status))
                device->flags.lockable = 1;
 
+       /* Power resources cannot be power manageable. */
+       if (device->device_type == ACPI_BUS_TYPE_POWER)
+               return 0;
+
        /* Presence of _PS0|_PR0 indicates 'power manageable' */
        status = acpi_get_handle(device->handle, "_PS0", &temp);
        if (ACPI_FAILURE(status))
index 39d829cd82dd4dfae5f87ee59bdb9f0f300ede8c..71afe0371311d7475e7034bb5ab1e483b2d3ce68 100644 (file)
@@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
                                 AHCI_HFLAG_YES_NCQ),
-               .flags          = AHCI_FLAG_COMMON,
+               .flags          = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
@@ -261,6 +261,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
        { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
        { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
index 39865009c25117410ba99f1a17141e8fd724dbe5..12c5282e7fca9c6effe1c42a2a7dae0a78395b2e 100644 (file)
@@ -229,6 +229,10 @@ enum {
        EM_CTL_ALHD             = (1 << 26), /* Activity LED */
        EM_CTL_XMT              = (1 << 25), /* Transmit Only */
        EM_CTL_SMB              = (1 << 24), /* Single Message Buffer */
+       EM_CTL_SGPIO            = (1 << 19), /* SGPIO messages supported */
+       EM_CTL_SES              = (1 << 18), /* SES-2 messages supported */
+       EM_CTL_SAFTE            = (1 << 17), /* SAF-TE messages supported */
+       EM_CTL_LED              = (1 << 16), /* LED messages supported */
 
        /* em message type */
        EM_MSG_TYPE_LED         = (1 << 0), /* LED */
index 0bc3fd6c3fdb8ea2f979f0a57b135ecc57a6e770..6f6e7718b05c7ff905ab3ad068aaa15160992581 100644 (file)
@@ -309,6 +309,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
        /* SATA Controller IDE (PBG) */
        { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        { }     /* terminate list */
 };
 
index 26d452339e98f59fc483cbc85e9c53f56b2a0183..d38c40fe4ddbfeace9bb1460505aac4add9d23f1 100644 (file)
@@ -109,6 +109,8 @@ static ssize_t ahci_read_em_buffer(struct device *dev,
 static ssize_t ahci_store_em_buffer(struct device *dev,
                                    struct device_attribute *attr,
                                    const char *buf, size_t size);
+static ssize_t ahci_show_em_supported(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
 
 static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -116,6 +118,7 @@ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
                   ahci_read_em_buffer, ahci_store_em_buffer);
+static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
 
 struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_link_power_management_policy,
@@ -126,6 +129,7 @@ struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_ahci_host_version,
        &dev_attr_ahci_port_cmd,
        &dev_attr_em_buffer,
+       &dev_attr_em_message_supported,
        NULL
 };
 EXPORT_SYMBOL_GPL(ahci_shost_attrs);
@@ -343,6 +347,24 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        return size;
 }
 
+static ssize_t ahci_show_em_supported(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *mmio = hpriv->mmio;
+       u32 em_ctl;
+
+       em_ctl = readl(mmio + HOST_EM_CTL);
+
+       return sprintf(buf, "%s%s%s%s\n",
+                      em_ctl & EM_CTL_LED ? "led " : "",
+                      em_ctl & EM_CTL_SAFTE ? "saf-te " : "",
+                      em_ctl & EM_CTL_SES ? "ses-2 " : "",
+                      em_ctl & EM_CTL_SGPIO ? "sgpio " : "");
+}
+
 /**
  *     ahci_save_initial_config - Save and fixup initial config values
  *     @dev: target AHCI device
@@ -1897,7 +1919,17 @@ static void ahci_pmp_attach(struct ata_port *ap)
        ahci_enable_fbs(ap);
 
        pp->intr_mask |= PORT_IRQ_BAD_PMP;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /*
+        * We must not change the port interrupt mask register if the
+        * port is marked frozen, the value in pp->intr_mask will be
+        * restored later when the port is thawed.
+        *
+        * Note that during initialization, the port is marked as
+        * frozen since the irq handler is not yet registered.
+        */
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 static void ahci_pmp_detach(struct ata_port *ap)
@@ -1913,7 +1945,10 @@ static void ahci_pmp_detach(struct ata_port *ap)
        writel(cmd, port_mmio + PORT_CMD);
 
        pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /* see comment above in ahci_pmp_attach() */
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 int ahci_port_resume(struct ata_port *ap)
index 423c0a6952b25af341bdd0360656af2be09019ff..76c3c15cb1e66680e11f9c5fb670d616e564acc5 100644 (file)
@@ -4139,6 +4139,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
         */
        { "PIONEER DVD-RW  DVRTD08",    "1.00", ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-212D",   "1.28", ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVR-216D",   "1.08", ATA_HORKAGE_NOSETXFER },
 
        /* End Marker */
        { }
@@ -5480,7 +5481,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
        if (!ap)
                return NULL;
 
-       ap->pflags |= ATA_PFLAG_INITIALIZING;
+       ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN;
        ap->lock = &host->lock;
        ap->print_id = -1;
        ap->host = host;
index 88cd22fa65cd82057b217f7b36a5e8657d910781..dad9fd660f379907b6bb80856d8e047959d1917a 100644 (file)
@@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        struct ata_eh_context *ehc = &link->eh_context;
        struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
        enum ata_lpm_policy old_policy = link->lpm_policy;
+       bool no_dipm = link->ap->flags & ATA_FLAG_NO_DIPM;
        unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
        unsigned int err_mask;
        int rc;
@@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
         */
        ata_for_each_dev(dev, link, ENABLED) {
                bool hipm = ata_id_has_hipm(dev->id);
-               bool dipm = ata_id_has_dipm(dev->id);
+               bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;
 
                /* find the first enabled and LPM enabled devices */
                if (!link_dev)
@@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 
        /* host config updated, enable DIPM if transitioning to MIN_POWER */
        ata_for_each_dev(dev, link, ENABLED) {
-               if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+               if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
+                   ata_id_has_dipm(dev->id)) {
                        err_mask = ata_dev_set_feature(dev,
                                        SETFEATURES_SATA_ENABLE, SATA_DIPM);
                        if (err_mask && err_mask != AC_ERR_DEV) {
index 0da0dcc7dd089427a988171c3f1a8b62c1b8f90f..a5fdbdcb0faf2ed8daa5c4fa77767da6cc3fa7ea 100644 (file)
 
 
 #define DRV_NAME "pata_at91"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define CF_IDE_OFFSET      0x00c00000
 #define CF_ALT_IDE_OFFSET   0x00e00000
 #define CF_IDE_RES_SIZE     0x08
+#define NCS_RD_PULSE_LIMIT  0x3f /* maximal value for pulse bitfields */
 
 struct at91_ide_info {
        unsigned long mode;
@@ -49,8 +50,18 @@ struct at91_ide_info {
        void __iomem *alt_addr;
 };
 
-static const struct ata_timing initial_timing =
-       {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
+static const struct ata_timing initial_timing = {
+       .mode           = XFER_PIO_0,
+       .setup          = 70,
+       .act8b          = 290,
+       .rec8b          = 240,
+       .cyc8b          = 600,
+       .active         = 165,
+       .recover        = 150,
+       .dmack_hold     = 0,
+       .cycle          = 600,
+       .udma           = 0
+};
 
 static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
 {
@@ -109,6 +120,11 @@ static void set_smc_timing(struct device *dev,
        /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
        ncs_read_setup = 1;
        ncs_read_pulse = read_cycle - 2;
+       if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) {
+               ncs_read_pulse = NCS_RD_PULSE_LIMIT;
+               dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n",
+                       ncs_read_pulse);
+       }
 
        /* Write timings same as read timings */
        write_cycle = read_cycle;
index bdd2719f3f68382084fb04170b1c14022e442425..bc9e702186dd64daf5445ea09710e5e8c7ee59eb 100644 (file)
@@ -2643,16 +2643,19 @@ fore200e_init(struct fore200e* fore200e, struct device *parent)
 }
 
 #ifdef CONFIG_SBUS
+static const struct of_device_id fore200e_sba_match[];
 static int __devinit fore200e_sba_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        const struct fore200e_bus *bus;
        struct fore200e *fore200e;
        static int index = 0;
        int err;
 
-       if (!op->dev.of_match)
+       match = of_match_device(fore200e_sba_match, &op->dev);
+       if (!match)
                return -EINVAL;
-       bus = op->dev.of_match->data;
+       bus = match->data;
 
        fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
        if (!fore200e)
index e9e5238f3106a93e8f7ea2090bde9ada492f8e87..d57e8d0fb8235085b60180230d04dc8cd61f3033 100644 (file)
@@ -168,11 +168,4 @@ config SYS_HYPERVISOR
        bool
        default n
 
-config ARCH_NO_SYSDEV_OPS
-       bool
-       ---help---
-         To be selected by architectures that don't use sysdev class or
-         sysdev driver power management (suspend/resume) and shutdown
-         operations.
-
 endmenu
index 19f49e41ce5de2ceb37adb1a278fa786ffa54391..a34dca0ad041713af58df661856195baaaf7ca63 100644 (file)
@@ -111,8 +111,6 @@ static inline int driver_match_device(struct device_driver *drv,
        return drv->bus->match ? drv->bus->match(dev, drv) : 1;
 }
 
-extern void sysdev_shutdown(void);
-
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
 extern int devres_release_all(struct device *dev);
index e3a3eff1dacc1fe58195c045f7eac211d5cd4dc6..6658da743c3adae5a7b7b1115cf2bcc878d588d4 100644 (file)
@@ -321,8 +321,7 @@ static void __device_release_driver(struct device *dev)
 
        drv = dev->driver;
        if (drv) {
-               pm_runtime_get_noresume(dev);
-               pm_runtime_barrier(dev);
+               pm_runtime_get_sync(dev);
 
                driver_sysfs_remove(dev);
 
@@ -331,6 +330,8 @@ static void __device_release_driver(struct device *dev)
                                                     BUS_NOTIFY_UNBIND_DRIVER,
                                                     dev);
 
+               pm_runtime_put_sync(dev);
+
                if (dev->bus && dev->bus->remove)
                        dev->bus->remove(dev);
                else if (drv->remove)
@@ -343,7 +344,6 @@ static void __device_release_driver(struct device *dev)
                                                     BUS_NOTIFY_UNBOUND_DRIVER,
                                                     dev);
 
-               pm_runtime_put_sync(dev);
        }
 }
 
index 8c798ef7f13fcc25ea1627ed3870dca0b97d1a21..bbb03e6f7255b715e894080e66a7ccfae34b2c24 100644 (file)
@@ -521,6 +521,11 @@ static int _request_firmware(const struct firmware **firmware_p,
        if (!firmware_p)
                return -EINVAL;
 
+       if (WARN_ON(usermodehelper_is_disabled())) {
+               dev_err(device, "firmware: %s will not be loaded\n", name);
+               return -EBUSY;
+       }
+
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
                dev_err(device, "%s: kmalloc(struct firmware) failed\n",
index 7d4bdaf557cff469f0c8c1fd60cbeeeb7829790f..1c291af637b3582e1419e665ee81e07ab6bdb019 100644 (file)
@@ -667,7 +667,7 @@ static int platform_legacy_resume(struct device *dev)
        return ret;
 }
 
-static int platform_pm_prepare(struct device *dev)
+int platform_pm_prepare(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -678,7 +678,7 @@ static int platform_pm_prepare(struct device *dev)
        return ret;
 }
 
-static void platform_pm_complete(struct device *dev)
+void platform_pm_complete(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
 
@@ -686,16 +686,11 @@ static void platform_pm_complete(struct device *dev)
                drv->pm->complete(dev);
 }
 
-#else /* !CONFIG_PM_SLEEP */
-
-#define platform_pm_prepare            NULL
-#define platform_pm_complete           NULL
-
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_SUSPEND
 
-int __weak platform_pm_suspend(struct device *dev)
+int platform_pm_suspend(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -713,7 +708,7 @@ int __weak platform_pm_suspend(struct device *dev)
        return ret;
 }
 
-int __weak platform_pm_suspend_noirq(struct device *dev)
+int platform_pm_suspend_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -729,7 +724,7 @@ int __weak platform_pm_suspend_noirq(struct device *dev)
        return ret;
 }
 
-int __weak platform_pm_resume(struct device *dev)
+int platform_pm_resume(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -747,7 +742,7 @@ int __weak platform_pm_resume(struct device *dev)
        return ret;
 }
 
-int __weak platform_pm_resume_noirq(struct device *dev)
+int platform_pm_resume_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -763,18 +758,11 @@ int __weak platform_pm_resume_noirq(struct device *dev)
        return ret;
 }
 
-#else /* !CONFIG_SUSPEND */
-
-#define platform_pm_suspend            NULL
-#define platform_pm_resume             NULL
-#define platform_pm_suspend_noirq      NULL
-#define platform_pm_resume_noirq       NULL
-
-#endif /* !CONFIG_SUSPEND */
+#endif /* CONFIG_SUSPEND */
 
 #ifdef CONFIG_HIBERNATE_CALLBACKS
 
-static int platform_pm_freeze(struct device *dev)
+int platform_pm_freeze(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -792,7 +780,7 @@ static int platform_pm_freeze(struct device *dev)
        return ret;
 }
 
-static int platform_pm_freeze_noirq(struct device *dev)
+int platform_pm_freeze_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -808,7 +796,7 @@ static int platform_pm_freeze_noirq(struct device *dev)
        return ret;
 }
 
-static int platform_pm_thaw(struct device *dev)
+int platform_pm_thaw(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -826,7 +814,7 @@ static int platform_pm_thaw(struct device *dev)
        return ret;
 }
 
-static int platform_pm_thaw_noirq(struct device *dev)
+int platform_pm_thaw_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -842,7 +830,7 @@ static int platform_pm_thaw_noirq(struct device *dev)
        return ret;
 }
 
-static int platform_pm_poweroff(struct device *dev)
+int platform_pm_poweroff(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -860,7 +848,7 @@ static int platform_pm_poweroff(struct device *dev)
        return ret;
 }
 
-static int platform_pm_poweroff_noirq(struct device *dev)
+int platform_pm_poweroff_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -876,7 +864,7 @@ static int platform_pm_poweroff_noirq(struct device *dev)
        return ret;
 }
 
-static int platform_pm_restore(struct device *dev)
+int platform_pm_restore(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -894,7 +882,7 @@ static int platform_pm_restore(struct device *dev)
        return ret;
 }
 
-static int platform_pm_restore_noirq(struct device *dev)
+int platform_pm_restore_noirq(struct device *dev)
 {
        struct device_driver *drv = dev->driver;
        int ret = 0;
@@ -910,62 +898,13 @@ static int platform_pm_restore_noirq(struct device *dev)
        return ret;
 }
 
-#else /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#define platform_pm_freeze             NULL
-#define platform_pm_thaw               NULL
-#define platform_pm_poweroff           NULL
-#define platform_pm_restore            NULL
-#define platform_pm_freeze_noirq       NULL
-#define platform_pm_thaw_noirq         NULL
-#define platform_pm_poweroff_noirq     NULL
-#define platform_pm_restore_noirq      NULL
-
-#endif /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#ifdef CONFIG_PM_RUNTIME
-
-int __weak platform_pm_runtime_suspend(struct device *dev)
-{
-       return pm_generic_runtime_suspend(dev);
-};
-
-int __weak platform_pm_runtime_resume(struct device *dev)
-{
-       return pm_generic_runtime_resume(dev);
-};
-
-int __weak platform_pm_runtime_idle(struct device *dev)
-{
-       return pm_generic_runtime_idle(dev);
-};
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define platform_pm_runtime_suspend NULL
-#define platform_pm_runtime_resume NULL
-#define platform_pm_runtime_idle NULL
-
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
 
 static const struct dev_pm_ops platform_dev_pm_ops = {
-       .prepare = platform_pm_prepare,
-       .complete = platform_pm_complete,
-       .suspend = platform_pm_suspend,
-       .resume = platform_pm_resume,
-       .freeze = platform_pm_freeze,
-       .thaw = platform_pm_thaw,
-       .poweroff = platform_pm_poweroff,
-       .restore = platform_pm_restore,
-       .suspend_noirq = platform_pm_suspend_noirq,
-       .resume_noirq = platform_pm_resume_noirq,
-       .freeze_noirq = platform_pm_freeze_noirq,
-       .thaw_noirq = platform_pm_thaw_noirq,
-       .poweroff_noirq = platform_pm_poweroff_noirq,
-       .restore_noirq = platform_pm_restore_noirq,
-       .runtime_suspend = platform_pm_runtime_suspend,
-       .runtime_resume = platform_pm_runtime_resume,
-       .runtime_idle = platform_pm_runtime_idle,
+       .runtime_suspend = pm_generic_runtime_suspend,
+       .runtime_resume = pm_generic_runtime_resume,
+       .runtime_idle = pm_generic_runtime_idle,
+       USE_PLATFORM_PM_SLEEP_OPS
 };
 
 struct bus_type platform_bus_type = {
@@ -977,41 +916,6 @@ struct bus_type platform_bus_type = {
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
-/**
- * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
- *
- * This function can be used by platform code to get the current
- * set of dev_pm_ops functions used by the platform_bus_type.
- */
-const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
-{
-       return platform_bus_type.pm;
-}
-
-/**
- * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
- *
- * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
- *
- * Platform code can override the dev_pm_ops methods of
- * platform_bus_type by using this function.  It is expected that
- * platform code will first do a platform_bus_get_pm_ops(), then
- * kmemdup it, then customize selected methods and pass a pointer to
- * the new struct dev_pm_ops to this function.
- *
- * Since platform-specific code is customizing methods for *all*
- * devices (not just platform-specific devices) it is expected that
- * any custom overrides of these functions will keep existing behavior
- * and simply extend it.  For example, any customization of the
- * runtime PM methods should continue to call the pm_generic_*
- * functions as the default ones do in addition to the
- * platform-specific behavior.
- */
-void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
-{
-       platform_bus_type.pm = pm;
-}
-
 int __init platform_bus_init(void)
 {
        int error;
index 118c1b92a511c3819ac27e424eaad23831dee0c6..3647e114d0e79cbf30c40a2260040c31b1b73972 100644 (file)
@@ -3,6 +3,6 @@ obj-$(CONFIG_PM_SLEEP)  += main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)       += runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)     += trace.o
 obj-$(CONFIG_PM_OPP)   += opp.o
+obj-$(CONFIG_HAVE_CLK) += clock_ops.o
 
-ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
-ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
\ No newline at end of file
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
new file mode 100644 (file)
index 0000000..c0dd09d
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
+ *
+ * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#ifdef CONFIG_PM_RUNTIME
+
+struct pm_runtime_clk_data {
+       struct list_head clock_list;
+       struct mutex lock;
+};
+
+enum pce_status {
+       PCE_STATUS_NONE = 0,
+       PCE_STATUS_ACQUIRED,
+       PCE_STATUS_ENABLED,
+       PCE_STATUS_ERROR,
+};
+
+struct pm_clock_entry {
+       struct list_head node;
+       char *con_id;
+       struct clk *clk;
+       enum pce_status status;
+};
+
+static struct pm_runtime_clk_data *__to_prd(struct device *dev)
+{
+       return dev ? dev->power.subsys_data : NULL;
+}
+
+/**
+ * pm_runtime_clk_add - Start using a device clock for runtime PM.
+ * @dev: Device whose clock is going to be used for runtime PM.
+ * @con_id: Connection ID of the clock.
+ *
+ * Add the clock represented by @con_id to the list of clocks used for
+ * the runtime PM of @dev.
+ */
+int pm_runtime_clk_add(struct device *dev, const char *con_id)
+{
+       struct pm_runtime_clk_data *prd = __to_prd(dev);
+       struct pm_clock_entry *ce;
+
+       if (!prd)
+               return -EINVAL;
+
+       ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+       if (!ce) {
+               dev_err(dev, "Not enough memory for clock entry.\n");
+               return -ENOMEM;
+       }
+
+       if (con_id) {
+               ce->con_id = kstrdup(con_id, GFP_KERNEL);
+               if (!ce->con_id) {
+                       dev_err(dev,
+                               "Not enough memory for clock connection ID.\n");
+                       kfree(ce);
+                       return -ENOMEM;
+               }
+       }
+
+       mutex_lock(&prd->lock);
+       list_add_tail(&ce->node, &prd->clock_list);
+       mutex_unlock(&prd->lock);
+       return 0;
+}
+
+/**
+ * __pm_runtime_clk_remove - Destroy runtime PM clock entry.
+ * @ce: Runtime PM clock entry to destroy.
+ *
+ * This routine must be called under the mutex protecting the runtime PM list
+ * of clocks corresponding the the @ce's device.
+ */
+static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
+{
+       if (!ce)
+               return;
+
+       list_del(&ce->node);
+
+       if (ce->status < PCE_STATUS_ERROR) {
+               if (ce->status == PCE_STATUS_ENABLED)
+                       clk_disable(ce->clk);
+
+               if (ce->status >= PCE_STATUS_ACQUIRED)
+                       clk_put(ce->clk);
+       }
+
+       if (ce->con_id)
+               kfree(ce->con_id);
+
+       kfree(ce);
+}
+
+/**
+ * pm_runtime_clk_remove - Stop using a device clock for runtime PM.
+ * @dev: Device whose clock should not be used for runtime PM any more.
+ * @con_id: Connection ID of the clock.
+ *
+ * Remove the clock represented by @con_id from the list of clocks used for
+ * the runtime PM of @dev.
+ */
+void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+{
+       struct pm_runtime_clk_data *prd = __to_prd(dev);
+       struct pm_clock_entry *ce;
+
+       if (!prd)
+               return;
+
+       mutex_lock(&prd->lock);
+
+       list_for_each_entry(ce, &prd->clock_list, node) {
+               if (!con_id && !ce->con_id) {
+                       __pm_runtime_clk_remove(ce);
+                       break;
+               } else if (!con_id || !ce->con_id) {
+                       continue;
+               } else if (!strcmp(con_id, ce->con_id)) {
+                       __pm_runtime_clk_remove(ce);
+                       break;
+               }
+       }
+
+       mutex_unlock(&prd->lock);
+}
+
+/**
+ * pm_runtime_clk_init - Initialize a device's list of runtime PM clocks.
+ * @dev: Device to initialize the list of runtime PM clocks for.
+ *
+ * Allocate a struct pm_runtime_clk_data object, initialize its lock member and
+ * make the @dev's power.subsys_data field point to it.
+ */
+int pm_runtime_clk_init(struct device *dev)
+{
+       struct pm_runtime_clk_data *prd;
+
+       prd = kzalloc(sizeof(*prd), GFP_KERNEL);
+       if (!prd) {
+               dev_err(dev, "Not enough memory fo runtime PM data.\n");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&prd->clock_list);
+       mutex_init(&prd->lock);
+       dev->power.subsys_data = prd;
+       return 0;
+}
+
+/**
+ * pm_runtime_clk_destroy - Destroy a device's list of runtime PM clocks.
+ * @dev: Device to destroy the list of runtime PM clocks for.
+ *
+ * Clear the @dev's power.subsys_data field, remove the list of clock entries
+ * from the struct pm_runtime_clk_data object pointed to by it before and free
+ * that object.
+ */
+void pm_runtime_clk_destroy(struct device *dev)
+{
+       struct pm_runtime_clk_data *prd = __to_prd(dev);
+       struct pm_clock_entry *ce, *c;
+
+       if (!prd)
+               return;
+
+       dev->power.subsys_data = NULL;
+
+       mutex_lock(&prd->lock);
+
+       list_for_each_entry_safe_reverse(ce, c, &prd->clock_list, node)
+               __pm_runtime_clk_remove(ce);
+
+       mutex_unlock(&prd->lock);
+
+       kfree(prd);
+}
+
+/**
+ * pm_runtime_clk_acquire - Acquire a device clock.
+ * @dev: Device whose clock is to be acquired.
+ * @con_id: Connection ID of the clock.
+ */
+static void pm_runtime_clk_acquire(struct device *dev,
+                                   struct pm_clock_entry *ce)
+{
+       ce->clk = clk_get(dev, ce->con_id);
+       if (IS_ERR(ce->clk)) {
+               ce->status = PCE_STATUS_ERROR;
+       } else {
+               ce->status = PCE_STATUS_ACQUIRED;
+               dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
+       }
+}
+
+/**
+ * pm_runtime_clk_suspend - Disable clocks in a device's runtime PM clock list.
+ * @dev: Device to disable the clocks for.
+ */
+int pm_runtime_clk_suspend(struct device *dev)
+{
+       struct pm_runtime_clk_data *prd = __to_prd(dev);
+       struct pm_clock_entry *ce;
+
+       dev_dbg(dev, "%s()\n", __func__);
+
+       if (!prd)
+               return 0;
+
+       mutex_lock(&prd->lock);
+
+       list_for_each_entry_reverse(ce, &prd->clock_list, node) {
+               if (ce->status == PCE_STATUS_NONE)
+                       pm_runtime_clk_acquire(dev, ce);
+
+               if (ce->status < PCE_STATUS_ERROR) {
+                       clk_disable(ce->clk);
+                       ce->status = PCE_STATUS_ACQUIRED;
+               }
+       }
+
+       mutex_unlock(&prd->lock);
+
+       return 0;
+}
+
+/**
+ * pm_runtime_clk_resume - Enable clocks in a device's runtime PM clock list.
+ * @dev: Device to enable the clocks for.
+ */
+int pm_runtime_clk_resume(struct device *dev)
+{
+       struct pm_runtime_clk_data *prd = __to_prd(dev);
+       struct pm_clock_entry *ce;
+
+       dev_dbg(dev, "%s()\n", __func__);
+
+       if (!prd)
+               return 0;
+
+       mutex_lock(&prd->lock);
+
+       list_for_each_entry(ce, &prd->clock_list, node) {
+               if (ce->status == PCE_STATUS_NONE)
+                       pm_runtime_clk_acquire(dev, ce);
+
+               if (ce->status < PCE_STATUS_ERROR) {
+                       clk_enable(ce->clk);
+                       ce->status = PCE_STATUS_ENABLED;
+               }
+       }
+
+       mutex_unlock(&prd->lock);
+
+       return 0;
+}
+
+/**
+ * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * @nb: Notifier block object this function is a member of.
+ * @action: Operation being carried out by the caller.
+ * @data: Device the routine is being run for.
+ *
+ * For this function to work, @nb must be a member of an object of type
+ * struct pm_clk_notifier_block containing all of the requisite data.
+ * Specifically, the pwr_domain member of that object is copied to the device's
+ * pwr_domain field and its con_ids member is used to populate the device's list
+ * of runtime PM clocks, depending on @action.
+ *
+ * If the device's pwr_domain field is already populated with a value different
+ * from the one stored in the struct pm_clk_notifier_block object, the function
+ * does nothing.
+ */
+static int pm_runtime_clk_notify(struct notifier_block *nb,
+                                unsigned long action, void *data)
+{
+       struct pm_clk_notifier_block *clknb;
+       struct device *dev = data;
+       char *con_id;
+       int error;
+
+       dev_dbg(dev, "%s() %ld\n", __func__, action);
+
+       clknb = container_of(nb, struct pm_clk_notifier_block, nb);
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               if (dev->pwr_domain)
+                       break;
+
+               error = pm_runtime_clk_init(dev);
+               if (error)
+                       break;
+
+               dev->pwr_domain = clknb->pwr_domain;
+               if (clknb->con_ids[0]) {
+                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+                               pm_runtime_clk_add(dev, con_id);
+               } else {
+                       pm_runtime_clk_add(dev, NULL);
+               }
+
+               break;
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (dev->pwr_domain != clknb->pwr_domain)
+                       break;
+
+               dev->pwr_domain = NULL;
+               pm_runtime_clk_destroy(dev);
+               break;
+       }
+
+       return 0;
+}
+
+#else /* !CONFIG_PM_RUNTIME */
+
+/**
+ * enable_clock - Enable a device clock.
+ * @dev: Device whose clock is to be enabled.
+ * @con_id: Connection ID of the clock.
+ */
+static void enable_clock(struct device *dev, const char *con_id)
+{
+       struct clk *clk;
+
+       clk = clk_get(dev, con_id);
+       if (!IS_ERR(clk)) {
+               clk_enable(clk);
+               clk_put(clk);
+               dev_info(dev, "Runtime PM disabled, clock forced on.\n");
+       }
+}
+
+/**
+ * disable_clock - Disable a device clock.
+ * @dev: Device whose clock is to be disabled.
+ * @con_id: Connection ID of the clock.
+ */
+static void disable_clock(struct device *dev, const char *con_id)
+{
+       struct clk *clk;
+
+       clk = clk_get(dev, con_id);
+       if (!IS_ERR(clk)) {
+               clk_disable(clk);
+               clk_put(clk);
+               dev_info(dev, "Runtime PM disabled, clock forced off.\n");
+       }
+}
+
+/**
+ * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * @nb: Notifier block object this function is a member of.
+ * @action: Operation being carried out by the caller.
+ * @data: Device the routine is being run for.
+ *
+ * For this function to work, @nb must be a member of an object of type
+ * struct pm_clk_notifier_block containing all of the requisite data.
+ * Specifically, the con_ids member of that object is used to enable or disable
+ * the device's clocks, depending on @action.
+ */
+static int pm_runtime_clk_notify(struct notifier_block *nb,
+                                unsigned long action, void *data)
+{
+       struct pm_clk_notifier_block *clknb;
+       struct device *dev = data;
+       char *con_id;
+
+       dev_dbg(dev, "%s() %ld\n", __func__, action);
+
+       clknb = container_of(nb, struct pm_clk_notifier_block, nb);
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               if (clknb->con_ids[0]) {
+                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+                               enable_clock(dev, con_id);
+               } else {
+                       enable_clock(dev, NULL);
+               }
+               break;
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (clknb->con_ids[0]) {
+                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+                               disable_clock(dev, con_id);
+               } else {
+                       disable_clock(dev, NULL);
+               }
+               break;
+       }
+
+       return 0;
+}
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+/**
+ * pm_runtime_clk_add_notifier - Add bus type notifier for runtime PM clocks.
+ * @bus: Bus type to add the notifier to.
+ * @clknb: Notifier to be added to the given bus type.
+ *
+ * The nb member of @clknb is not expected to be initialized and its
+ * notifier_call member will be replaced with pm_runtime_clk_notify().  However,
+ * the remaining members of @clknb should be populated prior to calling this
+ * routine.
+ */
+void pm_runtime_clk_add_notifier(struct bus_type *bus,
+                                struct pm_clk_notifier_block *clknb)
+{
+       if (!bus || !clknb)
+               return;
+
+       clknb->nb.notifier_call = pm_runtime_clk_notify;
+       bus_register_notifier(bus, &clknb->nb);
+}
index 42f97f925629b7422080e2453a1d02b24d033f5b..cb3bb368681c7379c7fed94060ddd80079b6d0a9 100644 (file)
@@ -73,6 +73,23 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
 #endif /* CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM_SLEEP
+/**
+ * pm_generic_prepare - Generic routine preparing a device for power transition.
+ * @dev: Device to prepare.
+ *
+ * Prepare a device for a system-wide power transition.
+ */
+int pm_generic_prepare(struct device *dev)
+{
+       struct device_driver *drv = dev->driver;
+       int ret = 0;
+
+       if (drv && drv->pm && drv->pm->prepare)
+               ret = drv->pm->prepare(dev);
+
+       return ret;
+}
+
 /**
  * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
  * @dev: Device to handle.
@@ -213,16 +230,38 @@ int pm_generic_restore(struct device *dev)
        return __pm_generic_resume(dev, PM_EVENT_RESTORE);
 }
 EXPORT_SYMBOL_GPL(pm_generic_restore);
+
+/**
+ * pm_generic_complete - Generic routine competing a device power transition.
+ * @dev: Device to handle.
+ *
+ * Complete a device power transition during a system-wide power transition.
+ */
+void pm_generic_complete(struct device *dev)
+{
+       struct device_driver *drv = dev->driver;
+
+       if (drv && drv->pm && drv->pm->complete)
+               drv->pm->complete(dev);
+
+       /*
+        * Let runtime PM try to suspend devices that haven't been in use before
+        * going into the system-wide sleep state we're resuming from.
+        */
+       pm_runtime_idle(dev);
+}
 #endif /* CONFIG_PM_SLEEP */
 
 struct dev_pm_ops generic_subsys_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
+       .prepare = pm_generic_prepare,
        .suspend = pm_generic_suspend,
        .resume = pm_generic_resume,
        .freeze = pm_generic_freeze,
        .thaw = pm_generic_thaw,
        .poweroff = pm_generic_poweroff,
        .restore = pm_generic_restore,
+       .complete = pm_generic_complete,
 #endif
 #ifdef CONFIG_PM_RUNTIME
        .runtime_suspend = pm_generic_runtime_suspend,
index fbc5b6e7c59156556cf4d02b0970411e0844dd80..aa6320207745d636641178f3d9ca89c2d489fe6e 100644 (file)
@@ -63,6 +63,7 @@ void device_pm_init(struct device *dev)
        dev->power.wakeup = NULL;
        spin_lock_init(&dev->power.lock);
        pm_runtime_init(dev);
+       INIT_LIST_HEAD(&dev->power.entry);
 }
 
 /**
@@ -425,10 +426,8 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 
        if (dev->pwr_domain) {
                pm_dev_dbg(dev, state, "EARLY power domain ");
-               pm_noirq_op(dev, &dev->pwr_domain->ops, state);
-       }
-
-       if (dev->type && dev->type->pm) {
+               error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+       } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "EARLY type ");
                error = pm_noirq_op(dev, dev->type->pm, state);
        } else if (dev->class && dev->class->pm) {
@@ -516,7 +515,8 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
        if (dev->pwr_domain) {
                pm_dev_dbg(dev, state, "power domain ");
-               pm_op(dev, &dev->pwr_domain->ops, state);
+               error = pm_op(dev, &dev->pwr_domain->ops, state);
+               goto End;
        }
 
        if (dev->type && dev->type->pm) {
@@ -579,11 +579,13 @@ static bool is_async(struct device *dev)
  * Execute the appropriate "resume" callback for all devices whose status
  * indicates that they are suspended.
  */
-static void dpm_resume(pm_message_t state)
+void dpm_resume(pm_message_t state)
 {
        struct device *dev;
        ktime_t starttime = ktime_get();
 
+       might_sleep();
+
        mutex_lock(&dpm_list_mtx);
        pm_transition = state;
        async_error = 0;
@@ -628,12 +630,11 @@ static void device_complete(struct device *dev, pm_message_t state)
 {
        device_lock(dev);
 
-       if (dev->pwr_domain && dev->pwr_domain->ops.complete) {
+       if (dev->pwr_domain) {
                pm_dev_dbg(dev, state, "completing power domain ");
-               dev->pwr_domain->ops.complete(dev);
-       }
-
-       if (dev->type && dev->type->pm) {
+               if (dev->pwr_domain->ops.complete)
+                       dev->pwr_domain->ops.complete(dev);
+       } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "completing type ");
                if (dev->type->pm->complete)
                        dev->type->pm->complete(dev);
@@ -657,10 +658,12 @@ static void device_complete(struct device *dev, pm_message_t state)
  * Execute the ->complete() callbacks for all devices whose PM status is not
  * DPM_ON (this allows new devices to be registered).
  */
-static void dpm_complete(pm_message_t state)
+void dpm_complete(pm_message_t state)
 {
        struct list_head list;
 
+       might_sleep();
+
        INIT_LIST_HEAD(&list);
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_prepared_list)) {
@@ -689,7 +692,6 @@ static void dpm_complete(pm_message_t state)
  */
 void dpm_resume_end(pm_message_t state)
 {
-       might_sleep();
        dpm_resume(state);
        dpm_complete(state);
 }
@@ -731,7 +733,12 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
        int error;
 
-       if (dev->type && dev->type->pm) {
+       if (dev->pwr_domain) {
+               pm_dev_dbg(dev, state, "LATE power domain ");
+               error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+               if (error)
+                       return error;
+       } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "LATE type ");
                error = pm_noirq_op(dev, dev->type->pm, state);
                if (error)
@@ -748,11 +755,6 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
                        return error;
        }
 
-       if (dev->pwr_domain) {
-               pm_dev_dbg(dev, state, "LATE power domain ");
-               pm_noirq_op(dev, &dev->pwr_domain->ops, state);
-       }
-
        return 0;
 }
 
@@ -840,21 +842,27 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
                goto End;
        }
 
+       if (dev->pwr_domain) {
+               pm_dev_dbg(dev, state, "power domain ");
+               error = pm_op(dev, &dev->pwr_domain->ops, state);
+               goto End;
+       }
+
        if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "type ");
                error = pm_op(dev, dev->type->pm, state);
-               goto Domain;
+               goto End;
        }
 
        if (dev->class) {
                if (dev->class->pm) {
                        pm_dev_dbg(dev, state, "class ");
                        error = pm_op(dev, dev->class->pm, state);
-                       goto Domain;
+                       goto End;
                } else if (dev->class->suspend) {
                        pm_dev_dbg(dev, state, "legacy class ");
                        error = legacy_suspend(dev, state, dev->class->suspend);
-                       goto Domain;
+                       goto End;
                }
        }
 
@@ -868,12 +876,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
                }
        }
 
- Domain:
-       if (!error && dev->pwr_domain) {
-               pm_dev_dbg(dev, state, "power domain ");
-               pm_op(dev, &dev->pwr_domain->ops, state);
-       }
-
  End:
        device_unlock(dev);
        complete_all(&dev->power.completion);
@@ -913,11 +915,13 @@ static int device_suspend(struct device *dev)
  * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
  * @state: PM transition of the system being carried out.
  */
-static int dpm_suspend(pm_message_t state)
+int dpm_suspend(pm_message_t state)
 {
        ktime_t starttime = ktime_get();
        int error = 0;
 
+       might_sleep();
+
        mutex_lock(&dpm_list_mtx);
        pm_transition = state;
        async_error = 0;
@@ -964,7 +968,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
 
        device_lock(dev);
 
-       if (dev->type && dev->type->pm) {
+       if (dev->pwr_domain) {
+               pm_dev_dbg(dev, state, "preparing power domain ");
+               if (dev->pwr_domain->ops.prepare)
+                       error = dev->pwr_domain->ops.prepare(dev);
+               suspend_report_result(dev->pwr_domain->ops.prepare, error);
+               if (error)
+                       goto End;
+       } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "preparing type ");
                if (dev->type->pm->prepare)
                        error = dev->type->pm->prepare(dev);
@@ -983,13 +994,6 @@ static int device_prepare(struct device *dev, pm_message_t state)
                if (dev->bus->pm->prepare)
                        error = dev->bus->pm->prepare(dev);
                suspend_report_result(dev->bus->pm->prepare, error);
-               if (error)
-                       goto End;
-       }
-
-       if (dev->pwr_domain && dev->pwr_domain->ops.prepare) {
-               pm_dev_dbg(dev, state, "preparing power domain ");
-               dev->pwr_domain->ops.prepare(dev);
        }
 
  End:
@@ -1004,10 +1008,12 @@ static int device_prepare(struct device *dev, pm_message_t state)
  *
  * Execute the ->prepare() callback(s) for all devices.
  */
-static int dpm_prepare(pm_message_t state)
+int dpm_prepare(pm_message_t state)
 {
        int error = 0;
 
+       might_sleep();
+
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_list)) {
                struct device *dev = to_device(dpm_list.next);
@@ -1056,7 +1062,6 @@ int dpm_suspend_start(pm_message_t state)
 {
        int error;
 
-       might_sleep();
        error = dpm_prepare(state);
        if (!error)
                error = dpm_suspend(state);
index 3172c60d23a96e0e2d910219deed3b40bc2f6c79..0d4587b15c5599372e7b9f917fcea636404bf8d9 100644 (file)
@@ -168,7 +168,6 @@ static int rpm_check_suspend_allowed(struct device *dev)
 static int rpm_idle(struct device *dev, int rpmflags)
 {
        int (*callback)(struct device *);
-       int (*domain_callback)(struct device *);
        int retval;
 
        retval = rpm_check_suspend_allowed(dev);
@@ -214,7 +213,9 @@ static int rpm_idle(struct device *dev, int rpmflags)
 
        dev->power.idle_notification = true;
 
-       if (dev->type && dev->type->pm)
+       if (dev->pwr_domain)
+               callback = dev->pwr_domain->ops.runtime_idle;
+       else if (dev->type && dev->type->pm)
                callback = dev->type->pm->runtime_idle;
        else if (dev->class && dev->class->pm)
                callback = dev->class->pm->runtime_idle;
@@ -223,19 +224,10 @@ static int rpm_idle(struct device *dev, int rpmflags)
        else
                callback = NULL;
 
-       if (dev->pwr_domain)
-               domain_callback = dev->pwr_domain->ops.runtime_idle;
-       else
-               domain_callback = NULL;
-
-       if (callback || domain_callback) {
+       if (callback) {
                spin_unlock_irq(&dev->power.lock);
 
-               if (domain_callback)
-                       retval = domain_callback(dev);
-
-               if (!retval && callback)
-                       callback(dev);
+               callback(dev);
 
                spin_lock_irq(&dev->power.lock);
        }
@@ -382,7 +374,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 
        __update_runtime_status(dev, RPM_SUSPENDING);
 
-       if (dev->type && dev->type->pm)
+       if (dev->pwr_domain)
+               callback = dev->pwr_domain->ops.runtime_suspend;
+       else if (dev->type && dev->type->pm)
                callback = dev->type->pm->runtime_suspend;
        else if (dev->class && dev->class->pm)
                callback = dev->class->pm->runtime_suspend;
@@ -400,8 +394,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                else
                        pm_runtime_cancel_pending(dev);
        } else {
-               if (dev->pwr_domain)
-                       rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
  no_callback:
                __update_runtime_status(dev, RPM_SUSPENDED);
                pm_runtime_deactivate_timer(dev);
@@ -582,9 +574,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
        __update_runtime_status(dev, RPM_RESUMING);
 
        if (dev->pwr_domain)
-               rpm_callback(dev->pwr_domain->ops.runtime_resume, dev);
-
-       if (dev->type && dev->type->pm)
+               callback = dev->pwr_domain->ops.runtime_resume;
+       else if (dev->type && dev->type->pm)
                callback = dev->type->pm->runtime_resume;
        else if (dev->class && dev->class->pm)
                callback = dev->class->pm->runtime_resume;
index fff49bee781d44f4fd2f35dda22f86a388fd9259..a9f5b89796111876e0f30f30a81bd45780901afa 100644 (file)
@@ -212,8 +212,9 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
 static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
                autosuspend_delay_ms_store);
 
-#endif
+#endif /* CONFIG_PM_RUNTIME */
 
+#ifdef CONFIG_PM_SLEEP
 static ssize_t
 wake_show(struct device * dev, struct device_attribute *attr, char * buf)
 {
@@ -248,7 +249,6 @@ wake_store(struct device * dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
 
-#ifdef CONFIG_PM_SLEEP
 static ssize_t wakeup_count_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
index 4573c83df6ddc4d996e342bc47bb54f717063474..84f7c7d5a0983f74f844c6b591c110fa1a89c5b4 100644 (file)
@@ -110,7 +110,6 @@ void wakeup_source_add(struct wakeup_source *ws)
        spin_lock_irq(&events_lock);
        list_add_rcu(&ws->entry, &wakeup_sources);
        spin_unlock_irq(&events_lock);
-       synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(wakeup_source_add);
 
@@ -258,7 +257,7 @@ void device_set_wakeup_capable(struct device *dev, bool capable)
        if (!!dev->power.can_wakeup == !!capable)
                return;
 
-       if (device_is_registered(dev)) {
+       if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
                if (capable) {
                        if (wakeup_sysfs_add(dev))
                                return;
index acde9b5ee1314b10577e00a38064cb25ea3118f7..9dff77bfe1e348a0ed3a3e4f450d192b6a4ac580 100644 (file)
@@ -328,203 +328,8 @@ void sysdev_unregister(struct sys_device *sysdev)
        kobject_put(&sysdev->kobj);
 }
 
-
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-/**
- *     sysdev_shutdown - Shut down all system devices.
- *
- *     Loop over each class of system devices, and the devices in each
- *     of those classes. For each device, we call the shutdown method for
- *     each driver registered for the device - the auxiliaries,
- *     and the class driver.
- *
- *     Note: The list is iterated in reverse order, so that we shut down
- *     child devices before we shut down their parents. The list ordering
- *     is guaranteed by virtue of the fact that child devices are registered
- *     after their parents.
- */
-void sysdev_shutdown(void)
-{
-       struct sysdev_class *cls;
-
-       pr_debug("Shutting Down System Devices\n");
-
-       mutex_lock(&sysdev_drivers_lock);
-       list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
-               struct sys_device *sysdev;
-
-               pr_debug("Shutting down type '%s':\n",
-                        kobject_name(&cls->kset.kobj));
-
-               list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-                       struct sysdev_driver *drv;
-                       pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
-                       /* Call auxiliary drivers first */
-                       list_for_each_entry(drv, &cls->drivers, entry) {
-                               if (drv->shutdown)
-                                       drv->shutdown(sysdev);
-                       }
-
-                       /* Now call the generic one */
-                       if (cls->shutdown)
-                               cls->shutdown(sysdev);
-               }
-       }
-       mutex_unlock(&sysdev_drivers_lock);
-}
-
-static void __sysdev_resume(struct sys_device *dev)
-{
-       struct sysdev_class *cls = dev->cls;
-       struct sysdev_driver *drv;
-
-       /* First, call the class-specific one */
-       if (cls->resume)
-               cls->resume(dev);
-       WARN_ONCE(!irqs_disabled(),
-               "Interrupts enabled after %pF\n", cls->resume);
-
-       /* Call auxiliary drivers next. */
-       list_for_each_entry(drv, &cls->drivers, entry) {
-               if (drv->resume)
-                       drv->resume(dev);
-               WARN_ONCE(!irqs_disabled(),
-                       "Interrupts enabled after %pF\n", drv->resume);
-       }
-}
-
-/**
- *     sysdev_suspend - Suspend all system devices.
- *     @state:         Power state to enter.
- *
- *     We perform an almost identical operation as sysdev_shutdown()
- *     above, though calling ->suspend() instead. Interrupts are disabled
- *     when this called. Devices are responsible for both saving state and
- *     quiescing or powering down the device.
- *
- *     This is only called by the device PM core, so we let them handle
- *     all synchronization.
- */
-int sysdev_suspend(pm_message_t state)
-{
-       struct sysdev_class *cls;
-       struct sys_device *sysdev, *err_dev;
-       struct sysdev_driver *drv, *err_drv;
-       int ret;
-
-       pr_debug("Checking wake-up interrupts\n");
-
-       /* Return error code if there are any wake-up interrupts pending */
-       ret = check_wakeup_irqs();
-       if (ret)
-               return ret;
-
-       WARN_ONCE(!irqs_disabled(),
-               "Interrupts enabled while suspending system devices\n");
-
-       pr_debug("Suspending System Devices\n");
-
-       list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
-               pr_debug("Suspending type '%s':\n",
-                        kobject_name(&cls->kset.kobj));
-
-               list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-                       pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
-                       /* Call auxiliary drivers first */
-                       list_for_each_entry(drv, &cls->drivers, entry) {
-                               if (drv->suspend) {
-                                       ret = drv->suspend(sysdev, state);
-                                       if (ret)
-                                               goto aux_driver;
-                               }
-                               WARN_ONCE(!irqs_disabled(),
-                                       "Interrupts enabled after %pF\n",
-                                       drv->suspend);
-                       }
-
-                       /* Now call the generic one */
-                       if (cls->suspend) {
-                               ret = cls->suspend(sysdev, state);
-                               if (ret)
-                                       goto cls_driver;
-                               WARN_ONCE(!irqs_disabled(),
-                                       "Interrupts enabled after %pF\n",
-                                       cls->suspend);
-                       }
-               }
-       }
-       return 0;
-       /* resume current sysdev */
-cls_driver:
-       drv = NULL;
-       printk(KERN_ERR "Class suspend failed for %s: %d\n",
-               kobject_name(&sysdev->kobj), ret);
-
-aux_driver:
-       if (drv)
-               printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
-                               kobject_name(&sysdev->kobj), ret);
-       list_for_each_entry(err_drv, &cls->drivers, entry) {
-               if (err_drv == drv)
-                       break;
-               if (err_drv->resume)
-                       err_drv->resume(sysdev);
-       }
-
-       /* resume other sysdevs in current class */
-       list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
-               if (err_dev == sysdev)
-                       break;
-               pr_debug(" %s\n", kobject_name(&err_dev->kobj));
-               __sysdev_resume(err_dev);
-       }
-
-       /* resume other classes */
-       list_for_each_entry_continue(cls, &system_kset->list, kset.kobj.entry) {
-               list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
-                       pr_debug(" %s\n", kobject_name(&err_dev->kobj));
-                       __sysdev_resume(err_dev);
-               }
-       }
-       return ret;
-}
-EXPORT_SYMBOL_GPL(sysdev_suspend);
-
-/**
- *     sysdev_resume - Bring system devices back to life.
- *
- *     Similar to sysdev_suspend(), but we iterate the list forwards
- *     to guarantee that parent devices are resumed before their children.
- *
- *     Note: Interrupts are disabled when called.
- */
-int sysdev_resume(void)
-{
-       struct sysdev_class *cls;
-
-       WARN_ONCE(!irqs_disabled(),
-               "Interrupts enabled while resuming system devices\n");
-
-       pr_debug("Resuming System Devices\n");
-
-       list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
-               struct sys_device *sysdev;
-
-               pr_debug("Resuming type '%s':\n",
-                        kobject_name(&cls->kset.kobj));
-
-               list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-                       pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
-                       __sysdev_resume(sysdev);
-               }
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(sysdev_resume);
-#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */
+EXPORT_SYMBOL_GPL(sysdev_register);
+EXPORT_SYMBOL_GPL(sysdev_unregister);
 
 int __init system_bus_init(void)
 {
@@ -534,9 +339,6 @@ int __init system_bus_init(void)
        return 0;
 }
 
-EXPORT_SYMBOL_GPL(sysdev_register);
-EXPORT_SYMBOL_GPL(sysdev_unregister);
-
 #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
 
 ssize_t sysdev_store_ulong(struct sys_device *sysdev,
index 90af2943f9e4a56bb284aab6ce5bab177cfba794..c126db3cb7d12c92be4b5d62abfd58d4a699a961 100644 (file)
@@ -73,6 +73,7 @@ int syscore_suspend(void)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(syscore_suspend);
 
 /**
  * syscore_resume - Execute all the registered system core resume callbacks.
@@ -95,6 +96,7 @@ void syscore_resume(void)
                                "Interrupts enabled after %pF\n", ops->resume);
                }
 }
+EXPORT_SYMBOL_GPL(syscore_resume);
 #endif /* CONFIG_PM_SLEEP */
 
 /**
index 8066d086578a7124a4873bb8376389dc9a010be9..e086fbbbe853ed1d083e368092a9b71b59ec2b8a 100644 (file)
@@ -2547,7 +2547,6 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
        disk->major = MajorNumber;
        disk->first_minor = n << DAC960_MaxPartitionsBits;
        disk->fops = &DAC960_BlockDeviceOperations;
-       disk->events = DISK_EVENT_MEDIA_CHANGE;
    }
   /*
     Indicate the Block Device Registration completed successfully,
index 456c0cc90dcfd58d87de3d34ace5dda354795112..8eba86bba5992ec2b546559c96f7a848e0c2c4e4 100644 (file)
@@ -1736,7 +1736,6 @@ static int __init fd_probe_drives(void)
                disk->major = FLOPPY_MAJOR;
                disk->first_minor = drive;
                disk->fops = &floppy_fops;
-               disk->events = DISK_EVENT_MEDIA_CHANGE;
                sprintf(disk->disk_name, "fd%d", drive);
                disk->private_data = &unit[drive];
                set_capacity(disk, 880*2);
index c871eae14120423f2cd618742730a6f6b51edeb3..ede16c64ff07dbb524cdf84ba8e3622d9efe306b 100644 (file)
@@ -1964,7 +1964,6 @@ static int __init atari_floppy_init (void)
                unit[i].disk->first_minor = i;
                sprintf(unit[i].disk->disk_name, "fd%d", i);
                unit[i].disk->fops = &floppy_fops;
-               unit[i].disk->events = DISK_EVENT_MEDIA_CHANGE;
                unit[i].disk->private_data = &unit[i];
                unit[i].disk->queue = blk_init_queue(do_fd_request,
                                        &ataflop_lock);
index 301d7a9a41a6b51be0ae02f6ca92b2fb063316a7..db8f88586c8d3b2d97dbc910835a0de846ac1fd1 100644 (file)
@@ -4205,7 +4205,6 @@ static int __init floppy_init(void)
                disks[dr]->major = FLOPPY_MAJOR;
                disks[dr]->first_minor = TOMINOR(dr);
                disks[dr]->fops = &floppy_fops;
-               disks[dr]->events = DISK_EVENT_MEDIA_CHANGE;
                sprintf(disks[dr]->disk_name, "fd%d", dr);
 
                init_timer(&motor_off_timer[dr]);
index 2f2ccf6862519c4bb44493ccab140cbbdab37a93..8690e31d993287e16a68caca0e2125c0c7e6bdb0 100644 (file)
@@ -320,7 +320,6 @@ static void pcd_init_units(void)
                disk->first_minor = unit;
                strcpy(disk->disk_name, cd->name);      /* umm... */
                disk->fops = &pcd_bdops;
-               disk->events = DISK_EVENT_MEDIA_CHANGE;
        }
 }
 
index 21dfdb7768695cfe8d9517dc59f4cf7a5b1df279..869e7676d46f47abcb1ffe1812efd3316d234f74 100644 (file)
@@ -837,7 +837,6 @@ static void pd_probe_drive(struct pd_unit *disk)
        p->fops = &pd_fops;
        p->major = major;
        p->first_minor = (disk - pd) << PD_BITS;
-       p->events = DISK_EVENT_MEDIA_CHANGE;
        disk->gd = p;
        p->private_data = disk;
        p->queue = pd_queue;
index 7adeb1edbf43faf02b5f68f79d93f6d839baa9e4..f21b520ef4195228713d34c2f2157ce1b928e37d 100644 (file)
@@ -294,7 +294,6 @@ static void __init pf_init_units(void)
                disk->first_minor = unit;
                strcpy(disk->disk_name, pf->name);
                disk->fops = &pf_fops;
-               disk->events = DISK_EVENT_MEDIA_CHANGE;
                if (!(*drives[unit])[D_PRT])
                        pf_drive_count++;
        }
index 16dc3645291cd7bbb3eab203b83dde68939b61d7..9712fad82bc6cf2be78daaa503432e8725ab2a4f 100644 (file)
@@ -92,6 +92,8 @@ struct rbd_client {
        struct list_head        node;
 };
 
+struct rbd_req_coll;
+
 /*
  * a single io request
  */
@@ -100,6 +102,24 @@ struct rbd_request {
        struct bio              *bio;           /* cloned bio */
        struct page             **pages;        /* list of used pages */
        u64                     len;
+       int                     coll_index;
+       struct rbd_req_coll     *coll;
+};
+
+struct rbd_req_status {
+       int done;
+       int rc;
+       u64 bytes;
+};
+
+/*
+ * a collection of requests
+ */
+struct rbd_req_coll {
+       int                     total;
+       int                     num_done;
+       struct kref             kref;
+       struct rbd_req_status   status[0];
 };
 
 struct rbd_snap {
@@ -416,6 +436,17 @@ static void rbd_put_client(struct rbd_device *rbd_dev)
        rbd_dev->client = NULL;
 }
 
+/*
+ * Destroy requests collection
+ */
+static void rbd_coll_release(struct kref *kref)
+{
+       struct rbd_req_coll *coll =
+               container_of(kref, struct rbd_req_coll, kref);
+
+       dout("rbd_coll_release %p\n", coll);
+       kfree(coll);
+}
 
 /*
  * Create a new header structure, translate header format from the on-disk
@@ -590,6 +621,14 @@ static u64 rbd_get_segment(struct rbd_image_header *header,
        return len;
 }
 
+static int rbd_get_num_segments(struct rbd_image_header *header,
+                               u64 ofs, u64 len)
+{
+       u64 start_seg = ofs >> header->obj_order;
+       u64 end_seg = (ofs + len - 1) >> header->obj_order;
+       return end_seg - start_seg + 1;
+}
+
 /*
  * bio helpers
  */
@@ -735,6 +774,50 @@ static void rbd_destroy_ops(struct ceph_osd_req_op *ops)
        kfree(ops);
 }
 
+static void rbd_coll_end_req_index(struct request *rq,
+                                  struct rbd_req_coll *coll,
+                                  int index,
+                                  int ret, u64 len)
+{
+       struct request_queue *q;
+       int min, max, i;
+
+       dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n",
+            coll, index, ret, len);
+
+       if (!rq)
+               return;
+
+       if (!coll) {
+               blk_end_request(rq, ret, len);
+               return;
+       }
+
+       q = rq->q;
+
+       spin_lock_irq(q->queue_lock);
+       coll->status[index].done = 1;
+       coll->status[index].rc = ret;
+       coll->status[index].bytes = len;
+       max = min = coll->num_done;
+       while (max < coll->total && coll->status[max].done)
+               max++;
+
+       for (i = min; i<max; i++) {
+               __blk_end_request(rq, coll->status[i].rc,
+                                 coll->status[i].bytes);
+               coll->num_done++;
+               kref_put(&coll->kref, rbd_coll_release);
+       }
+       spin_unlock_irq(q->queue_lock);
+}
+
+static void rbd_coll_end_req(struct rbd_request *req,
+                            int ret, u64 len)
+{
+       rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len);
+}
+
 /*
  * Send ceph osd request
  */
@@ -749,6 +832,8 @@ static int rbd_do_request(struct request *rq,
                          int flags,
                          struct ceph_osd_req_op *ops,
                          int num_reply,
+                         struct rbd_req_coll *coll,
+                         int coll_index,
                          void (*rbd_cb)(struct ceph_osd_request *req,
                                         struct ceph_msg *msg),
                          struct ceph_osd_request **linger_req,
@@ -763,12 +848,20 @@ static int rbd_do_request(struct request *rq,
        struct ceph_osd_request_head *reqhead;
        struct rbd_image_header *header = &dev->header;
 
-       ret = -ENOMEM;
        req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
-       if (!req_data)
-               goto done;
+       if (!req_data) {
+               if (coll)
+                       rbd_coll_end_req_index(rq, coll, coll_index,
+                                              -ENOMEM, len);
+               return -ENOMEM;
+       }
 
-       dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs);
+       if (coll) {
+               req_data->coll = coll;
+               req_data->coll_index = coll_index;
+       }
+
+       dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs);
 
        down_read(&header->snap_rwsem);
 
@@ -777,9 +870,9 @@ static int rbd_do_request(struct request *rq,
                                      ops,
                                      false,
                                      GFP_NOIO, pages, bio);
-       if (IS_ERR(req)) {
+       if (!req) {
                up_read(&header->snap_rwsem);
-               ret = PTR_ERR(req);
+               ret = -ENOMEM;
                goto done_pages;
        }
 
@@ -828,7 +921,8 @@ static int rbd_do_request(struct request *rq,
                ret = ceph_osdc_wait_request(&dev->client->osdc, req);
                if (ver)
                        *ver = le64_to_cpu(req->r_reassert_version.version);
-               dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version));
+               dout("reassert_ver=%lld\n",
+                    le64_to_cpu(req->r_reassert_version.version));
                ceph_osdc_put_request(req);
        }
        return ret;
@@ -837,10 +931,8 @@ done_err:
        bio_chain_put(req_data->bio);
        ceph_osdc_put_request(req);
 done_pages:
+       rbd_coll_end_req(req_data, ret, len);
        kfree(req_data);
-done:
-       if (rq)
-               blk_end_request(rq, ret, len);
        return ret;
 }
 
@@ -874,7 +966,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
                bytes = req_data->len;
        }
 
-       blk_end_request(req_data->rq, rc, bytes);
+       rbd_coll_end_req(req_data, rc, bytes);
 
        if (req_data->bio)
                bio_chain_put(req_data->bio);
@@ -934,6 +1026,7 @@ static int rbd_req_sync_op(struct rbd_device *dev,
                          flags,
                          ops,
                          2,
+                         NULL, 0,
                          NULL,
                          linger_req, ver);
        if (ret < 0)
@@ -959,7 +1052,9 @@ static int rbd_do_op(struct request *rq,
                     u64 snapid,
                     int opcode, int flags, int num_reply,
                     u64 ofs, u64 len,
-                    struct bio *bio)
+                    struct bio *bio,
+                    struct rbd_req_coll *coll,
+                    int coll_index)
 {
        char *seg_name;
        u64 seg_ofs;
@@ -995,7 +1090,10 @@ static int rbd_do_op(struct request *rq,
                             flags,
                             ops,
                             num_reply,
+                            coll, coll_index,
                             rbd_req_cb, 0, NULL);
+
+       rbd_destroy_ops(ops);
 done:
        kfree(seg_name);
        return ret;
@@ -1008,13 +1106,15 @@ static int rbd_req_write(struct request *rq,
                         struct rbd_device *rbd_dev,
                         struct ceph_snap_context *snapc,
                         u64 ofs, u64 len,
-                        struct bio *bio)
+                        struct bio *bio,
+                        struct rbd_req_coll *coll,
+                        int coll_index)
 {
        return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
                         CEPH_OSD_OP_WRITE,
                         CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
                         2,
-                        ofs, len, bio);
+                        ofs, len, bio, coll, coll_index);
 }
 
 /*
@@ -1024,14 +1124,16 @@ static int rbd_req_read(struct request *rq,
                         struct rbd_device *rbd_dev,
                         u64 snapid,
                         u64 ofs, u64 len,
-                        struct bio *bio)
+                        struct bio *bio,
+                        struct rbd_req_coll *coll,
+                        int coll_index)
 {
        return rbd_do_op(rq, rbd_dev, NULL,
                         (snapid ? snapid : CEPH_NOSNAP),
                         CEPH_OSD_OP_READ,
                         CEPH_OSD_FLAG_READ,
                         2,
-                        ofs, len, bio);
+                        ofs, len, bio, coll, coll_index);
 }
 
 /*
@@ -1063,7 +1165,9 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev,
 {
        struct ceph_osd_req_op *ops;
        struct page **pages = NULL;
-       int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0);
+       int ret;
+
+       ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0);
        if (ret < 0)
                return ret;
 
@@ -1077,6 +1181,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev,
                          CEPH_OSD_FLAG_READ,
                          ops,
                          1,
+                         NULL, 0,
                          rbd_simple_req_cb, 0, NULL);
 
        rbd_destroy_ops(ops);
@@ -1274,6 +1379,20 @@ static int rbd_req_sync_exec(struct rbd_device *dev,
        return ret;
 }
 
+static struct rbd_req_coll *rbd_alloc_coll(int num_reqs)
+{
+       struct rbd_req_coll *coll =
+                       kzalloc(sizeof(struct rbd_req_coll) +
+                               sizeof(struct rbd_req_status) * num_reqs,
+                               GFP_ATOMIC);
+
+       if (!coll)
+               return NULL;
+       coll->total = num_reqs;
+       kref_init(&coll->kref);
+       return coll;
+}
+
 /*
  * block device queue callback
  */
@@ -1291,6 +1410,8 @@ static void rbd_rq_fn(struct request_queue *q)
                bool do_write;
                int size, op_size = 0;
                u64 ofs;
+               int num_segs, cur_seg = 0;
+               struct rbd_req_coll *coll;
 
                /* peek at request from block layer */
                if (!rq)
@@ -1321,6 +1442,14 @@ static void rbd_rq_fn(struct request_queue *q)
                     do_write ? "write" : "read",
                     size, blk_rq_pos(rq) * 512ULL);
 
+               num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
+               coll = rbd_alloc_coll(num_segs);
+               if (!coll) {
+                       spin_lock_irq(q->queue_lock);
+                       __blk_end_request_all(rq, -ENOMEM);
+                       goto next;
+               }
+
                do {
                        /* a bio clone to be passed down to OSD req */
                        dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
@@ -1328,35 +1457,41 @@ static void rbd_rq_fn(struct request_queue *q)
                                                  rbd_dev->header.block_name,
                                                  ofs, size,
                                                  NULL, NULL);
+                       kref_get(&coll->kref);
                        bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
                                              op_size, GFP_ATOMIC);
                        if (!bio) {
-                               spin_lock_irq(q->queue_lock);
-                               __blk_end_request_all(rq, -ENOMEM);
-                               goto next;
+                               rbd_coll_end_req_index(rq, coll, cur_seg,
+                                                      -ENOMEM, op_size);
+                               goto next_seg;
                        }
 
+
                        /* init OSD command: write or read */
                        if (do_write)
                                rbd_req_write(rq, rbd_dev,
                                              rbd_dev->header.snapc,
                                              ofs,
-                                             op_size, bio);
+                                             op_size, bio,
+                                             coll, cur_seg);
                        else
                                rbd_req_read(rq, rbd_dev,
                                             cur_snap_id(rbd_dev),
                                             ofs,
-                                            op_size, bio);
+                                            op_size, bio,
+                                            coll, cur_seg);
 
+next_seg:
                        size -= op_size;
                        ofs += op_size;
 
+                       cur_seg++;
                        rq_bio = next_bio;
                } while (size > 0);
+               kref_put(&coll->kref, rbd_coll_release);
 
                if (bp)
                        bio_pair_release(bp);
-
                spin_lock_irq(q->queue_lock);
 next:
                rq = blk_fetch_request(q);
index 24a482f2fbd60fcfd0917374bd6197a76d6ddf85..fd5adcd55944ac3a9384f86bbe3d7507df0f9964 100644 (file)
@@ -858,7 +858,6 @@ static int __devinit swim_floppy_init(struct swim_priv *swd)
                swd->unit[drive].disk->first_minor = drive;
                sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
                swd->unit[drive].disk->fops = &floppy_fops;
-               swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
                swd->unit[drive].disk->private_data = &swd->unit[drive];
                swd->unit[drive].disk->queue = swd->queue;
                set_capacity(swd->unit[drive].disk, 2880);
index 4c10f56facbff8b5c0e56615c0ebc79a1179903f..773bfa7927775396f80c004b4d6551c485efe4c6 100644 (file)
@@ -1163,7 +1163,6 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device
        disk->major = FLOPPY_MAJOR;
        disk->first_minor = i;
        disk->fops = &floppy_fops;
-       disk->events = DISK_EVENT_MEDIA_CHANGE;
        disk->private_data = &floppy_states[i];
        disk->queue = swim3_queue;
        disk->flags |= GENHD_FL_REMOVABLE;
index 68b9430c7cfe56f7f23330cb152b103aef3098b9..0e376d46bdd1d6f73a61583882eec6faa654a832 100644 (file)
@@ -2334,7 +2334,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
        disk->major = UB_MAJOR;
        disk->first_minor = lun->id * UB_PARTS_PER_LUN;
        disk->fops = &ub_bd_fops;
-       disk->events = DISK_EVENT_MEDIA_CHANGE;
        disk->private_data = lun;
        disk->driverfs_dev = &sc->intf->dev;
 
index 645ff765cd129cbb3046e57ea477e4b387205d45..6c7fd7db6dffc9e8cb287d30be803c8c59d0d770 100644 (file)
@@ -1005,7 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace)
        ace->gd->major = ace_major;
        ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
        ace->gd->fops = &ace_fops;
-       ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
        ace->gd->queue = ace->queue;
        ace->gd->private_data = ace;
        snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
index 514dd8efaf7385f03ab6d7566f4eaac38d4fd5aa..75fb965b8f72b1e9fa2a8001f7fb16fb12388d5c 100644 (file)
@@ -986,6 +986,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
 
        cdinfo(CD_OPEN, "entering cdrom_open\n"); 
 
+       /* open is event synchronization point, check events first */
+       check_disk_change(bdev);
+
        /* if this was a O_NONBLOCK open and we should honor the flags,
         * do a quick open without drive/disc integrity checks. */
        cdi->use_count++;
@@ -1012,9 +1015,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
 
        cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
                        cdi->name, cdi->use_count);
-       /* Do this on open.  Don't wait for mount, because they might
-           not be mounting, but opening with O_NONBLOCK */
-       check_disk_change(bdev);
        return 0;
 err_release:
        if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
index b2b034fea34e6b8eabf7054928e34bc4d6fc0e17..3ceaf006e7f080fabc94848e9fc3b53f3dd59f0a 100644 (file)
@@ -803,7 +803,6 @@ static int __devinit probe_gdrom(struct platform_device *devptr)
                goto probe_fail_cdrom_register;
        }
        gd.disk->fops = &gdrom_bdops;
-       gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
        /* latch on to the interrupt */
        err = gdrom_set_interrupt_handlers();
        if (err)
index 4e874c5fa60595036a7e10b26257384715b06b56..e427fbe459994a8491945a65fd085201f40ed01f 100644 (file)
@@ -626,7 +626,6 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        gendisk->queue = q;
        gendisk->fops = &viocd_fops;
        gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
-       gendisk->events = DISK_EVENT_MEDIA_CHANGE;
        set_capacity(gendisk, 0);
        gendisk->private_data = d;
        d->viocd_disk = gendisk;
index 012cba0d6d965219de4d286a855285eeab05ec23..b072648dc3f64904f60df2f58d230de06688024e 100644 (file)
@@ -115,6 +115,9 @@ static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
        struct agp_memory *new;
        unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
 
+       if (INT_MAX/sizeof(struct page *) < num_agp_pages)
+               return NULL;
+
        new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
        if (new == NULL)
                return NULL;
@@ -234,11 +237,14 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
        int scratch_pages;
        struct agp_memory *new;
        size_t i;
+       int cur_memory;
 
        if (!bridge)
                return NULL;
 
-       if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
+       cur_memory = atomic_read(&bridge->current_memory_agp);
+       if ((cur_memory + page_count > bridge->max_memory_agp) ||
+           (cur_memory + page_count < page_count))
                return NULL;
 
        if (type >= AGP_USER_TYPES) {
@@ -1089,8 +1095,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
                return -EINVAL;
        }
 
-       /* AK: could wrap */
-       if ((pg_start + mem->page_count) > num_entries)
+       if (((pg_start + mem->page_count) > num_entries) ||
+           ((pg_start + mem->page_count) < pg_start))
                return -EINVAL;
 
        j = pg_start;
@@ -1124,7 +1130,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        size_t i;
        struct agp_bridge_data *bridge;
-       int mask_type;
+       int mask_type, num_entries;
 
        bridge = mem->bridge;
        if (!bridge)
@@ -1136,6 +1142,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
        if (type != mem->type)
                return -EINVAL;
 
+       num_entries = agp_num_entries();
+       if (((pg_start + mem->page_count) > num_entries) ||
+           ((pg_start + mem->page_count) < pg_start))
+               return -EINVAL;
+
        mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
        if (mask_type != 0) {
                /* The generic routines know nothing of memory types */
index 7066e801b9d348e9506651e11bf51197b24d2847..051474c65b783c5e9f3315de2fb3732516810027 100644 (file)
@@ -84,8 +84,6 @@ static struct clocksource clocksource_hpet = {
        .rating         = 250,
        .read           = read_hpet,
        .mask           = CLOCKSOURCE_MASK(64),
-       .mult           = 0,            /* to be calculated */
-       .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 static struct clocksource *hpet_clocksource;
@@ -934,9 +932,7 @@ int hpet_alloc(struct hpet_data *hdp)
        if (!hpet_clocksource) {
                hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
                CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
-               clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq,
-                                               clocksource_hpet.shift);
-               clocksource_register(&clocksource_hpet);
+               clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
                hpetp->hp_clocksource = &clocksource_hpet;
                hpet_clocksource = &clocksource_hpet;
        }
index 43ac61978d8b2661672418901bde4242462a6165..ac6739e085e3cede7ede5588854aeca8503f1c7c 100644 (file)
@@ -619,15 +619,18 @@ static void __devinit n2rng_driver_version(void)
                pr_info("%s", version);
 }
 
+static const struct of_device_id n2rng_match[];
 static int __devinit n2rng_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        int victoria_falls;
        int err = -ENOMEM;
        struct n2rng *np;
 
-       if (!op->dev.of_match)
+       match = of_match_device(n2rng_match, &op->dev);
+       if (!match)
                return -EINVAL;
-       victoria_falls = (op->dev.of_match->data != NULL);
+       victoria_falls = (match->data != NULL);
 
        n2rng_driver_version();
        np = kzalloc(sizeof(*np), GFP_KERNEL);
index cc6c9b2546a30eed5dad30ac8a928e19514bc1c9..64c6b85306150723ad8206f11fab7f54d8dd597b 100644 (file)
@@ -2554,9 +2554,11 @@ static struct pci_driver ipmi_pci_driver = {
 };
 #endif /* CONFIG_PCI */
 
+static struct of_device_id ipmi_match[];
 static int __devinit ipmi_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_OF
+       const struct of_device_id *match;
        struct smi_info *info;
        struct resource resource;
        const __be32 *regsize, *regspacing, *regshift;
@@ -2566,7 +2568,8 @@ static int __devinit ipmi_probe(struct platform_device *dev)
 
        dev_info(&dev->dev, "probing via device tree\n");
 
-       if (!dev->dev.of_match)
+       match = of_match_device(ipmi_match, &dev->dev);
+       if (!match)
                return -EINVAL;
 
        ret = of_address_to_resource(np, 0, &resource);
@@ -2601,7 +2604,7 @@ static int __devinit ipmi_probe(struct platform_device *dev)
                return -ENOMEM;
        }
 
-       info->si_type           = (enum si_type) dev->dev.of_match->data;
+       info->si_type           = (enum si_type) match->data;
        info->addr_source       = SI_DEVICETREE;
        info->irq_setup         = std_irq_setup;
 
index 84b164d1eb2b16d29db4d87ed6a7d745fa1938bc..838568a7dbf56845755bf6e579142505a7172809 100644 (file)
@@ -1280,18 +1280,7 @@ static void unplug_port(struct port *port)
                spin_lock_irq(&pdrvdata_lock);
                list_del(&port->cons.list);
                spin_unlock_irq(&pdrvdata_lock);
-#if 0
-               /*
-                * hvc_remove() not called as removing one hvc port
-                * results in other hvc ports getting frozen.
-                *
-                * Once this is resolved in hvc, this functionality
-                * will be enabled.  Till that is done, the -EPIPE
-                * return from get_chars() above will help
-                * hvc_console.c to clean up on ports we remove here.
-                */
                hvc_remove(port->cons.hvc);
-#endif
        }
 
        /* Remove unused data this port might have received. */
index d6412c16385f72940da3d501052742a250bdb8ed..39ccdeada79101fe2e910328110843fd569d3188 100644 (file)
@@ -715,13 +715,13 @@ static int __devexit hwicap_remove(struct device *dev)
 }
 
 #ifdef CONFIG_OF
-static int __devinit hwicap_of_probe(struct platform_device *op)
+static int __devinit hwicap_of_probe(struct platform_device *op,
+                                    const struct hwicap_driver_config *config)
 {
        struct resource res;
        const unsigned int *id;
        const char *family;
        int rc;
-       const struct hwicap_driver_config *config = op->dev.of_match->data;
        const struct config_registers *regs;
 
 
@@ -751,20 +751,24 @@ static int __devinit hwicap_of_probe(struct platform_device *op)
                        regs);
 }
 #else
-static inline int hwicap_of_probe(struct platform_device *op)
+static inline int hwicap_of_probe(struct platform_device *op,
+                                 const struct hwicap_driver_config *config)
 {
        return -EINVAL;
 }
 #endif /* CONFIG_OF */
 
+static const struct of_device_id __devinitconst hwicap_of_match[];
 static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *match;
        struct resource *res;
        const struct config_registers *regs;
        const char *family;
 
-       if (pdev->dev.of_match)
-               return hwicap_of_probe(pdev);
+       match = of_match_device(hwicap_of_match, &pdev->dev);
+       if (match)
+               return hwicap_of_probe(pdev, match->data);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
index 0fc0a79852de0f919bd2ac9ac117533ed8a0f991..6db161f64ae0e9ab42a17f04608ab3ac18638141 100644 (file)
@@ -32,10 +32,9 @@ static DEFINE_MUTEX(clocks_mutex);
  * Then we take the most specific entry - with the following
  * order of precedence: dev+con > dev only > con only.
  */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
+static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 {
-       struct clk_lookup *p;
-       struct clk *clk = NULL;
+       struct clk_lookup *p, *cl = NULL;
        int match, best = 0;
 
        list_for_each_entry(p, &clocks, node) {
@@ -52,27 +51,27 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
                }
 
                if (match > best) {
-                       clk = p->clk;
+                       cl = p;
                        if (match != 3)
                                best = match;
                        else
                                break;
                }
        }
-       return clk;
+       return cl;
 }
 
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
-       struct clk *clk;
+       struct clk_lookup *cl;
 
        mutex_lock(&clocks_mutex);
-       clk = clk_find(dev_id, con_id);
-       if (clk && !__clk_get(clk))
-               clk = NULL;
+       cl = clk_find(dev_id, con_id);
+       if (cl && !__clk_get(cl->clk))
+               cl = NULL;
        mutex_unlock(&clocks_mutex);
 
-       return clk ? clk : ERR_PTR(-ENOENT);
+       return cl ? cl->clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
new file mode 100644 (file)
index 0000000..110aeeb
--- /dev/null
@@ -0,0 +1,2 @@
+config CLKSRC_I8253
+       bool
index be61ece6330bee0965ed3e8de273daa38946b984..cfb6383b543a6dc8dd38a1d26c5fc4448e705f62 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)    += cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)     += sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)    += sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)     += sh_tmu.o
+obj-$(CONFIG_CLKSRC_I8253)     += i8253.o
index 64e528e8bfa68f8dba9d92b1f0e2b6e2c5bdda29..72f811f73e9c7807796e4da2814e3845d5986a0b 100644 (file)
@@ -29,8 +29,6 @@ static struct clocksource clocksource_cyclone = {
        .rating         = 250,
        .read           = read_cyclone,
        .mask           = CYCLONE_TIMER_MASK,
-       .mult           = 10,
-       .shift          = 0,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -108,12 +106,8 @@ static int __init init_cyclone_clocksource(void)
        }
        cyclone_ptr = cyclone_timer;
 
-       /* sort out mult/shift values: */
-       clocksource_cyclone.shift = 22;
-       clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ,
-                                               clocksource_cyclone.shift);
-
-       return clocksource_register(&clocksource_cyclone);
+       return clocksource_register_hz(&clocksource_cyclone,
+                                       CYCLONE_TIMER_FREQ);
 }
 
 arch_initcall(init_cyclone_clocksource);
diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c
new file mode 100644 (file)
index 0000000..225c176
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * i8253 PIT clocksource
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/timex.h>
+
+#include <asm/i8253.h>
+
+/*
+ * Since the PIT overflows every tick, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static cycle_t i8253_read(struct clocksource *cs)
+{
+       static int old_count;
+       static u32 old_jifs;
+       unsigned long flags;
+       int count;
+       u32 jifs;
+
+       raw_spin_lock_irqsave(&i8253_lock, flags);
+       /*
+        * Although our caller may have the read side of xtime_lock,
+        * this is now a seqlock, and we are cheating in this routine
+        * by having side effects on state that we cannot undo if
+        * there is a collision on the seqlock and our caller has to
+        * retry.  (Namely, old_jifs and old_count.)  So we must treat
+        * jiffies as volatile despite the lock.  We read jiffies
+        * before latching the timer count to guarantee that although
+        * the jiffies value might be older than the count (that is,
+        * the counter may underflow between the last point where
+        * jiffies was incremented and the point where we latch the
+        * count), it cannot be newer.
+        */
+       jifs = jiffies;
+       outb_pit(0x00, PIT_MODE);       /* latch the count ASAP */
+       count = inb_pit(PIT_CH0);       /* read the latched count */
+       count |= inb_pit(PIT_CH0) << 8;
+
+       /* VIA686a test code... reset the latch if count > max + 1 */
+       if (count > LATCH) {
+               outb_pit(0x34, PIT_MODE);
+               outb_pit(PIT_LATCH & 0xff, PIT_CH0);
+               outb_pit(PIT_LATCH >> 8, PIT_CH0);
+               count = PIT_LATCH - 1;
+       }
+
+       /*
+        * It's possible for count to appear to go the wrong way for a
+        * couple of reasons:
+        *
+        *  1. The timer counter underflows, but we haven't handled the
+        *     resulting interrupt and incremented jiffies yet.
+        *  2. Hardware problem with the timer, not giving us continuous time,
+        *     the counter does small "jumps" upwards on some Pentium systems,
+        *     (see c't 95/10 page 335 for Neptun bug.)
+        *
+        * Previous attempts to handle these cases intelligently were
+        * buggy, so we just do the simple thing now.
+        */
+       if (count > old_count && jifs == old_jifs)
+               count = old_count;
+
+       old_count = count;
+       old_jifs = jifs;
+
+       raw_spin_unlock_irqrestore(&i8253_lock, flags);
+
+       count = (PIT_LATCH - 1) - count;
+
+       return (cycle_t)(jifs * PIT_LATCH) + count;
+}
+
+static struct clocksource i8253_cs = {
+       .name           = "pit",
+       .rating         = 110,
+       .read           = i8253_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+};
+
+int __init clocksource_i8253_init(void)
+{
+       return clocksource_register_hz(&i8253_cs, PIT_TICK_RATE);
+}
index d77005849af857935fe270725f2ee0d08561d265..219d88a0eeae07c1e963c4997f6894fe79046d2a 100644 (file)
@@ -142,6 +142,7 @@ static int cn_call_callback(struct sk_buff *skb)
                cbq->callback(msg, nsp);
                kfree_skb(skb);
                cn_queue_release_callback(cbq);
+               err = 0;
        }
 
        return err;
index ca8ee8093d6c604266c13b94a0949f4ca6c0abba..9fb84853d8e307d6f0e6f70e14f485c98c8784d3 100644 (file)
@@ -1,3 +1,5 @@
+menu "CPU Frequency scaling"
+
 config CPU_FREQ
        bool "CPU Frequency scaling"
        help
@@ -18,19 +20,6 @@ if CPU_FREQ
 config CPU_FREQ_TABLE
        tristate
 
-config CPU_FREQ_DEBUG
-       bool "Enable CPUfreq debugging"
-       help
-         Say Y here to enable CPUfreq subsystem (including drivers)
-         debugging. You will need to activate it via the kernel
-         command line by passing
-            cpufreq.debug=<value>
-
-         To get <value>, add 
-              1 to activate CPUfreq core debugging,
-              2 to activate CPUfreq drivers debugging, and
-              4 to activate CPUfreq governor debugging
-
 config CPU_FREQ_STAT
        tristate "CPU frequency translation statistics"
        select CPU_FREQ_TABLE
@@ -190,4 +179,10 @@ config CPU_FREQ_GOV_CONSERVATIVE
 
          If in doubt, say N.
 
-endif  # CPU_FREQ
+menu "x86 CPU frequency scaling drivers"
+depends on X86
+source "drivers/cpufreq/Kconfig.x86"
+endmenu
+
+endif
+endmenu
similarity index 97%
rename from arch/x86/kernel/cpu/cpufreq/Kconfig
rename to drivers/cpufreq/Kconfig.x86
index 870e6cc6ad28bc5d69b292a228992c0f448bb66c..78ff7ee48951b6d6d488f0da4d40e47929608f24 100644 (file)
@@ -1,15 +1,7 @@
 #
-# CPU Frequency scaling
+# x86 CPU Frequency scaling drivers
 #
 
-menu "CPU Frequency scaling"
-
-source "drivers/cpufreq/Kconfig"
-
-if CPU_FREQ
-
-comment "CPUFreq processor drivers"
-
 config X86_PCC_CPUFREQ
        tristate "Processor Clocking Control interface driver"
        depends on ACPI && ACPI_PROCESSOR
@@ -43,7 +35,7 @@ config X86_ACPI_CPUFREQ
 config ELAN_CPUFREQ
        tristate "AMD Elan SC400 and SC410"
        select CPU_FREQ_TABLE
-       depends on X86_ELAN
+       depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC400 and SC410
          processors.
@@ -59,7 +51,7 @@ config ELAN_CPUFREQ
 config SC520_CPUFREQ
        tristate "AMD Elan SC520"
        select CPU_FREQ_TABLE
-       depends on X86_ELAN
+       depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC520 processor.
 
@@ -261,6 +253,3 @@ config X86_SPEEDSTEP_RELAXED_CAP_CHECK
          option lets the probing code bypass some of those checks if the
          parameter "relaxed_check=1" is passed to the module.
 
-endif  # CPU_FREQ
-
-endmenu
index 71fc3b4173f10d2d81930ae003445f0037fb1e7d..c7f1a6f16b6e6a6b1faf2dfb2a3c180cea7aec1f 100644 (file)
@@ -13,3 +13,29 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)      += cpufreq_conservative.o
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
 
+##################################################################################d
+# x86 drivers.
+# Link order matters. K8 is preferred to ACPI because of firmware bugs in early
+# K8 systems. ACPI is preferred to all other hardware-specific drivers.
+# speedstep-* is preferred over p4-clockmod.
+
+obj-$(CONFIG_X86_POWERNOW_K8)          += powernow-k8.o mperf.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ)         += acpi-cpufreq.o mperf.o
+obj-$(CONFIG_X86_PCC_CPUFREQ)          += pcc-cpufreq.o
+obj-$(CONFIG_X86_POWERNOW_K6)          += powernow-k6.o
+obj-$(CONFIG_X86_POWERNOW_K7)          += powernow-k7.o
+obj-$(CONFIG_X86_LONGHAUL)             += longhaul.o
+obj-$(CONFIG_X86_E_POWERSAVER)         += e_powersaver.o
+obj-$(CONFIG_ELAN_CPUFREQ)             += elanfreq.o
+obj-$(CONFIG_SC520_CPUFREQ)            += sc520_freq.o
+obj-$(CONFIG_X86_LONGRUN)              += longrun.o
+obj-$(CONFIG_X86_GX_SUSPMOD)           += gx-suspmod.o
+obj-$(CONFIG_X86_SPEEDSTEP_ICH)                += speedstep-ich.o
+obj-$(CONFIG_X86_SPEEDSTEP_LIB)                += speedstep-lib.o
+obj-$(CONFIG_X86_SPEEDSTEP_SMI)                += speedstep-smi.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)   += speedstep-centrino.o
+obj-$(CONFIG_X86_P4_CLOCKMOD)          += p4-clockmod.o
+obj-$(CONFIG_X86_CPUFREQ_NFORCE2)      += cpufreq-nforce2.o
+
+##################################################################################d
+
similarity index 94%
rename from arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
rename to drivers/cpufreq/acpi-cpufreq.c
index a2baafb2fe6d38cddaf3e62dc1a8dd9feb18baf3..4e04e1274388744efa6689da9fb7922974182999 100644 (file)
@@ -47,9 +47,6 @@
 #include <asm/cpufeature.h>
 #include "mperf.h"
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "acpi-cpufreq", msg)
-
 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
 MODULE_LICENSE("GPL");
@@ -233,7 +230,7 @@ static u32 get_cur_val(const struct cpumask *mask)
        cmd.mask = mask;
        drv_read(&cmd);
 
-       dprintk("get_cur_val = %u\n", cmd.val);
+       pr_debug("get_cur_val = %u\n", cmd.val);
 
        return cmd.val;
 }
@@ -244,7 +241,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
        unsigned int freq;
        unsigned int cached_freq;
 
-       dprintk("get_cur_freq_on_cpu (%d)\n", cpu);
+       pr_debug("get_cur_freq_on_cpu (%d)\n", cpu);
 
        if (unlikely(data == NULL ||
                     data->acpi_data == NULL || data->freq_table == NULL)) {
@@ -261,7 +258,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
                data->resume = 1;
        }
 
-       dprintk("cur freq = %u\n", freq);
+       pr_debug("cur freq = %u\n", freq);
 
        return freq;
 }
@@ -293,7 +290,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        unsigned int i;
        int result = 0;
 
-       dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
+       pr_debug("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
 
        if (unlikely(data == NULL ||
             data->acpi_data == NULL || data->freq_table == NULL)) {
@@ -313,11 +310,11 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        next_perf_state = data->freq_table[next_state].index;
        if (perf->state == next_perf_state) {
                if (unlikely(data->resume)) {
-                       dprintk("Called after resume, resetting to P%d\n",
+                       pr_debug("Called after resume, resetting to P%d\n",
                                next_perf_state);
                        data->resume = 0;
                } else {
-                       dprintk("Already at target state (P%d)\n",
+                       pr_debug("Already at target state (P%d)\n",
                                next_perf_state);
                        goto out;
                }
@@ -357,7 +354,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 
        if (acpi_pstate_strict) {
                if (!check_freqs(cmd.mask, freqs.new, data)) {
-                       dprintk("acpi_cpufreq_target failed (%d)\n",
+                       pr_debug("acpi_cpufreq_target failed (%d)\n",
                                policy->cpu);
                        result = -EAGAIN;
                        goto out;
@@ -378,7 +375,7 @@ static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
 {
        struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
-       dprintk("acpi_cpufreq_verify\n");
+       pr_debug("acpi_cpufreq_verify\n");
 
        return cpufreq_frequency_table_verify(policy, data->freq_table);
 }
@@ -433,11 +430,11 @@ static void free_acpi_perf_data(void)
 static int __init acpi_cpufreq_early_init(void)
 {
        unsigned int i;
-       dprintk("acpi_cpufreq_early_init\n");
+       pr_debug("acpi_cpufreq_early_init\n");
 
        acpi_perf_data = alloc_percpu(struct acpi_processor_performance);
        if (!acpi_perf_data) {
-               dprintk("Memory allocation error for acpi_perf_data.\n");
+               pr_debug("Memory allocation error for acpi_perf_data.\n");
                return -ENOMEM;
        }
        for_each_possible_cpu(i) {
@@ -519,7 +516,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        static int blacklisted;
 #endif
 
-       dprintk("acpi_cpufreq_cpu_init\n");
+       pr_debug("acpi_cpufreq_cpu_init\n");
 
 #ifdef CONFIG_SMP
        if (blacklisted)
@@ -566,7 +563,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        /* capability check */
        if (perf->state_count <= 1) {
-               dprintk("No P-States\n");
+               pr_debug("No P-States\n");
                result = -ENODEV;
                goto err_unreg;
        }
@@ -578,11 +575,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        switch (perf->control_register.space_id) {
        case ACPI_ADR_SPACE_SYSTEM_IO:
-               dprintk("SYSTEM IO addr space\n");
+               pr_debug("SYSTEM IO addr space\n");
                data->cpu_feature = SYSTEM_IO_CAPABLE;
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
-               dprintk("HARDWARE addr space\n");
+               pr_debug("HARDWARE addr space\n");
                if (!check_est_cpu(cpu)) {
                        result = -ENODEV;
                        goto err_unreg;
@@ -590,7 +587,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
                break;
        default:
-               dprintk("Unknown addr space %d\n",
+               pr_debug("Unknown addr space %d\n",
                        (u32) (perf->control_register.space_id));
                result = -ENODEV;
                goto err_unreg;
@@ -661,9 +658,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        if (cpu_has(c, X86_FEATURE_APERFMPERF))
                acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
 
-       dprintk("CPU%u - ACPI performance management activated.\n", cpu);
+       pr_debug("CPU%u - ACPI performance management activated.\n", cpu);
        for (i = 0; i < perf->state_count; i++)
-               dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
+               pr_debug("     %cP%d: %d MHz, %d mW, %d uS\n",
                        (i == perf->state ? '*' : ' '), i,
                        (u32) perf->states[i].core_frequency,
                        (u32) perf->states[i].power,
@@ -694,7 +691,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
        struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
-       dprintk("acpi_cpufreq_cpu_exit\n");
+       pr_debug("acpi_cpufreq_cpu_exit\n");
 
        if (data) {
                cpufreq_frequency_table_put_attr(policy->cpu);
@@ -712,7 +709,7 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
 {
        struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
-       dprintk("acpi_cpufreq_resume\n");
+       pr_debug("acpi_cpufreq_resume\n");
 
        data->resume = 1;
 
@@ -743,7 +740,7 @@ static int __init acpi_cpufreq_init(void)
        if (acpi_disabled)
                return 0;
 
-       dprintk("acpi_cpufreq_init\n");
+       pr_debug("acpi_cpufreq_init\n");
 
        ret = acpi_cpufreq_early_init();
        if (ret)
@@ -758,7 +755,7 @@ static int __init acpi_cpufreq_init(void)
 
 static void __exit acpi_cpufreq_exit(void)
 {
-       dprintk("acpi_cpufreq_exit\n");
+       pr_debug("acpi_cpufreq_exit\n");
 
        cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
similarity index 97%
rename from arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
rename to drivers/cpufreq/cpufreq-nforce2.c
index 141abebc4516a2070c7607a6135a5c20abe107b8..7bac808804f3ad61bce2643c5c00665777f98afd 100644 (file)
@@ -57,8 +57,6 @@ MODULE_PARM_DESC(min_fsb,
                "Minimum FSB to use, if not defined: current FSB - 50");
 
 #define PFX "cpufreq-nforce2: "
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "cpufreq-nforce2", msg)
 
 /**
  * nforce2_calc_fsb - calculate FSB
@@ -270,7 +268,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
        if (freqs.old == freqs.new)
                return 0;
 
-       dprintk("Old CPU frequency %d kHz, new %d kHz\n",
+       pr_debug("Old CPU frequency %d kHz, new %d kHz\n",
               freqs.old, freqs.new);
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -282,7 +280,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
                printk(KERN_ERR PFX "Changing FSB to %d failed\n",
                        target_fsb);
        else
-               dprintk("Changed FSB successfully to %d\n",
+               pr_debug("Changed FSB successfully to %d\n",
                        target_fsb);
 
        /* Enable IRQs */
index 2dafc5c38ae7530584aa6e0fc73c9aa438eaa293..0a5bea9e3585c2cc9daff87417a42e25ad4469b8 100644 (file)
@@ -32,9 +32,6 @@
 
 #include <trace/events/power.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
-                                               "cpufreq-core", msg)
-
 /**
  * The "cpufreq driver" - the arch- or hardware-dependent low
  * level driver of CPUFreq support, and its spinlock. This lock
@@ -180,93 +177,6 @@ void cpufreq_cpu_put(struct cpufreq_policy *data)
 EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
 
-/*********************************************************************
- *                     UNIFIED DEBUG HELPERS                         *
- *********************************************************************/
-#ifdef CONFIG_CPU_FREQ_DEBUG
-
-/* what part(s) of the CPUfreq subsystem are debugged? */
-static unsigned int debug;
-
-/* is the debug output ratelimit'ed using printk_ratelimit? User can
- * set or modify this value.
- */
-static unsigned int debug_ratelimit = 1;
-
-/* is the printk_ratelimit'ing enabled? It's enabled after a successful
- * loading of a cpufreq driver, temporarily disabled when a new policy
- * is set, and disabled upon cpufreq driver removal
- */
-static unsigned int disable_ratelimit = 1;
-static DEFINE_SPINLOCK(disable_ratelimit_lock);
-
-static void cpufreq_debug_enable_ratelimit(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&disable_ratelimit_lock, flags);
-       if (disable_ratelimit)
-               disable_ratelimit--;
-       spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
-}
-
-static void cpufreq_debug_disable_ratelimit(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&disable_ratelimit_lock, flags);
-       disable_ratelimit++;
-       spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
-}
-
-void cpufreq_debug_printk(unsigned int type, const char *prefix,
-                       const char *fmt, ...)
-{
-       char s[256];
-       va_list args;
-       unsigned int len;
-       unsigned long flags;
-
-       WARN_ON(!prefix);
-       if (type & debug) {
-               spin_lock_irqsave(&disable_ratelimit_lock, flags);
-               if (!disable_ratelimit && debug_ratelimit
-                                       && !printk_ratelimit()) {
-                       spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
-                       return;
-               }
-               spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
-
-               len = snprintf(s, 256, KERN_DEBUG "%s: ", prefix);
-
-               va_start(args, fmt);
-               len += vsnprintf(&s[len], (256 - len), fmt, args);
-               va_end(args);
-
-               printk(s);
-
-               WARN_ON(len < 5);
-       }
-}
-EXPORT_SYMBOL(cpufreq_debug_printk);
-
-
-module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core,"
-                       " 2 to debug drivers, and 4 to debug governors.");
-
-module_param(debug_ratelimit, uint, 0644);
-MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging:"
-                                       " set to 0 to disable ratelimiting.");
-
-#else /* !CONFIG_CPU_FREQ_DEBUG */
-
-static inline void cpufreq_debug_enable_ratelimit(void) { return; }
-static inline void cpufreq_debug_disable_ratelimit(void) { return; }
-
-#endif /* CONFIG_CPU_FREQ_DEBUG */
-
-
 /*********************************************************************
  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
  *********************************************************************/
@@ -291,7 +201,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
        if (!l_p_j_ref_freq) {
                l_p_j_ref = loops_per_jiffy;
                l_p_j_ref_freq = ci->old;
-               dprintk("saving %lu as reference value for loops_per_jiffy; "
+               pr_debug("saving %lu as reference value for loops_per_jiffy; "
                        "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
        }
        if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
@@ -299,7 +209,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
            (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
                loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
                                                                ci->new);
-               dprintk("scaling loops_per_jiffy to %lu "
+               pr_debug("scaling loops_per_jiffy to %lu "
                        "for frequency %u kHz\n", loops_per_jiffy, ci->new);
        }
 }
@@ -326,7 +236,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
        BUG_ON(irqs_disabled());
 
        freqs->flags = cpufreq_driver->flags;
-       dprintk("notification %u of frequency transition to %u kHz\n",
+       pr_debug("notification %u of frequency transition to %u kHz\n",
                state, freqs->new);
 
        policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
@@ -340,7 +250,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
                if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
                        if ((policy) && (policy->cpu == freqs->cpu) &&
                            (policy->cur) && (policy->cur != freqs->old)) {
-                               dprintk("Warning: CPU frequency is"
+                               pr_debug("Warning: CPU frequency is"
                                        " %u, cpufreq assumed %u kHz.\n",
                                        freqs->old, policy->cur);
                                freqs->old = policy->cur;
@@ -353,7 +263,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 
        case CPUFREQ_POSTCHANGE:
                adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-               dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
+               pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
                        (unsigned long)freqs->cpu);
                trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
                trace_cpu_frequency(freqs->new, freqs->cpu);
@@ -411,21 +321,14 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
                t = __find_governor(str_governor);
 
                if (t == NULL) {
-                       char *name = kasprintf(GFP_KERNEL, "cpufreq_%s",
-                                                               str_governor);
-
-                       if (name) {
-                               int ret;
+                       int ret;
 
-                               mutex_unlock(&cpufreq_governor_mutex);
-                               ret = request_module("%s", name);
-                               mutex_lock(&cpufreq_governor_mutex);
+                       mutex_unlock(&cpufreq_governor_mutex);
+                       ret = request_module("cpufreq_%s", str_governor);
+                       mutex_lock(&cpufreq_governor_mutex);
 
-                               if (ret == 0)
-                                       t = __find_governor(str_governor);
-                       }
-
-                       kfree(name);
+                       if (ret == 0)
+                               t = __find_governor(str_governor);
                }
 
                if (t != NULL) {
@@ -753,7 +656,7 @@ no_policy:
 static void cpufreq_sysfs_release(struct kobject *kobj)
 {
        struct cpufreq_policy *policy = to_policy(kobj);
-       dprintk("last reference is dropped\n");
+       pr_debug("last reference is dropped\n");
        complete(&policy->kobj_unregister);
 }
 
@@ -788,7 +691,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu,
        gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
        if (gov) {
                policy->governor = gov;
-               dprintk("Restoring governor %s for cpu %d\n",
+               pr_debug("Restoring governor %s for cpu %d\n",
                       policy->governor->name, cpu);
        }
 #endif
@@ -824,7 +727,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu,
                        per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
                        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-                       dprintk("CPU already managed, adding link\n");
+                       pr_debug("CPU already managed, adding link\n");
                        ret = sysfs_create_link(&sys_dev->kobj,
                                                &managed_policy->kobj,
                                                "cpufreq");
@@ -865,7 +768,7 @@ static int cpufreq_add_dev_symlink(unsigned int cpu,
                if (!cpu_online(j))
                        continue;
 
-               dprintk("CPU %u already managed, adding link\n", j);
+               pr_debug("CPU %u already managed, adding link\n", j);
                managed_policy = cpufreq_cpu_get(cpu);
                cpu_sys_dev = get_cpu_sysdev(j);
                ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
@@ -941,7 +844,7 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
        policy->user_policy.governor = policy->governor;
 
        if (ret) {
-               dprintk("setting policy failed\n");
+               pr_debug("setting policy failed\n");
                if (cpufreq_driver->exit)
                        cpufreq_driver->exit(policy);
        }
@@ -977,8 +880,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        if (cpu_is_offline(cpu))
                return 0;
 
-       cpufreq_debug_disable_ratelimit();
-       dprintk("adding CPU %u\n", cpu);
+       pr_debug("adding CPU %u\n", cpu);
 
 #ifdef CONFIG_SMP
        /* check whether a different CPU already registered this
@@ -986,7 +888,6 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        policy = cpufreq_cpu_get(cpu);
        if (unlikely(policy)) {
                cpufreq_cpu_put(policy);
-               cpufreq_debug_enable_ratelimit();
                return 0;
        }
 #endif
@@ -1037,7 +938,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
         */
        ret = cpufreq_driver->init(policy);
        if (ret) {
-               dprintk("initialization failed\n");
+               pr_debug("initialization failed\n");
                goto err_unlock_policy;
        }
        policy->user_policy.min = policy->min;
@@ -1063,8 +964,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
 
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        module_put(cpufreq_driver->owner);
-       dprintk("initialization complete\n");
-       cpufreq_debug_enable_ratelimit();
+       pr_debug("initialization complete\n");
 
        return 0;
 
@@ -1088,7 +988,6 @@ err_free_policy:
 nomem_out:
        module_put(cpufreq_driver->owner);
 module_out:
-       cpufreq_debug_enable_ratelimit();
        return ret;
 }
 
@@ -1112,15 +1011,13 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
        unsigned int j;
 #endif
 
-       cpufreq_debug_disable_ratelimit();
-       dprintk("unregistering CPU %u\n", cpu);
+       pr_debug("unregistering CPU %u\n", cpu);
 
        spin_lock_irqsave(&cpufreq_driver_lock, flags);
        data = per_cpu(cpufreq_cpu_data, cpu);
 
        if (!data) {
                spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-               cpufreq_debug_enable_ratelimit();
                unlock_policy_rwsem_write(cpu);
                return -EINVAL;
        }
@@ -1132,12 +1029,11 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
         * only need to unlink, put and exit
         */
        if (unlikely(cpu != data->cpu)) {
-               dprintk("removing link\n");
+               pr_debug("removing link\n");
                cpumask_clear_cpu(cpu, data->cpus);
                spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
                kobj = &sys_dev->kobj;
                cpufreq_cpu_put(data);
-               cpufreq_debug_enable_ratelimit();
                unlock_policy_rwsem_write(cpu);
                sysfs_remove_link(kobj, "cpufreq");
                return 0;
@@ -1170,7 +1066,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
                for_each_cpu(j, data->cpus) {
                        if (j == cpu)
                                continue;
-                       dprintk("removing link for cpu %u\n", j);
+                       pr_debug("removing link for cpu %u\n", j);
 #ifdef CONFIG_HOTPLUG_CPU
                        strncpy(per_cpu(cpufreq_cpu_governor, j),
                                data->governor->name, CPUFREQ_NAME_LEN);
@@ -1199,21 +1095,35 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
         * not referenced anymore by anybody before we proceed with
         * unloading.
         */
-       dprintk("waiting for dropping of refcount\n");
+       pr_debug("waiting for dropping of refcount\n");
        wait_for_completion(cmp);
-       dprintk("wait complete\n");
+       pr_debug("wait complete\n");
 
        lock_policy_rwsem_write(cpu);
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(data);
        unlock_policy_rwsem_write(cpu);
 
+#ifdef CONFIG_HOTPLUG_CPU
+       /* when the CPU which is the parent of the kobj is hotplugged
+        * offline, check for siblings, and create cpufreq sysfs interface
+        * and symlinks
+        */
+       if (unlikely(cpumask_weight(data->cpus) > 1)) {
+               /* first sibling now owns the new sysfs dir */
+               cpumask_clear_cpu(cpu, data->cpus);
+               cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus)));
+
+               /* finally remove our own symlink */
+               lock_policy_rwsem_write(cpu);
+               __cpufreq_remove_dev(sys_dev);
+       }
+#endif
+
        free_cpumask_var(data->related_cpus);
        free_cpumask_var(data->cpus);
        kfree(data);
-       per_cpu(cpufreq_cpu_data, cpu) = NULL;
 
-       cpufreq_debug_enable_ratelimit();
        return 0;
 }
 
@@ -1239,7 +1149,7 @@ static void handle_update(struct work_struct *work)
        struct cpufreq_policy *policy =
                container_of(work, struct cpufreq_policy, update);
        unsigned int cpu = policy->cpu;
-       dprintk("handle_update for cpu %u called\n", cpu);
+       pr_debug("handle_update for cpu %u called\n", cpu);
        cpufreq_update_policy(cpu);
 }
 
@@ -1257,7 +1167,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
 {
        struct cpufreq_freqs freqs;
 
-       dprintk("Warning: CPU frequency out of sync: cpufreq and timing "
+       pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
               "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
        freqs.cpu = cpu;
@@ -1360,7 +1270,7 @@ static int cpufreq_bp_suspend(void)
        int cpu = smp_processor_id();
        struct cpufreq_policy *cpu_policy;
 
-       dprintk("suspending cpu %u\n", cpu);
+       pr_debug("suspending cpu %u\n", cpu);
 
        /* If there's no policy for the boot CPU, we have nothing to do. */
        cpu_policy = cpufreq_cpu_get(cpu);
@@ -1398,7 +1308,7 @@ static void cpufreq_bp_resume(void)
        int cpu = smp_processor_id();
        struct cpufreq_policy *cpu_policy;
 
-       dprintk("resuming cpu %u\n", cpu);
+       pr_debug("resuming cpu %u\n", cpu);
 
        /* If there's no policy for the boot CPU, we have nothing to do. */
        cpu_policy = cpufreq_cpu_get(cpu);
@@ -1510,7 +1420,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 {
        int retval = -EINVAL;
 
-       dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
+       pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
                target_freq, relation);
        if (cpu_online(policy->cpu) && cpufreq_driver->target)
                retval = cpufreq_driver->target(policy, target_freq, relation);
@@ -1596,7 +1506,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
        if (!try_module_get(policy->governor->owner))
                return -EINVAL;
 
-       dprintk("__cpufreq_governor for CPU %u, event %u\n",
+       pr_debug("__cpufreq_governor for CPU %u, event %u\n",
                                                policy->cpu, event);
        ret = policy->governor->governor(policy, event);
 
@@ -1697,8 +1607,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
 {
        int ret = 0;
 
-       cpufreq_debug_disable_ratelimit();
-       dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
+       pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
                policy->min, policy->max);
 
        memcpy(&policy->cpuinfo, &data->cpuinfo,
@@ -1735,19 +1644,19 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
        data->min = policy->min;
        data->max = policy->max;
 
-       dprintk("new min and max freqs are %u - %u kHz\n",
+       pr_debug("new min and max freqs are %u - %u kHz\n",
                                        data->min, data->max);
 
        if (cpufreq_driver->setpolicy) {
                data->policy = policy->policy;
-               dprintk("setting range\n");
+               pr_debug("setting range\n");
                ret = cpufreq_driver->setpolicy(policy);
        } else {
                if (policy->governor != data->governor) {
                        /* save old, working values */
                        struct cpufreq_governor *old_gov = data->governor;
 
-                       dprintk("governor switch\n");
+                       pr_debug("governor switch\n");
 
                        /* end old governor */
                        if (data->governor)
@@ -1757,7 +1666,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
                        data->governor = policy->governor;
                        if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
                                /* new governor failed, so re-start old one */
-                               dprintk("starting governor %s failed\n",
+                               pr_debug("starting governor %s failed\n",
                                                        data->governor->name);
                                if (old_gov) {
                                        data->governor = old_gov;
@@ -1769,12 +1678,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
                        }
                        /* might be a policy change, too, so fall through */
                }
-               dprintk("governor: change or update limits\n");
+               pr_debug("governor: change or update limits\n");
                __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
        }
 
 error_out:
-       cpufreq_debug_enable_ratelimit();
        return ret;
 }
 
@@ -1801,7 +1709,7 @@ int cpufreq_update_policy(unsigned int cpu)
                goto fail;
        }
 
-       dprintk("updating policy for CPU %u\n", cpu);
+       pr_debug("updating policy for CPU %u\n", cpu);
        memcpy(&policy, data, sizeof(struct cpufreq_policy));
        policy.min = data->user_policy.min;
        policy.max = data->user_policy.max;
@@ -1813,7 +1721,7 @@ int cpufreq_update_policy(unsigned int cpu)
        if (cpufreq_driver->get) {
                policy.cur = cpufreq_driver->get(cpu);
                if (!data->cur) {
-                       dprintk("Driver did not initialize current freq");
+                       pr_debug("Driver did not initialize current freq");
                        data->cur = policy.cur;
                } else {
                        if (data->cur != policy.cur)
@@ -1889,7 +1797,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
            ((!driver_data->setpolicy) && (!driver_data->target)))
                return -EINVAL;
 
-       dprintk("trying to register driver %s\n", driver_data->name);
+       pr_debug("trying to register driver %s\n", driver_data->name);
 
        if (driver_data->setpolicy)
                driver_data->flags |= CPUFREQ_CONST_LOOPS;
@@ -1920,15 +1828,14 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 
                /* if all ->init() calls failed, unregister */
                if (ret) {
-                       dprintk("no CPU initialized for driver %s\n",
+                       pr_debug("no CPU initialized for driver %s\n",
                                                        driver_data->name);
                        goto err_sysdev_unreg;
                }
        }
 
        register_hotcpu_notifier(&cpufreq_cpu_notifier);
-       dprintk("driver %s up and running\n", driver_data->name);
-       cpufreq_debug_enable_ratelimit();
+       pr_debug("driver %s up and running\n", driver_data->name);
 
        return 0;
 err_sysdev_unreg:
@@ -1955,14 +1862,10 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
        unsigned long flags;
 
-       cpufreq_debug_disable_ratelimit();
-
-       if (!cpufreq_driver || (driver != cpufreq_driver)) {
-               cpufreq_debug_enable_ratelimit();
+       if (!cpufreq_driver || (driver != cpufreq_driver))
                return -EINVAL;
-       }
 
-       dprintk("unregistering driver %s\n", driver->name);
+       pr_debug("unregistering driver %s\n", driver->name);
 
        sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
        unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
index 7e2e515087f89aba2498508460d1125f2f9f9f68..f13a8a9af6a130d999a3794588218ee652d5f076 100644 (file)
@@ -15,9 +15,6 @@
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg)
-
 
 static int cpufreq_governor_performance(struct cpufreq_policy *policy,
                                        unsigned int event)
@@ -25,7 +22,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
        switch (event) {
        case CPUFREQ_GOV_START:
        case CPUFREQ_GOV_LIMITS:
-               dprintk("setting to %u kHz because of event %u\n",
+               pr_debug("setting to %u kHz because of event %u\n",
                                                policy->max, event);
                __cpufreq_driver_target(policy, policy->max,
                                                CPUFREQ_RELATION_H);
index e6db5faf3eb112f118cf8ce920168b3635602b78..4c2eb512f2bc3a3da1921ffc4c3ebca61908cd19 100644 (file)
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg)
-
 static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
                                        unsigned int event)
 {
        switch (event) {
        case CPUFREQ_GOV_START:
        case CPUFREQ_GOV_LIMITS:
-               dprintk("setting to %u kHz because of event %u\n",
+               pr_debug("setting to %u kHz because of event %u\n",
                                                        policy->min, event);
                __cpufreq_driver_target(policy, policy->min,
                                                CPUFREQ_RELATION_L);
index 00d73fc8e4e2853d26d217761a2d2e40a2b22ead..b60a4c263686ab56693c5df6993e084e8f9f7e29 100644 (file)
@@ -165,17 +165,27 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
        return -1;
 }
 
+/* should be called late in the CPU removal sequence so that the stats
+ * memory is still available in case someone tries to use it.
+ */
 static void cpufreq_stats_free_table(unsigned int cpu)
 {
        struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
-       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-       if (policy && policy->cpu == cpu)
-               sysfs_remove_group(&policy->kobj, &stats_attr_group);
        if (stat) {
                kfree(stat->time_in_state);
                kfree(stat);
        }
        per_cpu(cpufreq_stats_table, cpu) = NULL;
+}
+
+/* must be called early in the CPU removal sequence (before
+ * cpufreq_remove_dev) so that policy is still valid.
+ */
+static void cpufreq_stats_free_sysfs(unsigned int cpu)
+{
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       if (policy && policy->cpu == cpu)
+               sysfs_remove_group(&policy->kobj, &stats_attr_group);
        if (policy)
                cpufreq_cpu_put(policy);
 }
@@ -316,6 +326,9 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
        case CPU_ONLINE_FROZEN:
                cpufreq_update_policy(cpu);
                break;
+       case CPU_DOWN_PREPARE:
+               cpufreq_stats_free_sysfs(cpu);
+               break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
                cpufreq_stats_free_table(cpu);
@@ -324,9 +337,10 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
-{
+/* priority=1 so this will get called before cpufreq_remove_dev */
+static struct notifier_block cpufreq_stat_cpu_notifier __refdata = {
        .notifier_call = cpufreq_stat_cpu_callback,
+       .priority = 1,
 };
 
 static struct notifier_block notifier_policy_block = {
index 66d2d1d6c80f1dbc0c17388e4dbea81c18c5628e..f231015904c0a6584ed0fb4c57d78de4636746b4 100644 (file)
@@ -37,9 +37,6 @@ static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
 static DEFINE_MUTEX(userspace_mutex);
 static int cpus_using_userspace_governor;
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
-
 /* keep track of frequency transitions */
 static int
 userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
@@ -50,7 +47,7 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
        if (!per_cpu(cpu_is_managed, freq->cpu))
                return 0;
 
-       dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+       pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
                        freq->cpu, freq->new);
        per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
 
@@ -73,7 +70,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
 {
        int ret = -EINVAL;
 
-       dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
+       pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
        mutex_lock(&userspace_mutex);
        if (!per_cpu(cpu_is_managed, policy->cpu))
@@ -134,7 +131,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
                per_cpu(cpu_max_freq, cpu) = policy->max;
                per_cpu(cpu_cur_freq, cpu) = policy->cur;
                per_cpu(cpu_set_freq, cpu) = policy->cur;
-               dprintk("managing cpu %u started "
+               pr_debug("managing cpu %u started "
                        "(%u - %u kHz, currently %u kHz)\n",
                                cpu,
                                per_cpu(cpu_min_freq, cpu),
@@ -156,12 +153,12 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
                per_cpu(cpu_min_freq, cpu) = 0;
                per_cpu(cpu_max_freq, cpu) = 0;
                per_cpu(cpu_set_freq, cpu) = 0;
-               dprintk("managing cpu %u stopped\n", cpu);
+               pr_debug("managing cpu %u stopped\n", cpu);
                mutex_unlock(&userspace_mutex);
                break;
        case CPUFREQ_GOV_LIMITS:
                mutex_lock(&userspace_mutex);
-               dprintk("limit event for cpu %u: %u - %u kHz, "
+               pr_debug("limit event for cpu %u: %u - %u kHz, "
                        "currently %u kHz, last set to %u kHz\n",
                        cpu, policy->min, policy->max,
                        per_cpu(cpu_cur_freq, cpu),
index 05432216e2246ac4d4c78a665e3e63ec67370015..90431cb92804b5cb166c231acd709093cfcf6ff6 100644 (file)
@@ -14,9 +14,6 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
-
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
@@ -31,11 +28,11 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
        for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
                unsigned int freq = table[i].frequency;
                if (freq == CPUFREQ_ENTRY_INVALID) {
-                       dprintk("table entry %u is invalid, skipping\n", i);
+                       pr_debug("table entry %u is invalid, skipping\n", i);
 
                        continue;
                }
-               dprintk("table entry %u: %u kHz, %u index\n",
+               pr_debug("table entry %u: %u kHz, %u index\n",
                                        i, freq, table[i].index);
                if (freq < min_freq)
                        min_freq = freq;
@@ -61,7 +58,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
        unsigned int i;
        unsigned int count = 0;
 
-       dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n",
+       pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
                                        policy->min, policy->max, policy->cpu);
 
        if (!cpu_online(policy->cpu))
@@ -86,7 +83,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
        cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
                                     policy->cpuinfo.max_freq);
 
-       dprintk("verification lead to (%u - %u kHz) for cpu %u\n",
+       pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
                                policy->min, policy->max, policy->cpu);
 
        return 0;
@@ -110,7 +107,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
        };
        unsigned int i;
 
-       dprintk("request for target %u kHz (relation: %u) for cpu %u\n",
+       pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
                                        target_freq, relation, policy->cpu);
 
        switch (relation) {
@@ -167,7 +164,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
        } else
                *index = optimal.index;
 
-       dprintk("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
+       pr_debug("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
                table[*index].index);
 
        return 0;
@@ -216,14 +213,14 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
 void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu)
 {
-       dprintk("setting show_table for cpu %u to %p\n", cpu, table);
+       pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
        per_cpu(cpufreq_show_table, cpu) = table;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu)
 {
-       dprintk("clearing show_table for cpu %u\n", cpu);
+       pr_debug("clearing show_table for cpu %u\n", cpu);
        per_cpu(cpufreq_show_table, cpu) = NULL;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
similarity index 95%
rename from arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
rename to drivers/cpufreq/gx-suspmod.c
index 32974cf84232fd2226f479003d13559ea983610c..ffe1f2c92ed3f6c10da0749b087b39eb4bd9c390 100644 (file)
@@ -142,9 +142,6 @@ module_param(max_duration, int, 0444);
 #define POLICY_MIN_DIV 20
 
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "gx-suspmod", msg)
-
 /**
  * we can detect a core multipiler from dir0_lsb
  * from GX1 datasheet p.56,
@@ -191,7 +188,7 @@ static __init struct pci_dev *gx_detect_chipset(void)
        /* check if CPU is a MediaGX or a Geode. */
        if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
            (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
-               dprintk("error: no MediaGX/Geode processor found!\n");
+               pr_debug("error: no MediaGX/Geode processor found!\n");
                return NULL;
        }
 
@@ -201,7 +198,7 @@ static __init struct pci_dev *gx_detect_chipset(void)
                        return gx_pci;
        }
 
-       dprintk("error: no supported chipset found!\n");
+       pr_debug("error: no supported chipset found!\n");
        return NULL;
 }
 
@@ -305,14 +302,14 @@ static void gx_set_cpuspeed(unsigned int khz)
                        break;
                default:
                        local_irq_restore(flags);
-                       dprintk("fatal: try to set unknown chipset.\n");
+                       pr_debug("fatal: try to set unknown chipset.\n");
                        return;
                }
        } else {
                suscfg = gx_params->pci_suscfg & ~(SUSMOD);
                gx_params->off_duration = 0;
                gx_params->on_duration = 0;
-               dprintk("suspend modulation disabled: cpu runs 100%% speed.\n");
+               pr_debug("suspend modulation disabled: cpu runs 100%% speed.\n");
        }
 
        gx_write_byte(PCI_MODOFF, gx_params->off_duration);
@@ -327,9 +324,9 @@ static void gx_set_cpuspeed(unsigned int khz)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-       dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
+       pr_debug("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
                gx_params->on_duration * 32, gx_params->off_duration * 32);
-       dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
+       pr_debug("suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
 }
 
 /****************************************************************
@@ -428,8 +425,8 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
        stock_freq = maxfreq;
        curfreq = gx_get_cpuspeed(0);
 
-       dprintk("cpu max frequency is %d.\n", maxfreq);
-       dprintk("cpu current frequency is %dkHz.\n", curfreq);
+       pr_debug("cpu max frequency is %d.\n", maxfreq);
+       pr_debug("cpu current frequency is %dkHz.\n", curfreq);
 
        /* setup basic struct for cpufreq API */
        policy->cpu = 0;
@@ -475,7 +472,7 @@ static int __init cpufreq_gx_init(void)
        if (max_duration > 0xff)
                max_duration = 0xff;
 
-       dprintk("geode suspend modulation available.\n");
+       pr_debug("geode suspend modulation available.\n");
 
        params = kzalloc(sizeof(struct gxfreq_params), GFP_KERNEL);
        if (params == NULL)
similarity index 98%
rename from arch/x86/kernel/cpu/cpufreq/longhaul.c
rename to drivers/cpufreq/longhaul.c
index cf48cdd6907de8abcc67ec906f007149b0f9d7de..f47d26e2a13566d870a54ad6f284736f9ffa0209 100644 (file)
@@ -77,9 +77,6 @@ static int scale_voltage;
 static int disable_acpi_c3;
 static int revid_errata;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "longhaul", msg)
-
 
 /* Clock ratios multiplied by 10 */
 static int mults[32];
@@ -87,7 +84,6 @@ static int eblcr[32];
 static int longhaul_version;
 static struct cpufreq_frequency_table *longhaul_table;
 
-#ifdef CONFIG_CPU_FREQ_DEBUG
 static char speedbuffer[8];
 
 static char *print_speed(int speed)
@@ -106,7 +102,6 @@ static char *print_speed(int speed)
 
        return speedbuffer;
 }
-#endif
 
 
 static unsigned int calc_speed(int mult)
@@ -275,7 +270,7 @@ static void longhaul_setstate(unsigned int table_index)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-       dprintk("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
+       pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
                        fsb, mult/10, mult%10, print_speed(speed/1000));
 retry_loop:
        preempt_disable();
@@ -460,12 +455,12 @@ static int __cpuinit longhaul_get_ranges(void)
                break;
        }
 
-       dprintk("MinMult:%d.%dx MaxMult:%d.%dx\n",
+       pr_debug("MinMult:%d.%dx MaxMult:%d.%dx\n",
                 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
        highest_speed = calc_speed(maxmult);
        lowest_speed = calc_speed(minmult);
-       dprintk("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
+       pr_debug("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
                 print_speed(lowest_speed/1000),
                 print_speed(highest_speed/1000));
 
similarity index 94%
rename from arch/x86/kernel/cpu/cpufreq/longrun.c
rename to drivers/cpufreq/longrun.c
index d9f51367666b0c3096829b69fb1db04fb0f34d63..34ea359b370ebca7c74b6470d78bc0731d521c57 100644 (file)
@@ -15,9 +15,6 @@
 #include <asm/msr.h>
 #include <asm/processor.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "longrun", msg)
-
 static struct cpufreq_driver   longrun_driver;
 
 /**
@@ -40,14 +37,14 @@ static void __cpuinit longrun_get_policy(struct cpufreq_policy *policy)
        u32 msr_lo, msr_hi;
 
        rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
-       dprintk("longrun flags are %x - %x\n", msr_lo, msr_hi);
+       pr_debug("longrun flags are %x - %x\n", msr_lo, msr_hi);
        if (msr_lo & 0x01)
                policy->policy = CPUFREQ_POLICY_PERFORMANCE;
        else
                policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
        rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
-       dprintk("longrun ctrl is %x - %x\n", msr_lo, msr_hi);
+       pr_debug("longrun ctrl is %x - %x\n", msr_lo, msr_hi);
        msr_lo &= 0x0000007F;
        msr_hi &= 0x0000007F;
 
@@ -150,7 +147,7 @@ static unsigned int longrun_get(unsigned int cpu)
                return 0;
 
        cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
-       dprintk("cpuid eax is %u\n", eax);
+       pr_debug("cpuid eax is %u\n", eax);
 
        return eax * 1000;
 }
@@ -196,7 +193,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
                rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
                *high_freq = msr_lo * 1000; /* to kHz */
 
-               dprintk("longrun table interface told %u - %u kHz\n",
+               pr_debug("longrun table interface told %u - %u kHz\n",
                                *low_freq, *high_freq);
 
                if (*low_freq > *high_freq)
@@ -207,7 +204,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
        /* set the upper border to the value determined during TSC init */
        *high_freq = (cpu_khz / 1000);
        *high_freq = *high_freq * 1000;
-       dprintk("high frequency is %u kHz\n", *high_freq);
+       pr_debug("high frequency is %u kHz\n", *high_freq);
 
        /* get current borders */
        rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
@@ -233,7 +230,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
                /* restore values */
                wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
        }
-       dprintk("percentage is %u %%, freq is %u MHz\n", ecx, eax);
+       pr_debug("percentage is %u %%, freq is %u MHz\n", ecx, eax);
 
        /* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
         * eqals
@@ -249,7 +246,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
        edx = ((eax - ebx) * 100) / (100 - ecx);
        *low_freq = edx * 1000; /* back to kHz */
 
-       dprintk("low frequency is %u kHz\n", *low_freq);
+       pr_debug("low frequency is %u kHz\n", *low_freq);
 
        if (*low_freq > *high_freq)
                *low_freq = *high_freq;
similarity index 96%
rename from arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
rename to drivers/cpufreq/p4-clockmod.c
index 52c93648e492f10c8c6da916f7c1cd4dc25f2807..6be3e0760c26f0d7b0b3750d165d527b64aaff88 100644 (file)
@@ -35,8 +35,6 @@
 #include "speedstep-lib.h"
 
 #define PFX    "p4-clockmod: "
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "p4-clockmod", msg)
 
 /*
  * Duty Cycle (3bits), note DC_DISABLE is not specified in
@@ -66,7 +64,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
        rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h);
 
        if (l & 0x01)
-               dprintk("CPU#%d currently thermal throttled\n", cpu);
+               pr_debug("CPU#%d currently thermal throttled\n", cpu);
 
        if (has_N44_O17_errata[cpu] &&
            (newstate == DC_25PT || newstate == DC_DFLT))
@@ -74,10 +72,10 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
 
        rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
        if (newstate == DC_DISABLE) {
-               dprintk("CPU#%d disabling modulation\n", cpu);
+               pr_debug("CPU#%d disabling modulation\n", cpu);
                wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
        } else {
-               dprintk("CPU#%d setting duty cycle to %d%%\n",
+               pr_debug("CPU#%d setting duty cycle to %d%%\n",
                        cpu, ((125 * newstate) / 10));
                /* bits 63 - 5  : reserved
                 * bit  4       : enable/disable
@@ -217,7 +215,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
        case 0x0f11:
        case 0x0f12:
                has_N44_O17_errata[policy->cpu] = 1;
-               dprintk("has errata -- disabling low frequencies\n");
+               pr_debug("has errata -- disabling low frequencies\n");
        }
 
        if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4D &&
similarity index 91%
rename from arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
rename to drivers/cpufreq/pcc-cpufreq.c
index 755a31e0f5b0d07ea574e020a87327500eac0308..7b0603eb01297a7088c24d0ab1101e5e9625713b 100644 (file)
@@ -39,7 +39,7 @@
 
 #include <acpi/processor.h>
 
-#define PCC_VERSION    "1.00.00"
+#define PCC_VERSION    "1.10.00"
 #define POLL_LOOPS     300
 
 #define CMD_COMPLETE   0x1
@@ -48,9 +48,6 @@
 
 #define BUF_SZ         4
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER,     \
-                                            "pcc-cpufreq", msg)
-
 struct pcc_register_resource {
        u8 descriptor;
        u16 length;
@@ -102,7 +99,7 @@ static struct acpi_generic_address doorbell;
 static u64 doorbell_preserve;
 static u64 doorbell_write;
 
-static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f,
+static u8 OSC_UUID[16] = {0x9F, 0x2C, 0x9B, 0x63, 0x91, 0x70, 0x1f, 0x49,
                          0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46};
 
 struct pcc_cpu {
@@ -152,7 +149,7 @@ static unsigned int pcc_get_freq(unsigned int cpu)
 
        spin_lock(&pcc_lock);
 
-       dprintk("get: get_freq for CPU %d\n", cpu);
+       pr_debug("get: get_freq for CPU %d\n", cpu);
        pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
 
        input_buffer = 0x1;
@@ -170,7 +167,7 @@ static unsigned int pcc_get_freq(unsigned int cpu)
 
        status = ioread16(&pcch_hdr->status);
        if (status != CMD_COMPLETE) {
-               dprintk("get: FAILED: for CPU %d, status is %d\n",
+               pr_debug("get: FAILED: for CPU %d, status is %d\n",
                        cpu, status);
                goto cmd_incomplete;
        }
@@ -178,14 +175,14 @@ static unsigned int pcc_get_freq(unsigned int cpu)
        curr_freq = (((ioread32(&pcch_hdr->nominal) * (output_buffer & 0xff))
                        / 100) * 1000);
 
-       dprintk("get: SUCCESS: (virtual) output_offset for cpu %d is "
-               "0x%x, contains a value of: 0x%x. Speed is: %d MHz\n",
+       pr_debug("get: SUCCESS: (virtual) output_offset for cpu %d is "
+               "0x%p, contains a value of: 0x%x. Speed is: %d MHz\n",
                cpu, (pcch_virt_addr + pcc_cpu_data->output_offset),
                output_buffer, curr_freq);
 
        freq_limit = (output_buffer >> 8) & 0xff;
        if (freq_limit != 0xff) {
-               dprintk("get: frequency for cpu %d is being temporarily"
+               pr_debug("get: frequency for cpu %d is being temporarily"
                        " capped at %d\n", cpu, curr_freq);
        }
 
@@ -212,8 +209,8 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
        cpu = policy->cpu;
        pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
 
-       dprintk("target: CPU %d should go to target freq: %d "
-               "(virtual) input_offset is 0x%x\n",
+       pr_debug("target: CPU %d should go to target freq: %d "
+               "(virtual) input_offset is 0x%p\n",
                cpu, target_freq,
                (pcch_virt_addr + pcc_cpu_data->input_offset));
 
@@ -234,14 +231,14 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
 
        status = ioread16(&pcch_hdr->status);
        if (status != CMD_COMPLETE) {
-               dprintk("target: FAILED for cpu %d, with status: 0x%x\n",
+               pr_debug("target: FAILED for cpu %d, with status: 0x%x\n",
                        cpu, status);
                goto cmd_incomplete;
        }
        iowrite16(0, &pcch_hdr->status);
 
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-       dprintk("target: was SUCCESSFUL for cpu %d\n", cpu);
+       pr_debug("target: was SUCCESSFUL for cpu %d\n", cpu);
        spin_unlock(&pcc_lock);
 
        return 0;
@@ -293,7 +290,7 @@ static int pcc_get_offset(int cpu)
        memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
        memset_io((pcch_virt_addr + pcc_cpu_data->output_offset), 0, BUF_SZ);
 
-       dprintk("pcc_get_offset: for CPU %d: pcc_cpu_data "
+       pr_debug("pcc_get_offset: for CPU %d: pcc_cpu_data "
                "input_offset: 0x%x, pcc_cpu_data output_offset: 0x%x\n",
                cpu, pcc_cpu_data->input_offset, pcc_cpu_data->output_offset);
 out_free:
@@ -410,7 +407,7 @@ static int __init pcc_cpufreq_probe(void)
        if (ACPI_SUCCESS(status)) {
                ret = pcc_cpufreq_do_osc(&osc_handle);
                if (ret)
-                       dprintk("probe: _OSC evaluation did not succeed\n");
+                       pr_debug("probe: _OSC evaluation did not succeed\n");
                /* Firmware's use of _OSC is optional */
                ret = 0;
        }
@@ -433,7 +430,7 @@ static int __init pcc_cpufreq_probe(void)
 
        mem_resource = (struct pcc_memory_resource *)member->buffer.pointer;
 
-       dprintk("probe: mem_resource descriptor: 0x%x,"
+       pr_debug("probe: mem_resource descriptor: 0x%x,"
                " length: %d, space_id: %d, resource_usage: %d,"
                " type_specific: %d, granularity: 0x%llx,"
                " minimum: 0x%llx, maximum: 0x%llx,"
@@ -453,13 +450,13 @@ static int __init pcc_cpufreq_probe(void)
        pcch_virt_addr = ioremap_nocache(mem_resource->minimum,
                                        mem_resource->address_length);
        if (pcch_virt_addr == NULL) {
-               dprintk("probe: could not map shared mem region\n");
+               pr_debug("probe: could not map shared mem region\n");
                goto out_free;
        }
        pcch_hdr = pcch_virt_addr;
 
-       dprintk("probe: PCCH header (virtual) addr: 0x%p\n", pcch_hdr);
-       dprintk("probe: PCCH header is at physical address: 0x%llx,"
+       pr_debug("probe: PCCH header (virtual) addr: 0x%p\n", pcch_hdr);
+       pr_debug("probe: PCCH header is at physical address: 0x%llx,"
                " signature: 0x%x, length: %d bytes, major: %d, minor: %d,"
                " supported features: 0x%x, command field: 0x%x,"
                " status field: 0x%x, nominal latency: %d us\n",
@@ -469,7 +466,7 @@ static int __init pcc_cpufreq_probe(void)
                ioread16(&pcch_hdr->command), ioread16(&pcch_hdr->status),
                ioread32(&pcch_hdr->latency));
 
-       dprintk("probe: min time between commands: %d us,"
+       pr_debug("probe: min time between commands: %d us,"
                " max time between commands: %d us,"
                " nominal CPU frequency: %d MHz,"
                " minimum CPU frequency: %d MHz,"
@@ -494,7 +491,7 @@ static int __init pcc_cpufreq_probe(void)
        doorbell.access_width = 64;
        doorbell.address = reg_resource->address;
 
-       dprintk("probe: doorbell: space_id is %d, bit_width is %d, "
+       pr_debug("probe: doorbell: space_id is %d, bit_width is %d, "
                "bit_offset is %d, access_width is %d, address is 0x%llx\n",
                doorbell.space_id, doorbell.bit_width, doorbell.bit_offset,
                doorbell.access_width, reg_resource->address);
@@ -515,7 +512,7 @@ static int __init pcc_cpufreq_probe(void)
 
        doorbell_write = member->integer.value;
 
-       dprintk("probe: doorbell_preserve: 0x%llx,"
+       pr_debug("probe: doorbell_preserve: 0x%llx,"
                " doorbell_write: 0x%llx\n",
                doorbell_preserve, doorbell_write);
 
@@ -550,7 +547,7 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        result = pcc_get_offset(cpu);
        if (result) {
-               dprintk("init: PCCP evaluation failed\n");
+               pr_debug("init: PCCP evaluation failed\n");
                goto out;
        }
 
@@ -561,12 +558,12 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
        policy->cur = pcc_get_freq(cpu);
 
        if (!policy->cur) {
-               dprintk("init: Unable to get current CPU frequency\n");
+               pr_debug("init: Unable to get current CPU frequency\n");
                result = -EINVAL;
                goto out;
        }
 
-       dprintk("init: policy->max is %d, policy->min is %d\n",
+       pr_debug("init: policy->max is %d, policy->min is %d\n",
                policy->max, policy->min);
 out:
        return result;
@@ -597,7 +594,7 @@ static int __init pcc_cpufreq_init(void)
 
        ret = pcc_cpufreq_probe();
        if (ret) {
-               dprintk("pcc_cpufreq_init: PCCH evaluation failed\n");
+               pr_debug("pcc_cpufreq_init: PCCH evaluation failed\n");
                return ret;
        }
 
similarity index 95%
rename from arch/x86/kernel/cpu/cpufreq/powernow-k7.c
rename to drivers/cpufreq/powernow-k7.c
index 4a45fd6e41ba9bb5a0fc533b95dae8a569119c88..d71d9f3723590cd659323e58338ca0c2a7ee9319 100644 (file)
@@ -68,7 +68,6 @@ union powernow_acpi_control_t {
 };
 #endif
 
-#ifdef CONFIG_CPU_FREQ_DEBUG
 /* divide by 1000 to get VCore voltage in V. */
 static const int mobile_vid_table[32] = {
     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
@@ -76,7 +75,6 @@ static const int mobile_vid_table[32] = {
     1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
     1075, 1050, 1025, 1000, 975, 950, 925, 0,
 };
-#endif
 
 /* divide by 10 to get FID. */
 static const int fid_codes[32] = {
@@ -103,9 +101,6 @@ static unsigned int fsb;
 static unsigned int latency;
 static char have_a0;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "powernow-k7", msg)
-
 static int check_fsb(unsigned int fsbspeed)
 {
        int delta;
@@ -209,7 +204,7 @@ static int get_ranges(unsigned char *pst)
                vid = *pst++;
                powernow_table[j].index |= (vid << 8); /* upper 8 bits */
 
-               dprintk("   FID: 0x%x (%d.%dx [%dMHz])  "
+               pr_debug("   FID: 0x%x (%d.%dx [%dMHz])  "
                         "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
                         fid_codes[fid] % 10, speed/1000, vid,
                         mobile_vid_table[vid]/1000,
@@ -367,7 +362,7 @@ static int powernow_acpi_init(void)
                unsigned int speed, speed_mhz;
 
                pc.val = (unsigned long) state->control;
-               dprintk("acpi:  P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
+               pr_debug("acpi:  P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
                         i,
                         (u32) state->core_frequency,
                         (u32) state->power,
@@ -401,7 +396,7 @@ static int powernow_acpi_init(void)
                                invalidate_entry(i);
                }
 
-               dprintk("   FID: 0x%x (%d.%dx [%dMHz])  "
+               pr_debug("   FID: 0x%x (%d.%dx [%dMHz])  "
                         "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
                         fid_codes[fid] % 10, speed_mhz, vid,
                         mobile_vid_table[vid]/1000,
@@ -409,7 +404,7 @@ static int powernow_acpi_init(void)
 
                if (state->core_frequency != speed_mhz) {
                        state->core_frequency = speed_mhz;
-                       dprintk("   Corrected ACPI frequency to %d\n",
+                       pr_debug("   Corrected ACPI frequency to %d\n",
                                speed_mhz);
                }
 
@@ -453,8 +448,8 @@ static int powernow_acpi_init(void)
 
 static void print_pst_entry(struct pst_s *pst, unsigned int j)
 {
-       dprintk("PST:%d (@%p)\n", j, pst);
-       dprintk(" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
+       pr_debug("PST:%d (@%p)\n", j, pst);
+       pr_debug(" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
                pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
 }
 
@@ -474,20 +469,20 @@ static int powernow_decode_bios(int maxfid, int startvid)
                p = phys_to_virt(i);
 
                if (memcmp(p, "AMDK7PNOW!",  10) == 0) {
-                       dprintk("Found PSB header at %p\n", p);
+                       pr_debug("Found PSB header at %p\n", p);
                        psb = (struct psb_s *) p;
-                       dprintk("Table version: 0x%x\n", psb->tableversion);
+                       pr_debug("Table version: 0x%x\n", psb->tableversion);
                        if (psb->tableversion != 0x12) {
                                printk(KERN_INFO PFX "Sorry, only v1.2 tables"
                                                " supported right now\n");
                                return -ENODEV;
                        }
 
-                       dprintk("Flags: 0x%x\n", psb->flags);
+                       pr_debug("Flags: 0x%x\n", psb->flags);
                        if ((psb->flags & 1) == 0)
-                               dprintk("Mobile voltage regulator\n");
+                               pr_debug("Mobile voltage regulator\n");
                        else
-                               dprintk("Desktop voltage regulator\n");
+                               pr_debug("Desktop voltage regulator\n");
 
                        latency = psb->settlingtime;
                        if (latency < 100) {
@@ -497,9 +492,9 @@ static int powernow_decode_bios(int maxfid, int startvid)
                                                "Correcting.\n", latency);
                                latency = 100;
                        }
-                       dprintk("Settling Time: %d microseconds.\n",
+                       pr_debug("Settling Time: %d microseconds.\n",
                                        psb->settlingtime);
-                       dprintk("Has %d PST tables. (Only dumping ones "
+                       pr_debug("Has %d PST tables. (Only dumping ones "
                                        "relevant to this CPU).\n",
                                        psb->numpst);
 
@@ -650,7 +645,7 @@ static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy)
                printk(KERN_WARNING PFX "can not determine bus frequency\n");
                return -EINVAL;
        }
-       dprintk("FSB: %3dMHz\n", fsb/1000);
+       pr_debug("FSB: %3dMHz\n", fsb/1000);
 
        if (dmi_check_system(powernow_dmi_table) || acpi_force) {
                printk(KERN_INFO PFX "PSB/PST known to be broken.  "
similarity index 93%
rename from arch/x86/kernel/cpu/cpufreq/powernow-k8.c
rename to drivers/cpufreq/powernow-k8.c
index 2368e38327b351dc1d0b983a12c79d7f3d558960..83479b6fb9a14fc9ef9826c18274560951c45f19 100644 (file)
@@ -139,7 +139,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
        }
        do {
                if (i++ > 10000) {
-                       dprintk("detected change pending stuck\n");
+                       pr_debug("detected change pending stuck\n");
                        return 1;
                }
                rdmsr(MSR_FIDVID_STATUS, lo, hi);
@@ -176,7 +176,7 @@ static void fidvid_msr_init(void)
        fid = lo & MSR_S_LO_CURRENT_FID;
        lo = fid | (vid << MSR_C_LO_VID_SHIFT);
        hi = MSR_C_HI_STP_GNT_BENIGN;
-       dprintk("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi);
+       pr_debug("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi);
        wrmsr(MSR_FIDVID_CTL, lo, hi);
 }
 
@@ -196,7 +196,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid)
        lo |= (data->currvid << MSR_C_LO_VID_SHIFT);
        lo |= MSR_C_LO_INIT_FID_VID;
 
-       dprintk("writing fid 0x%x, lo 0x%x, hi 0x%x\n",
+       pr_debug("writing fid 0x%x, lo 0x%x, hi 0x%x\n",
                fid, lo, data->plllock * PLL_LOCK_CONVERSION);
 
        do {
@@ -244,7 +244,7 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid)
        lo |= (vid << MSR_C_LO_VID_SHIFT);
        lo |= MSR_C_LO_INIT_FID_VID;
 
-       dprintk("writing vid 0x%x, lo 0x%x, hi 0x%x\n",
+       pr_debug("writing vid 0x%x, lo 0x%x, hi 0x%x\n",
                vid, lo, STOP_GRANT_5NS);
 
        do {
@@ -325,7 +325,7 @@ static int transition_fid_vid(struct powernow_k8_data *data,
                return 1;
        }
 
-       dprintk("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n",
+       pr_debug("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n",
                smp_processor_id(), data->currfid, data->currvid);
 
        return 0;
@@ -339,7 +339,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
        u32 savefid = data->currfid;
        u32 maxvid, lo, rvomult = 1;
 
-       dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
+       pr_debug("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
                "reqvid 0x%x, rvo 0x%x\n",
                smp_processor_id(),
                data->currfid, data->currvid, reqvid, data->rvo);
@@ -349,12 +349,12 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
        rvosteps *= rvomult;
        rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
        maxvid = 0x1f & (maxvid >> 16);
-       dprintk("ph1 maxvid=0x%x\n", maxvid);
+       pr_debug("ph1 maxvid=0x%x\n", maxvid);
        if (reqvid < maxvid) /* lower numbers are higher voltages */
                reqvid = maxvid;
 
        while (data->currvid > reqvid) {
-               dprintk("ph1: curr 0x%x, req vid 0x%x\n",
+               pr_debug("ph1: curr 0x%x, req vid 0x%x\n",
                        data->currvid, reqvid);
                if (decrease_vid_code_by_step(data, reqvid, data->vidmvs))
                        return 1;
@@ -365,7 +365,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
                if (data->currvid == maxvid) {
                        rvosteps = 0;
                } else {
-                       dprintk("ph1: changing vid for rvo, req 0x%x\n",
+                       pr_debug("ph1: changing vid for rvo, req 0x%x\n",
                                data->currvid - 1);
                        if (decrease_vid_code_by_step(data, data->currvid-1, 1))
                                return 1;
@@ -382,7 +382,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
                return 1;
        }
 
-       dprintk("ph1 complete, currfid 0x%x, currvid 0x%x\n",
+       pr_debug("ph1 complete, currfid 0x%x, currvid 0x%x\n",
                data->currfid, data->currvid);
 
        return 0;
@@ -400,7 +400,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
                return 0;
        }
 
-       dprintk("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, "
+       pr_debug("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, "
                "reqfid 0x%x\n",
                smp_processor_id(),
                data->currfid, data->currvid, reqfid);
@@ -457,7 +457,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
                return 1;
        }
 
-       dprintk("ph2 complete, currfid 0x%x, currvid 0x%x\n",
+       pr_debug("ph2 complete, currfid 0x%x, currvid 0x%x\n",
                data->currfid, data->currvid);
 
        return 0;
@@ -470,7 +470,7 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
        u32 savefid = data->currfid;
        u32 savereqvid = reqvid;
 
-       dprintk("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n",
+       pr_debug("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n",
                smp_processor_id(),
                data->currfid, data->currvid);
 
@@ -498,17 +498,17 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
                return 1;
 
        if (savereqvid != data->currvid) {
-               dprintk("ph3 failed, currvid 0x%x\n", data->currvid);
+               pr_debug("ph3 failed, currvid 0x%x\n", data->currvid);
                return 1;
        }
 
        if (savefid != data->currfid) {
-               dprintk("ph3 failed, currfid changed 0x%x\n",
+               pr_debug("ph3 failed, currfid changed 0x%x\n",
                        data->currfid);
                return 1;
        }
 
-       dprintk("ph3 complete, currfid 0x%x, currvid 0x%x\n",
+       pr_debug("ph3 complete, currfid 0x%x, currvid 0x%x\n",
                data->currfid, data->currvid);
 
        return 0;
@@ -707,7 +707,7 @@ static int fill_powernow_table(struct powernow_k8_data *data,
                return -EIO;
        }
 
-       dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
+       pr_debug("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
        data->powernow_table = powernow_table;
        if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu)
                print_basics(data);
@@ -717,7 +717,7 @@ static int fill_powernow_table(struct powernow_k8_data *data,
                    (pst[j].vid == data->currvid))
                        return 0;
 
-       dprintk("currfid/vid do not match PST, ignoring\n");
+       pr_debug("currfid/vid do not match PST, ignoring\n");
        return 0;
 }
 
@@ -739,36 +739,36 @@ static int find_psb_table(struct powernow_k8_data *data)
                if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
                        continue;
 
-               dprintk("found PSB header at 0x%p\n", psb);
+               pr_debug("found PSB header at 0x%p\n", psb);
 
-               dprintk("table vers: 0x%x\n", psb->tableversion);
+               pr_debug("table vers: 0x%x\n", psb->tableversion);
                if (psb->tableversion != PSB_VERSION_1_4) {
                        printk(KERN_ERR FW_BUG PFX "PSB table is not v1.4\n");
                        return -ENODEV;
                }
 
-               dprintk("flags: 0x%x\n", psb->flags1);
+               pr_debug("flags: 0x%x\n", psb->flags1);
                if (psb->flags1) {
                        printk(KERN_ERR FW_BUG PFX "unknown flags\n");
                        return -ENODEV;
                }
 
                data->vstable = psb->vstable;
-               dprintk("voltage stabilization time: %d(*20us)\n",
+               pr_debug("voltage stabilization time: %d(*20us)\n",
                                data->vstable);
 
-               dprintk("flags2: 0x%x\n", psb->flags2);
+               pr_debug("flags2: 0x%x\n", psb->flags2);
                data->rvo = psb->flags2 & 3;
                data->irt = ((psb->flags2) >> 2) & 3;
                mvs = ((psb->flags2) >> 4) & 3;
                data->vidmvs = 1 << mvs;
                data->batps = ((psb->flags2) >> 6) & 3;
 
-               dprintk("ramp voltage offset: %d\n", data->rvo);
-               dprintk("isochronous relief time: %d\n", data->irt);
-               dprintk("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs);
+               pr_debug("ramp voltage offset: %d\n", data->rvo);
+               pr_debug("isochronous relief time: %d\n", data->irt);
+               pr_debug("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs);
 
-               dprintk("numpst: 0x%x\n", psb->num_tables);
+               pr_debug("numpst: 0x%x\n", psb->num_tables);
                cpst = psb->num_tables;
                if ((psb->cpuid == 0x00000fc0) ||
                    (psb->cpuid == 0x00000fe0)) {
@@ -783,13 +783,13 @@ static int find_psb_table(struct powernow_k8_data *data)
                }
 
                data->plllock = psb->plllocktime;
-               dprintk("plllocktime: 0x%x (units 1us)\n", psb->plllocktime);
-               dprintk("maxfid: 0x%x\n", psb->maxfid);
-               dprintk("maxvid: 0x%x\n", psb->maxvid);
+               pr_debug("plllocktime: 0x%x (units 1us)\n", psb->plllocktime);
+               pr_debug("maxfid: 0x%x\n", psb->maxfid);
+               pr_debug("maxvid: 0x%x\n", psb->maxvid);
                maxvid = psb->maxvid;
 
                data->numps = psb->numps;
-               dprintk("numpstates: 0x%x\n", data->numps);
+               pr_debug("numpstates: 0x%x\n", data->numps);
                return fill_powernow_table(data,
                                (struct pst_s *)(psb+1), maxvid);
        }
@@ -834,13 +834,13 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
        u64 control, status;
 
        if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
-               dprintk("register performance failed: bad ACPI data\n");
+               pr_debug("register performance failed: bad ACPI data\n");
                return -EIO;
        }
 
        /* verify the data contained in the ACPI structures */
        if (data->acpi_data.state_count <= 1) {
-               dprintk("No ACPI P-States\n");
+               pr_debug("No ACPI P-States\n");
                goto err_out;
        }
 
@@ -849,7 +849,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 
        if ((control != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
            (status != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
-               dprintk("Invalid control/status registers (%x - %x)\n",
+               pr_debug("Invalid control/status registers (%llx - %llx)\n",
                        control, status);
                goto err_out;
        }
@@ -858,7 +858,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
        powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
                * (data->acpi_data.state_count + 1)), GFP_KERNEL);
        if (!powernow_table) {
-               dprintk("powernow_table memory alloc failure\n");
+               pr_debug("powernow_table memory alloc failure\n");
                goto err_out;
        }
 
@@ -928,7 +928,7 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
                }
                rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
                if (!(hi & HW_PSTATE_VALID_MASK)) {
-                       dprintk("invalid pstate %d, ignoring\n", index);
+                       pr_debug("invalid pstate %d, ignoring\n", index);
                        invalidate_entry(powernow_table, i);
                        continue;
                }
@@ -968,7 +968,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
                        vid = (control >> VID_SHIFT) & VID_MASK;
                }
 
-               dprintk("   %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
+               pr_debug("   %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
 
                index = fid | (vid<<8);
                powernow_table[i].index = index;
@@ -978,7 +978,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
 
                /* verify frequency is OK */
                if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
-                       dprintk("invalid freq %u kHz, ignoring\n", freq);
+                       pr_debug("invalid freq %u kHz, ignoring\n", freq);
                        invalidate_entry(powernow_table, i);
                        continue;
                }
@@ -986,7 +986,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
                /* verify voltage is OK -
                 * BIOSs are using "off" to indicate invalid */
                if (vid == VID_OFF) {
-                       dprintk("invalid vid %u, ignoring\n", vid);
+                       pr_debug("invalid vid %u, ignoring\n", vid);
                        invalidate_entry(powernow_table, i);
                        continue;
                }
@@ -1047,7 +1047,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
        int res, i;
        struct cpufreq_freqs freqs;
 
-       dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
+       pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index);
 
        /* fid/vid correctness check for k8 */
        /* fid are the lower 8 bits of the index we stored into
@@ -1057,18 +1057,18 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
        fid = data->powernow_table[index].index & 0xFF;
        vid = (data->powernow_table[index].index & 0xFF00) >> 8;
 
-       dprintk("table matched fid 0x%x, giving vid 0x%x\n", fid, vid);
+       pr_debug("table matched fid 0x%x, giving vid 0x%x\n", fid, vid);
 
        if (query_current_values_with_pending_wait(data))
                return 1;
 
        if ((data->currvid == vid) && (data->currfid == fid)) {
-               dprintk("target matches current values (fid 0x%x, vid 0x%x)\n",
+               pr_debug("target matches current values (fid 0x%x, vid 0x%x)\n",
                        fid, vid);
                return 0;
        }
 
-       dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
+       pr_debug("cpu %d, changing to fid 0x%x, vid 0x%x\n",
                smp_processor_id(), fid, vid);
        freqs.old = find_khz_freq_from_fid(data->currfid);
        freqs.new = find_khz_freq_from_fid(fid);
@@ -1096,7 +1096,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
        int res, i;
        struct cpufreq_freqs freqs;
 
-       dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
+       pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index);
 
        /* get MSR index for hardware pstate transition */
        pstate = index & HW_PSTATE_MASK;
@@ -1156,14 +1156,14 @@ static int powernowk8_target(struct cpufreq_policy *pol,
                goto err_out;
        }
 
-       dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
+       pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
                pol->cpu, targfreq, pol->min, pol->max, relation);
 
        if (query_current_values_with_pending_wait(data))
                goto err_out;
 
        if (cpu_family != CPU_HW_PSTATE) {
-               dprintk("targ: curr fid 0x%x, vid 0x%x\n",
+               pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
                data->currfid, data->currvid);
 
                if ((checkvid != data->currvid) ||
@@ -1319,7 +1319,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
                                data->currpstate);
        else
                pol->cur = find_khz_freq_from_fid(data->currfid);
-       dprintk("policy current frequency %d kHz\n", pol->cur);
+       pr_debug("policy current frequency %d kHz\n", pol->cur);
 
        /* min/max the cpu is capable of */
        if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
@@ -1337,10 +1337,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
        cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
        if (cpu_family == CPU_HW_PSTATE)
-               dprintk("cpu_init done, current pstate 0x%x\n",
+               pr_debug("cpu_init done, current pstate 0x%x\n",
                                data->currpstate);
        else
-               dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
+               pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
                        data->currfid, data->currvid);
 
        per_cpu(powernow_data, pol->cpu) = data;
@@ -1586,7 +1586,7 @@ static int __cpuinit powernowk8_init(void)
 /* driver entry point for term */
 static void __exit powernowk8_exit(void)
 {
-       dprintk("exit\n");
+       pr_debug("exit\n");
 
        if (boot_cpu_has(X86_FEATURE_CPB)) {
                msrs_free(msrs);
similarity index 98%
rename from arch/x86/kernel/cpu/cpufreq/powernow-k8.h
rename to drivers/cpufreq/powernow-k8.h
index df3529b1c02d7bfe468d8d073f51099400805ce6..3744d26cdc2b31524fe6686e33a28f2ada18f30b 100644 (file)
@@ -211,8 +211,6 @@ struct pst_s {
        u8 vid;
 };
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg)
-
 static int core_voltage_pre_transition(struct powernow_k8_data *data,
        u32 reqvid, u32 regfid);
 static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid);
similarity index 95%
rename from arch/x86/kernel/cpu/cpufreq/sc520_freq.c
rename to drivers/cpufreq/sc520_freq.c
index 435a996a613a6cb3e1a5da201c45ff48b7ac9f3e..1e205e6b1727e5e1f78260b7baa1faa1ca27d2b3 100644 (file)
@@ -29,8 +29,6 @@
 
 static __u8 __iomem *cpuctl;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "sc520_freq", msg)
 #define PFX "sc520_freq: "
 
 static struct cpufreq_frequency_table sc520_freq_table[] = {
@@ -66,7 +64,7 @@ static void sc520_freq_set_cpu_state(unsigned int state)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-       dprintk("attempting to set frequency to %i kHz\n",
+       pr_debug("attempting to set frequency to %i kHz\n",
                        sc520_freq_table[state].frequency);
 
        local_irq_disable();
@@ -161,7 +159,7 @@ static int __init sc520_freq_init(void)
        /* Test if we have the right hardware */
        if (c->x86_vendor != X86_VENDOR_AMD ||
            c->x86 != 4 || c->x86_model != 9) {
-               dprintk("no Elan SC520 processor found!\n");
+               pr_debug("no Elan SC520 processor found!\n");
                return -ENODEV;
        }
        cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
similarity index 96%
rename from arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
rename to drivers/cpufreq/speedstep-centrino.c
index 9b1ff37de46ae6a729f48d2d94ad30548806884d..6ea3455def2165e970ee3e35e6910f2598af8218 100644 (file)
@@ -29,9 +29,6 @@
 #define PFX            "speedstep-centrino: "
 #define MAINTAINER     "cpufreq@vger.kernel.org"
 
-#define dprintk(msg...) \
-       cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
-
 #define INTEL_MSR_RANGE        (0xffff)
 
 struct cpu_id
@@ -244,7 +241,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 
        if (model->cpu_id == NULL) {
                /* No match at all */
-               dprintk("no support for CPU model \"%s\": "
+               pr_debug("no support for CPU model \"%s\": "
                       "send /proc/cpuinfo to " MAINTAINER "\n",
                       cpu->x86_model_id);
                return -ENOENT;
@@ -252,15 +249,15 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 
        if (model->op_points == NULL) {
                /* Matched a non-match */
-               dprintk("no table support for CPU model \"%s\"\n",
+               pr_debug("no table support for CPU model \"%s\"\n",
                       cpu->x86_model_id);
-               dprintk("try using the acpi-cpufreq driver\n");
+               pr_debug("try using the acpi-cpufreq driver\n");
                return -ENOENT;
        }
 
        per_cpu(centrino_model, policy->cpu) = model;
 
-       dprintk("found \"%s\": max frequency: %dkHz\n",
+       pr_debug("found \"%s\": max frequency: %dkHz\n",
               model->model_name, model->max_freq);
 
        return 0;
@@ -369,7 +366,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                per_cpu(centrino_cpu, policy->cpu) = &cpu_ids[i];
 
        if (!per_cpu(centrino_cpu, policy->cpu)) {
-               dprintk("found unsupported CPU with "
+               pr_debug("found unsupported CPU with "
                "Enhanced SpeedStep: send /proc/cpuinfo to "
                MAINTAINER "\n");
                return -ENODEV;
@@ -385,7 +382,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
 
        if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
                l |= MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP;
-               dprintk("trying to enable Enhanced SpeedStep (%x)\n", l);
+               pr_debug("trying to enable Enhanced SpeedStep (%x)\n", l);
                wrmsr(MSR_IA32_MISC_ENABLE, l, h);
 
                /* check to see if it stuck */
@@ -402,7 +399,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                                                /* 10uS transition latency */
        policy->cur = freq;
 
-       dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur);
+       pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur);
 
        ret = cpufreq_frequency_table_cpuinfo(policy,
                per_cpu(centrino_model, policy->cpu)->op_points);
@@ -498,7 +495,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                        good_cpu = j;
 
                if (good_cpu >= nr_cpu_ids) {
-                       dprintk("couldn't limit to CPUs in this domain\n");
+                       pr_debug("couldn't limit to CPUs in this domain\n");
                        retval = -EAGAIN;
                        if (first_cpu) {
                                /* We haven't started the transition yet. */
@@ -512,7 +509,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                if (first_cpu) {
                        rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h);
                        if (msr == (oldmsr & 0xffff)) {
-                               dprintk("no change needed - msr was and needs "
+                               pr_debug("no change needed - msr was and needs "
                                        "to be %x\n", oldmsr);
                                retval = 0;
                                goto out;
@@ -521,7 +518,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                        freqs.old = extract_clock(oldmsr, cpu, 0);
                        freqs.new = extract_clock(msr, cpu, 0);
 
-                       dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
+                       pr_debug("target=%dkHz old=%d new=%d msr=%04x\n",
                                target_freq, freqs.old, freqs.new, msr);
 
                        for_each_cpu(k, policy->cpus) {
similarity index 92%
rename from arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
rename to drivers/cpufreq/speedstep-ich.c
index 561758e951802356aa88bb78d4b10c5da2c4e6c7..a748ce782fee7bbb7da944d4a76dec63c472cf37 100644 (file)
@@ -53,10 +53,6 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
 };
 
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "speedstep-ich", msg)
-
-
 /**
  * speedstep_find_register - read the PMBASE address
  *
@@ -80,7 +76,7 @@ static int speedstep_find_register(void)
                return -ENODEV;
        }
 
-       dprintk("pmbase is 0x%x\n", pmbase);
+       pr_debug("pmbase is 0x%x\n", pmbase);
        return 0;
 }
 
@@ -106,13 +102,13 @@ static void speedstep_set_state(unsigned int state)
        /* read state */
        value = inb(pmbase + 0x50);
 
-       dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
+       pr_debug("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
 
        /* write new state */
        value &= 0xFE;
        value |= state;
 
-       dprintk("writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);
+       pr_debug("writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);
 
        /* Disable bus master arbitration */
        pm2_blk = inb(pmbase + 0x20);
@@ -132,10 +128,10 @@ static void speedstep_set_state(unsigned int state)
        /* Enable IRQs */
        local_irq_restore(flags);
 
-       dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
+       pr_debug("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
 
        if (state == (value & 0x1))
-               dprintk("change to %u MHz succeeded\n",
+               pr_debug("change to %u MHz succeeded\n",
                        speedstep_get_frequency(speedstep_processor) / 1000);
        else
                printk(KERN_ERR "cpufreq: change failed - I/O error\n");
@@ -165,7 +161,7 @@ static int speedstep_activate(void)
        pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value);
        if (!(value & 0x08)) {
                value |= 0x08;
-               dprintk("activating SpeedStep (TM) registers\n");
+               pr_debug("activating SpeedStep (TM) registers\n");
                pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
        }
 
@@ -218,7 +214,7 @@ static unsigned int speedstep_detect_chipset(void)
                        return 2; /* 2-M */
 
                if (hostbridge->revision < 5) {
-                       dprintk("hostbridge does not support speedstep\n");
+                       pr_debug("hostbridge does not support speedstep\n");
                        speedstep_chipset_dev = NULL;
                        pci_dev_put(hostbridge);
                        return 0;
@@ -246,7 +242,7 @@ static unsigned int speedstep_get(unsigned int cpu)
        if (smp_call_function_single(cpu, get_freq_data, &speed, 1) != 0)
                BUG();
 
-       dprintk("detected %u kHz as current frequency\n", speed);
+       pr_debug("detected %u kHz as current frequency\n", speed);
        return speed;
 }
 
@@ -276,7 +272,7 @@ static int speedstep_target(struct cpufreq_policy *policy,
        freqs.new = speedstep_freqs[newstate].frequency;
        freqs.cpu = policy->cpu;
 
-       dprintk("transiting from %u to %u kHz\n", freqs.old, freqs.new);
+       pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new);
 
        /* no transition necessary */
        if (freqs.old == freqs.new)
@@ -351,7 +347,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
        if (!speed)
                return -EIO;
 
-       dprintk("currently at %s speed setting - %i MHz\n",
+       pr_debug("currently at %s speed setting - %i MHz\n",
                (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
                ? "low" : "high",
                (speed / 1000));
@@ -405,14 +401,14 @@ static int __init speedstep_init(void)
        /* detect processor */
        speedstep_processor = speedstep_detect_processor();
        if (!speedstep_processor) {
-               dprintk("Intel(R) SpeedStep(TM) capable processor "
+               pr_debug("Intel(R) SpeedStep(TM) capable processor "
                                "not found\n");
                return -ENODEV;
        }
 
        /* detect chipset */
        if (!speedstep_detect_chipset()) {
-               dprintk("Intel(R) SpeedStep(TM) for this chipset not "
+               pr_debug("Intel(R) SpeedStep(TM) for this chipset not "
                                "(yet) available.\n");
                return -ENODEV;
        }
similarity index 90%
rename from arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
rename to drivers/cpufreq/speedstep-lib.c
index a94ec6be69fa5c798381d41c1c4cb10a0029d385..8af2d2fd9d511913f4648f9f13e90f21d09b36d3 100644 (file)
@@ -18,9 +18,6 @@
 #include <asm/tsc.h>
 #include "speedstep-lib.h"
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "speedstep-lib", msg)
-
 #define PFX "speedstep-lib: "
 
 #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK
@@ -75,7 +72,7 @@ static unsigned int pentium3_get_frequency(enum speedstep_processor processor)
 
        /* read MSR 0x2a - we only need the low 32 bits */
        rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
-       dprintk("P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+       pr_debug("P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
        msr_tmp = msr_lo;
 
        /* decode the FSB */
@@ -89,7 +86,7 @@ static unsigned int pentium3_get_frequency(enum speedstep_processor processor)
 
        /* decode the multiplier */
        if (processor == SPEEDSTEP_CPU_PIII_C_EARLY) {
-               dprintk("workaround for early PIIIs\n");
+               pr_debug("workaround for early PIIIs\n");
                msr_lo &= 0x03c00000;
        } else
                msr_lo &= 0x0bc00000;
@@ -100,7 +97,7 @@ static unsigned int pentium3_get_frequency(enum speedstep_processor processor)
                j++;
        }
 
-       dprintk("speed is %u\n",
+       pr_debug("speed is %u\n",
                (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100));
 
        return msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100;
@@ -112,7 +109,7 @@ static unsigned int pentiumM_get_frequency(void)
        u32 msr_lo, msr_tmp;
 
        rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
-       dprintk("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+       pr_debug("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
 
        /* see table B-2 of 24547212.pdf */
        if (msr_lo & 0x00040000) {
@@ -122,7 +119,7 @@ static unsigned int pentiumM_get_frequency(void)
        }
 
        msr_tmp = (msr_lo >> 22) & 0x1f;
-       dprintk("bits 22-26 are 0x%x, speed is %u\n",
+       pr_debug("bits 22-26 are 0x%x, speed is %u\n",
                        msr_tmp, (msr_tmp * 100 * 1000));
 
        return msr_tmp * 100 * 1000;
@@ -160,11 +157,11 @@ static unsigned int pentium_core_get_frequency(void)
        }
 
        rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
-       dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n",
+       pr_debug("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n",
                        msr_lo, msr_tmp);
 
        msr_tmp = (msr_lo >> 22) & 0x1f;
-       dprintk("bits 22-26 are 0x%x, speed is %u\n",
+       pr_debug("bits 22-26 are 0x%x, speed is %u\n",
                        msr_tmp, (msr_tmp * fsb));
 
        ret = (msr_tmp * fsb);
@@ -190,7 +187,7 @@ static unsigned int pentium4_get_frequency(void)
 
        rdmsr(0x2c, msr_lo, msr_hi);
 
-       dprintk("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
+       pr_debug("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
 
        /* decode the FSB: see IA-32 Intel (C) Architecture Software
         * Developer's Manual, Volume 3: System Prgramming Guide,
@@ -217,7 +214,7 @@ static unsigned int pentium4_get_frequency(void)
        /* Multiplier. */
        mult = msr_lo >> 24;
 
-       dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n",
+       pr_debug("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n",
                        fsb, mult, (fsb * mult));
 
        ret = (fsb * mult);
@@ -257,7 +254,7 @@ unsigned int speedstep_detect_processor(void)
        struct cpuinfo_x86 *c = &cpu_data(0);
        u32 ebx, msr_lo, msr_hi;
 
-       dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
+       pr_debug("x86: %x, model: %x\n", c->x86, c->x86_model);
 
        if ((c->x86_vendor != X86_VENDOR_INTEL) ||
            ((c->x86 != 6) && (c->x86 != 0xF)))
@@ -272,7 +269,7 @@ unsigned int speedstep_detect_processor(void)
                ebx = cpuid_ebx(0x00000001);
                ebx &= 0x000000FF;
 
-               dprintk("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
+               pr_debug("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
 
                switch (c->x86_mask) {
                case 4:
@@ -327,7 +324,7 @@ unsigned int speedstep_detect_processor(void)
                /* cpuid_ebx(1) is 0x04 for desktop PIII,
                 * 0x06 for mobile PIII-M */
                ebx = cpuid_ebx(0x00000001);
-               dprintk("ebx is %x\n", ebx);
+               pr_debug("ebx is %x\n", ebx);
 
                ebx &= 0x000000FF;
 
@@ -344,7 +341,7 @@ unsigned int speedstep_detect_processor(void)
                /* all mobile PIII Coppermines have FSB 100 MHz
                 * ==> sort out a few desktop PIIIs. */
                rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi);
-               dprintk("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n",
+               pr_debug("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n",
                                msr_lo, msr_hi);
                msr_lo &= 0x00c0000;
                if (msr_lo != 0x0080000)
@@ -357,12 +354,12 @@ unsigned int speedstep_detect_processor(void)
                 * bit 56 or 57 is set
                 */
                rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi);
-               dprintk("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n",
+               pr_debug("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n",
                                msr_lo, msr_hi);
                if ((msr_hi & (1<<18)) &&
                    (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
                        if (c->x86_mask == 0x01) {
-                               dprintk("early PIII version\n");
+                               pr_debug("early PIII version\n");
                                return SPEEDSTEP_CPU_PIII_C_EARLY;
                        } else
                                return SPEEDSTEP_CPU_PIII_C;
@@ -393,14 +390,14 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
        if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
                return -EINVAL;
 
-       dprintk("trying to determine both speeds\n");
+       pr_debug("trying to determine both speeds\n");
 
        /* get current speed */
        prev_speed = speedstep_get_frequency(processor);
        if (!prev_speed)
                return -EIO;
 
-       dprintk("previous speed is %u\n", prev_speed);
+       pr_debug("previous speed is %u\n", prev_speed);
 
        local_irq_save(flags);
 
@@ -412,7 +409,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
                goto out;
        }
 
-       dprintk("low speed is %u\n", *low_speed);
+       pr_debug("low speed is %u\n", *low_speed);
 
        /* start latency measurement */
        if (transition_latency)
@@ -431,7 +428,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
                goto out;
        }
 
-       dprintk("high speed is %u\n", *high_speed);
+       pr_debug("high speed is %u\n", *high_speed);
 
        if (*low_speed == *high_speed) {
                ret = -ENODEV;
@@ -445,7 +442,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
        if (transition_latency) {
                *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
                        tv2.tv_usec - tv1.tv_usec;
-               dprintk("transition latency is %u uSec\n", *transition_latency);
+               pr_debug("transition latency is %u uSec\n", *transition_latency);
 
                /* convert uSec to nSec and add 20% for safety reasons */
                *transition_latency *= 1200;
similarity index 90%
rename from arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
rename to drivers/cpufreq/speedstep-smi.c
index 91bc25b67bc11693d2feff66b4a361da4f59d3bd..c76ead3490bf73bc1a831508f8a3e826de256c04 100644 (file)
@@ -55,9 +55,6 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
  * of DMA activity going on? */
 #define SMI_TRIES 5
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
-               "speedstep-smi", msg)
-
 /**
  * speedstep_smi_ownership
  */
@@ -70,7 +67,7 @@ static int speedstep_smi_ownership(void)
        command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
        magic = virt_to_phys(magic_data);
 
-       dprintk("trying to obtain ownership with command %x at port %x\n",
+       pr_debug("trying to obtain ownership with command %x at port %x\n",
                        command, smi_port);
 
        __asm__ __volatile__(
@@ -85,7 +82,7 @@ static int speedstep_smi_ownership(void)
                : "memory"
        );
 
-       dprintk("result is %x\n", result);
+       pr_debug("result is %x\n", result);
 
        return result;
 }
@@ -106,13 +103,13 @@ static int speedstep_smi_get_freqs(unsigned int *low, unsigned int *high)
        u32 function = GET_SPEEDSTEP_FREQS;
 
        if (!(ist_info.event & 0xFFFF)) {
-               dprintk("bug #1422 -- can't read freqs from BIOS\n");
+               pr_debug("bug #1422 -- can't read freqs from BIOS\n");
                return -ENODEV;
        }
 
        command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-       dprintk("trying to determine frequencies with command %x at port %x\n",
+       pr_debug("trying to determine frequencies with command %x at port %x\n",
                        command, smi_port);
 
        __asm__ __volatile__(
@@ -129,7 +126,7 @@ static int speedstep_smi_get_freqs(unsigned int *low, unsigned int *high)
                  "d" (smi_port), "S" (0), "D" (0)
        );
 
-       dprintk("result %x, low_freq %u, high_freq %u\n",
+       pr_debug("result %x, low_freq %u, high_freq %u\n",
                        result, low_mhz, high_mhz);
 
        /* abort if results are obviously incorrect... */
@@ -154,7 +151,7 @@ static int speedstep_get_state(void)
 
        command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-       dprintk("trying to determine current setting with command %x "
+       pr_debug("trying to determine current setting with command %x "
                "at port %x\n", command, smi_port);
 
        __asm__ __volatile__(
@@ -168,7 +165,7 @@ static int speedstep_get_state(void)
                  "d" (smi_port), "S" (0), "D" (0)
        );
 
-       dprintk("state is %x, result is %x\n", state, result);
+       pr_debug("state is %x, result is %x\n", state, result);
 
        return state & 1;
 }
@@ -194,13 +191,13 @@ static void speedstep_set_state(unsigned int state)
 
        command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-       dprintk("trying to set frequency to state %u "
+       pr_debug("trying to set frequency to state %u "
                "with command %x at port %x\n",
                state, command, smi_port);
 
        do {
                if (retry) {
-                       dprintk("retry %u, previous result %u, waiting...\n",
+                       pr_debug("retry %u, previous result %u, waiting...\n",
                                        retry, result);
                        mdelay(retry * 50);
                }
@@ -221,7 +218,7 @@ static void speedstep_set_state(unsigned int state)
        local_irq_restore(flags);
 
        if (new_state == state)
-               dprintk("change to %u MHz succeeded after %u tries "
+               pr_debug("change to %u MHz succeeded after %u tries "
                        "with result %u\n",
                        (speedstep_freqs[new_state].frequency / 1000),
                        retry, result);
@@ -292,7 +289,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
 
        result = speedstep_smi_ownership();
        if (result) {
-               dprintk("fails in acquiring ownership of a SMI interface.\n");
+               pr_debug("fails in acquiring ownership of a SMI interface.\n");
                return -EINVAL;
        }
 
@@ -304,7 +301,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
        if (result) {
                /* fall back to speedstep_lib.c dection mechanism:
                 * try both states out */
-               dprintk("could not detect low and high frequencies "
+               pr_debug("could not detect low and high frequencies "
                                "by SMI call.\n");
                result = speedstep_get_freqs(speedstep_processor,
                                low, high,
@@ -312,18 +309,18 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
                                &speedstep_set_state);
 
                if (result) {
-                       dprintk("could not detect two different speeds"
+                       pr_debug("could not detect two different speeds"
                                        " -- aborting.\n");
                        return result;
                } else
-                       dprintk("workaround worked.\n");
+                       pr_debug("workaround worked.\n");
        }
 
        /* get current speed setting */
        state = speedstep_get_state();
        speed = speedstep_freqs[state].frequency;
 
-       dprintk("currently at %s speed setting - %i MHz\n",
+       pr_debug("currently at %s speed setting - %i MHz\n",
                (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
                ? "low" : "high",
                (speed / 1000));
@@ -360,7 +357,7 @@ static int speedstep_resume(struct cpufreq_policy *policy)
        int result = speedstep_smi_ownership();
 
        if (result)
-               dprintk("fails in re-acquiring ownership of a SMI interface.\n");
+               pr_debug("fails in re-acquiring ownership of a SMI interface.\n");
 
        return result;
 }
@@ -403,12 +400,12 @@ static int __init speedstep_init(void)
        }
 
        if (!speedstep_processor) {
-               dprintk("No supported Intel CPU detected.\n");
+               pr_debug("No supported Intel CPU detected.\n");
                return -ENODEV;
        }
 
-       dprintk("signature:0x%.8lx, command:0x%.8lx, "
-               "event:0x%.8lx, perf_level:0x%.8lx.\n",
+       pr_debug("signature:0x%.8ulx, command:0x%.8ulx, "
+               "event:0x%.8ulx, perf_level:0x%.8ulx.\n",
                ist_info.signature, ist_info.command,
                ist_info.event, ist_info.perf_level);
 
index 31e71c4fc83171e7da846740533f63131189327b..9a8bebcf6b177fa79e9635ecde71f05b2578e798 100644 (file)
@@ -211,8 +211,6 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 
        scrubval = scrubval & 0x001F;
 
-       amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval);
-
        for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
                if (scrubrates[i].scrubval == scrubval) {
                        retval = scrubrates[i].bandwidth;
@@ -933,25 +931,74 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
 /* On F10h and later ErrAddr is MC4_ADDR[47:1] */
 static u64 get_error_address(struct mce *m)
 {
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+       u64 addr;
        u8 start_bit = 1;
        u8 end_bit   = 47;
 
-       if (boot_cpu_data.x86 == 0xf) {
+       if (c->x86 == 0xf) {
                start_bit = 3;
                end_bit   = 39;
        }
 
-       return m->addr & GENMASK(start_bit, end_bit);
+       addr = m->addr & GENMASK(start_bit, end_bit);
+
+       /*
+        * Erratum 637 workaround
+        */
+       if (c->x86 == 0x15) {
+               struct amd64_pvt *pvt;
+               u64 cc6_base, tmp_addr;
+               u32 tmp;
+               u8 mce_nid, intlv_en;
+
+               if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
+                       return addr;
+
+               mce_nid = amd_get_nb_id(m->extcpu);
+               pvt     = mcis[mce_nid]->pvt_info;
+
+               amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
+               intlv_en = tmp >> 21 & 0x7;
+
+               /* add [47:27] + 3 trailing bits */
+               cc6_base  = (tmp & GENMASK(0, 20)) << 3;
+
+               /* reverse and add DramIntlvEn */
+               cc6_base |= intlv_en ^ 0x7;
+
+               /* pin at [47:24] */
+               cc6_base <<= 24;
+
+               if (!intlv_en)
+                       return cc6_base | (addr & GENMASK(0, 23));
+
+               amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);
+
+                                                       /* faster log2 */
+               tmp_addr  = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);
+
+               /* OR DramIntlvSel into bits [14:12] */
+               tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;
+
+               /* add remaining [11:0] bits from original MC4_ADDR */
+               tmp_addr |= addr & GENMASK(0, 11);
+
+               return cc6_base | tmp_addr;
+       }
+
+       return addr;
 }
 
 static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 {
+       struct cpuinfo_x86 *c = &boot_cpu_data;
        int off = range << 3;
 
        amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off,  &pvt->ranges[range].base.lo);
        amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo);
 
-       if (boot_cpu_data.x86 == 0xf)
+       if (c->x86 == 0xf)
                return;
 
        if (!dram_rw(pvt, range))
@@ -959,6 +1006,31 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 
        amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off,  &pvt->ranges[range].base.hi);
        amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi);
+
+       /* Factor in CC6 save area by reading dst node's limit reg */
+       if (c->x86 == 0x15) {
+               struct pci_dev *f1 = NULL;
+               u8 nid = dram_dst_node(pvt, range);
+               u32 llim;
+
+               f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1));
+               if (WARN_ON(!f1))
+                       return;
+
+               amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
+
+               pvt->ranges[range].lim.lo &= GENMASK(0, 15);
+
+                                           /* {[39:27],111b} */
+               pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
+
+               pvt->ranges[range].lim.hi &= GENMASK(0, 7);
+
+                                           /* [47:40] */
+               pvt->ranges[range].lim.hi |= llim >> 13;
+
+               pci_dev_put(f1);
+       }
 }
 
 static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
@@ -1403,12 +1475,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
                return -EINVAL;
        }
 
-       if (intlv_en &&
-           (intlv_sel != ((sys_addr >> 12) & intlv_en))) {
-               amd64_warn("Botched intlv bits, en: 0x%x, sel: 0x%x\n",
-                          intlv_en, intlv_sel);
+       if (intlv_en && (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
-       }
 
        sys_addr = f1x_swap_interleaved_region(pvt, sys_addr);
 
index 11be36a311eb55d312178e8e6886f6abc6594cd8..9a666cb985b2bd446edba7c249f3740d23e49d8e 100644 (file)
 
 #define DCT_CFG_SEL                    0x10C
 
+#define DRAM_LOCAL_NODE_BASE           0x120
+#define DRAM_LOCAL_NODE_LIM            0x124
+
 #define DRAM_BASE_HI                   0x140
 #define DRAM_LIMIT_HI                  0x144
 
index 26343fd46596da9d44e5fdc6f20ab71d10f5f0ce..29ffa350bfbe00281376c61c5c5c9c8434098a37 100644 (file)
@@ -458,13 +458,13 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
                return -EINVAL;
 
        new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
-       if (new_bw >= 0) {
-               edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
-               return count;
+       if (new_bw < 0) {
+               edac_printk(KERN_WARNING, EDAC_MC,
+                           "Error setting scrub rate to: %lu\n", bandwidth);
+               return -EINVAL;
        }
 
-       edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
-       return -EINVAL;
+       return count;
 }
 
 /*
@@ -483,7 +483,6 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
                return bandwidth;
        }
 
-       edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
        return sprintf(data, "%d\n", bandwidth);
 }
 
index c1f0045ceb8e708ced1a6163ae921b03efe4e9d5..af8e7b1aa290a2e0d682de5d1aefb9e8808c23e1 100644 (file)
@@ -1019,7 +1019,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
        struct ppc4xx_edac_pdata *pdata = NULL;
        const struct device_node *np = op->dev.of_node;
 
-       if (op->dev.of_match == NULL)
+       if (of_match_device(ppc4xx_edac_match, &op->dev) == NULL)
                return -EINVAL;
 
        /* Initial driver pointers and private data */
index f903d7b6f34a92bca580b5ed01cf422c9a8caf7c..23d1468ad253d54c9c0745a858b6b155123e76e7 100644 (file)
@@ -2199,7 +2199,6 @@ static int ohci_set_config_rom(struct fw_card *card,
 {
        struct fw_ohci *ohci;
        unsigned long flags;
-       int ret = -EBUSY;
        __be32 *next_config_rom;
        dma_addr_t uninitialized_var(next_config_rom_bus);
 
@@ -2240,22 +2239,37 @@ static int ohci_set_config_rom(struct fw_card *card,
 
        spin_lock_irqsave(&ohci->lock, flags);
 
+       /*
+        * If there is not an already pending config_rom update,
+        * push our new allocation into the ohci->next_config_rom
+        * and then mark the local variable as null so that we
+        * won't deallocate the new buffer.
+        *
+        * OTOH, if there is a pending config_rom update, just
+        * use that buffer with the new config_rom data, and
+        * let this routine free the unused DMA allocation.
+        */
+
        if (ohci->next_config_rom == NULL) {
                ohci->next_config_rom = next_config_rom;
                ohci->next_config_rom_bus = next_config_rom_bus;
+               next_config_rom = NULL;
+       }
 
-               copy_config_rom(ohci->next_config_rom, config_rom, length);
+       copy_config_rom(ohci->next_config_rom, config_rom, length);
 
-               ohci->next_header = config_rom[0];
-               ohci->next_config_rom[0] = 0;
+       ohci->next_header = config_rom[0];
+       ohci->next_config_rom[0] = 0;
 
-               reg_write(ohci, OHCI1394_ConfigROMmap,
-                         ohci->next_config_rom_bus);
-               ret = 0;
-       }
+       reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
 
        spin_unlock_irqrestore(&ohci->lock, flags);
 
+       /* If we didn't use the DMA allocation, delete it. */
+       if (next_config_rom != NULL)
+               dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+                                 next_config_rom, next_config_rom_bus);
+
        /*
         * Now initiate a bus reset to have the changes take
         * effect. We clean up the old config rom memory and DMA
@@ -2263,13 +2277,10 @@ static int ohci_set_config_rom(struct fw_card *card,
         * controller could need to access it before the bus reset
         * takes effect.
         */
-       if (ret == 0)
-               fw_schedule_bus_reset(&ohci->card, true, true);
-       else
-               dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-                                 next_config_rom, next_config_rom_bus);
 
-       return ret;
+       fw_schedule_bus_reset(&ohci->card, true, true);
+
+       return 0;
 }
 
 static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
index 96c25d93eed1c9083bae7b8d0081c5f7255d1f95..f1b7f659d3c988d74d1453533ff75bd078c04ba9 100644 (file)
@@ -531,8 +531,8 @@ static int
 edd_has_edd30(struct edd_device *edev)
 {
        struct edd_info *info;
-       int i, nonzero_path = 0;
-       char c;
+       int i;
+       u8 csum = 0;
 
        if (!edev)
                return 0;
@@ -544,16 +544,16 @@ edd_has_edd30(struct edd_device *edev)
                return 0;
        }
 
-       for (i = 30; i <= 73; i++) {
-               c = *(((uint8_t *) info) + i + 4);
-               if (c) {
-                       nonzero_path++;
-                       break;
-               }
-       }
-       if (!nonzero_path) {
+
+       /* We support only T13 spec */
+       if (info->params.device_path_info_length != 44)
+               return 0;
+
+       for (i = 30; i < info->params.device_path_info_length + 30; i++)
+               csum += *(((u8 *)&info->params) + i);
+
+       if (csum)
                return 0;
-       }
 
        return 1;
 }
index 2192456dfd68329a97881c6103d4a4f2e66753eb..f032e446fc11bb8a0c943e519b0987c8cdd02d01 100644 (file)
 struct acpi_table_ibft *ibft_addr;
 EXPORT_SYMBOL_GPL(ibft_addr);
 
-#define IBFT_SIGN "iBFT"
+static const struct {
+       char *sign;
+} ibft_signs[] = {
+#ifdef CONFIG_ACPI
+       /*
+        * One spec says "IBFT", the other says "iBFT". We have to check
+        * for both.
+        */
+       { ACPI_SIG_IBFT },
+#endif
+       { "iBFT" },
+       { "BIFT" },     /* Broadcom iSCSI Offload */
+};
+
 #define IBFT_SIGN_LEN 4
 #define IBFT_START 0x80000 /* 512kB */
 #define IBFT_END 0x100000 /* 1MB */
@@ -62,6 +75,7 @@ static int __init find_ibft_in_mem(void)
        unsigned long pos;
        unsigned int len = 0;
        void *virt;
+       int i;
 
        for (pos = IBFT_START; pos < IBFT_END; pos += 16) {
                /* The table can't be inside the VGA BIOS reserved space,
@@ -69,18 +83,23 @@ static int __init find_ibft_in_mem(void)
                if (pos == VGA_MEM)
                        pos += VGA_SIZE;
                virt = isa_bus_to_virt(pos);
-               if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) {
-                       unsigned long *addr =
-                           (unsigned long *)isa_bus_to_virt(pos + 4);
-                       len = *addr;
-                       /* if the length of the table extends past 1M,
-                        * the table cannot be valid. */
-                       if (pos + len <= (IBFT_END-1)) {
-                               ibft_addr = (struct acpi_table_ibft *)virt;
-                               break;
+
+               for (i = 0; i < ARRAY_SIZE(ibft_signs); i++) {
+                       if (memcmp(virt, ibft_signs[i].sign, IBFT_SIGN_LEN) ==
+                           0) {
+                               unsigned long *addr =
+                                   (unsigned long *)isa_bus_to_virt(pos + 4);
+                               len = *addr;
+                               /* if the length of the table extends past 1M,
+                                * the table cannot be valid. */
+                               if (pos + len <= (IBFT_END-1)) {
+                                       ibft_addr = (struct acpi_table_ibft *)virt;
+                                       goto done;
+                               }
                        }
                }
        }
+done:
        return len;
 }
 /*
@@ -89,18 +108,12 @@ static int __init find_ibft_in_mem(void)
  */
 unsigned long __init find_ibft_region(unsigned long *sizep)
 {
-
+       int i;
        ibft_addr = NULL;
 
 #ifdef CONFIG_ACPI
-       /*
-        * One spec says "IBFT", the other says "iBFT". We have to check
-        * for both.
-        */
-       if (!ibft_addr)
-               acpi_table_parse(ACPI_SIG_IBFT, acpi_find_ibft);
-       if (!ibft_addr)
-               acpi_table_parse(IBFT_SIGN, acpi_find_ibft);
+       for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)
+               acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);
 #endif /* CONFIG_ACPI */
 
        /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
index c58f691ec3ce6f4d62aaf3248b6bec39a887c60a..b493663c7ba717a0652e45b456fac3d95aa56de4 100644 (file)
@@ -24,6 +24,7 @@ config DRM_KMS_HELPER
        depends on DRM
        select FB
        select FRAMEBUFFER_CONSOLE if !EXPERT
+       select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
        help
          FB and CRTC helpers for KMS drivers.
 
index 950720473967069ff093712b172446183a7c493f..140b9525b48a47a83cf159c010f9818969ee3877 100644 (file)
@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+       bool error = false;
+       int i, ret;
+       for (i = 0; i < fb_helper->crtc_count; i++) {
+               struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+               ret = drm_crtc_helper_set_config(mode_set);
+               if (ret)
+                       error = true;
+       }
+       return error;
+}
+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
+
 bool drm_fb_helper_force_kernel_mode(void)
 {
-       int i = 0;
        bool ret, error = false;
        struct drm_fb_helper *helper;
 
@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void)
                return false;
 
        list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-               for (i = 0; i < helper->crtc_count; i++) {
-                       struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-                       ret = drm_crtc_helper_set_config(mode_set);
-                       if (ret)
-                               error = true;
-               }
+               if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+                       continue;
+
+               ret = drm_fb_helper_restore_fbdev_mode(helper);
+               if (ret)
+                       error = true;
        }
        return error;
 }
@@ -1503,17 +1516,33 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 }
 EXPORT_SYMBOL(drm_fb_helper_initial_config);
 
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
+/**
+ * drm_fb_helper_hotplug_event - respond to a hotplug notification by
+ *                               probing all the outputs attached to the fb.
+ * @fb_helper: the drm_fb_helper
+ *
+ * LOCKING:
+ * Called at runtime, must take mode config lock.
+ *
+ * Scan the connectors attached to the fb_helper and try to put together a
+ * setup after *notification of a change in output configuration.
+ *
+ * RETURNS:
+ * 0 on success and a non-zero error code otherwise.
+ */
+int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
+       struct drm_device *dev = fb_helper->dev;
        int count = 0;
        u32 max_width, max_height, bpp_sel;
        bool bound = false, crtcs_bound = false;
        struct drm_crtc *crtc;
 
        if (!fb_helper->fb)
-               return false;
+               return 0;
 
-       list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (crtc->fb)
                        crtcs_bound = true;
                if (crtc->fb == fb_helper->fb)
@@ -1522,7 +1551,8 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
        if (!bound && crtcs_bound) {
                fb_helper->delayed_hotplug = true;
-               return false;
+               mutex_unlock(&dev->mode_config.mutex);
+               return 0;
        }
        DRM_DEBUG_KMS("\n");
 
@@ -1533,6 +1563,7 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
        count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
                                                    max_height);
        drm_setup_crtcs(fb_helper);
+       mutex_unlock(&dev->mode_config.mutex);
 
        return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
 }
index 741457bd1c46ef1f54af12296e348a053430329e..a1f12cb043deb233484f9a4957300fa475c3a024 100644 (file)
@@ -932,11 +932,34 @@ EXPORT_SYMBOL(drm_vblank_put);
 
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
+       struct drm_pending_vblank_event *e, *t;
+       struct timeval now;
        unsigned long irqflags;
+       unsigned int seq;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        vblank_disable_and_save(dev, crtc);
        DRM_WAKEUP(&dev->vbl_queue[crtc]);
+
+       /* Send any queued vblank events, lest the natives grow disquiet */
+       seq = drm_vblank_count_and_time(dev, crtc, &now);
+       list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
+               if (e->pipe != crtc)
+                       continue;
+               DRM_DEBUG("Sending premature vblank event on disable: \
+                         wanted %d, current %d\n",
+                         e->event.sequence, seq);
+
+               e->event.sequence = seq;
+               e->event.tv_sec = now.tv_sec;
+               e->event.tv_usec = now.tv_usec;
+               drm_vblank_put(dev, e->pipe);
+               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+               wake_up_interruptible(&e->base.file_priv->event_wait);
+               trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+                                                e->event.sequence);
+       }
+
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
index 5d00b0fc0d91d837f6aa47b49901cb04bd6db1c0..959186cbf3280b90b911ff54373531ee577eef97 100644 (file)
@@ -431,7 +431,7 @@ EXPORT_SYMBOL(drm_mm_search_free_in_range);
 void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
 {
        list_replace(&old->node_list, &new->node_list);
-       list_replace(&old->node_list, &new->hole_stack);
+       list_replace(&old->hole_stack, &new->hole_stack);
        new->hole_follows = old->hole_follows;
        new->mm = old->mm;
        new->start = old->start;
@@ -699,8 +699,8 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
                                entry->size);
                total_used += entry->size;
                if (entry->hole_follows) {
-                       hole_start = drm_mm_hole_node_start(&mm->head_node);
-                       hole_end = drm_mm_hole_node_end(&mm->head_node);
+                       hole_start = drm_mm_hole_node_start(entry);
+                       hole_end = drm_mm_hole_node_end(entry);
                        hole_size = hole_end - hole_start;
                        seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
                                        hole_start, hole_end, hole_size);
index 72730377a01b7cac5fec231c2fd93e5b81b01f99..12876f2795d2b373d9cac4130ec0052b44db23e6 100644 (file)
@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-               drm_fb_helper_restore();
+               intel_fb_restore_mode(dev);
                vga_switcheroo_process_delayed_switch();
                return;
        }
index c34a8dd31d02fdc2111070e0589f9a02e16eb4a8..32d1b3e829c8d35433f0b170052e9be96f358a1c 100644 (file)
@@ -49,7 +49,7 @@ module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
 unsigned int i915_powersave = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
 
-unsigned int i915_semaphores = 1;
+unsigned int i915_semaphores = 0;
 module_param_named(semaphores, i915_semaphores, int, 0600);
 
 unsigned int i915_enable_rc6 = 0;
index 432fc04c6bffc1b58d8da1645a8a5687049a9bc2..2166ee071ddbe99655c3c977beecec68bb6a7a19 100644 (file)
@@ -3771,8 +3771,11 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        int entries, tlb_miss;
 
        crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled)
+       if (crtc->fb == NULL || !crtc->enabled) {
+               *cursor_wm = cursor->guard_size;
+               *plane_wm = display->guard_size;
                return false;
+       }
 
        htotal = crtc->mode.htotal;
        hdisplay = crtc->mode.hdisplay;
@@ -5602,9 +5605,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
        intel_clock_t clock;
 
        if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-               fp = FP0(pipe);
+               fp = I915_READ(FP0(pipe));
        else
-               fp = FP1(pipe);
+               fp = I915_READ(FP1(pipe));
 
        clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
        if (IS_PINEVIEW(dev)) {
@@ -6215,36 +6218,6 @@ cleanup_work:
        return ret;
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       /* Reset flags back to the 'unknown' status so that they
-        * will be correctly set on the initial modeset.
-        */
-       intel_crtc->dpms_mode = -1;
-}
-
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-       .dpms = intel_crtc_dpms,
-       .mode_fixup = intel_crtc_mode_fixup,
-       .mode_set = intel_crtc_mode_set,
-       .mode_set_base = intel_pipe_set_base,
-       .mode_set_base_atomic = intel_pipe_set_base_atomic,
-       .load_lut = intel_crtc_load_lut,
-       .disable = intel_crtc_disable,
-};
-
-static const struct drm_crtc_funcs intel_crtc_funcs = {
-       .reset = intel_crtc_reset,
-       .cursor_set = intel_crtc_cursor_set,
-       .cursor_move = intel_crtc_cursor_move,
-       .gamma_set = intel_crtc_gamma_set,
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = intel_crtc_destroy,
-       .page_flip = intel_crtc_page_flip,
-};
-
 static void intel_sanitize_modesetting(struct drm_device *dev,
                                       int pipe, int plane)
 {
@@ -6281,6 +6254,42 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
        intel_disable_pipe(dev_priv, pipe);
 }
 
+static void intel_crtc_reset(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       /* Reset flags back to the 'unknown' status so that they
+        * will be correctly set on the initial modeset.
+        */
+       intel_crtc->dpms_mode = -1;
+
+       /* We need to fix up any BIOS configuration that conflicts with
+        * our expectations.
+        */
+       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
+}
+
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+       .dpms = intel_crtc_dpms,
+       .mode_fixup = intel_crtc_mode_fixup,
+       .mode_set = intel_crtc_mode_set,
+       .mode_set_base = intel_pipe_set_base,
+       .mode_set_base_atomic = intel_pipe_set_base_atomic,
+       .load_lut = intel_crtc_load_lut,
+       .disable = intel_crtc_disable,
+};
+
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+       .reset = intel_crtc_reset,
+       .cursor_set = intel_crtc_cursor_set,
+       .cursor_move = intel_crtc_cursor_move,
+       .gamma_set = intel_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = intel_crtc_destroy,
+       .page_flip = intel_crtc_page_flip,
+};
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -6330,8 +6339,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
                    (unsigned long)intel_crtc);
-
-       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -6572,8 +6579,10 @@ intel_user_framebuffer_create(struct drm_device *dev,
                return ERR_PTR(-ENOENT);
 
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb)
+       if (!intel_fb) {
+               drm_gem_object_unreference_unlocked(&obj->base);
                return ERR_PTR(-ENOMEM);
+       }
 
        ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
        if (ret) {
index cb8578b7e4432c1aad04f79324be3d588c1e74e0..a4d80314e7f8cf5edb13bce97328a60f1f26f6ce 100644 (file)
@@ -1470,7 +1470,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        if (!HAS_PCH_CPT(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-               struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+               struct drm_crtc *crtc = intel_dp->base.base.crtc;
+
                /* Hardware workaround: leaving our transcoder select
                 * set to transcoder B while it's off will prevent the
                 * corresponding HDMI output on transcoder A.
@@ -1485,7 +1486,19 @@ intel_dp_link_down(struct intel_dp *intel_dp)
                /* Changes to enable or select take place the vblank
                 * after being written.
                 */
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
+               if (crtc == NULL) {
+                       /* We can arrive here never having been attached
+                        * to a CRTC, for instance, due to inheriting
+                        * random state from the BIOS.
+                        *
+                        * If the pipe is not running, play safe and
+                        * wait for the clocks to stabilise before
+                        * continuing.
+                        */
+                       POSTING_READ(intel_dp->output_reg);
+                       msleep(50);
+               } else
+                       intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
        }
 
        I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
index f5b0d8306d8372142f8c649f815a170d348be99e..1d20712d527f1e5d38a192f59f2aa3c6493e5e53 100644 (file)
@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
                               struct drm_file *file_priv);
 
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
+extern void intel_fb_restore_mode(struct drm_device *dev);
 #endif /* __INTEL_DRV_H__ */
index 512782728e5127aed5ea383efb7f4d79dd2b8cb7..ec49bae7338260d77cc6b78f9bc15d948303c1e8 100644 (file)
@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
+
+void intel_fb_restore_mode(struct drm_device *dev)
+{
+       int ret;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
+       if (ret)
+               DRM_DEBUG("failed to restore crtc mode\n");
+}
index a562bd2648c7bb76f2db4df8a167f755db57ae1b..67cb076d271b5eb00a4c87a9022f0957f3ff569e 100644 (file)
@@ -539,6 +539,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        struct drm_device *dev = dev_priv->dev;
        struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+       if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
+               return NOTIFY_OK;
+
        /*
         * check and update the status of LVDS connector after receiving
         * the LID nofication event.
index 4256b8ef3947454048d2d432c3375776983c3e06..6b22c1dcc015f406bf2fcdbc866511bc92f3d882 100644 (file)
@@ -1151,10 +1151,10 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                            (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
        {
                int pipeconf_reg = PIPECONF(pipe);
-               int dspcntr_reg = DSPCNTR(pipe);
+               int dspcntr_reg = DSPCNTR(intel_crtc->plane);
                int pipeconf = I915_READ(pipeconf_reg);
                int dspcntr = I915_READ(dspcntr_reg);
-               int dspbase_reg = DSPADDR(pipe);
+               int dspbase_reg = DSPADDR(intel_crtc->plane);
                int xpos = 0x0, ypos = 0x0;
                unsigned int xsize, ysize;
                /* Pipe must be off here */
@@ -1378,7 +1378,9 @@ intel_tv_detect(struct drm_connector *connector, bool force)
        if (type < 0)
                return connector_status_disconnected;
 
+       intel_tv->type = type;
        intel_tv_find_better_format(connector);
+
        return connector_status_connected;
 }
 
@@ -1670,8 +1672,7 @@ intel_tv_init(struct drm_device *dev)
         *
         * More recent chipsets favour HDMI rather than integrated S-Video.
         */
-       connector->polled =
-               DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
                           DRM_MODE_CONNECTOR_SVIDEO);
index ce38e97b9428eaaaf81e248572555a80736c9242..568caedd7216e141a148753ea1dd55d8657ff261 100644 (file)
@@ -83,7 +83,7 @@ nouveau_dma_init(struct nouveau_channel *chan)
                return ret;
 
        /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
-       ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfd0, 0x1000,
+       ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000,
                                     &chan->m2mf_ntfy);
        if (ret)
                return ret;
index 856d56a98d1e7cf9621939b4fa5b80f02e1cf7bd..a76514a209b369880ac8b5ced881bb337a186695 100644 (file)
@@ -682,6 +682,9 @@ struct drm_nouveau_private {
        /* For PFIFO and PGRAPH. */
        spinlock_t context_switch_lock;
 
+       /* VM/PRAMIN flush, legacy PRAMIN aperture */
+       spinlock_t vm_lock;
+
        /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
        struct nouveau_ramht  *ramht;
        struct nouveau_gpuobj *ramfc;
index 889c4454682e674316685ac322b55b3960610dc1..39aee6d4daf869ab5c5c931bd7174b249aab10b5 100644 (file)
@@ -181,13 +181,13 @@ nouveau_fbcon_sync(struct fb_info *info)
                OUT_RING  (chan, 0);
        }
 
-       nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
+       nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3, 0xffffffff);
        FIRE_RING(chan);
        mutex_unlock(&chan->mutex);
 
        ret = -EBUSY;
        for (i = 0; i < 100000; i++) {
-               if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) {
+               if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3)) {
                        ret = 0;
                        break;
                }
index 78f467fe30be2524e8ee9b4ecc2f654619ec7577..c3e953b089923d552de922e8007c13e1e8eb94e5 100644 (file)
@@ -152,8 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       nouveau_bo_ref(NULL, &dev_priv->vga_ram);
-
        ttm_bo_device_release(&dev_priv->ttm.bdev);
 
        nouveau_ttm_global_release(dev_priv);
@@ -398,7 +396,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
                        dma_bits = 40;
        } else
        if (drm_pci_device_is_pcie(dev) &&
-           dev_priv->chipset != 0x40 &&
+           dev_priv->chipset  > 0x40 &&
            dev_priv->chipset != 0x45) {
                if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
                        dma_bits = 39;
index 7ba3fc0b30c19a5dfdcda496202b99c2d141e0a8..5b39718ae1f8359683f96295d96a55ac4fdc56a8 100644 (file)
@@ -35,19 +35,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct nouveau_bo *ntfy = NULL;
-       uint32_t flags;
+       uint32_t flags, ttmpl;
        int ret;
 
-       if (nouveau_vram_notify)
+       if (nouveau_vram_notify) {
                flags = NOUVEAU_GEM_DOMAIN_VRAM;
-       else
+               ttmpl = TTM_PL_FLAG_VRAM;
+       } else {
                flags = NOUVEAU_GEM_DOMAIN_GART;
+               ttmpl = TTM_PL_FLAG_TT;
+       }
 
        ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
        if (ret)
                return ret;
 
-       ret = nouveau_bo_pin(ntfy, flags);
+       ret = nouveau_bo_pin(ntfy, ttmpl);
        if (ret)
                goto out_err;
 
index 4f00c87ed86eefda49bbd4e01559d51007700082..67a16e01ffa6db3030fd789d500dafd9b03eaf54 100644 (file)
@@ -1039,19 +1039,20 @@ nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset)
 {
        struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
        struct drm_device *dev = gpuobj->dev;
+       unsigned long flags;
 
        if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
                u64  ptr = gpuobj->vinst + offset;
                u32 base = ptr >> 16;
                u32  val;
 
-               spin_lock(&dev_priv->ramin_lock);
+               spin_lock_irqsave(&dev_priv->vm_lock, flags);
                if (dev_priv->ramin_base != base) {
                        dev_priv->ramin_base = base;
                        nv_wr32(dev, 0x001700, dev_priv->ramin_base);
                }
                val = nv_rd32(dev, 0x700000 + (ptr & 0xffff));
-               spin_unlock(&dev_priv->ramin_lock);
+               spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
                return val;
        }
 
@@ -1063,18 +1064,19 @@ nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val)
 {
        struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
        struct drm_device *dev = gpuobj->dev;
+       unsigned long flags;
 
        if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
                u64  ptr = gpuobj->vinst + offset;
                u32 base = ptr >> 16;
 
-               spin_lock(&dev_priv->ramin_lock);
+               spin_lock_irqsave(&dev_priv->vm_lock, flags);
                if (dev_priv->ramin_base != base) {
                        dev_priv->ramin_base = base;
                        nv_wr32(dev, 0x001700, dev_priv->ramin_base);
                }
                nv_wr32(dev, 0x700000 + (ptr & 0xffff), val);
-               spin_unlock(&dev_priv->ramin_lock);
+               spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
                return;
        }
 
index a33fe4019286e39294af123b7f8140973451c623..c77111eca6acefc8ab31acb7bb060547b64b5f7a 100644 (file)
@@ -42,7 +42,8 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
 
        nvbe->nr_pages = 0;
        while (num_pages--) {
-               if (dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE) {
+               /* this code path isn't called and is incorrect anyways */
+               if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/
                        nvbe->pages[nvbe->nr_pages] =
                                        dma_addrs[nvbe->nr_pages];
                        nvbe->ttm_alloced[nvbe->nr_pages] = true;
@@ -55,6 +56,7 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
                                be->func->clear(be);
                                return -EFAULT;
                        }
+                       nvbe->ttm_alloced[nvbe->nr_pages] = false;
                }
 
                nvbe->nr_pages++;
@@ -427,7 +429,7 @@ nouveau_sgdma_init(struct drm_device *dev)
        u32 aper_size, align;
        int ret;
 
-       if (dev_priv->card_type >= NV_50 || drm_pci_device_is_pcie(dev))
+       if (dev_priv->card_type >= NV_40 && drm_pci_device_is_pcie(dev))
                aper_size = 512 * 1024 * 1024;
        else
                aper_size = 64 * 1024 * 1024;
@@ -457,7 +459,7 @@ nouveau_sgdma_init(struct drm_device *dev)
                dev_priv->gart_info.func = &nv50_sgdma_backend;
        } else
        if (drm_pci_device_is_pcie(dev) &&
-           dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
+           dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
                if (nv44_graph_class(dev)) {
                        dev_priv->gart_info.func = &nv44_sgdma_backend;
                        align = 512 * 1024;
index 6e2b1a6caa2df48d97a99c693dcccd4d7de23bd8..915fbce8959517f4c51a9114a8224617ecbe265b 100644 (file)
@@ -608,6 +608,7 @@ nouveau_card_init(struct drm_device *dev)
        spin_lock_init(&dev_priv->channels.lock);
        spin_lock_init(&dev_priv->tile.lock);
        spin_lock_init(&dev_priv->context_switch_lock);
+       spin_lock_init(&dev_priv->vm_lock);
 
        /* Make the CRTCs and I2C buses accessible */
        ret = engine->display.early_init(dev);
@@ -767,6 +768,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
        engine->mc.takedown(dev);
        engine->display.late_takedown(dev);
 
+       if (dev_priv->vga_ram) {
+               nouveau_bo_unpin(dev_priv->vga_ram);
+               nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+       }
+
        mutex_lock(&dev->struct_mutex);
        ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
        ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
index a6f8aa651fc6e585c5af4104c7b0e9146a45c3b9..4f95a1e5822e151ab89fcc51ba665c47cc4b50e4 100644 (file)
@@ -404,23 +404,25 @@ void
 nv50_instmem_flush(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       unsigned long flags;
 
-       spin_lock(&dev_priv->ramin_lock);
+       spin_lock_irqsave(&dev_priv->vm_lock, flags);
        nv_wr32(dev, 0x00330c, 0x00000001);
        if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000))
                NV_ERROR(dev, "PRAMIN flush timeout\n");
-       spin_unlock(&dev_priv->ramin_lock);
+       spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
 
 void
 nv84_instmem_flush(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       unsigned long flags;
 
-       spin_lock(&dev_priv->ramin_lock);
+       spin_lock_irqsave(&dev_priv->vm_lock, flags);
        nv_wr32(dev, 0x070000, 0x00000001);
        if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
                NV_ERROR(dev, "PRAMIN flush timeout\n");
-       spin_unlock(&dev_priv->ramin_lock);
+       spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
 
index 4fd3432b5b8d36023a853101074bd74d90073c9a..6c26944907418b0d090d35758b8e22d7ce9de06c 100644 (file)
@@ -174,10 +174,11 @@ void
 nv50_vm_flush_engine(struct drm_device *dev, int engine)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       unsigned long flags;
 
-       spin_lock(&dev_priv->ramin_lock);
+       spin_lock_irqsave(&dev_priv->vm_lock, flags);
        nv_wr32(dev, 0x100c80, (engine << 16) | 1);
        if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000))
                NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
-       spin_unlock(&dev_priv->ramin_lock);
+       spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
index a0a2a0277f7381e876a39bc1870ec18371fc935a..a179e6c55afbaeaaabcc71de6d834c5426abb6b9 100644 (file)
@@ -104,11 +104,12 @@ nvc0_vm_flush(struct nouveau_vm *vm)
        struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
        struct drm_device *dev = vm->dev;
        struct nouveau_vm_pgd *vpgd;
+       unsigned long flags;
        u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5;
 
        pinstmem->flush(vm->dev);
 
-       spin_lock(&dev_priv->ramin_lock);
+       spin_lock_irqsave(&dev_priv->vm_lock, flags);
        list_for_each_entry(vpgd, &vm->pgd_list, head) {
                /* looks like maybe a "free flush slots" counter, the
                 * faster you write to 0x100cbc to more it decreases
@@ -125,5 +126,5 @@ nvc0_vm_flush(struct nouveau_vm *vm)
                                 nv_rd32(dev, 0x100c80), engine);
                }
        }
-       spin_unlock(&dev_priv->ramin_lock);
+       spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
index d71d375149f85b8b90ebb173a88d5ba1ba451929..7bd7456890974025c74bfce11f8516bad909eacf 100644 (file)
@@ -135,7 +135,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
                case ATOM_IIO_MOVE_INDEX:
                        temp &=
                            ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-                             CU8(base + 2));
+                             CU8(base + 3));
                        temp |=
                            ((index >> CU8(base + 2)) &
                             (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -145,7 +145,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
                case ATOM_IIO_MOVE_DATA:
                        temp &=
                            ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-                             CU8(base + 2));
+                             CU8(base + 3));
                        temp |=
                            ((data >> CU8(base + 2)) &
                             (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -155,7 +155,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
                case ATOM_IIO_MOVE_ATTR:
                        temp &=
                            ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-                             CU8(base + 2));
+                             CU8(base + 3));
                        temp |=
                            ((ctx->
                              io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
index 9d516a8c4dfa8bf8f8dda8935ece51ac4716efb7..529a3a704731ba39d77b423ac1ebe670697816f3 100644 (file)
@@ -532,10 +532,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                else
                        pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
-               if ((rdev->family == CHIP_R600) ||
-                   (rdev->family == CHIP_RV610) ||
-                   (rdev->family == CHIP_RV630) ||
-                   (rdev->family == CHIP_RV670))
+               if (rdev->family < CHIP_RV770)
                        pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
        } else {
                pll->flags |= RADEON_PLL_LEGACY;
@@ -565,7 +562,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
                                if (ss_enabled) {
                                        if (ss->refdiv) {
-                                               pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
                                                pll->flags |= RADEON_PLL_USE_REF_DIV;
                                                pll->reference_div = ss->refdiv;
                                                if (ASIC_IS_AVIVO(rdev))
index 3453910ee0f383b48049b8f8c5405f11114f9256..9073e3bfb08c7cde39ee411700e0ba838611fc2c 100644 (file)
@@ -353,7 +353,7 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev,
                                        struct drm_display_mode *mode,
                                        struct drm_display_mode *other_mode)
 {
-       u32 tmp = 0;
+       u32 tmp;
        /*
         * Line Buffer Setup
         * There are 3 line buffers, each one shared by 2 display controllers.
@@ -363,64 +363,63 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev,
         * first display controller
         *  0 - first half of lb (3840 * 2)
         *  1 - first 3/4 of lb (5760 * 2)
-        *  2 - whole lb (7680 * 2)
+        *  2 - whole lb (7680 * 2), other crtc must be disabled
         *  3 - first 1/4 of lb (1920 * 2)
         * second display controller
         *  4 - second half of lb (3840 * 2)
         *  5 - second 3/4 of lb (5760 * 2)
-        *  6 - whole lb (7680 * 2)
+        *  6 - whole lb (7680 * 2), other crtc must be disabled
         *  7 - last 1/4 of lb (1920 * 2)
         */
-       if (mode && other_mode) {
-               if (mode->hdisplay > other_mode->hdisplay) {
-                       if (mode->hdisplay > 2560)
-                               tmp = 1; /* 3/4 */
-                       else
-                               tmp = 0; /* 1/2 */
-               } else if (other_mode->hdisplay > mode->hdisplay) {
-                       if (other_mode->hdisplay > 2560)
-                               tmp = 3; /* 1/4 */
-                       else
-                               tmp = 0; /* 1/2 */
-               } else
+       /* this can get tricky if we have two large displays on a paired group
+        * of crtcs.  Ideally for multiple large displays we'd assign them to
+        * non-linked crtcs for maximum line buffer allocation.
+        */
+       if (radeon_crtc->base.enabled && mode) {
+               if (other_mode)
                        tmp = 0; /* 1/2 */
-       } else if (mode)
-               tmp = 2; /* whole */
-       else if (other_mode)
-               tmp = 3; /* 1/4 */
+               else
+                       tmp = 2; /* whole */
+       } else
+               tmp = 0;
 
        /* second controller of the pair uses second half of the lb */
        if (radeon_crtc->crtc_id % 2)
                tmp += 4;
        WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp);
 
-       switch (tmp) {
-       case 0:
-       case 4:
-       default:
-               if (ASIC_IS_DCE5(rdev))
-                       return 4096 * 2;
-               else
-                       return 3840 * 2;
-       case 1:
-       case 5:
-               if (ASIC_IS_DCE5(rdev))
-                       return 6144 * 2;
-               else
-                       return 5760 * 2;
-       case 2:
-       case 6:
-               if (ASIC_IS_DCE5(rdev))
-                       return 8192 * 2;
-               else
-                       return 7680 * 2;
-       case 3:
-       case 7:
-               if (ASIC_IS_DCE5(rdev))
-                       return 2048 * 2;
-               else
-                       return 1920 * 2;
+       if (radeon_crtc->base.enabled && mode) {
+               switch (tmp) {
+               case 0:
+               case 4:
+               default:
+                       if (ASIC_IS_DCE5(rdev))
+                               return 4096 * 2;
+                       else
+                               return 3840 * 2;
+               case 1:
+               case 5:
+                       if (ASIC_IS_DCE5(rdev))
+                               return 6144 * 2;
+                       else
+                               return 5760 * 2;
+               case 2:
+               case 6:
+                       if (ASIC_IS_DCE5(rdev))
+                               return 8192 * 2;
+                       else
+                               return 7680 * 2;
+               case 3:
+               case 7:
+                       if (ASIC_IS_DCE5(rdev))
+                               return 2048 * 2;
+                       else
+                               return 1920 * 2;
+               }
        }
+
+       /* controller not enabled, so no lb used */
+       return 0;
 }
 
 static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev)
@@ -863,9 +862,15 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
                SYSTEM_ACCESS_MODE_NOT_IN_SYS |
                SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
                EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
-       WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
-       WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
-       WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       if (rdev->flags & RADEON_IS_IGP) {
+               WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp);
+               WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp);
+               WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp);
+       } else {
+               WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+               WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+               WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       }
        WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
@@ -1775,7 +1780,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
 
 
        mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
-       mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+       if (rdev->flags & RADEON_IS_IGP)
+               mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG);
+       else
+               mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
 
        switch (rdev->config.evergreen.max_tile_pipes) {
        case 1:
@@ -2581,7 +2589,7 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
        u32 wptr, tmp;
 
        if (rdev->wb.enabled)
-               wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4];
+               wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]);
        else
                wptr = RREG32(IH_RB_WPTR);
 
@@ -2924,11 +2932,6 @@ static int evergreen_startup(struct radeon_device *rdev)
                rdev->asic->copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
-       /* XXX: ontario has problems blitting to gart at the moment */
-       if (rdev->family == CHIP_PALM) {
-               rdev->asic->copy = NULL;
-               radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-       }
 
        /* allocate wb buffer */
        r = radeon_wb_init(rdev);
index 9aaa3f0c9372135e8d55c0cb79e925f1656264e1..fc40e0cc34516bb96af19f1a7615b6889a7425e3 100644 (file)
 #define                BURSTLENGTH_SHIFT                               9
 #define                BURSTLENGTH_MASK                                0x00000200
 #define                CHANSIZE_OVERRIDE                               (1 << 11)
+#define        FUS_MC_ARB_RAMCFG                               0x2768
 #define        MC_VM_AGP_TOP                                   0x2028
 #define        MC_VM_AGP_BOT                                   0x202C
 #define        MC_VM_AGP_BASE                                  0x2030
 #define        MC_VM_MD_L1_TLB0_CNTL                           0x2654
 #define        MC_VM_MD_L1_TLB1_CNTL                           0x2658
 #define        MC_VM_MD_L1_TLB2_CNTL                           0x265C
+
+#define        FUS_MC_VM_MD_L1_TLB0_CNTL                       0x265C
+#define        FUS_MC_VM_MD_L1_TLB1_CNTL                       0x2660
+#define        FUS_MC_VM_MD_L1_TLB2_CNTL                       0x2664
+
 #define        MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR              0x203C
 #define        MC_VM_SYSTEM_APERTURE_HIGH_ADDR                 0x2038
 #define        MC_VM_SYSTEM_APERTURE_LOW_ADDR                  0x2034
index 7aade20f63a8c5fb932776a084aceffe5366faff..3d8a7634bbe99ade0344aeb2061bc5f3ac183757 100644 (file)
@@ -674,7 +674,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 
        cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE);
        cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG);
-       cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE);
+       cgts_tcc_disable = 0xff000000;
        gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE);
        gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG);
        cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE);
@@ -871,7 +871,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 
        smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
        smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
-       smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets);
+       smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets);
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
        WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
@@ -887,20 +887,20 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 
        WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
 
-       WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) |
-                                       POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) |
-                                       SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1)));
+       WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) |
+                                       POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) |
+                                       SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1)));
 
-       WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) |
-                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) |
-                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size)));
+       WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) |
+                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) |
+                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size)));
 
 
        WREG32(VGT_NUM_INSTANCES, 1);
 
        WREG32(CP_PERFMON_CNTL, 0);
 
-       WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) |
+       WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) |
                                  FETCH_FIFO_HIWATER(0x4) |
                                  DONE_FIFO_HIWATER(0xe0) |
                                  ALU_UPDATE_FIFO_HIWATER(0x8)));
index 15d58292677a42021be6d047e1a4b31484c1525b..6f27593901c7110752b9b2f39267f04546f544eb 100644 (file)
@@ -3231,7 +3231,7 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
        u32 wptr, tmp;
 
        if (rdev->wb.enabled)
-               wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4];
+               wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]);
        else
                wptr = RREG32(IH_RB_WPTR);
 
index f5d12fb103fadd982d6b3ae4d2ad5a227ee1f50b..90dfb2b8cf0318529b28b84b0bfd831764e5d59e 100644 (file)
@@ -431,7 +431,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
                }
        }
 
-       /* Acer laptop (Acer TravelMate 5730G) has an HDMI port
+       /* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
         * on the laptop and a DVI port on the docking station and
         * both share the same encoder, hpd pin, and ddc line.
         * So while the bios table is technically correct,
@@ -440,7 +440,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
         * with different crtcs which isn't possible on the hardware
         * side and leaves no crtcs for LVDS or VGA.
         */
-       if ((dev->pdev->device == 0x95c4) &&
+       if (((dev->pdev->device == 0x95c4) || (dev->pdev->device == 0x9591)) &&
            (dev->pdev->subsystem_vendor == 0x1025) &&
            (dev->pdev->subsystem_device == 0x013c)) {
                if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
@@ -1574,9 +1574,17 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                        ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
                        ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
                        bool bad_record = false;
-                       u8 *record = (u8 *)(mode_info->atom_context->bios +
-                                           data_offset +
-                                           le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+                       u8 *record;
+
+                       if ((frev == 1) && (crev < 2))
+                               /* absolute */
+                               record = (u8 *)(mode_info->atom_context->bios +
+                                               le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+                       else
+                               /* relative */
+                               record = (u8 *)(mode_info->atom_context->bios +
+                                               data_offset +
+                                               le16_to_cpu(lvds_info->info.usModePatchTableOffset));
                        while (*record != ATOM_RECORD_END_TYPE) {
                                switch (*record) {
                                case LCD_MODE_PATCH_RECORD_MODE_TYPE:
@@ -1599,9 +1607,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                                                        memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
                                                               fake_edid_record->ucFakeEDIDLength);
 
-                                                       if (drm_edid_is_valid(edid))
+                                                       if (drm_edid_is_valid(edid)) {
                                                                rdev->mode_info.bios_hardcoded_edid = edid;
-                                                       else
+                                                               rdev->mode_info.bios_hardcoded_edid_size = edid_size;
+                                                       } else
                                                                kfree(edid);
                                                }
                                        }
index ed5dfe58f29c0845e8eb8a478560b9a01fe17677..9d95792bea3eab3c961b1221918beb1e4378d2f9 100644 (file)
@@ -15,6 +15,9 @@
 #define ATPX_VERSION 0
 #define ATPX_GPU_PWR 2
 #define ATPX_MUX_SELECT 3
+#define ATPX_I2C_MUX_SELECT 4
+#define ATPX_SWITCH_START 5
+#define ATPX_SWITCH_END 6
 
 #define ATPX_INTEGRATED 0
 #define ATPX_DISCRETE 1
@@ -149,13 +152,35 @@ static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id)
        return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id);
 }
 
+static int radeon_atpx_switch_i2c_mux(acpi_handle handle, int mux_id)
+{
+       return radeon_atpx_execute(handle, ATPX_I2C_MUX_SELECT, mux_id);
+}
+
+static int radeon_atpx_switch_start(acpi_handle handle, int gpu_id)
+{
+       return radeon_atpx_execute(handle, ATPX_SWITCH_START, gpu_id);
+}
+
+static int radeon_atpx_switch_end(acpi_handle handle, int gpu_id)
+{
+       return radeon_atpx_execute(handle, ATPX_SWITCH_END, gpu_id);
+}
 
 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 {
+       int gpu_id;
+
        if (id == VGA_SWITCHEROO_IGD)
-               radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0);
+               gpu_id = ATPX_INTEGRATED;
        else
-               radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1);
+               gpu_id = ATPX_DISCRETE;
+
+       radeon_atpx_switch_start(radeon_atpx_priv.atpx_handle, gpu_id);
+       radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, gpu_id);
+       radeon_atpx_switch_i2c_mux(radeon_atpx_priv.atpx_handle, gpu_id);
+       radeon_atpx_switch_end(radeon_atpx_priv.atpx_handle, gpu_id);
+
        return 0;
 }
 
index 2ef6d513506404075307c5f5865e091b8e4653ea..5f45fa12bb8b88471f5a301e44a893c97a6f96b3 100644 (file)
@@ -1199,7 +1199,7 @@ radeon_add_atom_connector(struct drm_device *dev,
        if (router->ddc_valid || router->cd_valid) {
                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
                if (!radeon_connector->router_bus)
-                       goto failed;
+                       DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
        }
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
@@ -1208,7 +1208,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                radeon_connector->dac_load_detect = true;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1226,7 +1226,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                radeon_connector->dac_load_detect = true;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1249,7 +1249,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                subpixel_order = SubPixelHorizontalRGB;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1290,7 +1290,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.coherent_mode_property,
@@ -1329,10 +1329,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                        else
                                radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
                        if (!radeon_dig_connector->dp_i2c_bus)
-                               goto failed;
+                               DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                subpixel_order = SubPixelHorizontalRGB;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1381,7 +1381,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                drm_connector_attach_property(&radeon_connector->base,
                                              dev->mode_config.scaling_mode_property,
@@ -1457,7 +1457,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                radeon_connector->dac_load_detect = true;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1475,7 +1475,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                radeon_connector->dac_load_detect = true;
                drm_connector_attach_property(&radeon_connector->base,
@@ -1493,7 +1493,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                if (connector_type == DRM_MODE_CONNECTOR_DVII) {
                        radeon_connector->dac_load_detect = true;
@@ -1538,7 +1538,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                if (i2c_bus->valid) {
                        radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
-                               goto failed;
+                               DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
                }
                drm_connector_attach_property(&radeon_connector->base,
                                              dev->mode_config.scaling_mode_property,
@@ -1567,9 +1567,4 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                radeon_legacy_backlight_init(radeon_encoder, connector);
                }
        }
-       return;
-
-failed:
-       drm_connector_cleanup(connector);
-       kfree(connector);
 }
index bdf2fa1189ae7a3c1aa5e1ae41a1ded25c96b9f7..3189a7efb2e97e0ee25f111db13e42c5b41c7c76 100644 (file)
@@ -167,9 +167,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
-       radeon_crtc->cursor_width = width;
-       radeon_crtc->cursor_height = height;
-
        obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
        if (!obj) {
                DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
@@ -180,6 +177,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
        if (ret)
                goto fail;
 
+       radeon_crtc->cursor_width = width;
+       radeon_crtc->cursor_height = height;
+
        radeon_lock_cursor(crtc, true);
        /* XXX only 27 bit offset for legacy cursor */
        radeon_set_cursor(crtc, obj, gpu_addr);
index 8a955bbdb6082521c725b81bbf5ee0e34e7934b6..a533f52fd163b51c3c89c6f501792e167b9a727a 100644 (file)
@@ -181,9 +181,9 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
        p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 
        for (i = 0; i < pages; i++, p++) {
-               /* On TTM path, we only use the DMA API if TTM_PAGE_FLAG_DMA32
-                * is requested. */
-               if (dma_addr[i] != DMA_ERROR_CODE) {
+               /* we reverted the patch using dma_addr in TTM for now but this
+                * code stops building on alpha so just comment it out for now */
+               if (0) { /*dma_addr[i] != DMA_ERROR_CODE) */
                        rdev->gart.ttm_alloced[p] = true;
                        rdev->gart.pages_addr[p] = dma_addr[i];
                } else {
index ccbabf734a61816a76a6229fbaa393124927853e..983cbac75af0159d493c7b81dbe2da1fd90866e6 100644 (file)
@@ -1096,6 +1096,9 @@ void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector)
        if (!radeon_connector->router.ddc_valid)
                return;
 
+       if (!radeon_connector->router_bus)
+               return;
+
        radeon_i2c_get_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x3, &val);
@@ -1121,6 +1124,9 @@ void radeon_router_select_cd_port(struct radeon_connector *radeon_connector)
        if (!radeon_connector->router.cd_valid)
                return;
 
+       if (!radeon_connector->router_bus)
+               return;
+
        radeon_i2c_get_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x3, &val);
index bf7d4c061451cc35c396cee0d739c40dca6f33eb..bd58af658581b3d3672aa363f7e5c7418abaaefa 100644 (file)
@@ -221,6 +221,22 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        return -EINVAL;
                }
                break;
+       case RADEON_INFO_NUM_TILE_PIPES:
+               if (rdev->family >= CHIP_CAYMAN)
+                       value = rdev->config.cayman.max_tile_pipes;
+               else if (rdev->family >= CHIP_CEDAR)
+                       value = rdev->config.evergreen.max_tile_pipes;
+               else if (rdev->family >= CHIP_RV770)
+                       value = rdev->config.rv770.max_tile_pipes;
+               else if (rdev->family >= CHIP_R600)
+                       value = rdev->config.r600.max_tile_pipes;
+               else {
+                       return -EINVAL;
+               }
+               break;
+       case RADEON_INFO_FUSION_GART_WORKING:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
index 6334f8ac12093af149581ee95d080ff6e84fe249..0aa8e85a94575f4c092affcb2dc3e08bd8717bdf 100644 (file)
@@ -33,6 +33,7 @@ cayman 0x9400
 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
 0x00009100 SPI_CONFIG_CNTL
 0x0000913C SPI_CONFIG_CNTL_1
+0x00009508 TA_CNTL_AUX
 0x00009830 DB_DEBUG
 0x00009834 DB_DEBUG2
 0x00009838 DB_DEBUG3
index 7e1637176e082ba15ecbc832ba3d951d878a06d4..0e28cae7ea43a713c93c5b4277ee4c63c1ec4b41 100644 (file)
@@ -46,6 +46,7 @@ evergreen 0x9400
 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
 0x00009100 SPI_CONFIG_CNTL
 0x0000913C SPI_CONFIG_CNTL_1
+0x00009508 TA_CNTL_AUX
 0x00009700 VC_CNTL
 0x00009714 VC_ENHANCE
 0x00009830 DB_DEBUG
index af0da4ae3f55acb5223f2791940ec90c1db20bce..92f1900dc7caf10f14dba34edec2e34b721ff09d 100644 (file)
@@ -708,6 +708,7 @@ r600 0x9400
 0x00028D0C DB_RENDER_CONTROL
 0x00028D10 DB_RENDER_OVERRIDE
 0x0002880C DB_SHADER_CONTROL
+0x00028D28 DB_SRESULTS_COMPARE_STATE0
 0x00028D2C DB_SRESULTS_COMPARE_STATE1
 0x00028430 DB_STENCILREFMASK
 0x00028434 DB_STENCILREFMASK_BF
index e01cacba685f771f0f82a660b1e1bc21cd0b40e8..498b284e5ef955d11b3ccc3b4a9aaad7bd275df6 100644 (file)
@@ -219,9 +219,6 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
        int i;
        struct vga_switcheroo_client *active = NULL;
 
-       if (new_client->active == true)
-               return 0;
-
        for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
                if (vgasr_priv.clients[i].active == true) {
                        active = &vgasr_priv.clients[i];
@@ -372,6 +369,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
                goto out;
        }
 
+       if (client->active == true)
+               goto out;
+
        /* okay we want a switch - test if devices are willing to switch */
        can_switch = true;
        for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
index 060ef63278763f2a96da76365f6a2a617f84f191..50e40dbd8bb64877a66a0f2d70d71053b972aad8 100644 (file)
@@ -110,8 +110,7 @@ config SENSORS_ADM1021
        help
          If you say yes here you get support for Analog Devices ADM1021
          and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
-         Genesys Logic GL523SM, National Semiconductor LM84, TI THMC10,
-         and the XEON processor built-in sensor.
+         Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10.
 
          This driver can also be built as a module.  If so, the module
          will be called adm1021.
@@ -618,10 +617,10 @@ config SENSORS_LM90
        depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM90,
-         LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim
-         MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-         MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, and Winbond/Nuvoton
-         W83L771W/G/AWG/ASG sensor chips.
+         LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
+         Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
+         MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
+         and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm90.
index 250d099ca3980e1dbb8131e4748610d137049658..da72dc12068c11f85769f93aa57a6370ffa2ffd0 100644 (file)
@@ -1094,6 +1094,7 @@ static struct attribute *lm85_attributes_minctl[] = {
        &sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
        &sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
        &sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group lm85_group_minctl = {
@@ -1104,6 +1105,7 @@ static struct attribute *lm85_attributes_temp_off[] = {
        &sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
        &sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
        &sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group lm85_group_temp_off = {
@@ -1329,11 +1331,11 @@ static int lm85_probe(struct i2c_client *client,
        if (data->type != emc6d103s) {
                err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
                if (err)
-                       goto err_kfree;
+                       goto err_remove_files;
                err = sysfs_create_group(&client->dev.kobj,
                                         &lm85_group_temp_off);
                if (err)
-                       goto err_kfree;
+                       goto err_remove_files;
        }
 
        /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
index c43b4e9f96a9ecd6816954e6c9964b581c2ac1b4..2f94f9504804f29963a17b9327abd860be851436 100644 (file)
  * chips, but support three temperature sensors instead of two. MAX6695
  * and MAX6696 only differ in the pinout so they can be treated identically.
  *
- * This driver also supports the ADT7461 chip from Analog Devices.
- * It's supported in both compatibility and extended mode. It is mostly
- * compatible with LM90 except for a data format difference for the
- * temperature value registers.
+ * This driver also supports ADT7461 and ADT7461A from Analog Devices as well as
+ * NCT1008 from ON Semiconductor. The chips are supported in both compatibility
+ * and extended mode. They are mostly compatible with LM90 except for a data
+ * format difference for the temperature value registers.
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659, MAX6680 and MAX6681.
- * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657,
- * MAX6658 and W83L771 have address 0x4c.
- * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, ADT7461A, MAX6649,
+ * MAX6657, MAX6658, NCT1008 and W83L771 have address 0x4c.
+ * ADM1032-2, ADT7461-2, ADT7461A-2, LM89-1, LM99-1, MAX6646, and NCT1008D
+ * have address 0x4d.
  * MAX6647 has address 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e.
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
@@ -174,6 +175,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 static const struct i2c_device_id lm90_id[] = {
        { "adm1032", adm1032 },
        { "adt7461", adt7461 },
+       { "adt7461a", adt7461 },
        { "lm90", lm90 },
        { "lm86", lm86 },
        { "lm89", lm86 },
@@ -188,6 +190,7 @@ static const struct i2c_device_id lm90_id[] = {
        { "max6681", max6680 },
        { "max6695", max6696 },
        { "max6696", max6696 },
+       { "nct1008", adt7461 },
        { "w83l771", w83l771 },
        { }
 };
@@ -1153,6 +1156,11 @@ static int lm90_detect(struct i2c_client *new_client,
                 && (reg_config1 & 0x1B) == 0x00
                 && reg_convrate <= 0x0A) {
                        name = "adt7461";
+               } else
+               if (chip_id == 0x57 /* ADT7461A, NCT1008 */
+                && (reg_config1 & 0x1B) == 0x00
+                && reg_convrate <= 0x0A) {
+                       name = "adt7461a";
                }
        } else
        if (man_id == 0x4D) { /* Maxim */
index edfb92e41735df7f713a2283a12a299e764423ca..196ffafafd88ff3cebf37de7bae8d37494d2dc34 100644 (file)
@@ -139,7 +139,6 @@ struct pmbus_data {
         * A single status register covers multiple attributes,
         * so we keep them all together.
         */
-       u8 status_bits;
        u8 status[PB_NUM_STATUS_REG];
 
        u8 currpage;
index de5819199e2e35cd65d8b2816431328a3ddd58cf..57240740b161d190329b5ca3b7dfaf0d049ef02e 100644 (file)
@@ -98,7 +98,6 @@ static const struct attribute_group twl4030_madc_group = {
 static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
 {
        int ret;
-       int status;
        struct device *hwmon;
 
        ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
@@ -107,7 +106,7 @@ static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
        hwmon = hwmon_device_register(&pdev->dev);
        if (IS_ERR(hwmon)) {
                dev_err(&pdev->dev, "hwmon_device_register failed.\n");
-               status = PTR_ERR(hwmon);
+               ret = PTR_ERR(hwmon);
                goto err_reg;
        }
 
index 72c0415f6f944922470ad962361c086ac4290809..455e909bc768637a1a7f6d793f626baef082f46d 100644 (file)
                                 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
                                 SMBHSTSTS_INTR)
 
+/* Older devices have their ID defined in <linux/pci_ids.h> */
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS  0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS     0x1d22
 /* Patsburg also has three 'Integrated Device Function' SMBus controllers */
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0        0x1d70
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1        0x1d71
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2        0x1d72
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 
 struct i801_priv {
        struct i2c_adapter adapter;
index 75b984c519acd18750f5ce2b6002e60c152c5b21..107397a606b48957638a9569c2672ba363a5c57d 100644 (file)
@@ -560,15 +560,18 @@ static struct i2c_adapter mpc_ops = {
        .timeout = HZ,
 };
 
+static const struct of_device_id mpc_i2c_of_match[];
 static int __devinit fsl_i2c_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        struct mpc_i2c *i2c;
        const u32 *prop;
        u32 clock = MPC_I2C_CLOCK_LEGACY;
        int result = 0;
        int plen;
 
-       if (!op->dev.of_match)
+       match = of_match_device(mpc_i2c_of_match, &op->dev);
+       if (!match)
                return -EINVAL;
 
        i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
@@ -605,8 +608,8 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
                        clock = *prop;
        }
 
-       if (op->dev.of_match->data) {
-               struct mpc_i2c_data *data = op->dev.of_match->data;
+       if (match->data) {
+               struct mpc_i2c_data *data = match->data;
                data->setup(op->dev.of_node, i2c, clock, data->prescaler);
        } else {
                /* Backwards compatibility */
index 0eb1515541e72446a4e81e3bf54702bcf0635347..2dbba163b10202cf51aba175f7ffbf9cfd57aea2 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-smbus.h>
 #include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@ struct i2c_par {
        struct i2c_algo_bit_data algo_data;
        struct i2c_smbus_alert_setup alert_data;
        struct i2c_client *ara;
-       struct i2c_par *next;
+       struct list_head node;
 };
 
-static struct i2c_par *adapter_list;
+static LIST_HEAD(adapter_list);
+static DEFINE_MUTEX(adapter_list_lock);
 
 /* ----- Low-level parallel port access ----------------------------------- */
 
@@ -228,8 +231,9 @@ static void i2c_parport_attach (struct parport *port)
        }
 
        /* Add the new adapter to the list */
-       adapter->next = adapter_list;
-       adapter_list = adapter;
+       mutex_lock(&adapter_list_lock);
+       list_add_tail(&adapter->node, &adapter_list);
+       mutex_unlock(&adapter_list_lock);
         return;
 
 ERROR1:
@@ -241,11 +245,11 @@ ERROR0:
 
 static void i2c_parport_detach (struct parport *port)
 {
-       struct i2c_par *adapter, *prev;
+       struct i2c_par *adapter, *_n;
 
        /* Walk the list */
-       for (prev = NULL, adapter = adapter_list; adapter;
-            prev = adapter, adapter = adapter->next) {
+       mutex_lock(&adapter_list_lock);
+       list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
                if (adapter->pdev->port == port) {
                        if (adapter->ara) {
                                parport_disable_irq(port);
@@ -259,14 +263,11 @@ static void i2c_parport_detach (struct parport *port)
                                
                        parport_release(adapter->pdev);
                        parport_unregister_device(adapter->pdev);
-                       if (prev)
-                               prev->next = adapter->next;
-                       else
-                               adapter_list = adapter->next;
+                       list_del(&adapter->node);
                        kfree(adapter);
-                       return;
                }
        }
+       mutex_unlock(&adapter_list_lock);
 }
 
 static struct parport_driver i2c_parport_driver = {
index a97e3fec814826c8676f60743025f0ba6988ca0c..04be9f82e14bda8518c4d9562c680731e42c23b3 100644 (file)
@@ -65,7 +65,7 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
                jiffies, expires);
 
        timer->expires = jiffies + expires;
-       timer->data = (unsigned long)&alg_data;
+       timer->data = (unsigned long)alg_data;
 
        add_timer(timer);
 }
index fd1e117991373853d5b51d8827f99157fabd3b55..a5ec5a7cb381bbffac45a13c9e2cdccfd0a7d8b0 100644 (file)
@@ -1782,7 +1782,6 @@ static int ide_cd_probe(ide_drive_t *drive)
        ide_cd_read_toc(drive, &sense);
        g->fops = &idecd_ops;
        g->flags |= GENHD_FL_REMOVABLE;
-       g->events = DISK_EVENT_MEDIA_CHANGE;
        add_disk(g);
        return 0;
 
index 2a6bc50e8a41e8918da5ad8aca49686d68da318c..02caa7dd51c83f99e34e05de972f67020945a2d6 100644 (file)
@@ -79,6 +79,12 @@ int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
        return CDS_DRIVE_NOT_READY;
 }
 
+/*
+ * ide-cd always generates media changed event if media is missing, which
+ * makes it impossible to use for proper event reporting, so disk->events
+ * is cleared to 0 and the following function is used only to trigger
+ * revalidation and never propagated to userland.
+ */
 unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi,
                                         unsigned int clearing, int slot_nr)
 {
index c4ffd4888939a7f4e67ee7f1191a08d485c85e44..70ea8763567dcc7b1b7fd946275dea49303534f6 100644 (file)
@@ -298,6 +298,12 @@ static unsigned int ide_gd_check_events(struct gendisk *disk,
                return 0;
        }
 
+       /*
+        * The following is used to force revalidation on the first open on
+        * removeable devices, and never gets reported to userland as
+        * genhd->events is 0.  This is intended as removeable ide disk
+        * can't really detect MEDIA_CHANGE events.
+        */
        ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
        drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
 
@@ -413,7 +419,6 @@ static int ide_gd_probe(ide_drive_t *drive)
        if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
                g->flags = GENHD_FL_REMOVABLE;
        g->fops = &ide_gd_ops;
-       g->events = DISK_EVENT_MEDIA_CHANGE;
        add_disk(g);
        return 0;
 
index 5ed9d25d021a867878d0374182e327d7dd46171d..99dde874fbbdf53e93675643ac1b1e1bba372bd9 100644 (file)
@@ -148,6 +148,7 @@ struct rdma_id_private {
        u32                     qp_num;
        u8                      srq;
        u8                      tos;
+       u8                      reuseaddr;
 };
 
 struct cma_multicast {
@@ -712,6 +713,21 @@ static inline int cma_any_addr(struct sockaddr *addr)
        return cma_zero_addr(addr) || cma_loopback_addr(addr);
 }
 
+static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst)
+{
+       if (src->sa_family != dst->sa_family)
+               return -1;
+
+       switch (src->sa_family) {
+       case AF_INET:
+               return ((struct sockaddr_in *) src)->sin_addr.s_addr !=
+                      ((struct sockaddr_in *) dst)->sin_addr.s_addr;
+       default:
+               return ipv6_addr_cmp(&((struct sockaddr_in6 *) src)->sin6_addr,
+                                    &((struct sockaddr_in6 *) dst)->sin6_addr);
+       }
+}
+
 static inline __be16 cma_port(struct sockaddr *addr)
 {
        if (addr->sa_family == AF_INET)
@@ -1564,50 +1580,6 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv)
        mutex_unlock(&lock);
 }
 
-int rdma_listen(struct rdma_cm_id *id, int backlog)
-{
-       struct rdma_id_private *id_priv;
-       int ret;
-
-       id_priv = container_of(id, struct rdma_id_private, id);
-       if (id_priv->state == CMA_IDLE) {
-               ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
-               ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
-               if (ret)
-                       return ret;
-       }
-
-       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
-               return -EINVAL;
-
-       id_priv->backlog = backlog;
-       if (id->device) {
-               switch (rdma_node_get_transport(id->device->node_type)) {
-               case RDMA_TRANSPORT_IB:
-                       ret = cma_ib_listen(id_priv);
-                       if (ret)
-                               goto err;
-                       break;
-               case RDMA_TRANSPORT_IWARP:
-                       ret = cma_iw_listen(id_priv, backlog);
-                       if (ret)
-                               goto err;
-                       break;
-               default:
-                       ret = -ENOSYS;
-                       goto err;
-               }
-       } else
-               cma_listen_on_all(id_priv);
-
-       return 0;
-err:
-       id_priv->backlog = 0;
-       cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
-       return ret;
-}
-EXPORT_SYMBOL(rdma_listen);
-
 void rdma_set_service_type(struct rdma_cm_id *id, int tos)
 {
        struct rdma_id_private *id_priv;
@@ -2090,6 +2062,25 @@ err:
 }
 EXPORT_SYMBOL(rdma_resolve_addr);
 
+int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse)
+{
+       struct rdma_id_private *id_priv;
+       unsigned long flags;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       spin_lock_irqsave(&id_priv->lock, flags);
+       if (id_priv->state == CMA_IDLE) {
+               id_priv->reuseaddr = reuse;
+               ret = 0;
+       } else {
+               ret = -EINVAL;
+       }
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_set_reuseaddr);
+
 static void cma_bind_port(struct rdma_bind_list *bind_list,
                          struct rdma_id_private *id_priv)
 {
@@ -2165,41 +2156,71 @@ retry:
        return -EADDRNOTAVAIL;
 }
 
-static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
+/*
+ * Check that the requested port is available.  This is called when trying to
+ * bind to a specific port, or when trying to listen on a bound port.  In
+ * the latter case, the provided id_priv may already be on the bind_list, but
+ * we still need to check that it's okay to start listening.
+ */
+static int cma_check_port(struct rdma_bind_list *bind_list,
+                         struct rdma_id_private *id_priv, uint8_t reuseaddr)
 {
        struct rdma_id_private *cur_id;
-       struct sockaddr_in *sin, *cur_sin;
-       struct rdma_bind_list *bind_list;
+       struct sockaddr *addr, *cur_addr;
        struct hlist_node *node;
+
+       addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
+       if (cma_any_addr(addr) && !reuseaddr)
+               return -EADDRNOTAVAIL;
+
+       hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
+               if (id_priv == cur_id)
+                       continue;
+
+               if ((cur_id->state == CMA_LISTEN) ||
+                   !reuseaddr || !cur_id->reuseaddr) {
+                       cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
+                       if (cma_any_addr(cur_addr))
+                               return -EADDRNOTAVAIL;
+
+                       if (!cma_addr_cmp(addr, cur_addr))
+                               return -EADDRINUSE;
+               }
+       }
+       return 0;
+}
+
+static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
+{
+       struct rdma_bind_list *bind_list;
        unsigned short snum;
+       int ret;
 
-       sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
-       snum = ntohs(sin->sin_port);
+       snum = ntohs(cma_port((struct sockaddr *) &id_priv->id.route.addr.src_addr));
        if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
                return -EACCES;
 
        bind_list = idr_find(ps, snum);
-       if (!bind_list)
-               return cma_alloc_port(ps, id_priv, snum);
-
-       /*
-        * We don't support binding to any address if anyone is bound to
-        * a specific address on the same port.
-        */
-       if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr))
-               return -EADDRNOTAVAIL;
-
-       hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
-               if (cma_any_addr((struct sockaddr *) &cur_id->id.route.addr.src_addr))
-                       return -EADDRNOTAVAIL;
-
-               cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
-               if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
-                       return -EADDRINUSE;
+       if (!bind_list) {
+               ret = cma_alloc_port(ps, id_priv, snum);
+       } else {
+               ret = cma_check_port(bind_list, id_priv, id_priv->reuseaddr);
+               if (!ret)
+                       cma_bind_port(bind_list, id_priv);
        }
+       return ret;
+}
 
-       cma_bind_port(bind_list, id_priv);
-       return 0;
+static int cma_bind_listen(struct rdma_id_private *id_priv)
+{
+       struct rdma_bind_list *bind_list = id_priv->bind_list;
+       int ret = 0;
+
+       mutex_lock(&lock);
+       if (bind_list->owners.first->next)
+               ret = cma_check_port(bind_list, id_priv, 0);
+       mutex_unlock(&lock);
+       return ret;
 }
 
 static int cma_get_port(struct rdma_id_private *id_priv)
@@ -2253,6 +2274,56 @@ static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
        return 0;
 }
 
+int rdma_listen(struct rdma_cm_id *id, int backlog)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id_priv->state == CMA_IDLE) {
+               ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
+               ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
+               return -EINVAL;
+
+       if (id_priv->reuseaddr) {
+               ret = cma_bind_listen(id_priv);
+               if (ret)
+                       goto err;
+       }
+
+       id_priv->backlog = backlog;
+       if (id->device) {
+               switch (rdma_node_get_transport(id->device->node_type)) {
+               case RDMA_TRANSPORT_IB:
+                       ret = cma_ib_listen(id_priv);
+                       if (ret)
+                               goto err;
+                       break;
+               case RDMA_TRANSPORT_IWARP:
+                       ret = cma_iw_listen(id_priv, backlog);
+                       if (ret)
+                               goto err;
+                       break;
+               default:
+                       ret = -ENOSYS;
+                       goto err;
+               }
+       } else
+               cma_listen_on_all(id_priv);
+
+       return 0;
+err:
+       id_priv->backlog = 0;
+       cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_listen);
+
 int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 {
        struct rdma_id_private *id_priv;
index 2a1e9ae134b4c330bbffd048d6ce037e75652d45..a9c042345c6fe14260d480c355aebea38d240842 100644 (file)
@@ -725,7 +725,7 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
         */
        clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
        BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
-       if (iw_event->status == IW_CM_EVENT_STATUS_ACCEPTED) {
+       if (iw_event->status == 0) {
                cm_id_priv->id.local_addr = iw_event->local_addr;
                cm_id_priv->id.remote_addr = iw_event->remote_addr;
                cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
index ec1e9da1488b321df67b7d77fe2921e364276115..b3fa798525b2a1d8d3df793f41fe255eacf676dd 100644 (file)
@@ -883,6 +883,13 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname,
                }
                rdma_set_service_type(ctx->cm_id, *((u8 *) optval));
                break;
+       case RDMA_OPTION_ID_REUSEADDR:
+               if (optlen != sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
+               break;
        default:
                ret = -ENOSYS;
        }
index 9d8dcfab2b38a7a2489cf7edc942c58c8c6c2c20..d7ee70fc917374fdb946f02f1f8a153df69c2161 100644 (file)
@@ -1198,9 +1198,7 @@ static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        }
        PDBG("%s ep %p status %d error %d\n", __func__, ep,
             rpl->status, status2errno(rpl->status));
-       ep->com.wr_wait.ret = status2errno(rpl->status);
-       ep->com.wr_wait.done = 1;
-       wake_up(&ep->com.wr_wait.wait);
+       c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
 
        return 0;
 }
@@ -1234,9 +1232,7 @@ static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_listen_ep *ep = lookup_stid(t, stid);
 
        PDBG("%s ep %p\n", __func__, ep);
-       ep->com.wr_wait.ret = status2errno(rpl->status);
-       ep->com.wr_wait.done = 1;
-       wake_up(&ep->com.wr_wait.wait);
+       c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
        return 0;
 }
 
@@ -1466,7 +1462,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_qp_attributes attrs;
        int disconnect = 1;
        int release = 0;
-       int closing = 0;
+       int abort = 0;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(hdr);
 
@@ -1492,23 +1488,22 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                 * in rdma connection migration (see c4iw_accept_cr()).
                 */
                __state_set(&ep->com, CLOSING);
-               ep->com.wr_wait.done = 1;
-               ep->com.wr_wait.ret = -ECONNRESET;
                PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-               wake_up(&ep->com.wr_wait.wait);
+               c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
                break;
        case MPA_REP_SENT:
                __state_set(&ep->com, CLOSING);
-               ep->com.wr_wait.done = 1;
-               ep->com.wr_wait.ret = -ECONNRESET;
                PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-               wake_up(&ep->com.wr_wait.wait);
+               c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
                break;
        case FPDU_MODE:
                start_ep_timer(ep);
                __state_set(&ep->com, CLOSING);
-               closing = 1;
+               attrs.next_state = C4IW_QP_STATE_CLOSING;
+               abort = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+                                      C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
                peer_close_upcall(ep);
+               disconnect = 1;
                break;
        case ABORTING:
                disconnect = 0;
@@ -1536,11 +1531,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                BUG_ON(1);
        }
        mutex_unlock(&ep->com.mutex);
-       if (closing) {
-               attrs.next_state = C4IW_QP_STATE_CLOSING;
-               c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
-       }
        if (disconnect)
                c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
        if (release)
@@ -1581,9 +1571,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Wake up any threads in rdma_init() or rdma_fini().
         */
-       ep->com.wr_wait.done = 1;
-       ep->com.wr_wait.ret = -ECONNRESET;
-       wake_up(&ep->com.wr_wait.wait);
+       c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 
        mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
@@ -1710,14 +1698,14 @@ static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
        ep = lookup_tid(t, tid);
        BUG_ON(!ep);
 
-       if (ep->com.qp) {
+       if (ep && ep->com.qp) {
                printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid,
                       ep->com.qp->wq.sq.qid);
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
                c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
        } else
-               printk(KERN_WARNING MOD "TERM received tid %u no qp\n", tid);
+               printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid);
 
        return 0;
 }
@@ -2296,14 +2284,8 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
                ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
                wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
                PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
-               if (wr_waitp) {
-                       if (ret)
-                               wr_waitp->ret = -ret;
-                       else
-                               wr_waitp->ret = 0;
-                       wr_waitp->done = 1;
-                       wake_up(&wr_waitp->wait);
-               }
+               if (wr_waitp)
+                       c4iw_wake_up(wr_waitp, ret ? -ret : 0);
                kfree_skb(skb);
                break;
        case 2:
index e29172c2afcbe963da9c581f3fdc60798d3fabf4..40a13cc633a342befeeb452d713df087bb219149 100644 (file)
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION("Chelsio T4 RDMA Driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
-static LIST_HEAD(dev_list);
+static LIST_HEAD(uld_ctx_list);
 static DEFINE_MUTEX(dev_mutex);
 
 static struct dentry *c4iw_debugfs_root;
@@ -370,18 +370,23 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
        c4iw_destroy_resource(&rdev->resource);
 }
 
-static void c4iw_remove(struct c4iw_dev *dev)
+struct uld_ctx {
+       struct list_head entry;
+       struct cxgb4_lld_info lldi;
+       struct c4iw_dev *dev;
+};
+
+static void c4iw_remove(struct uld_ctx *ctx)
 {
-       PDBG("%s c4iw_dev %p\n", __func__,  dev);
-       list_del(&dev->entry);
-       if (dev->registered)
-               c4iw_unregister_device(dev);
-       c4iw_rdev_close(&dev->rdev);
-       idr_destroy(&dev->cqidr);
-       idr_destroy(&dev->qpidr);
-       idr_destroy(&dev->mmidr);
-       iounmap(dev->rdev.oc_mw_kva);
-       ib_dealloc_device(&dev->ibdev);
+       PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
+       c4iw_unregister_device(ctx->dev);
+       c4iw_rdev_close(&ctx->dev->rdev);
+       idr_destroy(&ctx->dev->cqidr);
+       idr_destroy(&ctx->dev->qpidr);
+       idr_destroy(&ctx->dev->mmidr);
+       iounmap(ctx->dev->rdev.oc_mw_kva);
+       ib_dealloc_device(&ctx->dev->ibdev);
+       ctx->dev = NULL;
 }
 
 static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
@@ -392,7 +397,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
        devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
        if (!devp) {
                printk(KERN_ERR MOD "Cannot allocate ib device\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
        devp->rdev.lldi = *infop;
 
@@ -402,27 +407,23 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
        devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
                                               devp->rdev.lldi.vr->ocq.size);
 
-       printk(KERN_INFO MOD "ocq memory: "
+       PDBG(KERN_INFO MOD "ocq memory: "
               "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n",
               devp->rdev.lldi.vr->ocq.start, devp->rdev.lldi.vr->ocq.size,
               devp->rdev.oc_mw_pa, devp->rdev.oc_mw_kva);
 
-       mutex_lock(&dev_mutex);
-
        ret = c4iw_rdev_open(&devp->rdev);
        if (ret) {
                mutex_unlock(&dev_mutex);
                printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
                ib_dealloc_device(&devp->ibdev);
-               return NULL;
+               return ERR_PTR(ret);
        }
 
        idr_init(&devp->cqidr);
        idr_init(&devp->qpidr);
        idr_init(&devp->mmidr);
        spin_lock_init(&devp->lock);
-       list_add_tail(&devp->entry, &dev_list);
-       mutex_unlock(&dev_mutex);
 
        if (c4iw_debugfs_root) {
                devp->debugfs_root = debugfs_create_dir(
@@ -435,7 +436,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 
 static void *c4iw_uld_add(const struct cxgb4_lld_info *infop)
 {
-       struct c4iw_dev *dev;
+       struct uld_ctx *ctx;
        static int vers_printed;
        int i;
 
@@ -443,25 +444,33 @@ static void *c4iw_uld_add(const struct cxgb4_lld_info *infop)
                printk(KERN_INFO MOD "Chelsio T4 RDMA Driver - version %s\n",
                       DRV_VERSION);
 
-       dev = c4iw_alloc(infop);
-       if (!dev)
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx) {
+               ctx = ERR_PTR(-ENOMEM);
                goto out;
+       }
+       ctx->lldi = *infop;
 
        PDBG("%s found device %s nchan %u nrxq %u ntxq %u nports %u\n",
-            __func__, pci_name(dev->rdev.lldi.pdev),
-            dev->rdev.lldi.nchan, dev->rdev.lldi.nrxq,
-            dev->rdev.lldi.ntxq, dev->rdev.lldi.nports);
+            __func__, pci_name(ctx->lldi.pdev),
+            ctx->lldi.nchan, ctx->lldi.nrxq,
+            ctx->lldi.ntxq, ctx->lldi.nports);
+
+       mutex_lock(&dev_mutex);
+       list_add_tail(&ctx->entry, &uld_ctx_list);
+       mutex_unlock(&dev_mutex);
 
-       for (i = 0; i < dev->rdev.lldi.nrxq; i++)
-               PDBG("rxqid[%u] %u\n", i, dev->rdev.lldi.rxq_ids[i]);
+       for (i = 0; i < ctx->lldi.nrxq; i++)
+               PDBG("rxqid[%u] %u\n", i, ctx->lldi.rxq_ids[i]);
 out:
-       return dev;
+       return ctx;
 }
 
 static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
                        const struct pkt_gl *gl)
 {
-       struct c4iw_dev *dev = handle;
+       struct uld_ctx *ctx = handle;
+       struct c4iw_dev *dev = ctx->dev;
        struct sk_buff *skb;
        const struct cpl_act_establish *rpl;
        unsigned int opcode;
@@ -503,47 +512,49 @@ nomem:
 
 static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
 {
-       struct c4iw_dev *dev = handle;
+       struct uld_ctx *ctx = handle;
 
        PDBG("%s new_state %u\n", __func__, new_state);
        switch (new_state) {
        case CXGB4_STATE_UP:
-               printk(KERN_INFO MOD "%s: Up\n", pci_name(dev->rdev.lldi.pdev));
-               if (!dev->registered) {
-                       int ret;
-                       ret = c4iw_register_device(dev);
-                       if (ret)
+               printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
+               if (!ctx->dev) {
+                       int ret = 0;
+
+                       ctx->dev = c4iw_alloc(&ctx->lldi);
+                       if (!IS_ERR(ctx->dev))
+                               ret = c4iw_register_device(ctx->dev);
+                       if (IS_ERR(ctx->dev) || ret)
                                printk(KERN_ERR MOD
                                       "%s: RDMA registration failed: %d\n",
-                                      pci_name(dev->rdev.lldi.pdev), ret);
+                                      pci_name(ctx->lldi.pdev), ret);
                }
                break;
        case CXGB4_STATE_DOWN:
                printk(KERN_INFO MOD "%s: Down\n",
-                      pci_name(dev->rdev.lldi.pdev));
-               if (dev->registered)
-                       c4iw_unregister_device(dev);
+                      pci_name(ctx->lldi.pdev));
+               if (ctx->dev)
+                       c4iw_remove(ctx);
                break;
        case CXGB4_STATE_START_RECOVERY:
                printk(KERN_INFO MOD "%s: Fatal Error\n",
-                      pci_name(dev->rdev.lldi.pdev));
-               dev->rdev.flags |= T4_FATAL_ERROR;
-               if (dev->registered) {
+                      pci_name(ctx->lldi.pdev));
+               if (ctx->dev) {
                        struct ib_event event;
 
+                       ctx->dev->rdev.flags |= T4_FATAL_ERROR;
                        memset(&event, 0, sizeof event);
                        event.event  = IB_EVENT_DEVICE_FATAL;
-                       event.device = &dev->ibdev;
+                       event.device = &ctx->dev->ibdev;
                        ib_dispatch_event(&event);
-                       c4iw_unregister_device(dev);
+                       c4iw_remove(ctx);
                }
                break;
        case CXGB4_STATE_DETACH:
                printk(KERN_INFO MOD "%s: Detach\n",
-                      pci_name(dev->rdev.lldi.pdev));
-               mutex_lock(&dev_mutex);
-               c4iw_remove(dev);
-               mutex_unlock(&dev_mutex);
+                      pci_name(ctx->lldi.pdev));
+               if (ctx->dev)
+                       c4iw_remove(ctx);
                break;
        }
        return 0;
@@ -576,11 +587,13 @@ static int __init c4iw_init_module(void)
 
 static void __exit c4iw_exit_module(void)
 {
-       struct c4iw_dev *dev, *tmp;
+       struct uld_ctx *ctx, *tmp;
 
        mutex_lock(&dev_mutex);
-       list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
-               c4iw_remove(dev);
+       list_for_each_entry_safe(ctx, tmp, &uld_ctx_list, entry) {
+               if (ctx->dev)
+                       c4iw_remove(ctx);
+               kfree(ctx);
        }
        mutex_unlock(&dev_mutex);
        cxgb4_unregister_uld(CXGB4_ULD_RDMA);
index 9f6166f59268e8a597e7a8ea5a958184b217afc7..35d2a5dd9bb402d212c5f5ad5f8aa82480d7ce24 100644 (file)
@@ -131,42 +131,58 @@ static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
 
 #define C4IW_WR_TO (10*HZ)
 
+enum {
+       REPLY_READY = 0,
+};
+
 struct c4iw_wr_wait {
        wait_queue_head_t wait;
-       int done;
+       unsigned long status;
        int ret;
 };
 
 static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp)
 {
        wr_waitp->ret = 0;
-       wr_waitp->done = 0;
+       wr_waitp->status = 0;
        init_waitqueue_head(&wr_waitp->wait);
 }
 
+static inline void c4iw_wake_up(struct c4iw_wr_wait *wr_waitp, int ret)
+{
+       wr_waitp->ret = ret;
+       set_bit(REPLY_READY, &wr_waitp->status);
+       wake_up(&wr_waitp->wait);
+}
+
 static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
                                 struct c4iw_wr_wait *wr_waitp,
                                 u32 hwtid, u32 qpid,
                                 const char *func)
 {
        unsigned to = C4IW_WR_TO;
-       do {
+       int ret;
 
-               wait_event_timeout(wr_waitp->wait, wr_waitp->done, to);
-               if (!wr_waitp->done) {
+       do {
+               ret = wait_event_timeout(wr_waitp->wait,
+                       test_and_clear_bit(REPLY_READY, &wr_waitp->status), to);
+               if (!ret) {
                        printk(KERN_ERR MOD "%s - Device %s not responding - "
                               "tid %u qpid %u\n", func,
                               pci_name(rdev->lldi.pdev), hwtid, qpid);
+                       if (c4iw_fatal_error(rdev)) {
+                               wr_waitp->ret = -EIO;
+                               break;
+                       }
                        to = to << 2;
                }
-       } while (!wr_waitp->done);
+       } while (!ret);
        if (wr_waitp->ret)
-               printk(KERN_WARNING MOD "%s: FW reply %d tid %u qpid %u\n",
-                      pci_name(rdev->lldi.pdev), wr_waitp->ret, hwtid, qpid);
+               PDBG("%s: FW reply %d tid %u qpid %u\n",
+                    pci_name(rdev->lldi.pdev), wr_waitp->ret, hwtid, qpid);
        return wr_waitp->ret;
 }
 
-
 struct c4iw_dev {
        struct ib_device ibdev;
        struct c4iw_rdev rdev;
@@ -175,9 +191,7 @@ struct c4iw_dev {
        struct idr qpidr;
        struct idr mmidr;
        spinlock_t lock;
-       struct list_head entry;
        struct dentry *debugfs_root;
-       u8 registered;
 };
 
 static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
index f66dd8bf5128a0fd4f1a0acf686b4e4815813384..5b9e4220ca08f41cc9c8da8375b2e74ff5ee1d05 100644 (file)
@@ -516,7 +516,6 @@ int c4iw_register_device(struct c4iw_dev *dev)
                if (ret)
                        goto bail2;
        }
-       dev->registered = 1;
        return 0;
 bail2:
        ib_unregister_device(&dev->ibdev);
@@ -535,6 +534,5 @@ void c4iw_unregister_device(struct c4iw_dev *dev)
                                   c4iw_class_attributes[i]);
        ib_unregister_device(&dev->ibdev);
        kfree(dev->ibdev.iwcm);
-       dev->registered = 0;
        return;
 }
index 70a5a3c646da478a4ae1b1088f2440f604bfed94..3b773b05a8989a0a7b81bda16f64c0f747577344 100644 (file)
@@ -214,7 +214,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
                V_FW_RI_RES_WR_HOSTFCMODE(0) |  /* no host cidx updates */
                V_FW_RI_RES_WR_CPRIO(0) |       /* don't keep in chip cache */
                V_FW_RI_RES_WR_PCIECHN(0) |     /* set by uP at ri_init time */
-               t4_sq_onchip(&wq->sq) ? F_FW_RI_RES_WR_ONCHIP : 0 |
+               (t4_sq_onchip(&wq->sq) ? F_FW_RI_RES_WR_ONCHIP : 0) |
                V_FW_RI_RES_WR_IQID(scq->cqid));
        res->u.sqrq.dcaen_to_eqsize = cpu_to_be32(
                V_FW_RI_RES_WR_DCAEN(0) |
@@ -1210,7 +1210,6 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                        if (ret) {
                                if (internal)
                                        c4iw_get_ep(&qhp->ep->com);
-                               disconnect = abort = 1;
                                goto err;
                        }
                        break;
index 58c0e417bc30d78c16aba42aafd2b7253c627d12..be24ac726114172eba6bfd64939b480c961c4342 100644 (file)
@@ -398,7 +398,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
        struct ipath_devdata *dd;
        unsigned long long addr;
        u32 bar0 = 0, bar1 = 0;
-       u8 rev;
 
        dd = ipath_alloc_devdata(pdev);
        if (IS_ERR(dd)) {
@@ -540,13 +539,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
                goto bail_regions;
        }
 
-       ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-       if (ret) {
-               ipath_dev_err(dd, "Failed to read PCI revision ID unit "
-                             "%u: err %d\n", dd->ipath_unit, -ret);
-               goto bail_regions;      /* shouldn't ever happen */
-       }
-       dd->ipath_pcirev = rev;
+       dd->ipath_pcirev = pdev->revision;
 
 #if defined(__powerpc__)
        /* There isn't a generic way to specify writethrough mappings */
index 33c7eedaba6c28abfe21ab599bc356d67f055ad3..e74cdf9ef4716a4954f5608e2cc20121c05b67e7 100644 (file)
@@ -2563,7 +2563,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
        u16 last_ae;
        u8 original_hw_tcp_state;
        u8 original_ibqp_state;
-       enum iw_cm_event_status disconn_status = IW_CM_EVENT_STATUS_OK;
+       int disconn_status = 0;
        int issue_disconn = 0;
        int issue_close = 0;
        int issue_flush = 0;
@@ -2605,7 +2605,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
                issue_disconn = 1;
                if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET)
-                       disconn_status = IW_CM_EVENT_STATUS_RESET;
+                       disconn_status = -ECONNRESET;
        }
 
        if (((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
@@ -2666,7 +2666,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        cm_id->provider_data = nesqp;
                        /* Send up the close complete event */
                        cm_event.event = IW_CM_EVENT_CLOSE;
-                       cm_event.status = IW_CM_EVENT_STATUS_OK;
+                       cm_event.status = 0;
                        cm_event.provider_data = cm_id->provider_data;
                        cm_event.local_addr = cm_id->local_addr;
                        cm_event.remote_addr = cm_id->remote_addr;
@@ -2966,7 +2966,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        nes_add_ref(&nesqp->ibqp);
 
        cm_event.event = IW_CM_EVENT_ESTABLISHED;
-       cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
+       cm_event.status = 0;
        cm_event.provider_data = (void *)nesqp;
        cm_event.local_addr = cm_id->local_addr;
        cm_event.remote_addr = cm_id->remote_addr;
@@ -3377,7 +3377,7 @@ static void cm_event_connected(struct nes_cm_event *event)
 
        /* notify OF layer we successfully created the requested connection */
        cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
-       cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
+       cm_event.status = 0;
        cm_event.provider_data = cm_id->provider_data;
        cm_event.local_addr.sin_family = AF_INET;
        cm_event.local_addr.sin_port = cm_id->local_addr.sin_port;
@@ -3484,7 +3484,7 @@ static void cm_event_reset(struct nes_cm_event *event)
        nesqp->cm_id = NULL;
        /* cm_id->provider_data = NULL; */
        cm_event.event = IW_CM_EVENT_DISCONNECT;
-       cm_event.status = IW_CM_EVENT_STATUS_RESET;
+       cm_event.status = -ECONNRESET;
        cm_event.provider_data = cm_id->provider_data;
        cm_event.local_addr = cm_id->local_addr;
        cm_event.remote_addr = cm_id->remote_addr;
@@ -3495,7 +3495,7 @@ static void cm_event_reset(struct nes_cm_event *event)
        ret = cm_id->event_handler(cm_id, &cm_event);
        atomic_inc(&cm_closes);
        cm_event.event = IW_CM_EVENT_CLOSE;
-       cm_event.status = IW_CM_EVENT_STATUS_OK;
+       cm_event.status = 0;
        cm_event.provider_data = cm_id->provider_data;
        cm_event.local_addr = cm_id->local_addr;
        cm_event.remote_addr = cm_id->remote_addr;
@@ -3534,7 +3534,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
                        cm_node, cm_id, jiffies);
 
        cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
-       cm_event.status = IW_CM_EVENT_STATUS_OK;
+       cm_event.status = 0;
        cm_event.provider_data = (void *)cm_node;
 
        cm_event.local_addr.sin_family = AF_INET;
index 26d8018c0a7c557d6eb2f4f8f69adf09d916c781..95ca93ceedac993f68064671ee4f4d64f6ddc00b 100644 (file)
@@ -1484,7 +1484,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
                        (nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) {
                cm_id = nesqp->cm_id;
                cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
-               cm_event.status = IW_CM_EVENT_STATUS_TIMEOUT;
+               cm_event.status = -ETIMEDOUT;
                cm_event.local_addr = cm_id->local_addr;
                cm_event.remote_addr = cm_id->remote_addr;
                cm_event.private_data = NULL;
index 7de4b7ebffc541f1a204360fb6d9d39a5f9b96d1..d8ca0a0b970d39879e7d981acbf5cb1647dca424 100644 (file)
@@ -1799,7 +1799,7 @@ static int qib_6120_setup_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
        dd->int_counter = 0; /* so we check interrupts work again */
index 74fe0360bec7a00a7e082d1bdfc45004239e4e14..c765a2eb04cf27ba3b28ef4eb33e5e99ed6027ba 100644 (file)
@@ -2111,7 +2111,7 @@ static int qib_setup_7220_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
        dd->int_counter = 0; /* so we check interrupts work again */
index 55de3cf3441c51173c169064a891de38d138ca5b..9f53e68a096a329f499cbb1c9d63b6800b5add55 100644 (file)
@@ -3299,7 +3299,7 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT | QIB_BADINTR);
        dd->flags |= QIB_DOING_RESET;
@@ -7534,7 +7534,8 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
        ibsd_wr_allchans(ppd, 4, (1 << 10), BMASK(10, 10));
        tstart = get_jiffies_64();
        while (chan_done &&
-              !time_after64(tstart, tstart + msecs_to_jiffies(500))) {
+              !time_after64(get_jiffies_64(),
+                       tstart + msecs_to_jiffies(500))) {
                msleep(20);
                for (chan = 0; chan < SERDES_CHANS; ++chan) {
                        rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx),
index 48b6674cbc49f97b9fd4e8d225325b6304833b5d..891cc2ff5f00c3033ab026438b7b1a83f30feff6 100644 (file)
@@ -526,11 +526,8 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
         */
        devid = parent->device;
        if (devid >= 0x25e2 && devid <= 0x25fa) {
-               u8 rev;
-
                /* 5000 P/V/X/Z */
-               pci_read_config_byte(parent, PCI_REVISION_ID, &rev);
-               if (rev <= 0xb2)
+               if (parent->revision <= 0xb2)
                        bits = 1U << 10;
                else
                        bits = 7U << 10;
index 1839194ea98787ff9fb82f810c18fb4a8bdb893d..10bcd4ae54023a39bf7030546e1349780bef8ec5 100644 (file)
@@ -223,8 +223,9 @@ static int __init atakbd_init(void)
                return -ENODEV;
 
        // need to init core driver if not already done so
-       if (atari_keyb_init())
-               return -ENODEV;
+       error = atari_keyb_init();
+       if (error)
+               return error;
 
        atakbd_dev = input_allocate_device();
        if (!atakbd_dev)
index adf45b3040e90f036c685e37c72f83965499b5bb..5c4a692bf73aee120aaf928fb2d33104f51dea65 100644 (file)
@@ -77,15 +77,15 @@ static void atamouse_interrupt(char *buf)
 #endif
 
        /* only relative events get here */
-       dx =  buf[1];
-       dy = -buf[2];
+       dx = buf[1];
+       dy = buf[2];
 
        input_report_rel(atamouse_dev, REL_X, dx);
        input_report_rel(atamouse_dev, REL_Y, dy);
 
-       input_report_key(atamouse_dev, BTN_LEFT,   buttons & 0x1);
+       input_report_key(atamouse_dev, BTN_LEFT,   buttons & 0x4);
        input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
-       input_report_key(atamouse_dev, BTN_RIGHT,  buttons & 0x4);
+       input_report_key(atamouse_dev, BTN_RIGHT,  buttons & 0x1);
 
        input_sync(atamouse_dev);
 
@@ -108,7 +108,7 @@ static int atamouse_open(struct input_dev *dev)
 static void atamouse_close(struct input_dev *dev)
 {
        ikbd_mouse_disable();
-       atari_mouse_interrupt_hook = NULL;
+       atari_input_mouse_interrupt_hook = NULL;
 }
 
 static int __init atamouse_init(void)
@@ -118,8 +118,9 @@ static int __init atamouse_init(void)
        if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
                return -ENODEV;
 
-       if (!atari_keyb_init())
-               return -ENODEV;
+       error = atari_keyb_init();
+       if (error)
+               return error;
 
        atamouse_dev = input_allocate_device();
        if (!atamouse_dev)
index c24946f512564e35925d0e6c090b7fd4a6c4eccd..1de1c19dad30f2e0ef089f0901e8d6d0b2584b43 100644 (file)
@@ -281,17 +281,24 @@ struct ser_req {
        u8                      command;
        u8                      ref_off;
        u16                     scratch;
-       __be16                  sample;
        struct spi_message      msg;
        struct spi_transfer     xfer[6];
+       /*
+        * DMA (thus cache coherency maintenance) requires the
+        * transfer buffers to live in their own cache lines.
+        */
+       __be16 sample ____cacheline_aligned;
 };
 
 struct ads7845_ser_req {
        u8                      command[3];
-       u8                      pwrdown[3];
-       u8                      sample[3];
        struct spi_message      msg;
        struct spi_transfer     xfer[2];
+       /*
+        * DMA (thus cache coherency maintenance) requires the
+        * transfer buffers to live in their own cache lines.
+        */
+       u8 sample[3] ____cacheline_aligned;
 };
 
 static int ads7846_read12_ser(struct device *dev, unsigned command)
index 6ae054f8e0aa50b5e07f7d43f21f582bb19cf98f..9175d49d25469d0eaa7794960580c14d7740b9a9 100644 (file)
@@ -68,8 +68,23 @@ struct wm831x_ts {
        unsigned int pd_irq;
        bool pressure;
        bool pen_down;
+       struct work_struct pd_data_work;
 };
 
+static void wm831x_pd_data_work(struct work_struct *work)
+{
+       struct wm831x_ts *wm831x_ts =
+               container_of(work, struct wm831x_ts, pd_data_work);
+
+       if (wm831x_ts->pen_down) {
+               enable_irq(wm831x_ts->data_irq);
+               dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
+       } else {
+               enable_irq(wm831x_ts->pd_irq);
+               dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
+       }
+}
+
 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
 {
        struct wm831x_ts *wm831x_ts = irq_data;
@@ -110,6 +125,9 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
        }
 
        if (!wm831x_ts->pen_down) {
+               /* Switch from data to pen down */
+               dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
+
                disable_irq_nosync(wm831x_ts->data_irq);
 
                /* Don't need data any more */
@@ -128,6 +146,10 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
                                         ABS_PRESSURE, 0);
 
                input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
+
+               schedule_work(&wm831x_ts->pd_data_work);
+       } else {
+               input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
        }
 
        input_sync(wm831x_ts->input_dev);
@@ -141,6 +163,11 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
        struct wm831x *wm831x = wm831x_ts->wm831x;
        int ena = 0;
 
+       if (wm831x_ts->pen_down)
+               return IRQ_HANDLED;
+
+       disable_irq_nosync(wm831x_ts->pd_irq);
+
        /* Start collecting data */
        if (wm831x_ts->pressure)
                ena |= WM831X_TCH_Z_ENA;
@@ -149,14 +176,14 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
 
-       input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
-       input_sync(wm831x_ts->input_dev);
-
        wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
                        WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
 
        wm831x_ts->pen_down = true;
-       enable_irq(wm831x_ts->data_irq);
+
+       /* Switch from pen down to data */
+       dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
+       schedule_work(&wm831x_ts->pd_data_work);
 
        return IRQ_HANDLED;
 }
@@ -182,13 +209,28 @@ static void wm831x_ts_input_close(struct input_dev *idev)
        struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
        struct wm831x *wm831x = wm831x_ts->wm831x;
 
+       /* Shut the controller down, disabling all other functionality too */
        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
-                       WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
-                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
-                       WM831X_TCH_Z_ENA, 0);
+                       WM831X_TCH_ENA | WM831X_TCH_X_ENA |
+                       WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
 
-       if (wm831x_ts->pen_down)
+       /* Make sure any pending IRQs are done, the above will prevent
+        * new ones firing.
+        */
+       synchronize_irq(wm831x_ts->data_irq);
+       synchronize_irq(wm831x_ts->pd_irq);
+
+       /* Make sure the IRQ completion work is quiesced */
+       flush_work_sync(&wm831x_ts->pd_data_work);
+
+       /* If we ended up with the pen down then make sure we revert back
+        * to pen detection state for the next time we start up.
+        */
+       if (wm831x_ts->pen_down) {
                disable_irq(wm831x_ts->data_irq);
+               enable_irq(wm831x_ts->pd_irq);
+               wm831x_ts->pen_down = false;
+       }
 }
 
 static __devinit int wm831x_ts_probe(struct platform_device *pdev)
@@ -198,7 +240,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
        struct wm831x_touch_pdata *pdata = NULL;
        struct input_dev *input_dev;
-       int error;
+       int error, irqf;
 
        if (core_pdata)
                pdata = core_pdata->touch;
@@ -212,6 +254,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
 
        wm831x_ts->wm831x = wm831x;
        wm831x_ts->input_dev = input_dev;
+       INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
 
        /*
         * If we have a direct IRQ use it, otherwise use the interrupt
@@ -270,9 +313,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
                        WM831X_TCH_RATE_MASK, 6);
 
+       if (pdata && pdata->data_irqf)
+               irqf = pdata->data_irqf;
+       else
+               irqf = IRQF_TRIGGER_HIGH;
+
        error = request_threaded_irq(wm831x_ts->data_irq,
                                     NULL, wm831x_ts_data_irq,
-                                    IRQF_ONESHOT,
+                                    irqf | IRQF_ONESHOT,
                                     "Touchscreen data", wm831x_ts);
        if (error) {
                dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
@@ -281,9 +329,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        }
        disable_irq(wm831x_ts->data_irq);
 
+       if (pdata && pdata->pd_irqf)
+               irqf = pdata->pd_irqf;
+       else
+               irqf = IRQF_TRIGGER_HIGH;
+
        error = request_threaded_irq(wm831x_ts->pd_irq,
                                     NULL, wm831x_ts_pen_down_irq,
-                                    IRQF_ONESHOT,
+                                    irqf | IRQF_ONESHOT,
                                     "Touchscreen pen down", wm831x_ts);
        if (error) {
                dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
index e7089a1f6cb6c8bf2e54acc95ef8fac58c03ba59..b37e6186d0fa007e2edc23f8186643b803429b2b 100644 (file)
@@ -349,6 +349,7 @@ static const struct i2c_device_id lm3530_id[] = {
        {LM3530_NAME, 0},
        {}
 };
+MODULE_DEVICE_TABLE(i2c, lm3530_id);
 
 static struct i2c_driver lm3530_i2c_driver = {
        .probe = lm3530_probe,
index 0aaa0597a6223779e758d45875af4fb17cc3956c..34ae49dc557c9abe0816b3ffb5a6a80af39f525f 100644 (file)
@@ -5,8 +5,10 @@ config LGUEST
        ---help---
          This is a very simple module which allows you to run
          multiple instances of the same Linux kernel, using the
-         "lguest" command found in the Documentation/lguest directory.
+         "lguest" command found in the Documentation/virtual/lguest
+         directory.
+
          Note that "lguest" is pronounced to rhyme with "fell quest",
-         not "rustyvisor".  See Documentation/lguest/lguest.txt.
+         not "rustyvisor". See Documentation/virtual/lguest/lguest.txt.
 
          If unsure, say N.  If curious, say M.  If masochistic, say Y.
index 7d463c26124f38d9fb1545a6098f08b6d6c1d29f..8ac947c7e7c77e11cb08d8482221fb8e48087685 100644 (file)
@@ -18,7 +18,7 @@ Mastery: PREFIX=M
 Beer:
        @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}"
 Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery:
-       @sh ../../Documentation/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
+       @sh ../../Documentation/virtual/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
 Puppy:
        @clear
        @printf "      __  \n (___()'\`;\n /,    /\`\n \\\\\\\"--\\\\\\   \n"
index 6e853c61d87eee47d66ddb7a510270f1c4cb2cbc..7d6f7f18a92052e3258ffeae719c377b2df4fb78 100644 (file)
@@ -3170,6 +3170,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        mddev->layout = mddev->new_layout;
        mddev->chunk_sectors = mddev->new_chunk_sectors;
        mddev->delta_disks = 0;
+       mddev->degraded = 0;
        if (mddev->pers->sync_request == NULL) {
                /* this is now an array without redundancy, so
                 * it must always be in_sync
index f301e6ae220cfa964941d2a13546f3cfde7b62a5..49bf5f8914353a1c7972beaa27d6b5caee1031cc 100644 (file)
@@ -5151,7 +5151,6 @@ static int run(mddev_t *mddev)
 
                mddev->queue->backing_dev_info.congested_data = mddev;
                mddev->queue->backing_dev_info.congested_fn = raid5_congested;
-               mddev->queue->queue_lock = &conf->device_lock;
 
                chunk_size = mddev->chunk_sectors << 9;
                blk_queue_io_min(mddev->queue, chunk_size);
@@ -5679,6 +5678,7 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 static void *raid45_takeover_raid0(mddev_t *mddev, int level)
 {
        struct raid0_private_data *raid0_priv = mddev->private;
+       sector_t sectors;
 
        /* for raid0 takeover only one zone is supported */
        if (raid0_priv->nr_strip_zones > 1) {
@@ -5687,6 +5687,9 @@ static void *raid45_takeover_raid0(mddev_t *mddev, int level)
                return ERR_PTR(-EINVAL);
        }
 
+       sectors = raid0_priv->strip_zone[0].zone_end;
+       sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+       mddev->dev_sectors = sectors;
        mddev->new_level = level;
        mddev->new_layout = ALGORITHM_PARITY_N;
        mddev->new_chunk_sectors = mddev->chunk_sectors;
index 5466d47db899ea67c8551fafbe2a5e5bacb78ba7..aae40e52af5b1f3edf36c11154b6d04e41fd8273 100644 (file)
@@ -533,16 +533,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
        if (tda_fail(ret))
                goto fail;
 
-       regs[R_MPD]   = (0x77 & pd);
-
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_MPD]  &= ~0x08;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_MPD]  |=  0x08;
-               break;
-       }
+       regs[R_MPD]   = (0x7f & pd);
 
        div =  ((d * (freq / 1000)) << 7) / 125;
 
index 9ad4454a148d07040e03842bde866bf4dd42886a..d884f5eee73ca09b547bc168776fe1b89bac0650 100644 (file)
@@ -579,8 +579,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
 #define RF3 2
        u32 rf_default[3];
        u32 rf_freq[3];
-       u8 prog_cal[3];
-       u8 prog_tab[3];
+       s32 prog_cal[3];
+       s32 prog_tab[3];
 
        i = tda18271_lookup_rf_band(fe, &freq, NULL);
 
@@ -602,32 +602,33 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
                        return bcal;
 
                tda18271_calc_rf_cal(fe, &rf_freq[rf]);
-               prog_tab[rf] = regs[R_EB14];
+               prog_tab[rf] = (s32)regs[R_EB14];
 
                if (1 == bcal)
-                       prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
+                       prog_cal[rf] =
+                               (s32)tda18271_calibrate_rf(fe, rf_freq[rf]);
                else
                        prog_cal[rf] = prog_tab[rf];
 
                switch (rf) {
                case RF1:
                        map[i].rf_a1 = 0;
-                       map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]);
+                       map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]);
                        map[i].rf1   = rf_freq[RF1] / 1000;
                        break;
                case RF2:
-                       dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) -
-                                  (s32)(prog_cal[RF1] + prog_tab[RF1]);
+                       dividend = (prog_cal[RF2] - prog_tab[RF2] -
+                                   prog_cal[RF1] + prog_tab[RF1]);
                        divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000;
                        map[i].rf_a1 = (dividend / divisor);
                        map[i].rf2   = rf_freq[RF2] / 1000;
                        break;
                case RF3:
-                       dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) -
-                                  (s32)(prog_cal[RF2] + prog_tab[RF2]);
+                       dividend = (prog_cal[RF3] - prog_tab[RF3] -
+                                   prog_cal[RF2] + prog_tab[RF2]);
                        divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000;
                        map[i].rf_a2 = (dividend / divisor);
-                       map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]);
+                       map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]);
                        map[i].rf3   = rf_freq[RF3] / 1000;
                        break;
                default:
index e7f84c705da867f32ff7a3f663897b49c293c400..3d5b6ab7e3322630814036cf65654f545cc7e095 100644 (file)
@@ -229,8 +229,7 @@ static struct tda18271_map tda18271c2_km[] = {
 static struct tda18271_map tda18271_rf_band[] = {
        { .rfmax =  47900, .val = 0x00 },
        { .rfmax =  61100, .val = 0x01 },
-/*     { .rfmax = 152600, .val = 0x02 }, */
-       { .rfmax = 121200, .val = 0x02 },
+       { .rfmax = 152600, .val = 0x02 },
        { .rfmax = 164700, .val = 0x03 },
        { .rfmax = 203500, .val = 0x04 },
        { .rfmax = 457800, .val = 0x05 },
@@ -448,7 +447,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 150000, .val = 0xb0 },
        { .rfmax = 151000, .val = 0xb1 },
        { .rfmax = 152000, .val = 0xb7 },
-       { .rfmax = 153000, .val = 0xbd },
+       { .rfmax = 152600, .val = 0xbd },
        { .rfmax = 154000, .val = 0x20 },
        { .rfmax = 155000, .val = 0x22 },
        { .rfmax = 156000, .val = 0x24 },
@@ -459,7 +458,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 161000, .val = 0x2d },
        { .rfmax = 163000, .val = 0x2e },
        { .rfmax = 164000, .val = 0x2f },
-       { .rfmax = 165000, .val = 0x30 },
+       { .rfmax = 164700, .val = 0x30 },
        { .rfmax = 166000, .val = 0x11 },
        { .rfmax = 167000, .val = 0x12 },
        { .rfmax = 168000, .val = 0x13 },
@@ -510,7 +509,8 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 236000, .val = 0x1b },
        { .rfmax = 237000, .val = 0x1c },
        { .rfmax = 240000, .val = 0x1d },
-       { .rfmax = 242000, .val = 0x1f },
+       { .rfmax = 242000, .val = 0x1e },
+       { .rfmax = 244000, .val = 0x1f },
        { .rfmax = 247000, .val = 0x20 },
        { .rfmax = 249000, .val = 0x21 },
        { .rfmax = 252000, .val = 0x22 },
@@ -624,7 +624,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 453000, .val = 0x93 },
        { .rfmax = 454000, .val = 0x94 },
        { .rfmax = 456000, .val = 0x96 },
-       { .rfmax = 457000, .val = 0x98 },
+       { .rfmax = 457800, .val = 0x98 },
        { .rfmax = 461000, .val = 0x11 },
        { .rfmax = 468000, .val = 0x12 },
        { .rfmax = 472000, .val = 0x13 },
index 955254090a0e56fe3d7c42537f341802c6cfd2e4..03f96d6ca8946ecafc837295cee0bc41ec51b666 100644 (file)
@@ -38,7 +38,7 @@ MODULE_PARM_DESC(debug,
        DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_NAME "flexcop-pci"
 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 
 struct flexcop_pci {
index fe4f894183ffcf5bb65b85ab85b4ca0acc12473d..c545039287ad7b9b374696ddc01a2203dba22a85 100644 (file)
@@ -356,13 +356,15 @@ config DVB_USB_LME2510
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_STV0288 if !DVB_FE_CUSTOMISE
        select DVB_IX2505V if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
 
 config DVB_USB_TECHNISAT_USB2
        tristate "Technisat DVB-S/S2 USB2.0 support"
        depends on DVB_USB
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
+       select DVB_STV090x if !DVB_FE_CUSTOMISE
+       select DVB_STV6110x if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Technisat USB2 DVB-S/S2 device
index 97af266d7f1deb8543fe2343be238853e9e154be..65214af5cd741ddd6a5f18978350673339eab84c 100644 (file)
@@ -2162,7 +2162,7 @@ struct dibx000_agc_config dib7090_agc_config[2] = {
                .agc1_pt3       = 98,
                .agc1_slope1    = 0,
                .agc1_slope2    = 167,
-               .agc1_pt1       = 98,
+               .agc2_pt1       = 98,
                .agc2_pt2       = 255,
                .agc2_slope1    = 104,
                .agc2_slope2    = 0,
@@ -2440,11 +2440,11 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
        dib0700_set_i2c_speed(adap->dev, 340);
        adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
 
-       dib7090_slave_reset(adap->fe);
-
        if (adap->fe == NULL)
                return -ENODEV;
 
+       dib7090_slave_reset(adap->fe);
+
        return 0;
 }
 
index ccc2d1af49d4d65952d543d701d4096fa39666f9..6927c726ce35b4ec1c8139eb838e7822dded28da 100644 (file)
@@ -1520,6 +1520,7 @@ static int init_channel(struct ngene_channel *chan)
        if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
                dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
                set_transfer(chan, 1);
+               chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
                set_transfer(&chan->dev->channel[2], 1);
                dvb_register_device(adapter, &chan->ci_dev,
                                    &ngene_dvbdev_ci, (void *) chan,
index 23640ed44d8536a20b7c9ee56a572c704c3a0050..056138f63c7dc26d8d8b9757f2beb8b234b6209c 100644 (file)
@@ -378,7 +378,6 @@ EXPORT_SYMBOL_GPL(media_entity_create_link);
 
 static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
 {
-       const u32 mask = MEDIA_LNK_FL_ENABLED;
        int ret;
 
        /* Notify both entities. */
@@ -395,7 +394,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
                return ret;
        }
 
-       link->flags = (link->flags & ~mask) | (flags & mask);
+       link->flags = flags;
        link->reverse->flags = link->flags;
 
        return 0;
@@ -417,6 +416,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
  */
 int __media_entity_setup_link(struct media_link *link, u32 flags)
 {
+       const u32 mask = MEDIA_LNK_FL_ENABLED;
        struct media_device *mdev;
        struct media_entity *source, *sink;
        int ret = -EBUSY;
@@ -424,6 +424,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
        if (link == NULL)
                return -EINVAL;
 
+       /* The non-modifiable link flags must not be modified. */
+       if ((link->flags & ~mask) != (flags & ~mask))
+               return -EINVAL;
+
        if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
                return link->flags == flags ? 0 : -EINVAL;
 
index dc3f04c52d5e11e923829e74a548d78d1b3e6cad..87bad7678d92f63bab822d6e8a244a6d6729fd69 100644 (file)
@@ -170,7 +170,7 @@ static int fmr2_setfreq(struct fmr2 *dev)
        return 0;
 }
 
-/* !!! not tested, in my card this does't work !!! */
+/* !!! not tested, in my card this doesn't work !!! */
 static int fmr2_setvolume(struct fmr2 *dev)
 {
        int vol[16] = { 0x021, 0x084, 0x090, 0x104,
index 585680ffbfb64b121a4eb01eff27da0346660f6b..b1193dfc5087bb0ed2f5b24e09e9665107330c6f 100644 (file)
@@ -376,7 +376,7 @@ static int __devinit saa7706h_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%02x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 7c0d77751f6e66ba5d77a683fb1ba3890c0c4626..0991e1973678ce0751c455cb85249264935415fb 100644 (file)
@@ -176,7 +176,7 @@ static int __devinit tef6862_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%02x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        state->freq = TEF6862_LO_FREQ;
index ebd68edf5b245566338aebe8bc0d86ae0c836bab..8fc0f081b4701ddaf3c7ab0e79b7944f5fede297 100644 (file)
@@ -46,7 +46,7 @@
 #define MOD_AUTHOR     "Jarod Wilson <jarod@wilsonet.com>"
 #define MOD_DESC       "Driver for SoundGraph iMON MultiMedia IR/Display"
 #define MOD_NAME       "imon"
-#define MOD_VERSION    "0.9.2"
+#define MOD_VERSION    "0.9.3"
 
 #define DISPLAY_MINOR_BASE     144
 #define DEVICE_NAME    "lcd%d"
@@ -460,8 +460,9 @@ static int display_close(struct inode *inode, struct file *file)
 }
 
 /**
- * Sends a packet to the device -- this function must be called
- * with ictx->lock held.
+ * Sends a packet to the device -- this function must be called with
+ * ictx->lock held, or its unlock/lock sequence while waiting for tx
+ * to complete can/will lead to a deadlock.
  */
 static int send_packet(struct imon_context *ictx)
 {
@@ -991,12 +992,21 @@ static void imon_touch_display_timeout(unsigned long data)
  * the iMON remotes, and those used by the Windows MCE remotes (which is
  * really just RC-6), but only one or the other at a time, as the signals
  * are decoded onboard the receiver.
+ *
+ * This function gets called two different ways, one way is from
+ * rc_register_device, for initial protocol selection/setup, and the other is
+ * via a userspace-initiated protocol change request, either by direct sysfs
+ * prodding or by something like ir-keytable. In the rc_register_device case,
+ * the imon context lock is already held, but when initiated from userspace,
+ * it is not, so we must acquire it prior to calling send_packet, which
+ * requires that the lock is held.
  */
 static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
        int retval;
        struct imon_context *ictx = rc->priv;
        struct device *dev = ictx->dev;
+       bool unlock = false;
        unsigned char ir_proto_packet[] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
@@ -1029,6 +1039,11 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 
        memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
 
+       if (!mutex_is_locked(&ictx->lock)) {
+               unlock = true;
+               mutex_lock(&ictx->lock);
+       }
+
        retval = send_packet(ictx);
        if (retval)
                goto out;
@@ -1037,6 +1052,9 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        ictx->pad_mouse = false;
 
 out:
+       if (unlock)
+               mutex_unlock(&ictx->lock);
+
        return retval;
 }
 
@@ -2134,6 +2152,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
                goto rdev_setup_failed;
        }
 
+       mutex_unlock(&ictx->lock);
        return ictx;
 
 rdev_setup_failed:
@@ -2205,6 +2224,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
                goto urb_submit_failed;
        }
 
+       mutex_unlock(&ictx->lock);
        return ictx;
 
 urb_submit_failed:
@@ -2299,6 +2319,8 @@ static int __devinit imon_probe(struct usb_interface *interface,
        usb_set_intfdata(interface, ictx);
 
        if (ifnum == 0) {
+               mutex_lock(&ictx->lock);
+
                if (product == 0xffdc && ictx->rf_device) {
                        sysfs_err = sysfs_create_group(&interface->dev.kobj,
                                                       &imon_rf_attr_group);
@@ -2309,13 +2331,14 @@ static int __devinit imon_probe(struct usb_interface *interface,
 
                if (ictx->display_supported)
                        imon_init_display(ictx, interface);
+
+               mutex_unlock(&ictx->lock);
        }
 
        dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
                 "usb<%d:%d> initialized\n", vendor, product, ifnum,
                 usbdev->bus->busnum, usbdev->devnum);
 
-       mutex_unlock(&ictx->lock);
        mutex_unlock(&driver_lock);
 
        return 0;
index accaf6c9789a6bcae94157be03cd6240e15ad120..43908a70bd8b8df31e6965844883d68004328726 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/bitops.h>
index 044fb7a382d6bd888898cc889b78cdba15eeec90..0c273ec465c96142437ae4fe1272aee3a4e5f662 100644 (file)
@@ -220,6 +220,8 @@ static struct usb_device_id mceusb_dev_table[] = {
        { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
        /* Philips/Spinel plus IR transceiver for ASUS */
        { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
+       /* Philips IR transceiver (Dell branded) */
+       { USB_DEVICE(VENDOR_PHILIPS, 0x2093) },
        /* Realtek MCE IR Receiver and card reader */
        { USB_DEVICE(VENDOR_REALTEK, 0x0161),
          .driver_info = MULTIFUNCTION },
index f53f9c68d38dcddca8842a05e2e904b7174ae10a..a2706648e3651f30468310fcb9213bd7af7c4658 100644 (file)
@@ -707,7 +707,8 @@ static void ir_close(struct input_dev *idev)
 {
        struct rc_dev *rdev = input_get_drvdata(idev);
 
-       rdev->close(rdev);
+        if (rdev)
+               rdev->close(rdev);
 }
 
 /* class for /sys/class/rc */
@@ -733,6 +734,7 @@ static struct {
        { RC_TYPE_SONY,         "sony"          },
        { RC_TYPE_RC5_SZ,       "rc-5-sz"       },
        { RC_TYPE_LIRC,         "lirc"          },
+       { RC_TYPE_OTHER,        "other"         },
 };
 
 #define PROTO_NONE     "none"
index 4498b944dec81d8af9e9ae7a30370bde671bcce2..00f51dd121f3c3f029431af9fdf9cc0d4a421c60 100644 (file)
@@ -875,7 +875,7 @@ config MX3_VIDEO
 config VIDEO_MX3
        tristate "i.MX3x Camera Sensor Interface driver"
        depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
-       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF2_DMA_CONTIG
        select MX3_VIDEO
        ---help---
          This is a v4l2 driver for the i.MX3x Camera Sensor Interface
index c6e2ca3b1149ad37305a04dc40befac5b0ef8996..6fbc356113c18077352876da72ef0a93dbc3abdc 100644 (file)
@@ -350,9 +350,17 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
 
                /* No struct video_device, but can have buffers allocated */
                if (type == CX18_ENC_STREAM_TYPE_IDX) {
+                       /* If the module params didn't inhibit IDX ... */
                        if (cx->stream_buffers[type] != 0) {
                                cx->stream_buffers[type] = 0;
-                               cx18_stream_free(&cx->streams[type]);
+                               /*
+                                * Before calling cx18_stream_free(),
+                                * check if the IDX stream was actually set up.
+                                * Needed, since the cx18_probe() error path
+                                * exits through here as well as normal clean up
+                                */
+                               if (cx->streams[type].buffers != 0)
+                                       cx18_stream_free(&cx->streams[type]);
                        }
                        continue;
                }
index 3b6e7f28568e41164613d204c71fcea8ea05c19c..caab1bfb79e2b8d0cf943c83cf31c955fa191f06 100644 (file)
@@ -22,6 +22,7 @@ config VIDEO_CX23885
        select DVB_CX24116 if !DVB_FE_CUSTOMISE
        select DVB_STV0900 if !DVB_FE_CUSTOMISE
        select DVB_DS3000 if !DVB_FE_CUSTOMISE
+       select DVB_STV0367 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
index c820e2f53527333b6fe7a42961776deadb15c45a..3f442003623d30494cf63632355bd35e174cc97c 100644 (file)
@@ -524,7 +524,7 @@ void cx88_ir_irq(struct cx88_core *core)
        for (todo = 32; todo > 0; todo -= bits) {
                ev.pulse = samples & 0x80000000 ? false : true;
                bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
-               ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
+               ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
                ir_raw_event_store_with_filter(ir->dev, &ev);
                samples <<= bits;
        }
index 1a116911571629f3942436c7a407a2512a06870b..0382ea752e6fb0015119b5a30656f5e34d59ad41 100644 (file)
@@ -298,7 +298,7 @@ static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
 static int imx074_set_bus_param(struct soc_camera_device *icd,
                                 unsigned long flags)
 {
-       return -1;
+       return -EINVAL;
 }
 
 static struct soc_camera_ops imx074_ops = {
index 5e1c9a81984ca837955d2f67a895e5265bb37e6a..303ffa7df4aca521c617ed1629678deb91ea3606 100644 (file)
@@ -174,7 +174,7 @@ static int m52790_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
 
index 503bd7922bd6bcc8473bab58625506f56a082f35..472a69359e609c16c67b014da479e7bbeb2c29ed 100644 (file)
@@ -215,20 +215,21 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
        }
 
        switch (xclksel) {
-       case 0:
+       case ISP_XCLK_A:
                isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
                                ISPTCTRL_CTRL_DIVA_MASK,
                                divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
                dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
                        currentxclk);
                break;
-       case 1:
+       case ISP_XCLK_B:
                isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
                                ISPTCTRL_CTRL_DIVB_MASK,
                                divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
                dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
                        currentxclk);
                break;
+       case ISP_XCLK_NONE:
        default:
                omap3isp_put(isp);
                dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
@@ -237,13 +238,13 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
        }
 
        /* Do we go from stable whatever to clock? */
-       if (divisor >= 2 && isp->xclk_divisor[xclksel] < 2)
+       if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
                omap3isp_get(isp);
        /* Stopping the clock. */
-       else if (divisor < 2 && isp->xclk_divisor[xclksel] >= 2)
+       else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
                omap3isp_put(isp);
 
-       isp->xclk_divisor[xclksel] = divisor;
+       isp->xclk_divisor[xclksel - 1] = divisor;
 
        omap3isp_put(isp);
 
@@ -285,7 +286,8 @@ static void isp_power_settings(struct isp_device *isp, int idle)
  */
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata)
+                              const struct isp_parallel_platform_data *pdata,
+                              unsigned int shift)
 {
        u32 ispctrl_val;
 
@@ -298,9 +300,9 @@ void omap3isp_configure_bridge(struct isp_device *isp,
        switch (input) {
        case CCDC_INPUT_PARALLEL:
                ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
-               ispctrl_val |= pdata->data_lane_shift << ISPCTRL_SHIFT_SHIFT;
                ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
                ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
+               shift += pdata->data_lane_shift * 2;
                break;
 
        case CCDC_INPUT_CSI2A:
@@ -319,6 +321,8 @@ void omap3isp_configure_bridge(struct isp_device *isp,
                return;
        }
 
+       ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
+
        ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
        ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
 
@@ -658,6 +662,8 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
 
        /* Apply power change to connected non-nodes. */
        ret = isp_pipeline_pm_power(entity, change);
+       if (ret < 0)
+               entity->use_count -= change;
 
        mutex_unlock(&entity->parent->graph_mutex);
 
@@ -872,6 +878,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
                }
        }
 
+       if (failure < 0)
+               isp->needs_reset = true;
+
        return failure;
 }
 
@@ -884,7 +893,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
  * single-shot or continuous mode.
  *
  * Return 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
  */
 int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                                 enum isp_pipeline_stream_state state)
@@ -895,7 +905,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                ret = isp_pipeline_disable(pipe);
        else
                ret = isp_pipeline_enable(pipe, state);
-       pipe->stream_state = state;
+
+       if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
+               pipe->stream_state = state;
 
        return ret;
 }
@@ -1481,6 +1493,10 @@ void omap3isp_put(struct isp_device *isp)
        if (--isp->ref_count == 0) {
                isp_disable_interrupts(isp);
                isp_save_ctx(isp);
+               if (isp->needs_reset) {
+                       isp_reset(isp);
+                       isp->needs_reset = false;
+               }
                isp_disable_clocks(isp);
        }
        mutex_unlock(&isp->isp_mutex);
index cf5214e95a920ca11bc1cea5bac2c6efede31fbf..2620c405f5e42cf0f37d7d724535b7e3593f6a1c 100644 (file)
@@ -132,7 +132,6 @@ struct isp_reg {
 
 /**
  * struct isp_parallel_platform_data - Parallel interface platform data
- * @width: Parallel bus width in bits (8, 10, 11 or 12)
  * @data_lane_shift: Data lane shifter
  *             0 - CAMEXT[13:0] -> CAM[13:0]
  *             1 - CAMEXT[13:2] -> CAM[11:0]
@@ -146,7 +145,6 @@ struct isp_reg {
  *             ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
  */
 struct isp_parallel_platform_data {
-       unsigned int width;
        unsigned int data_lane_shift:2;
        unsigned int clk_pol:1;
        unsigned int bridge:4;
@@ -262,6 +260,7 @@ struct isp_device {
        /* ISP Obj */
        spinlock_t stat_lock;   /* common lock for statistic drivers */
        struct mutex isp_mutex; /* For handling ref_count field */
+       bool needs_reset;
        int has_context;
        int ref_count;
        unsigned int autoidle;
@@ -311,11 +310,12 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                                 enum isp_pipeline_stream_state state);
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata);
+                              const struct isp_parallel_platform_data *pdata,
+                              unsigned int shift);
 
-#define ISP_XCLK_NONE                  -1
-#define ISP_XCLK_A                     0
-#define ISP_XCLK_B                     1
+#define ISP_XCLK_NONE                  0
+#define ISP_XCLK_A                     1
+#define ISP_XCLK_B                     2
 
 struct isp_device *omap3isp_get(struct isp_device *isp);
 void omap3isp_put(struct isp_device *isp);
index 5ff9d14ce71099cc672e71e2bd1d7ca619bbcc98..39d501bda6362c485468dcc714b1a7fe3375dd8c 100644 (file)
@@ -43,6 +43,12 @@ __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
 
 static const unsigned int ccdc_fmts[] = {
        V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_Y10_1X10,
+       V4L2_MBUS_FMT_Y12_1X12,
+       V4L2_MBUS_FMT_SGRBG8_1X8,
+       V4L2_MBUS_FMT_SRGGB8_1X8,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+       V4L2_MBUS_FMT_SGBRG8_1X8,
        V4L2_MBUS_FMT_SGRBG10_1X10,
        V4L2_MBUS_FMT_SRGGB10_1X10,
        V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -1110,21 +1116,38 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        struct isp_parallel_platform_data *pdata = NULL;
        struct v4l2_subdev *sensor;
        struct v4l2_mbus_framefmt *format;
+       const struct isp_format_info *fmt_info;
+       struct v4l2_subdev_format fmt_src;
+       unsigned int depth_out;
+       unsigned int depth_in = 0;
        struct media_pad *pad;
        unsigned long flags;
+       unsigned int shift;
        u32 syn_mode;
        u32 ccdc_pattern;
 
-       if (ccdc->input == CCDC_INPUT_PARALLEL) {
-               pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
-               sensor = media_entity_to_v4l2_subdev(pad->entity);
+       pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
+       sensor = media_entity_to_v4l2_subdev(pad->entity);
+       if (ccdc->input == CCDC_INPUT_PARALLEL)
                pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
                        ->bus.parallel;
+
+       /* Compute shift value for lane shifter to configure the bridge. */
+       fmt_src.pad = pad->index;
+       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
+               fmt_info = omap3isp_video_format_info(fmt_src.format.code);
+               depth_in = fmt_info->bpp;
        }
 
-       omap3isp_configure_bridge(isp, ccdc->input, pdata);
+       fmt_info = omap3isp_video_format_info
+               (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
+       depth_out = fmt_info->bpp;
+
+       shift = depth_in - depth_out;
+       omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
 
-       ccdc->syncif.datsz = pdata ? pdata->width : 10;
+       ccdc->syncif.datsz = depth_out;
        ccdc_config_sync_if(ccdc, &ccdc->syncif);
 
        /* CCDC_PAD_SINK */
@@ -1338,7 +1361,7 @@ static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
  * @ccdc: Pointer to ISP CCDC device.
  * @event: Pointing which event trigger handler
  *
- * Return 1 when the event and stopping request combination is satisfyied,
+ * Return 1 when the event and stopping request combination is satisfied,
  * zero otherwise.
  */
 static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
@@ -1618,7 +1641,7 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
 
        ccdc_set_outaddr(ccdc, buffer->isp_addr);
 
-       /* We now have a buffer queued on the output, restart the pipeline in
+       /* We now have a buffer queued on the output, restart the pipeline
         * on the next CCDC interrupt if running in continuous mode (or when
         * starting the stream).
         */
index 2b16988a501d563ba15cfc17cb4f02987e3d3c4f..aba537af87e43fec1109c5d2dfada0ac88464eca 100644 (file)
@@ -755,7 +755,7 @@ static struct preview_update update_attrs[] = {
  * @configs - pointer to update config structure.
  * @config - return pointer to appropriate structure field.
  * @bit - for which feature to return pointers.
- * Return size of coresponding prev_params member
+ * Return size of corresponding prev_params member
  */
 static u32
 __preview_get_ptrs(struct prev_params *params, void **param,
index 8fddc5806b0d81365d67a8ee0c9195cc2b3d4262..9c317148205f82a73cb774607ca0a2ea412d2ea6 100644 (file)
@@ -339,7 +339,7 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
        up_read(&current->mm->mmap_sem);
 
        if (ret != buf->npages) {
-               buf->npages = ret;
+               buf->npages = ret < 0 ? 0 : ret;
                isp_video_buffer_cleanup(buf);
                return -EFAULT;
        }
@@ -408,8 +408,8 @@ done:
  * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
  *
  * This function locates the VMAs for the buffer's userspace address and checks
- * that their flags match. The onlflag that we need to care for at the moment is
- * VM_PFNMAP.
+ * that their flags match. The only flag that we need to care for at the moment
+ * is VM_PFNMAP.
  *
  * The buffer vm_flags field is set to the first VMA flags.
  *
index 653f88ba56db85f9deb786f1512ea3db200490b5..0bb0f8cd36f51c312979719b1515b8b52f029929 100644 (file)
@@ -714,19 +714,50 @@ static void resizer_print_status(struct isp_res_device *res)
  * iw and ih are the input width and height after cropping. Those equations need
  * to be satisfied exactly for the resizer to work correctly.
  *
- * Reverting the equations, we can compute the resizing ratios with
+ * The equations can't be easily reverted, as the >> 8 operation is not linear.
+ * In addition, not all input sizes can be achieved for a given output size. To
+ * get the highest input size lower than or equal to the requested input size,
+ * we need to compute the highest resizing ratio that satisfies the following
+ * inequality (taking the 4-tap mode width equation as an example)
+ *
+ *     iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
+ *
+ * (where iw is the requested input width) which can be rewritten as
+ *
+ *       iw - 7            >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
+ *      (iw - 7) << 8      >=  32 * sph + (ow - 1) * hrsz + 16 - b
+ *     ((iw - 7) << 8) + b >=  32 * sph + (ow - 1) * hrsz + 16
+ *
+ * where b is the value of the 8 least significant bits of the right hand side
+ * expression of the last inequality. The highest resizing ratio value will be
+ * achieved when b is equal to its maximum value of 255. That resizing ratio
+ * value will still satisfy the original inequality, as b will disappear when
+ * the expression will be shifted right by 8.
+ *
+ * The reverted the equations thus become
  *
  * - 8-phase, 4-tap mode
- *     hrsz = ((iw - 7) * 256 - 16 - 32 * sph) / (ow - 1)
- *     vrsz = ((ih - 4) * 256 - 16 - 32 * spv) / (oh - 1)
+ *     hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
+ *     vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
  * - 4-phase, 7-tap mode
- *     hrsz = ((iw - 7) * 256 - 32 - 64 * sph) / (ow - 1)
- *     vrsz = ((ih - 7) * 256 - 32 - 64 * spv) / (oh - 1)
+ *     hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
+ *     vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
  *
- * The ratios are integer values, and must be rounded down to ensure that the
- * cropped input size is not bigger than the uncropped input size. As the ratio
- * in 7-tap mode is always smaller than the ratio in 4-tap mode, we can use the
- * 7-tap mode equations to compute a ratio approximation.
+ * The ratios are integer values, and are rounded down to ensure that the
+ * cropped input size is not bigger than the uncropped input size.
+ *
+ * As the number of phases/taps, used to select the correct equations to compute
+ * the ratio, depends on the ratio, we start with the 4-tap mode equations to
+ * compute an approximation of the ratio, and switch to the 7-tap mode equations
+ * if the approximation is higher than the ratio threshold.
+ *
+ * As the 7-tap mode equations will return a ratio smaller than or equal to the
+ * 4-tap mode equations, the resulting ratio could become lower than or equal to
+ * the ratio threshold. This 'equations loop' isn't an issue as long as the
+ * correct equations are used to compute the final input size. Starting with the
+ * 4-tap mode equations ensure that, in case of values resulting in a 'ratio
+ * loop', the smallest of the ratio values will be used, never exceeding the
+ * requested input size.
  *
  * We first clamp the output size according to the hardware capabilitie to avoid
  * auto-cropping the input more than required to satisfy the TRM equations. The
@@ -775,6 +806,8 @@ static void resizer_calc_ratios(struct isp_res_device *res,
        unsigned int max_width;
        unsigned int max_height;
        unsigned int width_alignment;
+       unsigned int width;
+       unsigned int height;
 
        /*
         * Clamp the output height based on the hardware capabilities and
@@ -786,19 +819,22 @@ static void resizer_calc_ratios(struct isp_res_device *res,
        max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
        output->height = clamp(output->height, min_height, max_height);
 
-       ratio->vert = ((input->height - 7) * 256 - 32 - 64 * spv)
+       ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
                    / (output->height - 1);
+       if (ratio->vert > MID_RESIZE_VALUE)
+               ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
+                           / (output->height - 1);
        ratio->vert = clamp_t(unsigned int, ratio->vert,
                              MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
 
        if (ratio->vert <= MID_RESIZE_VALUE) {
                upscaled_height = (output->height - 1) * ratio->vert
                                + 32 * spv + 16;
-               input->height = (upscaled_height >> 8) + 4;
+               height = (upscaled_height >> 8) + 4;
        } else {
                upscaled_height = (output->height - 1) * ratio->vert
                                + 64 * spv + 32;
-               input->height = (upscaled_height >> 8) + 7;
+               height = (upscaled_height >> 8) + 7;
        }
 
        /*
@@ -854,20 +890,29 @@ static void resizer_calc_ratios(struct isp_res_device *res,
                              max_width & ~(width_alignment - 1));
        output->width = ALIGN(output->width, width_alignment);
 
-       ratio->horz = ((input->width - 7) * 256 - 32 - 64 * sph)
+       ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
                    / (output->width - 1);
+       if (ratio->horz > MID_RESIZE_VALUE)
+               ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
+                           / (output->width - 1);
        ratio->horz = clamp_t(unsigned int, ratio->horz,
                              MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
 
        if (ratio->horz <= MID_RESIZE_VALUE) {
                upscaled_width = (output->width - 1) * ratio->horz
                               + 32 * sph + 16;
-               input->width = (upscaled_width >> 8) + 7;
+               width = (upscaled_width >> 8) + 7;
        } else {
                upscaled_width = (output->width - 1) * ratio->horz
                               + 64 * sph + 32;
-               input->width = (upscaled_width >> 8) + 7;
+               width = (upscaled_width >> 8) + 7;
        }
+
+       /* Center the new crop rectangle. */
+       input->left += (input->width - width) / 2;
+       input->top += (input->height - height) / 2;
+       input->width = width;
+       input->height = height;
 }
 
 /*
index 820950c9ef464d0f9f0b419f14d89549c33e63eb..d86da94fa50dcb292e7c4899de498767ad954237 100644 (file)
@@ -131,9 +131,9 @@ struct ispstat {
 struct ispstat_generic_config {
        /*
         * Fields must be in the same order as in:
-        *  - isph3a_aewb_config
-        *  - isph3a_af_config
-        *  - isphist_config
+        *  - omap3isp_h3a_aewb_config
+        *  - omap3isp_h3a_af_config
+        *  - omap3isp_hist_config
         */
        u32 buf_size;
        u16 config_counter;
index 208a7ec739d711d11d2330b9af1e06cc36086006..9cd8f1aa567b9ce2f094b00a4d42f7c6132dd92c 100644 (file)
 
 static struct isp_format_info formats[] = {
        { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
-         V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
+         V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_GREY, 8, },
+       { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y10, 10, },
+       { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y12, 12, },
+       { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR8, 8, },
+       { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG8, 8, },
+       { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG8, 8, },
+       { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB8, 8, },
        { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
-         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+         V4L2_MBUS_FMT_SGRBG10_1X10, 0,
+         V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
        { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
-         V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
+         V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR10, 10, },
        { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
-         V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
+         V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG10, 10, },
        { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
-         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
+         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG10, 10, },
        { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
-         V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
+         V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB10, 10, },
        { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
-         V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
+         V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR12, 12, },
        { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
-         V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
+         V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG12, 12, },
        { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
-         V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
+         V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG12, 12, },
        { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
-         V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
+         V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB12, 12, },
        { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
-         V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
+         V4L2_MBUS_FMT_UYVY8_1X16, 0,
+         V4L2_PIX_FMT_UYVY, 16, },
        { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
-         V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
+         V4L2_MBUS_FMT_YUYV8_1X16, 0,
+         V4L2_PIX_FMT_YUYV, 16, },
 };
 
 const struct isp_format_info *
@@ -85,6 +115,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
        return NULL;
 }
 
+/*
+ * Decide whether desired output pixel code can be obtained with
+ * the lane shifter by shifting the input pixel code.
+ * @in: input pixelcode to shifter
+ * @out: output pixelcode from shifter
+ * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
+ *
+ * return true if the combination is possible
+ * return false otherwise
+ */
+static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
+               enum v4l2_mbus_pixelcode out,
+               unsigned int additional_shift)
+{
+       const struct isp_format_info *in_info, *out_info;
+
+       if (in == out)
+               return true;
+
+       in_info = omap3isp_video_format_info(in);
+       out_info = omap3isp_video_format_info(out);
+
+       if ((in_info->flavor == 0) || (out_info->flavor == 0))
+               return false;
+
+       if (in_info->flavor != out_info->flavor)
+               return false;
+
+       return in_info->bpp - out_info->bpp + additional_shift <= 6;
+}
+
 /*
  * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
  * @video: ISP video instance
@@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                return -EPIPE;
 
        while (1) {
+               unsigned int shifter_link;
                /* Retrieve the sink format */
                pad = &subdev->entity.pads[0];
                if (!(pad->flags & MEDIA_PAD_FL_SINK))
@@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                                return -ENOSPC;
                }
 
+               /* If sink pad is on CCDC, the link has the lane shifter
+                * in the middle of it. */
+               shifter_link = subdev == &isp->isp_ccdc.subdev;
+
                /* Retrieve the source format */
                pad = media_entity_remote_source(pad);
                if (pad == NULL ||
@@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                        return -EPIPE;
 
                /* Check if the two ends match */
-               if (fmt_source.format.code != fmt_sink.format.code ||
-                   fmt_source.format.width != fmt_sink.format.width ||
+               if (fmt_source.format.width != fmt_sink.format.width ||
                    fmt_source.format.height != fmt_sink.format.height)
                        return -EPIPE;
+
+               if (shifter_link) {
+                       unsigned int parallel_shift = 0;
+                       if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
+                               struct isp_parallel_platform_data *pdata =
+                                       &((struct isp_v4l2_subdevs_group *)
+                                             subdev->host_priv)->bus.parallel;
+                               parallel_shift = pdata->data_lane_shift * 2;
+                       }
+                       if (!isp_video_is_shiftable(fmt_source.format.code,
+                                               fmt_sink.format.code,
+                                               parallel_shift))
+                               return -EPIPE;
+               } else if (fmt_source.format.code != fmt_sink.format.code)
+                       return -EPIPE;
        }
 
        return 0;
index 524a1acd0906db272119820bf4c911324f2e426f..911bea64e78a318deded72ceac1701e1b55e8b6b 100644 (file)
@@ -49,6 +49,8 @@ struct v4l2_pix_format;
  *     bits. Identical to @code if the format is 10 bits wide or less.
  * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
  *     format. Identical to @code if the format is not DPCM compressed.
+ * @flavor: V4L2 media bus format code for the same pixel layout but
+ *     shifted to be 8 bits per pixel. =0 if format is not shiftable.
  * @pixelformat: V4L2 pixel format FCC identifier
  * @bpp: Bits per pixel
  */
@@ -56,6 +58,7 @@ struct isp_format_info {
        enum v4l2_mbus_pixelcode code;
        enum v4l2_mbus_pixelcode truncated;
        enum v4l2_mbus_pixelcode uncompressed;
+       enum v4l2_mbus_pixelcode flavor;
        u32 pixelformat;
        unsigned int bpp;
 };
index 95f8b4e11e46f71773b9f8f2556a06be094e9510..d142b40ea64efd1135dbfc242b5fd7d4c7092697 100644 (file)
@@ -527,7 +527,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
        if (ret)
                return ret;
 
-       if (vb2_is_streaming(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
+       if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
                return -EBUSY;
 
        frame = &ctx->d_frame;
@@ -539,8 +539,10 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       for (i = 0; i < frame->fmt->colplanes; i++)
-               frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+       for (i = 0; i < frame->fmt->colplanes; i++) {
+               frame->payload[i] =
+                       (pix->width * pix->height * frame->fmt->depth[i]) >> 3;
+       }
 
        /* Output DMA frame pixel size and offsets. */
        frame->f_width = pix->plane_fmt[0].bytesperline * 8
index 6c919b38a3d89c17c33d4cd5d4beee2252f23929..dc91a8511af66ca1bb0f898a68dba0ac4c873257 100644 (file)
@@ -361,10 +361,20 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
 {
        struct fimc_vid_cap *cap = &fimc->vid_cap;
        struct fimc_vid_buffer *v_buf;
+       struct timeval *tv;
+       struct timespec ts;
 
        if (!list_empty(&cap->active_buf_q) &&
            test_bit(ST_CAPT_RUN, &fimc->state)) {
+               ktime_get_real_ts(&ts);
+
                v_buf = active_queue_pop(cap);
+
+               tv = &v_buf->vb.v4l2_buf.timestamp;
+               tv->tv_sec = ts.tv_sec;
+               tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+               v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
+
                vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
        }
 
@@ -758,7 +768,7 @@ static void fimc_unlock(struct vb2_queue *vq)
        mutex_unlock(&ctx->fimc_dev->lock);
 }
 
-struct vb2_ops fimc_qops = {
+static struct vb2_ops fimc_qops = {
        .queue_setup     = fimc_queue_setup,
        .buf_prepare     = fimc_buf_prepare,
        .buf_queue       = fimc_buf_queue,
@@ -927,23 +937,23 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
        pix->num_planes = fmt->memplanes;
        pix->colorspace = V4L2_COLORSPACE_JPEG;
 
-       for (i = 0; i < pix->num_planes; ++i) {
-               int bpl = pix->plane_fmt[i].bytesperline;
 
-               dbg("[%d] bpl: %d, depth: %d, w: %d, h: %d",
-                   i, bpl, fmt->depth[i], pix->width, pix->height);
+       for (i = 0; i < pix->num_planes; ++i) {
+               u32 bpl = pix->plane_fmt[i].bytesperline;
+               u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
 
-               if (!bpl || (bpl * 8 / fmt->depth[i]) > pix->width)
-                       bpl = (pix->width * fmt->depth[0]) >> 3;
+               if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+                       bpl = pix->width; /* Planar */
 
-               if (!pix->plane_fmt[i].sizeimage)
-                       pix->plane_fmt[i].sizeimage = pix->height * bpl;
+               if (fmt->colplanes == 1 && /* Packed */
+                   (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
+                       bpl = (pix->width * fmt->depth[0]) / 8;
 
-               pix->plane_fmt[i].bytesperline = bpl;
+               if (i == 0) /* Same bytesperline for each plane. */
+                       mod_x = bpl;
 
-               dbg("[%d]: bpl: %d, sizeimage: %d",
-                   i, pix->plane_fmt[i].bytesperline,
-                   pix->plane_fmt[i].sizeimage);
+               pix->plane_fmt[i].bytesperline = mod_x;
+               *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
        }
 
        return 0;
@@ -965,7 +975,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
 
        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 
-       if (vb2_is_streaming(vq)) {
+       if (vb2_is_busy(vq)) {
                v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
                return -EBUSY;
        }
@@ -985,8 +995,10 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
        if (!frame->fmt)
                return -EINVAL;
 
-       for (i = 0; i < frame->fmt->colplanes; i++)
-               frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+       for (i = 0; i < frame->fmt->colplanes; i++) {
+               frame->payload[i] =
+                       (pix->width * pix->height * frame->fmt->depth[i]) / 8;
+       }
 
        frame->f_width  = pix->plane_fmt[0].bytesperline * 8 /
                frame->fmt->depth[0];
@@ -1750,7 +1762,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
 }
 
 /* Image pixel limits, similar across several FIMC HW revisions. */
-static struct fimc_pix_limit s5p_pix_limit[3] = {
+static struct fimc_pix_limit s5p_pix_limit[4] = {
        [0] = {
                .scaler_en_w    = 3264,
                .scaler_dis_w   = 8192,
@@ -1775,6 +1787,14 @@ static struct fimc_pix_limit s5p_pix_limit[3] = {
                .out_rot_en_w   = 1280,
                .out_rot_dis_w  = 1920,
        },
+       [3] = {
+               .scaler_en_w    = 1920,
+               .scaler_dis_w   = 8192,
+               .in_rot_en_h    = 1366,
+               .in_rot_dis_w   = 8192,
+               .out_rot_en_w   = 1366,
+               .out_rot_dis_w  = 1920,
+       },
 };
 
 static struct samsung_fimc_variant fimc0_variant_s5p = {
@@ -1827,7 +1847,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
        .pix_limit       = &s5p_pix_limit[2],
 };
 
-static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc0_variant_exynos4 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
@@ -1840,7 +1860,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
        .pix_limit       = &s5p_pix_limit[1],
 };
 
-static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc2_variant_exynos4 = {
        .pix_hoff        = 1,
        .has_cistatus2   = 1,
        .has_mainscaler_ext = 1,
@@ -1848,7 +1868,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
        .out_buf_count   = 32,
-       .pix_limit       = &s5p_pix_limit[2],
+       .pix_limit       = &s5p_pix_limit[3],
 };
 
 /* S5PC100 */
@@ -1874,12 +1894,12 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
 };
 
 /* S5PV310, S5PC210 */
-static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
+static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
        .variant = {
-               [0] = &fimc0_variant_s5pv310,
-               [1] = &fimc0_variant_s5pv310,
-               [2] = &fimc0_variant_s5pv310,
-               [3] = &fimc2_variant_s5pv310,
+               [0] = &fimc0_variant_exynos4,
+               [1] = &fimc0_variant_exynos4,
+               [2] = &fimc0_variant_exynos4,
+               [3] = &fimc2_variant_exynos4,
        },
        .num_entities = 4,
        .lclk_frequency = 166000000UL,
@@ -1893,8 +1913,8 @@ static struct platform_device_id fimc_driver_ids[] = {
                .name           = "s5pv210-fimc",
                .driver_data    = (unsigned long)&fimc_drvdata_s5pv210,
        }, {
-               .name           = "s5pv310-fimc",
-               .driver_data    = (unsigned long)&fimc_drvdata_s5pv310,
+               .name           = "exynos4-fimc",
+               .driver_data    = (unsigned long)&fimc_drvdata_exynos4,
        },
        {},
 };
index 3fe54bf41142d025437859ea71dbd0765bc67d0c..134e86bf6d9750e3c1f2db2685fc10d91c4a32d9 100644 (file)
@@ -922,7 +922,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                        /* Try 2560x1920, 1280x960, 640x480, 320x240 */
                        mf.width        = 2560 >> shift;
                        mf.height       = 1920 >> shift;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+                       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                         s_mbus_fmt, &mf);
                        if (ret < 0)
                                return ret;
@@ -1224,7 +1224,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
        struct v4l2_cropcap cap;
        int ret;
 
-       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                         s_mbus_fmt, mf);
        if (ret < 0)
                return ret;
@@ -1254,7 +1254,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
                tmp_h = min(2 * tmp_h, max_height);
                mf->width = tmp_w;
                mf->height = tmp_h;
-               ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+               ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                 s_mbus_fmt, mf);
                dev_geo(dev, "Camera scaled to %ux%u\n",
                        mf->width, mf->height);
@@ -1658,7 +1658,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
        mf.code         = xlate->code;
        mf.colorspace   = pix->colorspace;
 
-       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf);
+       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
        if (ret < 0)
                return ret;
 
@@ -1682,7 +1682,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
                         */
                        mf.width = 2560;
                        mf.height = 1920;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+                       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                         try_mbus_fmt, &mf);
                        if (ret < 0) {
                                /* Shouldn't actually happen... */
index dd1b81b1442bcbaa194f9f4830140e184a3d84af..98b87481fa94ba232e586323ebd3bb912abf11d5 100644 (file)
@@ -38,6 +38,8 @@ struct sh_csi2 {
        void __iomem                    *base;
        struct platform_device          *pdev;
        struct sh_csi2_client_config    *client;
+       unsigned long (*query_bus_param)(struct soc_camera_device *);
+       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
 };
 
 static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
@@ -208,6 +210,7 @@ static int sh_csi2_notify(struct notifier_block *nb,
        case BUS_NOTIFY_BOUND_DRIVER:
                snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
                         dev_name(v4l2_dev->dev), ".mipi-csi");
+               priv->subdev.grp_id = (long)icd;
                ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
                dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
                if (ret < 0)
@@ -215,6 +218,8 @@ static int sh_csi2_notify(struct notifier_block *nb,
 
                priv->client = pdata->clients + i;
 
+               priv->set_bus_param             = icd->ops->set_bus_param;
+               priv->query_bus_param           = icd->ops->query_bus_param;
                icd->ops->set_bus_param         = sh_csi2_set_bus_param;
                icd->ops->query_bus_param       = sh_csi2_query_bus_param;
 
@@ -226,8 +231,10 @@ static int sh_csi2_notify(struct notifier_block *nb,
                priv->client = NULL;
 
                /* Driver is about to be unbound */
-               icd->ops->set_bus_param         = NULL;
-               icd->ops->query_bus_param       = NULL;
+               icd->ops->set_bus_param         = priv->set_bus_param;
+               icd->ops->query_bus_param       = priv->query_bus_param;
+               priv->set_bus_param             = NULL;
+               priv->query_bus_param           = NULL;
 
                v4l2_device_unregister_subdev(&priv->subdev);
 
index 46284489e4eb8b89e96e354e4defca8bd1710ebd..ddb4c091dedc6b6740c013251524829c40fc6d5e 100644 (file)
@@ -136,11 +136,50 @@ unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
 }
 EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
 
+#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
+       ((x) >> 24) & 0xff
+
+static int soc_camera_try_fmt(struct soc_camera_device *icd,
+                             struct v4l2_format *f)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       int ret;
+
+       dev_dbg(&icd->dev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
+               pixfmtstr(pix->pixelformat), pix->width, pix->height);
+
+       pix->bytesperline = 0;
+       pix->sizeimage = 0;
+
+       ret = ici->ops->try_fmt(icd, f);
+       if (ret < 0)
+               return ret;
+
+       if (!pix->sizeimage) {
+               if (!pix->bytesperline) {
+                       const struct soc_camera_format_xlate *xlate;
+
+                       xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+                       if (!xlate)
+                               return -EINVAL;
+
+                       ret = soc_mbus_bytes_per_line(pix->width,
+                                                     xlate->host_fmt);
+                       if (ret > 0)
+                               pix->bytesperline = ret;
+               }
+               if (pix->bytesperline)
+                       pix->sizeimage = pix->bytesperline * pix->height;
+       }
+
+       return 0;
+}
+
 static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
                                      struct v4l2_format *f)
 {
        struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -149,7 +188,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
                return -EINVAL;
 
        /* limit format to hardware capabilities */
-       return ici->ops->try_fmt(icd, f);
+       return soc_camera_try_fmt(icd, f);
 }
 
 static int soc_camera_enum_input(struct file *file, void *priv,
@@ -362,9 +401,6 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
        icd->user_formats = NULL;
 }
 
-#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
-       ((x) >> 24) & 0xff
-
 /* Called with .vb_lock held, or from the first open(2), see comment there */
 static int soc_camera_set_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
@@ -377,7 +413,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
                pixfmtstr(pix->pixelformat), pix->width, pix->height);
 
        /* We always call try_fmt() before set_fmt() or set_crop() */
-       ret = ici->ops->try_fmt(icd, f);
+       ret = soc_camera_try_fmt(icd, f);
        if (ret < 0)
                return ret;
 
@@ -996,10 +1032,11 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
 {
        struct i2c_client *client =
                to_i2c_client(to_soc_camera_control(icd));
+       struct i2c_adapter *adap = client->adapter;
        dev_set_drvdata(&icd->dev, NULL);
        v4l2_device_unregister_subdev(i2c_get_clientdata(client));
        i2c_unregister_device(client);
-       i2c_put_adapter(client->adapter);
+       i2c_put_adapter(adap);
 }
 #else
 #define soc_camera_init_i2c(icd, icl)  (-ENODEV)
@@ -1071,6 +1108,9 @@ static int soc_camera_probe(struct device *dev)
                }
        }
 
+       sd = soc_camera_to_subdev(icd);
+       sd->grp_id = (long)icd;
+
        /* At this point client .probe() should have run already */
        ret = soc_camera_init_user_formats(icd);
        if (ret < 0)
@@ -1092,7 +1132,6 @@ static int soc_camera_probe(struct device *dev)
                goto evidstart;
 
        /* Try to improve our guess of a reasonable window format */
-       sd = soc_camera_to_subdev(icd);
        if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
                icd->user_width         = mf.width;
                icd->user_height        = mf.height;
index 5d4cf3b3d435076a2f8db0ff102aa1815894bbea..22fa8202d5ca314466c4c11d8f13c877777db454 100644 (file)
@@ -171,7 +171,7 @@ static int tda9840_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
index 19621ed523ec605c6f55945eb43c1cf19dd5febb..827425c5b866e9e895e8393a7d8e5c5c8ca98723 100644 (file)
@@ -152,7 +152,7 @@ static int tea6415c_probe(struct i2c_client *client,
 
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
index 5ea840401f21865120623691ecc0d20cc084decc..f350b6c24500110dbce1f064e24365dc5974fe7b 100644 (file)
@@ -125,7 +125,7 @@ static int tea6420_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
index f8138c75be8be3a25834ca4471da721b5163e5d1..1aab96a882034a41867641e3d1022a3643303dc2 100644 (file)
@@ -230,7 +230,7 @@ static int upd64031a_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 28e0e6b6ca8491d815de9f822e19fae412b23ca6..9bbe61700fd5c238d253d309ea37a21a4f3ca6a1 100644 (file)
@@ -202,7 +202,7 @@ static int upd64083_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 498e6742579e76bb400f79af9dac37d1d7fe10b4..6dc7196296b341bdf87956a600ae74ebb522835e 100644 (file)
@@ -389,7 +389,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV) {
                entity = media_entity_get(&vdev->entity);
                if (!entity) {
                        ret = -EBUSY;
@@ -415,7 +416,8 @@ err:
        /* decrease the refcount in case of an error */
        if (ret) {
 #if defined(CONFIG_MEDIA_CONTROLLER)
-               if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+               if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+                   vdev->vfl_type != VFL_TYPE_SUBDEV)
                        media_entity_put(entity);
 #endif
                video_put(vdev);
@@ -437,7 +439,8 @@ static int v4l2_release(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV)
                media_entity_put(&vdev->entity);
 #endif
        /* decrease the refcount unconditionally since the release()
@@ -686,7 +689,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
        /* Part 5: Register the entity. */
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV) {
                vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
                vdev->entity.name = vdev->name;
                vdev->entity.v4l.major = VIDEO_MAJOR;
@@ -733,7 +737,8 @@ void video_unregister_device(struct video_device *vdev)
                return;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV)
                media_device_unregister_entity(&vdev->entity);
 #endif
 
index 5aeaf876ba9b2ca4a04221e41fd4cf2bfbd7c0e1..4aae501f02d08f22148f5baf88d3620f3125f205 100644 (file)
@@ -155,8 +155,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
        sd->v4l2_dev = v4l2_dev;
        if (sd->internal_ops && sd->internal_ops->registered) {
                err = sd->internal_ops->registered(sd);
-               if (err)
+               if (err) {
+                       module_put(sd->owner);
                        return err;
+               }
        }
 
        /* This just returns 0 if either of the two args is NULL */
@@ -164,6 +166,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
        if (err) {
                if (sd->internal_ops && sd->internal_ops->unregistered)
                        sd->internal_ops->unregistered(sd);
+               module_put(sd->owner);
                return err;
        }
 
index 0b80644906769e698c3c3f7195be6fc3b2941c42..812729ebf09e53a5461a9df2667ad1f1ff9a286a 100644 (file)
@@ -155,25 +155,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        switch (cmd) {
        case VIDIOC_QUERYCTRL:
-               return v4l2_subdev_queryctrl(sd, arg);
+               return v4l2_queryctrl(sd->ctrl_handler, arg);
 
        case VIDIOC_QUERYMENU:
-               return v4l2_subdev_querymenu(sd, arg);
+               return v4l2_querymenu(sd->ctrl_handler, arg);
 
        case VIDIOC_G_CTRL:
-               return v4l2_subdev_g_ctrl(sd, arg);
+               return v4l2_g_ctrl(sd->ctrl_handler, arg);
 
        case VIDIOC_S_CTRL:
-               return v4l2_subdev_s_ctrl(sd, arg);
+               return v4l2_s_ctrl(sd->ctrl_handler, arg);
 
        case VIDIOC_G_EXT_CTRLS:
-               return v4l2_subdev_g_ext_ctrls(sd, arg);
+               return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
 
        case VIDIOC_S_EXT_CTRLS:
-               return v4l2_subdev_s_ext_ctrls(sd, arg);
+               return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
 
        case VIDIOC_TRY_EXT_CTRLS:
-               return v4l2_subdev_try_ext_ctrls(sd, arg);
+               return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
 
        case VIDIOC_DQEVENT:
                if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
index c4742fc15529a97cf4472dde06717f9ef7d31233..c9691115f2d26787fa9d85ae98382539d78a8a98 100644 (file)
@@ -300,7 +300,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
 
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
        retval = remap_pfn_range(vma, vma->vm_start,
-                                PFN_DOWN(virt_to_phys(mem->vaddr)),
+                                mem->dma_handle >> PAGE_SHIFT,
                                 size, vma->vm_page_prot);
        if (retval) {
                dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
index 6698c77e0f64c7f5667c1bb8556597f77675483b..6ba1461d51ef9456be18be6421837c0c279064b8 100644 (file)
@@ -37,6 +37,9 @@ module_param(debug, int, 0644);
 #define call_qop(q, op, args...)                                       \
        (((q)->ops->op) ? ((q)->ops->op(args)) : 0)
 
+#define V4L2_BUFFER_STATE_FLAGS        (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
+
 /**
  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
  */
@@ -51,7 +54,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
        for (plane = 0; plane < vb->num_planes; ++plane) {
                mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
                                        plane_sizes[plane]);
-               if (!mem_priv)
+               if (IS_ERR_OR_NULL(mem_priv))
                        goto free;
 
                /* Associate allocator private data with this plane */
@@ -284,7 +287,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        struct vb2_queue *q = vb->vb2_queue;
        int ret = 0;
 
-       /* Copy back data such as timestamp, input, etc. */
+       /* Copy back data such as timestamp, flags, input, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
        b->input = vb->v4l2_buf.input;
        b->reserved = vb->v4l2_buf.reserved;
@@ -313,7 +316,10 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
                        b->m.userptr = vb->v4l2_planes[0].m.userptr;
        }
 
-       b->flags = 0;
+       /*
+        * Clear any buffer state related flags.
+        */
+       b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
 
        switch (vb->state) {
        case VB2_BUF_STATE_QUEUED:
@@ -519,6 +525,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
        num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
        memset(plane_sizes, 0, sizeof(plane_sizes));
        memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+       q->memory = req->memory;
 
        /*
         * Ask the driver how many buffers and planes per buffer it requires.
@@ -560,8 +567,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                ret = num_buffers;
        }
 
-       q->memory = req->memory;
-
        /*
         * Return the number of successfully allocated buffers
         * to the userspace.
@@ -715,6 +720,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
 
        vb->v4l2_buf.field = b->field;
        vb->v4l2_buf.timestamp = b->timestamp;
+       vb->v4l2_buf.input = b->input;
+       vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
 
        return 0;
 }
index 58205d5961386cec699b9c680087619e603f0084..a790a5f8c06ff5e48566bfeb41a512975fc26d4f 100644 (file)
@@ -46,7 +46,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
                                        GFP_KERNEL);
        if (!buf->vaddr) {
                dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
-                       buf->size);
+                       size);
                kfree(buf);
                return ERR_PTR(-ENOMEM);
        }
index 643ad52e3ca2fe49399a6de0682a495789c32dde..4796bbf0ae4e5b4fdd1476ac8e6cd4e9e43ec6c5 100644 (file)
@@ -1000,7 +1000,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
        gd->major = I2O_MAJOR;
        gd->queue = queue;
        gd->fops = &i2o_block_fops;
-       gd->events = DISK_EVENT_MEDIA_CHANGE;
        gd->private_data = dev;
 
        dev->gd = gd;
index d4a851c6b5bf17f4da0b8326275a82c458c97983..0b4d5b23bec9b36d212fa068c6663b8f23365638 100644 (file)
@@ -144,7 +144,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
        int iter, i;
        unsigned long flags;
 
-       data->chip->irq_ack(irq_data);
+       data->chip->irq_ack(data);
 
        for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
                u32 status;
index 53450f433f1018dbf042b2dbf1ccaa490f802b60..3ab9ffa00aadf8c805477e2c323c2f1f889da2a8 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
 #include <plat/usb.h>
 
 #define USBHS_DRIVER_NAME      "usbhs-omap"
@@ -700,8 +699,7 @@ static int usbhs_enable(struct device *dev)
        dev_dbg(dev, "starting TI HSUSB Controller\n");
        if (!pdata) {
                dev_dbg(dev, "missing platform_data\n");
-               ret =  -ENODEV;
-               goto end_enable;
+               return  -ENODEV;
        }
 
        spin_lock_irqsave(&omap->lock, flags);
@@ -719,14 +717,14 @@ static int usbhs_enable(struct device *dev)
                        gpio_request(pdata->ehci_data->reset_gpio_port[0],
                                                "USB1 PHY reset");
                        gpio_direction_output
-                               (pdata->ehci_data->reset_gpio_port[0], 1);
+                               (pdata->ehci_data->reset_gpio_port[0], 0);
                }
 
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) {
                        gpio_request(pdata->ehci_data->reset_gpio_port[1],
                                                "USB2 PHY reset");
                        gpio_direction_output
-                               (pdata->ehci_data->reset_gpio_port[1], 1);
+                               (pdata->ehci_data->reset_gpio_port[1], 0);
                }
 
                /* Hold the PHY in RESET for enough time till DIR is high */
@@ -906,16 +904,17 @@ static int usbhs_enable(struct device *dev)
 
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
                        gpio_set_value
-                               (pdata->ehci_data->reset_gpio_port[0], 0);
+                               (pdata->ehci_data->reset_gpio_port[0], 1);
 
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
                        gpio_set_value
-                               (pdata->ehci_data->reset_gpio_port[1], 0);
+                               (pdata->ehci_data->reset_gpio_port[1], 1);
        }
 
 end_count:
        omap->count++;
-       goto end_enable;
+       spin_unlock_irqrestore(&omap->lock, flags);
+       return 0;
 
 err_tll:
        if (pdata->ehci_data->phy_reset) {
@@ -931,8 +930,6 @@ err_tll:
        clk_disable(omap->usbhost_fs_fck);
        clk_disable(omap->usbhost_hs_fck);
        clk_disable(omap->usbhost_ick);
-
-end_enable:
        spin_unlock_irqrestore(&omap->lock, flags);
        return ret;
 }
index 16422de0823a35447624353ba94d154ec1ed11be..2c0d4d16491ab4c3ef35d881c3fb11334b25ed7d 100644 (file)
@@ -447,12 +447,13 @@ static int __init load_twl4030_script(struct twl4030_script *tscript,
                if (err)
                        goto out;
        }
-       if (tscript->flags & TWL4030_SLEEP_SCRIPT)
+       if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
                if (order)
                        pr_warning("TWL4030: Bad order of scripts (sleep "\
                                        "script before wakeup) Leads to boot"\
                                        "failure on some boards\n");
                err = twl4030_config_sleep_sequence(address);
+       }
 out:
        return err;
 }
index 63667a8f140c458722c54b33b3e91d54e4cca029..d6d62fd07ee9fd0b492d6c7e0a80d116840009b2 100644 (file)
@@ -284,6 +284,7 @@ int mmc_add_card(struct mmc_card *card)
                type = "SD-combo";
                if (mmc_card_blockaddr(card))
                        type = "SDHC-combo";
+               break;
        default:
                type = "?";
                break;
index 2e032f0e8cf47e45730d99e8f9554c688eb756b1..a6c329040140420ab73ded04fa08c7ca9cdaa07e 100644 (file)
@@ -832,7 +832,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                return IRQ_HANDLED;
        }
 
-       if (end_command)
+       if (end_command && host->cmd)
                mmc_omap_cmd_done(host, host->cmd);
        if (host->data != NULL) {
                if (transfer_error)
index f9b611fc773e19d9133e79681280164c9e4d8538..60e4186a434592bc2a42b0a365578eed4ed525f3 100644 (file)
@@ -124,8 +124,10 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
 #endif
 }
 
+static const struct of_device_id sdhci_of_match[];
 static int __devinit sdhci_of_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct device_node *np = ofdev->dev.of_node;
        struct sdhci_of_data *sdhci_of_data;
        struct sdhci_host *host;
@@ -134,9 +136,10 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
        int size;
        int ret;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(sdhci_of_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
-       sdhci_of_data = ofdev->dev.of_match->data;
+       sdhci_of_data = match->data;
 
        if (!of_device_is_available(np))
                return -ENODEV;
index a136be7063478bc9f9f6b130cc92010c47737fc5..f8b5f37007b2a0b8115e62032664e6d96a04e214 100644 (file)
@@ -957,6 +957,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        host->ioaddr = pci_ioremap_bar(pdev, bar);
        if (!host->ioaddr) {
                dev_err(&pdev->dev, "failed to remap registers\n");
+               ret = -ENOMEM;
                goto release;
        }
 
index 9e15f41f87be8f4a79bd61b94ace660942512eb6..5d20661bc357ba387601b6b2089185bceb144aac 100644 (file)
@@ -1334,6 +1334,13 @@ static void sdhci_tasklet_finish(unsigned long param)
 
        host = (struct sdhci_host*)param;
 
+        /*
+         * If this tasklet gets rescheduled while running, it will
+         * be run again afterwards but without any active request.
+         */
+       if (!host->mrq)
+               return;
+
        spin_lock_irqsave(&host->lock, flags);
 
        del_timer(&host->timer);
@@ -1345,7 +1352,7 @@ static void sdhci_tasklet_finish(unsigned long param)
         * upon error conditions.
         */
        if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-               (mrq->cmd->error ||
+           ((mrq->cmd && mrq->cmd->error) ||
                 (mrq->data && (mrq->data->error ||
                  (mrq->data->stop && mrq->data->stop->error))) ||
                   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
index 62d37de6de76d7551d575f22df39909479030aec..710339a85c84676d9c72e2105f24108344248da2 100644 (file)
@@ -728,15 +728,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                tmio_mmc_set_clock(host, ios->clock);
 
        /* Power sequence - OFF -> UP -> ON */
-       if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
+       if (ios->power_mode == MMC_POWER_UP) {
+               /* power up SD bus */
+               if (host->set_pwr)
+                       host->set_pwr(host->pdev, 1);
+       } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
                /* power down SD bus */
                if (ios->power_mode == MMC_POWER_OFF && host->set_pwr)
                        host->set_pwr(host->pdev, 0);
                tmio_mmc_clk_stop(host);
-       } else if (ios->power_mode == MMC_POWER_UP) {
-               /* power up SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 1);
        } else {
                /* start bus clock */
                tmio_mmc_clk_start(host);
index 44b1f46458cabf89dafed26b1972ee9866141761..5069111c81cca9511c0f016cfd20705bf2c723a6 100644 (file)
@@ -260,6 +260,13 @@ config MTD_BCM963XX
          Support for parsing CFE image tag and creating MTD partitions on
          Broadcom BCM63xx boards.
 
+config MTD_LANTIQ
+       tristate "Lantiq SoC NOR support"
+       depends on LANTIQ
+       select MTD_PARTITIONS
+       help
+         Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
+
 config MTD_DILNETPC
        tristate "CFI Flash device mapped on DIL/Net PC"
        depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
index 08533bd5cba7c4adfeef23f4fe8d348b2ad0015d..6adf4c9b90578f546382f027ee716c47d1e8dc8a 100644 (file)
@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_VMU)         += vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)    += gpio-addr-flash.o
 obj-$(CONFIG_MTD_BCM963XX)     += bcm963xx-flash.o
 obj-$(CONFIG_MTD_LATCH_ADDR)   += latch-addr-flash.o
+obj-$(CONFIG_MTD_LANTIQ)       += lantiq-flash.o
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
new file mode 100644 (file)
index 0000000..a90cabd
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/cfi.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+/*
+ * The NOR flash is connected to the same external bus unit (EBU) as PCI.
+ * To make PCI work we need to enable the endianness swapping for the address
+ * written to the EBU. This endianness swapping works for PCI correctly but
+ * fails for attached NOR devices. To workaround this we need to use a complex
+ * map. The workaround involves swapping all addresses whilst probing the chip.
+ * Once probing is complete we stop swapping the addresses but swizzle the
+ * unlock addresses to ensure that access to the NOR device works correctly.
+ */
+
+enum {
+       LTQ_NOR_PROBING,
+       LTQ_NOR_NORMAL
+};
+
+struct ltq_mtd {
+       struct resource *res;
+       struct mtd_info *mtd;
+       struct map_info *map;
+};
+
+static char ltq_map_name[] = "ltq_nor";
+
+static map_word
+ltq_read16(struct map_info *map, unsigned long adr)
+{
+       unsigned long flags;
+       map_word temp;
+
+       if (map->map_priv_1 == LTQ_NOR_PROBING)
+               adr ^= 2;
+       spin_lock_irqsave(&ebu_lock, flags);
+       temp.x[0] = *(u16 *)(map->virt + adr);
+       spin_unlock_irqrestore(&ebu_lock, flags);
+       return temp;
+}
+
+static void
+ltq_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+       unsigned long flags;
+
+       if (map->map_priv_1 == LTQ_NOR_PROBING)
+               adr ^= 2;
+       spin_lock_irqsave(&ebu_lock, flags);
+       *(u16 *)(map->virt + adr) = d.x[0];
+       spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+/*
+ * The following 2 functions copy data between iomem and a cached memory
+ * section. As memcpy() makes use of pre-fetching we cannot use it here.
+ * The normal alternative of using memcpy_{to,from}io also makes use of
+ * memcpy() on MIPS so it is not applicable either. We are therefore stuck
+ * with having to use our own loop.
+ */
+static void
+ltq_copy_from(struct map_info *map, void *to,
+       unsigned long from, ssize_t len)
+{
+       unsigned char *f = (unsigned char *)map->virt + from;
+       unsigned char *t = (unsigned char *)to;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ebu_lock, flags);
+       while (len--)
+               *t++ = *f++;
+       spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void
+ltq_copy_to(struct map_info *map, unsigned long to,
+       const void *from, ssize_t len)
+{
+       unsigned char *f = (unsigned char *)from;
+       unsigned char *t = (unsigned char *)map->virt + to;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ebu_lock, flags);
+       while (len--)
+               *t++ = *f++;
+       spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static const char const *part_probe_types[] = { "cmdlinepart", NULL };
+
+static int __init
+ltq_mtd_probe(struct platform_device *pdev)
+{
+       struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+       struct ltq_mtd *ltq_mtd;
+       struct mtd_partition *parts;
+       struct resource *res;
+       int nr_parts = 0;
+       struct cfi_private *cfi;
+       int err;
+
+       ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL);
+       platform_set_drvdata(pdev, ltq_mtd);
+
+       ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!ltq_mtd->res) {
+               dev_err(&pdev->dev, "failed to get memory resource");
+               err = -ENOENT;
+               goto err_out;
+       }
+
+       res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start,
+               resource_size(ltq_mtd->res), dev_name(&pdev->dev));
+       if (!ltq_mtd->res) {
+               dev_err(&pdev->dev, "failed to request mem resource");
+               err = -EBUSY;
+               goto err_out;
+       }
+
+       ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+       ltq_mtd->map->phys = res->start;
+       ltq_mtd->map->size = resource_size(res);
+       ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev,
+                               ltq_mtd->map->phys, ltq_mtd->map->size);
+       if (!ltq_mtd->map->virt) {
+               dev_err(&pdev->dev, "failed to ioremap!\n");
+               err = -ENOMEM;
+               goto err_free;
+       }
+
+       ltq_mtd->map->name = ltq_map_name;
+       ltq_mtd->map->bankwidth = 2;
+       ltq_mtd->map->read = ltq_read16;
+       ltq_mtd->map->write = ltq_write16;
+       ltq_mtd->map->copy_from = ltq_copy_from;
+       ltq_mtd->map->copy_to = ltq_copy_to;
+
+       ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
+       ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
+       ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
+
+       if (!ltq_mtd->mtd) {
+               dev_err(&pdev->dev, "probing failed\n");
+               err = -ENXIO;
+               goto err_unmap;
+       }
+
+       ltq_mtd->mtd->owner = THIS_MODULE;
+
+       cfi = ltq_mtd->map->fldrv_priv;
+       cfi->addr_unlock1 ^= 1;
+       cfi->addr_unlock2 ^= 1;
+
+       nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
+                               part_probe_types, &parts, 0);
+       if (nr_parts > 0) {
+               dev_info(&pdev->dev,
+                       "using %d partitions from cmdline", nr_parts);
+       } else {
+               nr_parts = ltq_mtd_data->nr_parts;
+               parts = ltq_mtd_data->parts;
+       }
+
+       err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
+       if (err) {
+               dev_err(&pdev->dev, "failed to add partitions\n");
+               goto err_destroy;
+       }
+
+       return 0;
+
+err_destroy:
+       map_destroy(ltq_mtd->mtd);
+err_unmap:
+       iounmap(ltq_mtd->map->virt);
+err_free:
+       kfree(ltq_mtd->map);
+err_out:
+       kfree(ltq_mtd);
+       return err;
+}
+
+static int __devexit
+ltq_mtd_remove(struct platform_device *pdev)
+{
+       struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
+
+       if (ltq_mtd) {
+               if (ltq_mtd->mtd) {
+                       del_mtd_partitions(ltq_mtd->mtd);
+                       map_destroy(ltq_mtd->mtd);
+               }
+               if (ltq_mtd->map->virt)
+                       iounmap(ltq_mtd->map->virt);
+               kfree(ltq_mtd->map);
+               kfree(ltq_mtd);
+       }
+       return 0;
+}
+
+static struct platform_driver ltq_mtd_driver = {
+       .remove = __devexit_p(ltq_mtd_remove),
+       .driver = {
+               .name = "ltq_nor",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init
+init_ltq_mtd(void)
+{
+       int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
+
+       if (ret)
+               pr_err("ltq_nor: error registering platform driver");
+       return ret;
+}
+
+static void __exit
+exit_ltq_mtd(void)
+{
+       platform_driver_unregister(&ltq_mtd_driver);
+}
+
+module_init(init_ltq_mtd);
+module_exit(exit_ltq_mtd);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC NOR");
index bd483f0c57e1ae31ca98c1336cd3f4bed248310b..c1d33464aee8926e66afcccc23dbbbacdb718ba8 100644 (file)
@@ -214,11 +214,13 @@ static void __devinit of_free_probes(const char **probes)
 }
 #endif
 
+static struct of_device_id of_flash_match[];
 static int __devinit of_flash_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_MTD_PARTITIONS
        const char **part_probe_types;
 #endif
+       const struct of_device_id *match;
        struct device_node *dp = dev->dev.of_node;
        struct resource res;
        struct of_flash *info;
@@ -232,9 +234,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
        struct mtd_info **mtd_list = NULL;
        resource_size_t res_size;
 
-       if (!dev->dev.of_match)
+       match = of_match_device(of_flash_match, &dev->dev);
+       if (!match)
                return -EINVAL;
-       probe_type = dev->dev.of_match->data;
+       probe_type = match->data;
 
        reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
 
index 3ffe05db4923b662f51adcddb0e62cd1af09a5c8..5d513b54a7d7cd688711007145fa93d8d0b400ab 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -470,7 +471,7 @@ static int __init au1xxx_nand_init(void)
 
 #ifdef CONFIG_MIPS_PB1550
        /* set gpio206 high */
-       au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR);
+       gpio_direction_input(206);
 
        boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
 
index 96c0b34ba8dbcfb18b564cabf3c22f3bc74f5a19..657b9f4b6f9ba288ad4dbd5f7f1450e440e84360 100644 (file)
@@ -400,7 +400,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
        doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
        doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
-       /* We can't' use dev_ready here, but at least we wait for the
+       /* We can't use dev_ready here, but at least we wait for the
         * command to complete
         */
        udelay(50);
index dc280bc8eba2e0e0a8bc033b164d11b2707410bd..19f04a34783a2356fd8ad19ada6be3ca3fa46b04 100644 (file)
@@ -2017,6 +2017,13 @@ config FTMAC100
          from Faraday. It is used on Faraday A320, Andes AG101 and some
          other ARM/NDS32 SoC's.
 
+config LANTIQ_ETOP
+       tristate "Lantiq SoC ETOP driver"
+       depends on SOC_TYPE_XWAY
+       help
+         Support for the MII0 inside the Lantiq SoC
+
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
@@ -2536,7 +2543,7 @@ config S6GMAC
 source "drivers/net/stmmac/Kconfig"
 
 config PCH_GBE
-       tristate "PCH Gigabit Ethernet"
+       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
        depends on PCI
        select MII
        ---help---
@@ -2548,6 +2555,12 @@ config PCH_GBE
          to Gigabit Ethernet.
          This driver enables Gigabit Ethernet function.
 
+         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+         Output Hub), ML7223.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7223 is companion chip for Intel Atom E6xx series.
+         ML7223 is completely compatible for Intel EG20T PCH.
+
 endif # NETDEV_1000
 
 #
index 01b604ad155eec1d9f2f345c4b7537cafa7128dd..209fbb70619b8be9e5f6d6c871b82a88d86833fa 100644 (file)
@@ -144,7 +144,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o
 obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
@@ -219,7 +219,7 @@ obj-$(CONFIG_SC92031) += sc92031.o
 obj-$(CONFIG_LP486E) += lp486e.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o
 obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
 obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
 obj-$(CONFIG_EQUALIZER) += eql.o
@@ -231,7 +231,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
@@ -259,6 +259,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4/
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_ETHOC) += ethoc.o
 obj-$(CONFIG_GRETH) += greth.o
+obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
 
 obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
 
index 88495c48a81d3fef21340997537e5ed4f460ec2e..241b185e6569da605eea3fcdd089098b42262a6e 100644 (file)
@@ -106,7 +106,7 @@ MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "M
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
 module_param_array(speed_duplex, int, NULL, 0);
-MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotitate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
+MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
 module_param_array(coalesce, bool, NULL, 0);
 MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0: Disable");
 module_param_array(dynamic_ipg, bool, NULL, 0);
index 4af235d41fda656990a7a280976ecd6e477d2a49..fbfb5b47c506c87433e30f6c47ea9e4a584f2c04 100644 (file)
@@ -527,7 +527,7 @@ static void __init etherh_banner(void)
  * Read the ethernet address string from the on board rom.
  * This is an ascii string...
  */
-static int __init etherh_addr(char *addr, struct expansion_card *ec)
+static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
 {
        struct in_chunk_dir cd;
        char *s;
@@ -655,7 +655,7 @@ static const struct net_device_ops etherh_netdev_ops = {
 static u32 etherh_regoffsets[16];
 static u32 etherm_regoffsets[16];
 
-static int __init
+static int __devinit
 etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        const struct etherh_data *data = id->data;
index ce0091eb06f580a2b63bcc35f9f019a078d3acbb..1264d781b5549e7dd1ed8f9d56b339cd96a44ebc 100644 (file)
@@ -554,7 +554,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
                memaddr == (unsigned short *)0xffe00000) {
                /* PAMs card and Riebl on ST use level 5 autovector */
                if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,
-                           "PAM/Riebl-ST Ethernet", dev)) {
+                           "PAM,Riebl-ST Ethernet", dev)) {
                        printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
                        return 0;
                }
index 7cb375e0e29cd5e3219a86106f2288201cf20635..925929d764ca50eff2812842c611e0cfbdb3005a 100644 (file)
@@ -566,9 +566,9 @@ struct atl1c_adapter {
 #define __AT_TESTING        0x0001
 #define __AT_RESETTING      0x0002
 #define __AT_DOWN           0x0003
-       u8 work_event;
-#define ATL1C_WORK_EVENT_RESET                 0x01
-#define ATL1C_WORK_EVENT_LINK_CHANGE   0x02
+       unsigned long work_event;
+#define        ATL1C_WORK_EVENT_RESET          0
+#define        ATL1C_WORK_EVENT_LINK_CHANGE    1
        u32 msg_enable;
 
        bool have_msi;
index 7d9d5067a65ce1bb368bd2128d75c5ef87446828..a6e1c36e48e6812b7590a0e2e595abb956b417ab 100644 (file)
@@ -325,7 +325,7 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
                }
        }
 
-       adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
+       set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
        schedule_work(&adapter->common_task);
 }
 
@@ -337,20 +337,16 @@ static void atl1c_common_task(struct work_struct *work)
        adapter = container_of(work, struct atl1c_adapter, common_task);
        netdev = adapter->netdev;
 
-       if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
-               adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
+       if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) {
                netif_device_detach(netdev);
                atl1c_down(adapter);
                atl1c_up(adapter);
                netif_device_attach(netdev);
-               return;
        }
 
-       if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
-               adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
+       if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
+               &adapter->work_event))
                atl1c_check_link_status(adapter);
-       }
-       return;
 }
 
 
@@ -369,7 +365,7 @@ static void atl1c_tx_timeout(struct net_device *netdev)
        struct atl1c_adapter *adapter = netdev_priv(netdev);
 
        /* Do the reset outside of interrupt context */
-       adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+       set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
        schedule_work(&adapter->common_task);
 }
 
index 66823eded7a3b7d4ffa7525728d8c587f1628275..2353eca32593f7623490656e555cedb24bcc483a 100644 (file)
@@ -213,7 +213,7 @@ struct be_rx_stats {
 
 struct be_rx_compl_info {
        u32 rss_hash;
-       u16 vid;
+       u16 vlan_tag;
        u16 pkt_size;
        u16 rxq_idx;
        u16 mac_id;
index 1e2d825bb94a2b608bc4d8eacac2fa8e24dafaf3..9dc9394fd4cae51f5ec0b566daa6102d7b80e571 100644 (file)
@@ -132,7 +132,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
                struct be_async_event_grp5_pvid_state *evt)
 {
        if (evt->enabled)
-               adapter->pvid = evt->tag;
+               adapter->pvid = le16_to_cpu(evt->tag);
        else
                adapter->pvid = 0;
 }
index 7cb5a114c7338af0c584607c7bcd1e33dba4c0e2..9187fb4e08f1169baaec2c6974944d924d7d07d5 100644 (file)
@@ -1018,7 +1018,8 @@ static void be_rx_compl_process(struct be_adapter *adapter,
                        kfree_skb(skb);
                        return;
                }
-               vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rxcp->vid);
+               vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
+                                       rxcp->vlan_tag);
        } else {
                netif_receive_skb(skb);
        }
@@ -1076,7 +1077,8 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        if (likely(!rxcp->vlanf))
                napi_gro_frags(&eq_obj->napi);
        else
-               vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, rxcp->vid);
+               vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp,
+                               rxcp->vlan_tag);
 }
 
 static void be_parse_rx_compl_v1(struct be_adapter *adapter,
@@ -1102,7 +1104,8 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter,
        rxcp->pkt_type =
                AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl);
        rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl);
-       rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, compl);
+       rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
+                                       compl);
 }
 
 static void be_parse_rx_compl_v0(struct be_adapter *adapter,
@@ -1128,7 +1131,8 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter,
        rxcp->pkt_type =
                AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl);
        rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl);
-       rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, compl);
+       rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
+                                       compl);
 }
 
 static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
@@ -1155,9 +1159,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
                rxcp->vlanf = 0;
 
        if (!lancer_chip(adapter))
-               rxcp->vid = swab16(rxcp->vid);
+               rxcp->vlan_tag = swab16(rxcp->vlan_tag);
 
-       if ((adapter->pvid == rxcp->vid) && !adapter->vlan_tag[rxcp->vid])
+       if (((adapter->pvid & VLAN_VID_MASK) ==
+               (rxcp->vlan_tag & VLAN_VID_MASK)) &&
+               !adapter->vlan_tag[rxcp->vlan_tag])
                rxcp->vlanf = 0;
 
        /* As the compl has been parsed, reset it; we wont touch it again */
@@ -1873,6 +1879,7 @@ static void be_worker(struct work_struct *work)
                be_detect_dump_ue(adapter);
 
 reschedule:
+       adapter->work_counter++;
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
 }
 
index e3de0b8625cde247ee69f5fd45f06c32cfda53a2..7581518ecfa2eade4c4bb4cba60601e5f39b7be2 100644 (file)
@@ -38,6 +38,8 @@
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
 #define bfa_ioc_notify_fail(__ioc)                     \
                        ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_start(__ioc)               \
+                       ((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
 #define bfa_ioc_sync_join(__ioc)                       \
                        ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
 #define bfa_ioc_sync_leave(__ioc)                      \
@@ -602,7 +604,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
        switch (event) {
        case IOCPF_E_SEMLOCKED:
                if (bfa_ioc_firmware_lock(ioc)) {
-                       if (bfa_ioc_sync_complete(ioc)) {
+                       if (bfa_ioc_sync_start(ioc)) {
                                iocpf->retry_count = 0;
                                bfa_ioc_sync_join(ioc);
                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
@@ -1314,7 +1316,7 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
  * execution context (driver/bios) must match.
  */
 static bool
-bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
+bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
 {
        struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
 
@@ -1325,7 +1327,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
        if (fwhdr.signature != drv_fwhdr->signature)
                return false;
 
-       if (fwhdr.exec != drv_fwhdr->exec)
+       if (swab32(fwhdr.param) != boot_env)
                return false;
 
        return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
@@ -1352,9 +1354,12 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 {
        enum bfi_ioc_state ioc_fwstate;
        bool fwvalid;
+       u32 boot_env;
 
        ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
 
+       boot_env = BFI_BOOT_LOADER_OS;
+
        if (force)
                ioc_fwstate = BFI_IOC_UNINIT;
 
@@ -1362,10 +1367,10 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
         * check if firmware is valid
         */
        fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-               false : bfa_ioc_fwver_valid(ioc);
+               false : bfa_ioc_fwver_valid(ioc, boot_env);
 
        if (!fwvalid) {
-               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
                return;
        }
 
@@ -1396,7 +1401,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
        /**
         * Initialize the h/w for any other states.
         */
-       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
 }
 
 void
@@ -1506,7 +1511,7 @@ bfa_ioc_hb_stop(struct bfa_ioc *ioc)
  */
 static void
 bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
-                   u32 boot_param)
+                   u32 boot_env)
 {
        u32 *fwimg;
        u32 pgnum, pgoff;
@@ -1558,10 +1563,10 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
        /*
         * Set boot type and boot param at the end.
        */
-       writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
+       writel(boot_type, ((ioc->ioc_regs.smem_page_start)
                        + (BFI_BOOT_TYPE_OFF)));
-       writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
-                       + (BFI_BOOT_PARAM_OFF)));
+       writel(boot_env, ((ioc->ioc_regs.smem_page_start)
+                       + (BFI_BOOT_LOADER_OFF)));
 }
 
 static void
@@ -1721,7 +1726,7 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
  * as the entry vector.
  */
 static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
 {
        void __iomem *rb;
 
@@ -1734,7 +1739,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
         * Initialize IOC state of all functions on a chip reset.
         */
        rb = ioc->pcidev.pci_bar_kva;
-       if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+       if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
                writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
                writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
        } else {
@@ -1743,7 +1748,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
        }
 
        bfa_ioc_msgflush(ioc);
-       bfa_ioc_download_fw(ioc, boot_type, boot_param);
+       bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
        /**
         * Enable interrupts just before starting LPU
index e4974bc24ef69b3d05229398cc15b4977997226e..bd48abee781f17ed340d18317e07374d2000b8bb 100644 (file)
@@ -194,6 +194,7 @@ struct bfa_ioc_hwif {
                                        bool msix);
        void            (*ioc_notify_fail)      (struct bfa_ioc *ioc);
        void            (*ioc_ownership_reset)  (struct bfa_ioc *ioc);
+       bool            (*ioc_sync_start)       (struct bfa_ioc *ioc);
        void            (*ioc_sync_join)        (struct bfa_ioc *ioc);
        void            (*ioc_sync_leave)       (struct bfa_ioc *ioc);
        void            (*ioc_sync_ack)         (struct bfa_ioc *ioc);
index 469997c4ffd196a4609c58daf83c6112d4fc4995..87aecdf22cf9c29adf4379685d9813bbbebd2cd5 100644 (file)
@@ -41,6 +41,7 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
 static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
@@ -63,6 +64,7 @@ bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
        nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
        nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
        nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+       nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
        nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
        nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
        nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
@@ -342,6 +344,32 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
        bfa_nw_ioc_hw_sem_release(ioc);
 }
 
+/**
+ * Synchronized IOC failure processing routines
+ */
+static bool
+bfa_ioc_ct_sync_start(struct bfa_ioc *ioc)
+{
+       u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+       u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+
+       /*
+        * Driver load time.  If the sync required bit for this PCI fn
+        * is set, it is due to an unclean exit by the driver for this
+        * PCI fn in the previous incarnation. Whoever comes here first
+        * should clean it up, no matter which PCI fn.
+        */
+
+       if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
+               writel(0, ioc->ioc_regs.ioc_fail_sync);
+               writel(1, ioc->ioc_regs.ioc_usage_reg);
+               writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+               return true;
+       }
+
+       return bfa_ioc_ct_sync_complete(ioc);
+}
 /**
  * Synchronized IOC failure processing routines
  */
index a97396811050eaccc1bcd31064c0088c29479413..6050379526f74f737ed2ef8a12c8f44ece1241d5 100644 (file)
@@ -184,12 +184,14 @@ enum bfi_mclass {
 #define BFI_IOC_MSGLEN_MAX     32      /* 32 bytes */
 
 #define BFI_BOOT_TYPE_OFF              8
-#define BFI_BOOT_PARAM_OFF             12
+#define BFI_BOOT_LOADER_OFF            12
 
-#define BFI_BOOT_TYPE_NORMAL           0       /* param is device id */
+#define BFI_BOOT_TYPE_NORMAL           0
 #define        BFI_BOOT_TYPE_FLASH             1
 #define        BFI_BOOT_TYPE_MEMTEST           2
 
+#define BFI_BOOT_LOADER_OS             0
+
 #define BFI_BOOT_MEMTEST_RES_ADDR   0x900
 #define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
 
index 9f356d5d0f3318c42630cd0ce2b479e73a28b75b..8e6ceab9f4d800e4cbfee2cac22a297d0d987396 100644 (file)
@@ -1837,7 +1837,6 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
        /* Initialize the Rx event handlers */
        rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
        rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
-       rx_cbfn.rcb_destroy_cbfn = NULL;
        rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
        rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
        rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
index 8e6d618b53052139981cf5cc6df6720d11382a0c..d8383a9af9ad21a756a090bc1fd7342f3af005ee 100644 (file)
@@ -8413,6 +8413,8 @@ bnx2_remove_one(struct pci_dev *pdev)
 
        unregister_netdev(dev);
 
+       del_timer_sync(&bp->timer);
+
        if (bp->mips_firmware)
                release_firmware(bp->mips_firmware);
        if (bp->rv2p_firmware)
index e83ac6dd6fc076b85b752957b9d7a88985cb0412..16581df5ee4e62936afd0ac74ad50dbd108f5782 100644 (file)
@@ -2019,15 +2019,23 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
        u32 *parsing_data, u32 xmit_type)
 {
-       *parsing_data |= ((tcp_hdrlen(skb)/4) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
+       *parsing_data |=
+                       ((((u8 *)skb_transport_header(skb) - skb->data) >> 1) <<
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
-       *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
+       if (xmit_type & XMIT_CSUM_TCP) {
+               *parsing_data |= ((tcp_hdrlen(skb) / 4) <<
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-       return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+               return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+       } else
+               /* We support checksum offload for TCP and UDP only.
+                * No need to pass the UDP header length - it's a constant.
+                */
+               return skb_transport_header(skb) +
+                               sizeof(struct udphdr) - skb->data;
 }
 
 /**
@@ -2043,7 +2051,7 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
        struct eth_tx_parse_bd_e1x *pbd,
        u32 xmit_type)
 {
-       u8 hlen = (skb_network_header(skb) - skb->data) / 2;
+       u8 hlen = (skb_network_header(skb) - skb->data) >> 1;
 
        /* for now NS flag is not used in Linux */
        pbd->global_data =
@@ -2051,9 +2059,15 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
                         ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
 
        pbd->ip_hlen_w = (skb_transport_header(skb) -
-                       skb_network_header(skb)) / 2;
+                       skb_network_header(skb)) >> 1;
 
-       hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
+       hlen += pbd->ip_hlen_w;
+
+       /* We support checksum offload for TCP and UDP only */
+       if (xmit_type & XMIT_CSUM_TCP)
+               hlen += tcp_hdrlen(skb) / 2;
+       else
+               hlen += sizeof(struct udphdr) / 2;
 
        pbd->total_hlen_w = cpu_to_le16(hlen);
        hlen = hlen*2;
index f5050155c6b5e04d87a62be1f8f22a78dc953d9e..89cb977898cb5cfbce98bd53422c9d27128761e5 100644 (file)
@@ -2114,19 +2114,18 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
        for (i = 0; i < (data * 2); i++) {
                if ((i % 2) == 0)
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
-                                     LED_MODE_OPER, SPEED_1000);
+                                     LED_MODE_ON, SPEED_1000);
                else
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
-                                     LED_MODE_OFF, 0);
+                                     LED_MODE_FRONT_PANEL_OFF, 0);
 
                msleep_interruptible(500);
                if (signal_pending(current))
                        break;
        }
 
-       if (bp->link_vars.link_up)
-               bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
-                             bp->link_vars.line_speed);
+       bnx2x_set_led(&bp->link_params, &bp->link_vars,
+                     LED_MODE_OPER, bp->link_vars.line_speed);
 
        return 0;
 }
index 494bf960442d3ff533507661ce394d0d128a3d6f..31912f17653f74173368e36a03c924a4b1443975 100644 (file)
@@ -1482,8 +1482,11 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
 
 static int agg_device_up(const struct aggregator *agg)
 {
-       return (netif_running(agg->slave->dev) &&
-               netif_carrier_ok(agg->slave->dev));
+       struct port *port = agg->lag_ports;
+       if (!port)
+               return 0;
+       return (netif_running(port->slave->dev) &&
+               netif_carrier_ok(port->slave->dev));
 }
 
 /**
index b28baff708641b7b9375891222cc47f133eafdfb..01b8a6af275babb1be74839a489d2133728ddf05 100644 (file)
@@ -39,7 +39,7 @@
 
 typedef struct mac_addr {
        u8 mac_addr_value[ETH_ALEN];
-} mac_addr_t;
+} __packed mac_addr_t;
 
 enum {
        BOND_AD_STABLE = 0,
@@ -134,12 +134,12 @@ typedef struct lacpdu {
        u8 tlv_type_terminator;      // = terminator
        u8 terminator_length;        // = 0
        u8 reserved_50[50];          // = 0
-} lacpdu_t;
+} __packed lacpdu_t;
 
 typedef struct lacpdu_header {
        struct ethhdr hdr;
        struct lacpdu lacpdu;
-} lacpdu_header_t;
+} __packed lacpdu_header_t;
 
 // Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
 typedef struct bond_marker {
@@ -155,12 +155,12 @@ typedef struct bond_marker {
        u8 tlv_type_terminator;      //  = 0x00
        u8 terminator_length;        //  = 0x00
        u8 reserved_90[90];          //  = 0
-} bond_marker_t;
+} __packed bond_marker_t;
 
 typedef struct bond_marker_header {
        struct ethhdr hdr;
        struct bond_marker marker;
-} bond_marker_header_t;
+} __packed bond_marker_header_t;
 
 #pragma pack()
 
index 9bc5de3e04a8375894e040cd3cb794a0fff5f90c..ba715826e2a8f1c7cf66213f777527d5db053d4c 100644 (file)
@@ -176,7 +176,7 @@ static int tlb_initialize(struct bonding *bond)
        bond_info->tx_hashtbl = new_hashtbl;
 
        for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
-               tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
+               tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
        }
 
        _unlock_tx_hashtbl(bond);
@@ -701,7 +701,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
                 */
                rlb_choose_channel(skb, bond);
 
-               /* The ARP relpy packets must be delayed so that
+               /* The ARP reply packets must be delayed so that
                 * they can cancel out the influence of the ARP request.
                 */
                bond->alb_info.rlb_update_delay_counter = RLB_UPDATE_DELAY;
@@ -1042,7 +1042,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
  *
  * If the permanent hw address of @slave is @bond's hw address, we need to
  * find a different hw address to give @slave, that isn't in use by any other
- * slave in the bond. This address must be, of course, one of the premanent
+ * slave in the bond. This address must be, of course, one of the permanent
  * addresses of the other slaves.
  *
  * We go over the slave list, and for each slave there we compare its
index 86861f08b24d1ec91f3b80e8efe4f83999b404a7..8ca7158b2dda412f158ae790050c380e2abd2971 100644 (file)
@@ -75,7 +75,7 @@ struct tlb_client_info {
                                 * gave this entry index.
                                 */
        u32 tx_bytes;           /* Each Client accumulates the BytesTx that
-                                * were tranmitted to it, and after each
+                                * were transmitted to it, and after each
                                 * CallBack the LoadHistory is divided
                                 * by the balance interval
                                 */
@@ -122,7 +122,6 @@ struct tlb_slave_info {
 };
 
 struct alb_bond_info {
-       struct timer_list       alb_timer;
        struct tlb_client_info  *tx_hashtbl; /* Dynamically allocated */
        spinlock_t              tx_hashtbl_lock;
        u32                     unbalanced_load;
@@ -140,7 +139,6 @@ struct alb_bond_info {
        struct slave            *next_rx_slave;/* next slave to be assigned
                                                * to a new rx client for
                                                */
-       u32                     rlb_interval_counter;
        u8                      primary_is_promisc;        /* boolean */
        u32                     rlb_promisc_timeout_counter;/* counts primary
                                                             * promiscuity time
index c0a1bc5b14352288d5c73238031547e4afd9ee98..5fedc3375562316c3e13f0a9a7ff4b94854c9c34 100644 (file)
@@ -247,8 +247,10 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
 }
 #endif /* CONFIG_PPC_MPC512x */
 
+static struct of_device_id mpc5xxx_can_table[];
 static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct mpc5xxx_can_data *data;
        struct device_node *np = ofdev->dev.of_node;
        struct net_device *dev;
@@ -258,9 +260,10 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
        int irq, mscan_clksrc = 0;
        int err = -ENOMEM;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+       if (!match)
                return -EINVAL;
-       data = (struct mpc5xxx_can_data *)of_dev->dev.of_match->data;
+       data = match->data;
 
        base = of_iomap(np, 0);
        if (!base) {
index a358ea9445a20b5cc37341502e9590dd9ab91253..f501bba1fc6fc9d48cb923f9c963bea83cd3b406 100644 (file)
@@ -346,10 +346,10 @@ static void sja1000_rx(struct net_device *dev)
                    | (priv->read_reg(priv, REG_ID2) >> 5);
        }
 
+       cf->can_dlc = get_can_dlc(fi & 0x0F);
        if (fi & FI_RTR) {
                id |= CAN_RTR_FLAG;
        } else {
-               cf->can_dlc = get_can_dlc(fi & 0x0F);
                for (i = 0; i < cf->can_dlc; i++)
                        cf->data[i] = priv->read_reg(priv, dreg++);
        }
index b423965a78d16fe702ddbba08d7dd8d529cdf767..1b49df6b2470874b0cb76cf45214f247c6d3bf29 100644 (file)
@@ -583,7 +583,9 @@ static int slcan_open(struct tty_struct *tty)
        /* Done.  We have linked the TTY line to a channel. */
        rtnl_unlock();
        tty->receive_room = 65536;      /* We don't flow control */
-       return sl->dev->base_addr;
+
+       /* TTY layer expects 0 on success */
+       return 0;
 
 err_free_chan:
        sl->tty = NULL;
index 3e2e734fecb73b7ee586be244bd8775521a8c225..f3bbdcef338cfbd881cc4b8bc4e361791bf49bb6 100644 (file)
@@ -55,15 +55,20 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->duplex = -1;
        }
 
-       cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full
-                      | SUPPORTED_100baseT_Full |  SUPPORTED_100baseT_Half
-                      | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half
-                      | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-       cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg
-                        | ADVERTISED_FIBRE);
+       if (cmd->speed == SPEED_10000) {
+               cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+               cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+               cmd->port = PORT_FIBRE;
+       } else {
+               cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full
+                              | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full
+                              | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg
+                              | SUPPORTED_TP);
+               cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg
+                                | ADVERTISED_TP);
+               cmd->port = PORT_TP;
+       }
 
-       cmd->port = PORT_FIBRE;
        cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 
        return 0;
index f75d3144b8a508e9668c48be6592eff49fbb7e3f..cf79cf759e13608146f897e957128b927bb7479e 100644 (file)
@@ -2688,9 +2688,6 @@ static int ehea_open(struct net_device *dev)
                netif_start_queue(dev);
        }
 
-       init_waitqueue_head(&port->swqe_avail_wq);
-       init_waitqueue_head(&port->restart_wq);
-
        mutex_unlock(&port->port_lock);
 
        return ret;
@@ -3040,11 +3037,14 @@ static void ehea_rereg_mrs(void)
 
                                        if (dev->flags & IFF_UP) {
                                                mutex_lock(&port->port_lock);
-                                               port_napi_enable(port);
                                                ret = ehea_restart_qps(dev);
-                                               check_sqs(port);
-                                               if (!ret)
+                                               if (!ret) {
+                                                       check_sqs(port);
+                                                       port_napi_enable(port);
                                                        netif_wake_queue(dev);
+                                               } else {
+                                                       netdev_err(dev, "Unable to restart QPS\n");
+                                               }
                                                mutex_unlock(&port->port_lock);
                                        }
                                }
@@ -3273,6 +3273,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 
        INIT_WORK(&port->reset_task, ehea_reset_port);
 
+       init_waitqueue_head(&port->swqe_avail_wq);
+       init_waitqueue_head(&port->restart_wq);
+
        ret = register_netdev(dev);
        if (ret) {
                pr_err("register_netdev failed. ret=%d\n", ret);
index 24cb953900dde794e60fe3d5921c7e0698f800e8..5131e61c358cd8b9cde0ce4aa7dcfaf36df11249 100644 (file)
@@ -998,8 +998,10 @@ static const struct net_device_ops fs_enet_netdev_ops = {
 #endif
 };
 
+static struct of_device_id fs_enet_match[];
 static int __devinit fs_enet_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct net_device *ndev;
        struct fs_enet_private *fep;
        struct fs_platform_info *fpi;
@@ -1007,14 +1009,15 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
        const u8 *mac_addr;
        int privsize, len, ret = -ENODEV;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(fs_enet_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
 
        fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
        if (!fpi)
                return -ENOMEM;
 
-       if (!IS_FEC(ofdev->dev.of_match)) {
+       if (!IS_FEC(match)) {
                data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
                if (!data || len != 4)
                        goto out_free_fpi;
@@ -1049,7 +1052,7 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
        fep->dev = &ofdev->dev;
        fep->ndev = ndev;
        fep->fpi = fpi;
-       fep->ops = ofdev->dev.of_match->data;
+       fep->ops = match->data;
 
        ret = fep->ops->setup_data(ndev);
        if (ret)
index 61035fc5599b1bd552bf05e1a77289bd24bee53f..b9fbc83d64a7faa09acfdc2537427bda5f4c6f14 100644 (file)
@@ -226,8 +226,8 @@ static void set_multicast_finish(struct net_device *dev)
        }
 
        FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
-       FW(fecp, hash_table_high, fep->fec.hthi);
-       FW(fecp, hash_table_low, fep->fec.htlo);
+       FW(fecp, grp_hash_table_high, fep->fec.hthi);
+       FW(fecp, grp_hash_table_low, fep->fec.htlo);
 }
 
 static void set_multicast_list(struct net_device *dev)
@@ -273,8 +273,8 @@ static void restart(struct net_device *dev)
        /*
         * Reset all multicast.
         */
-       FW(fecp, hash_table_high, fep->fec.hthi);
-       FW(fecp, hash_table_low, fep->fec.htlo);
+       FW(fecp, grp_hash_table_high, fep->fec.hthi);
+       FW(fecp, grp_hash_table_low, fep->fec.htlo);
 
        /*
         * Set maximum receive buffer size.
index 7e840d373ab36b73fce7676684a1110056ccb4b5..6a2e150e75bb2d774d2afc50f3913f558c92ae77 100644 (file)
@@ -101,17 +101,20 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
        return 0;
 }
 
+static struct of_device_id fs_enet_mdio_fec_match[];
 static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct resource res;
        struct mii_bus *new_bus;
        struct fec_info *fec;
        int (*get_bus_freq)(struct device_node *);
        int ret = -ENOMEM, clock, speed;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
-       get_bus_freq = ofdev->dev.of_match->data;
+       get_bus_freq = match->data;
 
        new_bus = mdiobus_alloc();
        if (!new_bus)
index a31661948c420e0d467c7e8b7bb4ecae4c078de0..9bd7746cbfcfd1fc6b294cbdb2f499e7f21d5e96 100644 (file)
@@ -139,11 +139,11 @@ static int ftmac100_reset(struct ftmac100 *priv)
                         * that hardware reset completed (what the f*ck).
                         * We still need to wait for a while.
                         */
-                       usleep_range(500, 1000);
+                       udelay(500);
                        return 0;
                }
 
-               usleep_range(1000, 10000);
+               udelay(1000);
        }
 
        netdev_err(netdev, "software reset failed\n");
@@ -772,7 +772,7 @@ static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
                if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
                        return phycr & FTMAC100_PHYCR_MIIRDATA;
 
-               usleep_range(100, 1000);
+               udelay(100);
        }
 
        netdev_err(netdev, "mdio read timed out\n");
@@ -801,7 +801,7 @@ static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
                if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
                        return;
 
-               usleep_range(100, 1000);
+               udelay(100);
        }
 
        netdev_err(netdev, "mdio write timed out\n");
index c5ef62ceb8403ac777a36886156bec25a94006dd..1cd481c04202fac3c0df0f93047772a3b789ec6c 100644 (file)
@@ -98,15 +98,15 @@ static const struct net_device_ops hydra_netdev_ops = {
        .ndo_open               = hydra_open,
        .ndo_stop               = hydra_close,
 
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
+       .ndo_poll_controller    = __ei_poll,
 #endif
 };
 
@@ -125,7 +125,7 @@ static int __devinit hydra_init(struct zorro_dev *z)
        0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
 
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
        return -ENOMEM;
 
index 6f8adc7f5d7c123a5ed5b61d56622502eaf837b2..e145f2c455cb4733976e6c2b83456dbfdde2c5a3 100644 (file)
@@ -5100,11 +5100,6 @@ err_set_interrupt:
        return err;
 }
 
-static void ring_free_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct ixgbe_ring, rcu));
-}
-
 /**
  * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings
  * @adapter: board private structure to clear interrupt scheme on
@@ -5126,7 +5121,7 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
                /* ixgbe_get_stats64() might access this ring, we must wait
                 * a grace period before freeing it.
                 */
-               call_rcu(&ring->rcu, ring_free_rcu);
+               kfree_rcu(ring, rcu);
                adapter->rx_ring[i] = NULL;
        }
 
diff --git a/drivers/net/lantiq_etop.c b/drivers/net/lantiq_etop.c
new file mode 100644 (file)
index 0000000..45f252b
--- /dev/null
@@ -0,0 +1,805 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License version 2 as published
+ *   by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+
+#include <lantiq_soc.h>
+#include <xway_dma.h>
+#include <lantiq_platform.h>
+
+#define LTQ_ETOP_MDIO          0x11804
+#define MDIO_REQUEST           0x80000000
+#define MDIO_READ              0x40000000
+#define MDIO_ADDR_MASK         0x1f
+#define MDIO_ADDR_OFFSET       0x15
+#define MDIO_REG_MASK          0x1f
+#define MDIO_REG_OFFSET                0x10
+#define MDIO_VAL_MASK          0xffff
+
+#define PPE32_CGEN             0x800
+#define LQ_PPE32_ENET_MAC_CFG  0x1840
+
+#define LTQ_ETOP_ENETS0                0x11850
+#define LTQ_ETOP_MAC_DA0       0x1186C
+#define LTQ_ETOP_MAC_DA1       0x11870
+#define LTQ_ETOP_CFG           0x16020
+#define LTQ_ETOP_IGPLEN                0x16080
+
+#define MAX_DMA_CHAN           0x8
+#define MAX_DMA_CRC_LEN                0x4
+#define MAX_DMA_DATA_LEN       0x600
+
+#define ETOP_FTCU              BIT(28)
+#define ETOP_MII_MASK          0xf
+#define ETOP_MII_NORMAL                0xd
+#define ETOP_MII_REVERSE       0xe
+#define ETOP_PLEN_UNDER                0x40
+#define ETOP_CGEN              0x800
+
+/* use 2 static channels for TX/RX */
+#define LTQ_ETOP_TX_CHANNEL    1
+#define LTQ_ETOP_RX_CHANNEL    6
+#define IS_TX(x)               (x == LTQ_ETOP_TX_CHANNEL)
+#define IS_RX(x)               (x == LTQ_ETOP_RX_CHANNEL)
+
+#define ltq_etop_r32(x)                ltq_r32(ltq_etop_membase + (x))
+#define ltq_etop_w32(x, y)     ltq_w32(x, ltq_etop_membase + (y))
+#define ltq_etop_w32_mask(x, y, z)     \
+               ltq_w32_mask(x, y, ltq_etop_membase + (z))
+
+#define DRV_VERSION    "1.0"
+
+static void __iomem *ltq_etop_membase;
+
+struct ltq_etop_chan {
+       int idx;
+       int tx_free;
+       struct net_device *netdev;
+       struct napi_struct napi;
+       struct ltq_dma_channel dma;
+       struct sk_buff *skb[LTQ_DESC_NUM];
+};
+
+struct ltq_etop_priv {
+       struct net_device *netdev;
+       struct ltq_eth_data *pldata;
+       struct resource *res;
+
+       struct mii_bus *mii_bus;
+       struct phy_device *phydev;
+
+       struct ltq_etop_chan ch[MAX_DMA_CHAN];
+       int tx_free[MAX_DMA_CHAN >> 1];
+
+       spinlock_t lock;
+};
+
+static int
+ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
+{
+       ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
+       if (!ch->skb[ch->dma.desc])
+               return -ENOMEM;
+       ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
+               ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN,
+               DMA_FROM_DEVICE);
+       ch->dma.desc_base[ch->dma.desc].addr =
+               CPHYSADDR(ch->skb[ch->dma.desc]->data);
+       ch->dma.desc_base[ch->dma.desc].ctl =
+               LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
+               MAX_DMA_DATA_LEN;
+       skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
+       return 0;
+}
+
+static void
+ltq_etop_hw_receive(struct ltq_etop_chan *ch)
+{
+       struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+       struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+       struct sk_buff *skb = ch->skb[ch->dma.desc];
+       int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - MAX_DMA_CRC_LEN;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (ltq_etop_alloc_skb(ch)) {
+               netdev_err(ch->netdev,
+                       "failed to allocate new rx buffer, stopping DMA\n");
+               ltq_dma_close(&ch->dma);
+       }
+       ch->dma.desc++;
+       ch->dma.desc %= LTQ_DESC_NUM;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       skb_put(skb, len);
+       skb->dev = ch->netdev;
+       skb->protocol = eth_type_trans(skb, ch->netdev);
+       netif_receive_skb(skb);
+}
+
+static int
+ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+{
+       struct ltq_etop_chan *ch = container_of(napi,
+                               struct ltq_etop_chan, napi);
+       int rx = 0;
+       int complete = 0;
+
+       while ((rx < budget) && !complete) {
+               struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+
+               if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+                       ltq_etop_hw_receive(ch);
+                       rx++;
+               } else {
+                       complete = 1;
+               }
+       }
+       if (complete || !rx) {
+               napi_complete(&ch->napi);
+               ltq_dma_ack_irq(&ch->dma);
+       }
+       return rx;
+}
+
+static int
+ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+{
+       struct ltq_etop_chan *ch =
+               container_of(napi, struct ltq_etop_chan, napi);
+       struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+       struct netdev_queue *txq =
+               netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       while ((ch->dma.desc_base[ch->tx_free].ctl &
+                       (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+               dev_kfree_skb_any(ch->skb[ch->tx_free]);
+               ch->skb[ch->tx_free] = NULL;
+               memset(&ch->dma.desc_base[ch->tx_free], 0,
+                       sizeof(struct ltq_dma_desc));
+               ch->tx_free++;
+               ch->tx_free %= LTQ_DESC_NUM;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (netif_tx_queue_stopped(txq))
+               netif_tx_start_queue(txq);
+       napi_complete(&ch->napi);
+       ltq_dma_ack_irq(&ch->dma);
+       return 1;
+}
+
+static irqreturn_t
+ltq_etop_dma_irq(int irq, void *_priv)
+{
+       struct ltq_etop_priv *priv = _priv;
+       int ch = irq - LTQ_DMA_CH0_INT;
+
+       napi_schedule(&priv->ch[ch].napi);
+       return IRQ_HANDLED;
+}
+
+static void
+ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       ltq_dma_free(&ch->dma);
+       if (ch->dma.irq)
+               free_irq(ch->dma.irq, priv);
+       if (IS_RX(ch->idx)) {
+               int desc;
+               for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+                       dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+       }
+}
+
+static void
+ltq_etop_hw_exit(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       int i;
+
+       ltq_pmu_disable(PMU_PPE);
+       for (i = 0; i < MAX_DMA_CHAN; i++)
+               if (IS_TX(i) || IS_RX(i))
+                       ltq_etop_free_channel(dev, &priv->ch[i]);
+}
+
+static int
+ltq_etop_hw_init(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       int i;
+
+       ltq_pmu_enable(PMU_PPE);
+
+       switch (priv->pldata->mii_mode) {
+       case PHY_INTERFACE_MODE_RMII:
+               ltq_etop_w32_mask(ETOP_MII_MASK,
+                       ETOP_MII_REVERSE, LTQ_ETOP_CFG);
+               break;
+
+       case PHY_INTERFACE_MODE_MII:
+               ltq_etop_w32_mask(ETOP_MII_MASK,
+                       ETOP_MII_NORMAL, LTQ_ETOP_CFG);
+               break;
+
+       default:
+               netdev_err(dev, "unknown mii mode %d\n",
+                       priv->pldata->mii_mode);
+               return -ENOTSUPP;
+       }
+
+       /* enable crc generation */
+       ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
+
+       ltq_dma_init_port(DMA_PORT_ETOP);
+
+       for (i = 0; i < MAX_DMA_CHAN; i++) {
+               int irq = LTQ_DMA_CH0_INT + i;
+               struct ltq_etop_chan *ch = &priv->ch[i];
+
+               ch->idx = ch->dma.nr = i;
+
+               if (IS_TX(i)) {
+                       ltq_dma_alloc_tx(&ch->dma);
+                       request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+                               "etop_tx", priv);
+               } else if (IS_RX(i)) {
+                       ltq_dma_alloc_rx(&ch->dma);
+                       for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+                                       ch->dma.desc++)
+                               if (ltq_etop_alloc_skb(ch))
+                                       return -ENOMEM;
+                       ch->dma.desc = 0;
+                       request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+                               "etop_rx", priv);
+               }
+               ch->dma.irq = irq;
+       }
+       return 0;
+}
+
+static void
+ltq_etop_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, "Lantiq ETOP");
+       strcpy(info->bus_info, "internal");
+       strcpy(info->version, DRV_VERSION);
+}
+
+static int
+ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_nway_reset(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       return phy_start_aneg(priv->phydev);
+}
+
+static const struct ethtool_ops ltq_etop_ethtool_ops = {
+       .get_drvinfo = ltq_etop_get_drvinfo,
+       .get_settings = ltq_etop_get_settings,
+       .set_settings = ltq_etop_set_settings,
+       .nway_reset = ltq_etop_nway_reset,
+};
+
+static int
+ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
+{
+       u32 val = MDIO_REQUEST |
+               ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+               ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) |
+               phy_data;
+
+       while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+               ;
+       ltq_etop_w32(val, LTQ_ETOP_MDIO);
+       return 0;
+}
+
+static int
+ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+       u32 val = MDIO_REQUEST | MDIO_READ |
+               ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+               ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET);
+
+       while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+               ;
+       ltq_etop_w32(val, LTQ_ETOP_MDIO);
+       while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+               ;
+       val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK;
+       return val;
+}
+
+static void
+ltq_etop_mdio_link(struct net_device *dev)
+{
+       /* nothing to do  */
+}
+
+static int
+ltq_etop_mdio_probe(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       struct phy_device *phydev = NULL;
+       int phy_addr;
+
+       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+               if (priv->mii_bus->phy_map[phy_addr]) {
+                       phydev = priv->mii_bus->phy_map[phy_addr];
+                       break;
+               }
+       }
+
+       if (!phydev) {
+               netdev_err(dev, "no PHY found\n");
+               return -ENODEV;
+       }
+
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
+                       0, priv->pldata->mii_mode);
+
+       if (IS_ERR(phydev)) {
+               netdev_err(dev, "Could not attach to PHY\n");
+               return PTR_ERR(phydev);
+       }
+
+       phydev->supported &= (SUPPORTED_10baseT_Half
+                             | SUPPORTED_10baseT_Full
+                             | SUPPORTED_100baseT_Half
+                             | SUPPORTED_100baseT_Full
+                             | SUPPORTED_Autoneg
+                             | SUPPORTED_MII
+                             | SUPPORTED_TP);
+
+       phydev->advertising = phydev->supported;
+       priv->phydev = phydev;
+       pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
+              dev->name, phydev->drv->name,
+              dev_name(&phydev->dev), phydev->irq);
+
+       return 0;
+}
+
+static int
+ltq_etop_mdio_init(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       int i;
+       int err;
+
+       priv->mii_bus = mdiobus_alloc();
+       if (!priv->mii_bus) {
+               netdev_err(dev, "failed to allocate mii bus\n");
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       priv->mii_bus->priv = dev;
+       priv->mii_bus->read = ltq_etop_mdio_rd;
+       priv->mii_bus->write = ltq_etop_mdio_wr;
+       priv->mii_bus->name = "ltq_mii";
+       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+       priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (!priv->mii_bus->irq) {
+               err = -ENOMEM;
+               goto err_out_free_mdiobus;
+       }
+
+       for (i = 0; i < PHY_MAX_ADDR; ++i)
+               priv->mii_bus->irq[i] = PHY_POLL;
+
+       if (mdiobus_register(priv->mii_bus)) {
+               err = -ENXIO;
+               goto err_out_free_mdio_irq;
+       }
+
+       if (ltq_etop_mdio_probe(dev)) {
+               err = -ENXIO;
+               goto err_out_unregister_bus;
+       }
+       return 0;
+
+err_out_unregister_bus:
+       mdiobus_unregister(priv->mii_bus);
+err_out_free_mdio_irq:
+       kfree(priv->mii_bus->irq);
+err_out_free_mdiobus:
+       mdiobus_free(priv->mii_bus);
+err_out:
+       return err;
+}
+
+static void
+ltq_etop_mdio_cleanup(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       phy_disconnect(priv->phydev);
+       mdiobus_unregister(priv->mii_bus);
+       kfree(priv->mii_bus->irq);
+       mdiobus_free(priv->mii_bus);
+}
+
+static int
+ltq_etop_open(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       int i;
+
+       for (i = 0; i < MAX_DMA_CHAN; i++) {
+               struct ltq_etop_chan *ch = &priv->ch[i];
+
+               if (!IS_TX(i) && (!IS_RX(i)))
+                       continue;
+               ltq_dma_open(&ch->dma);
+               napi_enable(&ch->napi);
+       }
+       phy_start(priv->phydev);
+       netif_tx_start_all_queues(dev);
+       return 0;
+}
+
+static int
+ltq_etop_stop(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       int i;
+
+       netif_tx_stop_all_queues(dev);
+       phy_stop(priv->phydev);
+       for (i = 0; i < MAX_DMA_CHAN; i++) {
+               struct ltq_etop_chan *ch = &priv->ch[i];
+
+               if (!IS_RX(i) && !IS_TX(i))
+                       continue;
+               napi_disable(&ch->napi);
+               ltq_dma_close(&ch->dma);
+       }
+       return 0;
+}
+
+static int
+ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       int queue = skb_get_queue_mapping(skb);
+       struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
+       struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+       int len;
+       unsigned long flags;
+       u32 byte_offset;
+
+       len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+       if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+               dev_kfree_skb_any(skb);
+               netdev_err(dev, "tx ring full\n");
+               netif_tx_stop_queue(txq);
+               return NETDEV_TX_BUSY;
+       }
+
+       /* dma needs to start on a 16 byte aligned address */
+       byte_offset = CPHYSADDR(skb->data) % 16;
+       ch->skb[ch->dma.desc] = skb;
+
+       dev->trans_start = jiffies;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
+                                               DMA_TO_DEVICE)) - byte_offset;
+       wmb();
+       desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+               LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+       ch->dma.desc++;
+       ch->dma.desc %= LTQ_DESC_NUM;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
+               netif_tx_stop_queue(txq);
+
+       return NETDEV_TX_OK;
+}
+
+static int
+ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
+{
+       int ret = eth_change_mtu(dev, new_mtu);
+
+       if (!ret) {
+               struct ltq_etop_priv *priv = netdev_priv(dev);
+               unsigned long flags;
+
+               spin_lock_irqsave(&priv->lock, flags);
+               ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
+                       LTQ_ETOP_IGPLEN);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       return ret;
+}
+
+static int
+ltq_etop_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+
+       /* TODO: mii-toll reports "No MII transceiver present!." ?!*/
+       return phy_mii_ioctl(priv->phydev, rq, cmd);
+}
+
+static int
+ltq_etop_set_mac_address(struct net_device *dev, void *p)
+{
+       int ret = eth_mac_addr(dev, p);
+
+       if (!ret) {
+               struct ltq_etop_priv *priv = netdev_priv(dev);
+               unsigned long flags;
+
+               /* store the mac for the unicast filter */
+               spin_lock_irqsave(&priv->lock, flags);
+               ltq_etop_w32(*((u32 *)dev->dev_addr), LTQ_ETOP_MAC_DA0);
+               ltq_etop_w32(*((u16 *)&dev->dev_addr[4]) << 16,
+                       LTQ_ETOP_MAC_DA1);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       return ret;
+}
+
+static void
+ltq_etop_set_multicast_list(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       /* ensure that the unicast filter is not enabled in promiscious mode */
+       spin_lock_irqsave(&priv->lock, flags);
+       if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI))
+               ltq_etop_w32_mask(ETOP_FTCU, 0, LTQ_ETOP_ENETS0);
+       else
+               ltq_etop_w32_mask(0, ETOP_FTCU, LTQ_ETOP_ENETS0);
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static u16
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       /* we are currently only using the first queue */
+       return 0;
+}
+
+static int
+ltq_etop_init(struct net_device *dev)
+{
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       struct sockaddr mac;
+       int err;
+
+       ether_setup(dev);
+       dev->watchdog_timeo = 10 * HZ;
+       err = ltq_etop_hw_init(dev);
+       if (err)
+               goto err_hw;
+       ltq_etop_change_mtu(dev, 1500);
+
+       memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+       if (!is_valid_ether_addr(mac.sa_data)) {
+               pr_warn("etop: invalid MAC, using random\n");
+               random_ether_addr(mac.sa_data);
+       }
+
+       err = ltq_etop_set_mac_address(dev, &mac);
+       if (err)
+               goto err_netdev;
+       ltq_etop_set_multicast_list(dev);
+       err = ltq_etop_mdio_init(dev);
+       if (err)
+               goto err_netdev;
+       return 0;
+
+err_netdev:
+       unregister_netdev(dev);
+       free_netdev(dev);
+err_hw:
+       ltq_etop_hw_exit(dev);
+       return err;
+}
+
+static void
+ltq_etop_tx_timeout(struct net_device *dev)
+{
+       int err;
+
+       ltq_etop_hw_exit(dev);
+       err = ltq_etop_hw_init(dev);
+       if (err)
+               goto err_hw;
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+       return;
+
+err_hw:
+       ltq_etop_hw_exit(dev);
+       netdev_err(dev, "failed to restart etop after TX timeout\n");
+}
+
+static const struct net_device_ops ltq_eth_netdev_ops = {
+       .ndo_open = ltq_etop_open,
+       .ndo_stop = ltq_etop_stop,
+       .ndo_start_xmit = ltq_etop_tx,
+       .ndo_change_mtu = ltq_etop_change_mtu,
+       .ndo_do_ioctl = ltq_etop_ioctl,
+       .ndo_set_mac_address = ltq_etop_set_mac_address,
+       .ndo_validate_addr = eth_validate_addr,
+       .ndo_set_multicast_list = ltq_etop_set_multicast_list,
+       .ndo_select_queue = ltq_etop_select_queue,
+       .ndo_init = ltq_etop_init,
+       .ndo_tx_timeout = ltq_etop_tx_timeout,
+};
+
+static int __init
+ltq_etop_probe(struct platform_device *pdev)
+{
+       struct net_device *dev;
+       struct ltq_etop_priv *priv;
+       struct resource *res;
+       int err;
+       int i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get etop resource\n");
+               err = -ENOENT;
+               goto err_out;
+       }
+
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               resource_size(res), dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev, "failed to request etop resource\n");
+               err = -EBUSY;
+               goto err_out;
+       }
+
+       ltq_etop_membase = devm_ioremap_nocache(&pdev->dev,
+               res->start, resource_size(res));
+       if (!ltq_etop_membase) {
+               dev_err(&pdev->dev, "failed to remap etop engine %d\n",
+                       pdev->id);
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+       strcpy(dev->name, "eth%d");
+       dev->netdev_ops = &ltq_eth_netdev_ops;
+       dev->ethtool_ops = &ltq_etop_ethtool_ops;
+       priv = netdev_priv(dev);
+       priv->res = res;
+       priv->pldata = dev_get_platdata(&pdev->dev);
+       priv->netdev = dev;
+       spin_lock_init(&priv->lock);
+
+       for (i = 0; i < MAX_DMA_CHAN; i++) {
+               if (IS_TX(i))
+                       netif_napi_add(dev, &priv->ch[i].napi,
+                               ltq_etop_poll_tx, 8);
+               else if (IS_RX(i))
+                       netif_napi_add(dev, &priv->ch[i].napi,
+                               ltq_etop_poll_rx, 32);
+               priv->ch[i].netdev = dev;
+       }
+
+       err = register_netdev(dev);
+       if (err)
+               goto err_free;
+
+       platform_set_drvdata(pdev, dev);
+       return 0;
+
+err_free:
+       kfree(dev);
+err_out:
+       return err;
+}
+
+static int __devexit
+ltq_etop_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (dev) {
+               netif_tx_stop_all_queues(dev);
+               ltq_etop_hw_exit(dev);
+               ltq_etop_mdio_cleanup(dev);
+               unregister_netdev(dev);
+       }
+       return 0;
+}
+
+static struct platform_driver ltq_mii_driver = {
+       .remove = __devexit_p(ltq_etop_remove),
+       .driver = {
+               .name = "ltq_etop",
+               .owner = THIS_MODULE,
+       },
+};
+
+int __init
+init_ltq_etop(void)
+{
+       int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
+
+       if (ret)
+               pr_err("ltq_etop: Error registering platfom driver!");
+       return ret;
+}
+
+static void __exit
+exit_ltq_etop(void)
+{
+       platform_driver_unregister(&ltq_mii_driver);
+}
+
+module_init(init_ltq_etop);
+module_exit(exit_ltq_etop);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC ETOP");
+MODULE_LICENSE("GPL");
index ea0dc451da9c874716c689a051cb967082c8bf6b..d70fb76edb7717062544a3c87d27e5799d0348c9 100644 (file)
@@ -173,7 +173,8 @@ static void loopback_setup(struct net_device *dev)
                | NETIF_F_RXCSUM
                | NETIF_F_HIGHDMA
                | NETIF_F_LLTX
-               | NETIF_F_NETNS_LOCAL;
+               | NETIF_F_NETNS_LOCAL
+               | NETIF_F_VLAN_CHALLENGED;
        dev->ethtool_ops        = &loopback_ethtool_ops;
        dev->header_ops         = &eth_header_ops;
        dev->netdev_ops         = &loopback_ops;
index 78e34e9e4f0082c12baf559ad0a242c2c48f2231..d8e4e69ad0b93f4b606de725b1b7b80e88f3cf54 100644 (file)
@@ -603,21 +603,13 @@ static int macvlan_port_create(struct net_device *dev)
        return err;
 }
 
-static void macvlan_port_rcu_free(struct rcu_head *head)
-{
-       struct macvlan_port *port;
-
-       port = container_of(head, struct macvlan_port, rcu);
-       kfree(port);
-}
-
 static void macvlan_port_destroy(struct net_device *dev)
 {
        struct macvlan_port *port = macvlan_port_get(dev);
 
        dev->priv_flags &= ~IFF_MACVLAN_PORT;
        netdev_rx_handler_unregister(dev);
-       call_rcu(&port->rcu, macvlan_port_rcu_free);
+       kfree_rcu(port, rcu);
 }
 
 static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
index 0a6c6a2e7550f17235827811be88140ba891a0f6..d4fc00b1ff93442f699844517736a0ac1b6a0bde 100644 (file)
@@ -49,6 +49,10 @@ static u32 mii_get_an(struct mii_if_info *mii, u16 addr)
                result |= ADVERTISED_100baseT_Half;
        if (advert & ADVERTISE_100FULL)
                result |= ADVERTISED_100baseT_Full;
+       if (advert & ADVERTISE_PAUSE_CAP)
+               result |= ADVERTISED_Pause;
+       if (advert & ADVERTISE_PAUSE_ASYM)
+               result |= ADVERTISED_Asym_Pause;
 
        return result;
 }
index aa2813e06d0033ebcc48f07967c884d9b20735d8..1074231f0a0d722a803bcc968372d9705b582a53 100644 (file)
@@ -860,6 +860,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
                prev_eedata = eedata;
        }
 
+       /* Store MAC Address in perm_addr */
+       memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+
        dev->base_addr = (unsigned long __force) ioaddr;
        dev->irq = irq;
 
index 30be8c634ebdd3722bd3c3e965348ccd638d12e2..7298a34bc7951d733f4de4071acc14aa5eab42e4 100644 (file)
@@ -167,7 +167,7 @@ static void cleanup_card(struct net_device *dev)
 #ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
-       struct net_device *dev = alloc_ei_netdev();
+       struct net_device *dev = ____alloc_ei_netdev(0);
        int err;
 
        if (!dev)
@@ -197,15 +197,15 @@ static const struct net_device_ops ne_netdev_ops = {
        .ndo_open               = ne_open,
        .ndo_stop               = ne_close,
 
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
+       .ndo_poll_controller    = __ei_poll,
 #endif
 };
 
@@ -637,7 +637,7 @@ int init_module(void)
        int err;
 
        for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = alloc_ei_netdev();
+               struct net_device *dev = ____alloc_ei_netdev(0);
                if (!dev)
                        break;
                if (io[this_dev]) {
index dfb67eb2a94b726cb590f8b3a015d98a719866d1..eb41e44921e665c3863dd82860b7c44413c7ef5e 100644 (file)
@@ -671,6 +671,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
                goto done;
 
        spin_lock_irqsave(&target_list_lock, flags);
+restart:
        list_for_each_entry(nt, &target_list, list) {
                netconsole_target_get(nt);
                if (nt->np.dev == dev) {
@@ -683,9 +684,16 @@ static int netconsole_netdev_event(struct notifier_block *this,
                                 * rtnl_lock already held
                                 */
                                if (nt->np.dev) {
+                                       spin_unlock_irqrestore(
+                                                             &target_list_lock,
+                                                             flags);
                                        __netpoll_cleanup(&nt->np);
+                                       spin_lock_irqsave(&target_list_lock,
+                                                         flags);
                                        dev_put(nt->np.dev);
                                        nt->np.dev = NULL;
+                                       netconsole_target_put(nt);
+                                       goto restart;
                                }
                                /* Fall through */
                        case NETDEV_GOING_DOWN:
index d7299f1a49401dc57d84610696008e63b90efe98..679dc8519c5b6db3c5916f81197b7413b66c44cc 100644 (file)
 
 #define        MAX_NUM_CARDS           4
 
-#define MAX_BUFFERS_PER_CMD    32
+#define NETXEN_MAX_FRAGS_PER_TX        14
 #define MAX_TSO_HEADER_DESC    2
 #define MGMT_CMD_DESC_RESV     4
 #define TX_STOP_THRESH         ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
@@ -558,7 +558,7 @@ struct netxen_recv_crb {
  */
 struct netxen_cmd_buffer {
        struct sk_buff *skb;
-       struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+       struct netxen_skb_frag frag_array[MAX_SKB_FRAGS + 1];
        u32 frag_count;
 };
 
index 83348dc4b184c5f8afbafc892b0c91dccd0dce13..e8a4b66559999b2fef6e375fb568abfa8f663786 100644 (file)
@@ -1844,6 +1844,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc, *first_desc;
        struct pci_dev *pdev;
        int i, k;
+       int delta = 0;
+       struct skb_frag_struct *frag;
 
        u32 producer;
        int frag_count, no_of_desc;
@@ -1851,6 +1853,21 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        frag_count = skb_shinfo(skb)->nr_frags + 1;
 
+       /* 14 frags supported for normal packet and
+        * 32 frags supported for TSO packet
+        */
+       if (!skb_is_gso(skb) && frag_count > NETXEN_MAX_FRAGS_PER_TX) {
+
+               for (i = 0; i < (frag_count - NETXEN_MAX_FRAGS_PER_TX); i++) {
+                       frag = &skb_shinfo(skb)->frags[i];
+                       delta += frag->size;
+               }
+
+               if (!__pskb_pull_tail(skb, delta))
+                       goto drop_packet;
+
+               frag_count = 1 + skb_shinfo(skb)->nr_frags;
+       }
        /* 4 fragments per cmd des */
        no_of_desc = (frag_count + 3) >> 2;
 
index 2ef2f9cdefa6ff1f0d991d734c340960486f420a..56d049a472da4ed41e426968d00e0034dda2bf1e 100644 (file)
@@ -34,6 +34,10 @@ const char pch_driver_version[] = DRV_VERSION;
 #define PCH_GBE_COPYBREAK_DEFAULT      256
 #define PCH_GBE_PCI_BAR                        1
 
+/* Macros for ML7223 */
+#define PCI_VENDOR_ID_ROHM                     0x10db
+#define PCI_DEVICE_ID_ROHM_ML7223_GBE          0x8013
+
 #define PCH_GBE_TX_WEIGHT         64
 #define PCH_GBE_RX_WEIGHT         64
 #define PCH_GBE_RX_BUFFER_WRITE   16
@@ -43,8 +47,7 @@ const char pch_driver_version[] = DRV_VERSION;
 
 #define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \
        PCH_GBE_CHIP_TYPE_INTERNAL | \
-       PCH_GBE_RGMII_MODE_RGMII   | \
-       PCH_GBE_CRS_SEL              \
+       PCH_GBE_RGMII_MODE_RGMII     \
        )
 
 /* Ethertype field values */
@@ -1494,12 +1497,11 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
                        /* Write meta date of skb */
                        skb_put(skb, length);
                        skb->protocol = eth_type_trans(skb, netdev);
-                       if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) ==
-                           PCH_GBE_RXD_ACC_STAT_TCPIPOK) {
-                               skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       } else {
+                       if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
                                skb->ip_summed = CHECKSUM_NONE;
-                       }
+                       else
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+
                        napi_gro_receive(&adapter->napi, skb);
                        (*work_done)++;
                        pr_debug("Receive skb->ip_summed: %d length: %d\n",
@@ -2420,6 +2422,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
         .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
         .class_mask = (0xFFFF00)
         },
+       {.vendor = PCI_VENDOR_ID_ROHM,
+        .device = PCI_DEVICE_ID_ROHM_ML7223_GBE,
+        .subvendor = PCI_ANY_ID,
+        .subdevice = PCI_ANY_ID,
+        .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+        .class_mask = (0xFFFF00)
+        },
        /* required last entry */
        {0}
 };
index dc44564ef6f9984fdc9a214491d9bdced015eb80..b0dead00b2d1d6b7809bd2b01906b5bff5a786b5 100644 (file)
@@ -99,6 +99,7 @@
 #define TX_UDPV6_PKT   0x0c
 
 /* Tx defines */
+#define QLCNIC_MAX_FRAGS_PER_TX        14
 #define MAX_TSO_HEADER_DESC    2
 #define MGMT_CMD_DESC_RESV     4
 #define TX_STOP_THRESH         ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
index cd88c7e1bfa9c76c3ae156da021a020f27346be5..cb1a1ef36c0ade56ddb5dfb98c2ef2ce8813b100 100644 (file)
@@ -2099,6 +2099,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc, *first_desc;
        struct pci_dev *pdev;
        struct ethhdr *phdr;
+       int delta = 0;
        int i, k;
 
        u32 producer;
@@ -2118,6 +2119,19 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }
 
        frag_count = skb_shinfo(skb)->nr_frags + 1;
+       /* 14 frags supported for normal packet and
+        * 32 frags supported for TSO packet
+        */
+       if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+
+               for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+                       delta += skb_shinfo(skb)->frags[i].size;
+
+               if (!__pskb_pull_tail(skb, delta))
+                       goto drop_packet;
+
+               frag_count = 1 + skb_shinfo(skb)->nr_frags;
+       }
 
        /* 4 fragments per cmd des */
        no_of_desc = (frag_count + 3) >> 2;
index 493b0de3848bf17fadd6741ad57d5b4701b2f074..397c36810a159ad7dfc143a819303e059008fe56 100644 (file)
@@ -170,6 +170,16 @@ static const struct {
 };
 #undef _R
 
+static const struct rtl_firmware_info {
+       int mac_version;
+       const char *fw_name;
+} rtl_firmware_infos[] = {
+       { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 },
+       { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 },
+       { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 },
+       { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }
+};
+
 enum cfg_version {
        RTL_CFG_0 = 0x00,
        RTL_CFG_1,
@@ -565,6 +575,7 @@ struct rtl8169_private {
        u32 saved_wolopts;
 
        const struct firmware *fw;
+#define RTL_FIRMWARE_UNKNOWN   ERR_PTR(-EAGAIN);
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -1789,25 +1800,26 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 
 static void rtl_release_firmware(struct rtl8169_private *tp)
 {
-       release_firmware(tp->fw);
-       tp->fw = NULL;
+       if (!IS_ERR_OR_NULL(tp->fw))
+               release_firmware(tp->fw);
+       tp->fw = RTL_FIRMWARE_UNKNOWN;
 }
 
-static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
+static void rtl_apply_firmware(struct rtl8169_private *tp)
 {
-       const struct firmware **fw = &tp->fw;
-       int rc = !*fw;
-
-       if (rc) {
-               rc = request_firmware(fw, fw_name, &tp->pci_dev->dev);
-               if (rc < 0)
-                       goto out;
-       }
+       const struct firmware *fw = tp->fw;
 
        /* TODO: release firmware once rtl_phy_write_fw signals failures. */
-       rtl_phy_write_fw(tp, *fw);
-out:
-       return rc;
+       if (!IS_ERR_OR_NULL(fw))
+               rtl_phy_write_fw(tp, fw);
+}
+
+static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
+{
+       if (rtl_readphy(tp, reg) != val)
+               netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
+       else
+               rtl_apply_firmware(tp);
 }
 
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
@@ -2246,10 +2258,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
 
        rtl_writephy(tp, 0x1f, 0x0005);
        rtl_writephy(tp, 0x05, 0x001b);
-       if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
-           (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-       }
+
+       rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
 
        rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2351,10 +2361,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
 
        rtl_writephy(tp, 0x1f, 0x0005);
        rtl_writephy(tp, 0x05, 0x001b);
-       if ((rtl_readphy(tp, 0x06) != 0xb300) ||
-           (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-       }
+
+       rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
 
        rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2474,8 +2482,7 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x18, 0x0310);
        msleep(100);
 
-       if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0)
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+       rtl_apply_firmware(tp);
 
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
@@ -3237,6 +3244,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->timer.data = (unsigned long) dev;
        tp->timer.function = rtl8169_phy_timer;
 
+       tp->fw = RTL_FIRMWARE_UNKNOWN;
+
        rc = register_netdev(dev);
        if (rc < 0)
                goto err_out_msi_4;
@@ -3288,10 +3297,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 
        cancel_delayed_work_sync(&tp->task);
 
-       rtl_release_firmware(tp);
-
        unregister_netdev(dev);
 
+       rtl_release_firmware(tp);
+
        if (pci_dev_run_wake(pdev))
                pm_runtime_get_noresume(&pdev->dev);
 
@@ -3303,6 +3312,37 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
+static void rtl_request_firmware(struct rtl8169_private *tp)
+{
+       int i;
+
+       /* Return early if the firmware is already loaded / cached. */
+       if (!IS_ERR(tp->fw))
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) {
+               const struct rtl_firmware_info *info = rtl_firmware_infos + i;
+
+               if (info->mac_version == tp->mac_version) {
+                       const char *name = info->fw_name;
+                       int rc;
+
+                       rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
+                       if (rc < 0) {
+                               netif_warn(tp, ifup, tp->dev, "unable to load "
+                                       "firmware patch %s (%d)\n", name, rc);
+                               goto out_disable_request_firmware;
+                       }
+                       goto out;
+               }
+       }
+
+out_disable_request_firmware:
+       tp->fw = NULL;
+out:
+       return;
+}
+
 static int rtl8169_open(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -3334,11 +3374,13 @@ static int rtl8169_open(struct net_device *dev)
 
        smp_mb();
 
+       rtl_request_firmware(tp);
+
        retval = request_irq(dev->irq, rtl8169_interrupt,
                             (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
                             dev->name, dev);
        if (retval < 0)
-               goto err_release_ring_2;
+               goto err_release_fw_2;
 
        napi_enable(&tp->napi);
 
@@ -3359,7 +3401,8 @@ static int rtl8169_open(struct net_device *dev)
 out:
        return retval;
 
-err_release_ring_2:
+err_release_fw_2:
+       rtl_release_firmware(tp);
        rtl8169_rx_clear(tp);
 err_free_rx_1:
        dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
index d890679e4c4d293538b0e8d98cb1f34466e23947..a3c2aab53de8d29407e11386e51c7fefcd00c402 100644 (file)
@@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget)
  * processing to finish, then directly poll (and ack ) the eventq.
  * Finally reenable NAPI and interrupts.
  *
- * Since we are touching interrupts the caller should hold the suspend lock
+ * This is for use only during a loopback self-test.  It must not
+ * deliver any packets up the stack as this can result in deadlock.
  */
 void efx_process_channel_now(struct efx_channel *channel)
 {
@@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel)
 
        BUG_ON(channel->channel >= efx->n_channels);
        BUG_ON(!channel->enabled);
+       BUG_ON(!efx->loopback_selftest);
 
        /* Disable interrupts and wait for ISRs to complete */
        efx_nic_disable_interrupts(efx);
@@ -1436,7 +1438,7 @@ static void efx_start_all(struct efx_nic *efx)
         * restart the transmit interface early so the watchdog timer stops */
        efx_start_port(efx);
 
-       if (efx_dev_registered(efx))
+       if (efx_dev_registered(efx) && !efx->port_inhibited)
                netif_tx_wake_all_queues(efx->net_dev);
 
        efx_for_each_channel(channel, efx)
index d9d8c2ef1074a3de6278eff70d7894cc8cc65991..cc978803d484bf84510ca5beb24ca41dd83a93ba 100644 (file)
@@ -152,6 +152,7 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value,
 
        spin_lock_irqsave(&efx->biu_lock, flags);
        value->u32[0] = _efx_readd(efx, reg + 0);
+       rmb();
        value->u32[1] = _efx_readd(efx, reg + 4);
        value->u32[2] = _efx_readd(efx, reg + 8);
        value->u32[3] = _efx_readd(efx, reg + 12);
@@ -174,6 +175,7 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
        value->u64[0] = (__force __le64)__raw_readq(membase + addr);
 #else
        value->u32[0] = (__force __le32)__raw_readl(membase + addr);
+       rmb();
        value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
 #endif
        spin_unlock_irqrestore(&efx->biu_lock, flags);
index d98479030ef2c3e3dbac1d9a0c0f4a3f1262e91f..3dd45ed61f0a33f5368c56df8347e1f3f5a7f1af 100644 (file)
@@ -50,6 +50,20 @@ static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
        return &nic_data->mcdi;
 }
 
+static inline void
+efx_mcdi_readd(struct efx_nic *efx, efx_dword_t *value, unsigned reg)
+{
+       struct siena_nic_data *nic_data = efx->nic_data;
+       value->u32[0] = (__force __le32)__raw_readl(nic_data->mcdi_smem + reg);
+}
+
+static inline void
+efx_mcdi_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned reg)
+{
+       struct siena_nic_data *nic_data = efx->nic_data;
+       __raw_writel((__force u32)value->u32[0], nic_data->mcdi_smem + reg);
+}
+
 void efx_mcdi_init(struct efx_nic *efx)
 {
        struct efx_mcdi_iface *mcdi;
@@ -70,8 +84,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
                            const u8 *inbuf, size_t inlen)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
-       unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
-       unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
+       unsigned pdu = MCDI_PDU(efx);
+       unsigned doorbell = MCDI_DOORBELL(efx);
        unsigned int i;
        efx_dword_t hdr;
        u32 xflags, seqno;
@@ -92,30 +106,28 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
                             MCDI_HEADER_SEQ, seqno,
                             MCDI_HEADER_XFLAGS, xflags);
 
-       efx_writed(efx, &hdr, pdu);
+       efx_mcdi_writed(efx, &hdr, pdu);
 
-       for (i = 0; i < inlen; i += 4) {
-               _efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i);
-               /* use wmb() within loop to inhibit write combining */
-               wmb();
-       }
+       for (i = 0; i < inlen; i += 4)
+               efx_mcdi_writed(efx, (const efx_dword_t *)(inbuf + i),
+                               pdu + 4 + i);
 
        /* ring the doorbell with a distinctive value */
-       _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
-       wmb();
+       EFX_POPULATE_DWORD_1(hdr, EFX_DWORD_0, 0x45789abc);
+       efx_mcdi_writed(efx, &hdr, doorbell);
 }
 
 static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
-       unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+       unsigned int pdu = MCDI_PDU(efx);
        int i;
 
        BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
        BUG_ON(outlen & 3 || outlen >= 0x100);
 
        for (i = 0; i < outlen; i += 4)
-               *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i);
+               efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i);
 }
 
 static int efx_mcdi_poll(struct efx_nic *efx)
@@ -123,7 +135,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
        unsigned int time, finish;
        unsigned int respseq, respcmd, error;
-       unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+       unsigned int pdu = MCDI_PDU(efx);
        unsigned int rc, spins;
        efx_dword_t reg;
 
@@ -149,8 +161,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 
                time = get_seconds();
 
-               rmb();
-               efx_readd(efx, &reg, pdu);
+               efx_mcdi_readd(efx, &reg, pdu);
 
                /* All 1's indicates that shared memory is in reset (and is
                 * not a valid header). Wait for it to come out reset before
@@ -177,7 +188,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
                          respseq, mcdi->seqno);
                rc = EIO;
        } else if (error) {
-               efx_readd(efx, &reg, pdu + 4);
+               efx_mcdi_readd(efx, &reg, pdu + 4);
                switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
 #define TRANSLATE_ERROR(name)                                  \
                case MC_CMD_ERR_ ## name:                       \
@@ -211,21 +222,21 @@ out:
 /* Test and clear MC-rebooted flag for this port/function */
 int efx_mcdi_poll_reboot(struct efx_nic *efx)
 {
-       unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx);
+       unsigned int addr = MCDI_REBOOT_FLAG(efx);
        efx_dword_t reg;
        uint32_t value;
 
        if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
                return false;
 
-       efx_readd(efx, &reg, addr);
+       efx_mcdi_readd(efx, &reg, addr);
        value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
 
        if (value == 0)
                return 0;
 
        EFX_ZERO_DWORD(reg);
-       efx_writed(efx, &reg, addr);
+       efx_mcdi_writed(efx, &reg, addr);
 
        if (value == MC_STATUS_DWORD_ASSERT)
                return -EINTR;
index 9ffa9a6b55a0b3cf76009bf146b7eee0c74a3750..191a311da2dc77b4bfa65bcb927148cf791a54a0 100644 (file)
@@ -330,7 +330,6 @@ enum efx_rx_alloc_method {
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
- * @magic_count: Event queue test event count
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -360,7 +359,6 @@ struct efx_channel {
        unsigned int eventq_mask;
        unsigned int eventq_read_ptr;
        unsigned int last_eventq_read_ptr;
-       unsigned int magic_count;
 
        unsigned int irq_count;
        unsigned int irq_mod_score;
index e8396614daf38b4e7d7c923a65d2bb109f066d98..9b29a8d7c449d56d7fd838dd1204435165d2fbda 100644 (file)
@@ -84,7 +84,8 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
 static inline efx_qword_t *efx_event(struct efx_channel *channel,
                                     unsigned int index)
 {
-       return ((efx_qword_t *) (channel->eventq.addr)) + index;
+       return ((efx_qword_t *) (channel->eventq.addr)) +
+               (index & channel->eventq_mask);
 }
 
 /* See if an event is present
@@ -673,7 +674,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
        efx_dword_t reg;
        struct efx_nic *efx = channel->efx;
 
-       EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr);
+       EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
+                            channel->eventq_read_ptr & channel->eventq_mask);
        efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
                         channel->channel);
 }
@@ -908,7 +910,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
 
        code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
        if (code == EFX_CHANNEL_MAGIC_TEST(channel))
-               ++channel->magic_count;
+               ; /* ignore */
        else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
                /* The queue must be empty, so we won't receive any rx
                 * events, so efx_process_channel() won't refill the
@@ -1015,8 +1017,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
                /* Clear this event by marking it all ones */
                EFX_SET_QWORD(*p_event);
 
-               /* Increment read pointer */
-               read_ptr = (read_ptr + 1) & channel->eventq_mask;
+               ++read_ptr;
 
                ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
 
@@ -1060,6 +1061,13 @@ out:
        return spent;
 }
 
+/* Check whether an event is present in the eventq at the current
+ * read pointer.  Only useful for self-test.
+ */
+bool efx_nic_event_present(struct efx_channel *channel)
+{
+       return efx_event_present(efx_event(channel, channel->eventq_read_ptr));
+}
 
 /* Allocate buffer table entries for event queue */
 int efx_nic_probe_eventq(struct efx_channel *channel)
@@ -1165,7 +1173,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
        unsigned int read_ptr = channel->eventq_read_ptr;
-       unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
+       unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
 
        do {
                efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1205,7 +1213,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
                 * it's ok to throw away every non-flush event */
                EFX_SET_QWORD(*event);
 
-               read_ptr = (read_ptr + 1) & channel->eventq_mask;
+               ++read_ptr;
        } while (read_ptr != end_ptr);
 
        channel->eventq_read_ptr = read_ptr;
@@ -1929,6 +1937,13 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
 
                size = min_t(size_t, table->step, 16);
 
+               if (table->offset >= efx->type->mem_map_size) {
+                       /* No longer mapped; return dummy data */
+                       memcpy(buf, "\xde\xc0\xad\xde", 4);
+                       buf += table->rows * size;
+                       continue;
+               }
+
                for (i = 0; i < table->rows; i++) {
                        switch (table->step) {
                        case 4: /* 32-bit register or SRAM */
index d9de1b647d416b601f62cb1e6a1a6f56f09a4830..d91701abd331c0680756b3b92a2f3ed95cf649fb 100644 (file)
@@ -143,10 +143,12 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
 /**
  * struct siena_nic_data - Siena NIC state
  * @mcdi: Management-Controller-to-Driver Interface
+ * @mcdi_smem: MCDI shared memory mapping. The mapping is always uncacheable.
  * @wol_filter_id: Wake-on-LAN packet filter id
  */
 struct siena_nic_data {
        struct efx_mcdi_iface mcdi;
+       void __iomem *mcdi_smem;
        int wol_filter_id;
 };
 
@@ -184,6 +186,7 @@ extern void efx_nic_fini_eventq(struct efx_channel *channel);
 extern void efx_nic_remove_eventq(struct efx_channel *channel);
 extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
 extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
+extern bool efx_nic_event_present(struct efx_channel *channel);
 
 /* MAC/PHY */
 extern void falcon_drain_tx_fifo(struct efx_nic *efx);
index a0f49b348d62872be7512019083badfc50ab9db8..50ad3bcaf68a243ec41d78d72e1cd358c0455e59 100644 (file)
@@ -131,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
 static int efx_test_interrupts(struct efx_nic *efx,
                               struct efx_self_tests *tests)
 {
-       struct efx_channel *channel;
-
        netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
        tests->interrupt = -1;
 
@@ -140,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx,
        efx->last_irq_cpu = -1;
        smp_wmb();
 
-       /* ACK each interrupting event queue. Receiving an interrupt due to
-        * traffic before a test event is raised is considered a pass */
-       efx_for_each_channel(channel, efx) {
-               if (channel->work_pending)
-                       efx_process_channel_now(channel);
-               if (efx->last_irq_cpu >= 0)
-                       goto success;
-       }
-
        efx_nic_generate_interrupt(efx);
 
        /* Wait for arrival of test interrupt. */
@@ -173,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
                               struct efx_self_tests *tests)
 {
        struct efx_nic *efx = channel->efx;
-       unsigned int magic_count, count;
+       unsigned int read_ptr, count;
 
        tests->eventq_dma[channel->channel] = -1;
        tests->eventq_int[channel->channel] = -1;
        tests->eventq_poll[channel->channel] = -1;
 
-       magic_count = channel->magic_count;
+       read_ptr = channel->eventq_read_ptr;
        channel->efx->last_irq_cpu = -1;
        smp_wmb();
 
@@ -190,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
        do {
                schedule_timeout_uninterruptible(HZ / 100);
 
-               if (channel->work_pending)
-                       efx_process_channel_now(channel);
-
-               if (channel->magic_count != magic_count)
+               if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
                        goto eventq_ok;
        } while (++count < 2);
 
@@ -211,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
        }
 
        /* Check to see if event was received even if interrupt wasn't */
-       efx_process_channel_now(channel);
-       if (channel->magic_count != magic_count) {
+       if (efx_nic_event_present(channel)) {
                netif_err(efx, drv, efx->net_dev,
                          "channel %d event was generated, but "
                          "failed to trigger an interrupt\n", channel->channel);
@@ -770,6 +755,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
        __efx_reconfigure_port(efx);
        mutex_unlock(&efx->mac_lock);
 
+       netif_tx_wake_all_queues(efx->net_dev);
+
        return rc_test;
 }
 
index e4dd8986b1feaa6c5b848dc8f8c948c4305592d8..837869b71db97f590b1b133eea717f78b2284ab1 100644 (file)
@@ -220,12 +220,26 @@ static int siena_probe_nic(struct efx_nic *efx)
        efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
        efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
 
+       /* Initialise MCDI */
+       nic_data->mcdi_smem = ioremap_nocache(efx->membase_phys +
+                                             FR_CZ_MC_TREG_SMEM,
+                                             FR_CZ_MC_TREG_SMEM_STEP *
+                                             FR_CZ_MC_TREG_SMEM_ROWS);
+       if (!nic_data->mcdi_smem) {
+               netif_err(efx, probe, efx->net_dev,
+                         "could not map MCDI at %llx+%x\n",
+                         (unsigned long long)efx->membase_phys +
+                         FR_CZ_MC_TREG_SMEM,
+                         FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS);
+               rc = -ENOMEM;
+               goto fail1;
+       }
        efx_mcdi_init(efx);
 
        /* Recover from a failed assertion before probing */
        rc = efx_mcdi_handle_assertion(efx);
        if (rc)
-               goto fail1;
+               goto fail2;
 
        /* Let the BMC know that the driver is now in charge of link and
         * filter settings. We must do this before we reset the NIC */
@@ -280,6 +294,7 @@ fail4:
 fail3:
        efx_mcdi_drv_attach(efx, false, NULL);
 fail2:
+       iounmap(nic_data->mcdi_smem);
 fail1:
        kfree(efx->nic_data);
        return rc;
@@ -359,6 +374,8 @@ static int siena_init_nic(struct efx_nic *efx)
 
 static void siena_remove_nic(struct efx_nic *efx)
 {
+       struct siena_nic_data *nic_data = efx->nic_data;
+
        efx_nic_free_buffer(efx, &efx->irq_status);
 
        siena_reset_hw(efx, RESET_TYPE_ALL);
@@ -368,7 +385,8 @@ static void siena_remove_nic(struct efx_nic *efx)
                efx_mcdi_drv_attach(efx, false, NULL);
 
        /* Tear down the private nic state */
-       kfree(efx->nic_data);
+       iounmap(nic_data->mcdi_smem);
+       kfree(nic_data);
        efx->nic_data = NULL;
 }
 
@@ -606,8 +624,7 @@ struct efx_nic_type siena_a0_nic_type = {
        .default_mac_ops = &efx_mcdi_mac_operations,
 
        .revision = EFX_REV_SIENA_A0,
-       .mem_map_size = (FR_CZ_MC_TREG_SMEM +
-                        FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS),
+       .mem_map_size = FR_CZ_MC_TREG_SMEM, /* MC_TREG_SMEM mapped separately */
        .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
        .rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
        .buf_tbl_base = FR_BZ_BUF_FULL_TBL,
index 13980190821762aa47a31729b688e5b36001ef77..d2c85dfdf3bf3a338349dbe21a5547d99cd6c98a 100644 (file)
@@ -435,7 +435,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
         * queue state. */
        smp_mb();
        if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
-           likely(efx->port_enabled)) {
+           likely(efx->port_enabled) &&
+           likely(!efx->port_inhibited)) {
                fill_level = tx_queue->insert_count - tx_queue->read_count;
                if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
                        EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
index cb317cd069ffcb5d13fa2fe5a5d920049b23ffeb..484f795a779dbca9b20e4f089d06cf1b9e253a50 100644 (file)
@@ -240,7 +240,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
  *     @net_dev: the net device to get address for
  *
  *     Older SiS900 and friends, use EEPROM to store MAC address.
- *     MAC address is read from read_eeprom() into @net_dev->dev_addr.
+ *     MAC address is read from read_eeprom() into @net_dev->dev_addr and
+ *     @net_dev->perm_addr.
  */
 
 static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
@@ -261,6 +262,9 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
        for (i = 0; i < 3; i++)
                ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        return 1;
 }
 
@@ -271,7 +275,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
  *
  *     SiS630E model, use APC CMOS RAM to store MAC address.
  *     APC CMOS RAM is accessed through ISA bridge.
- *     MAC address is read into @net_dev->dev_addr.
+ *     MAC address is read into @net_dev->dev_addr and
+ *     @net_dev->perm_addr.
  */
 
 static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
@@ -296,6 +301,10 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
                outb(0x09 + i, 0x70);
                ((u8 *)(net_dev->dev_addr))[i] = inb(0x71);
        }
+
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
        pci_dev_put(isa_bridge);
 
@@ -310,7 +319,7 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
  *
  *     SiS635 model, set MAC Reload Bit to load Mac address from APC
  *     to rfdr. rfdr is accessed through rfcr. MAC address is read into
- *     @net_dev->dev_addr.
+ *     @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
@@ -334,6 +343,9 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
                *( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
        }
 
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        /* enable packet filtering */
        outl(rfcrSave | RFEN, rfcr + ioaddr);
 
@@ -353,7 +365,7 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
  *     EEDONE signal to refuse EEPROM access by LAN.
  *     The EEPROM map of SiS962 or SiS963 is different to SiS900.
  *     The signature field in SiS962 or SiS963 spec is meaningless.
- *     MAC address is read into @net_dev->dev_addr.
+ *     MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
@@ -372,6 +384,9 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
                        for (i = 0; i < 3; i++)
                                ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+                       /* Store MAC Address in perm_addr */
+                       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
                        outl(EEDONE, ee_addr);
                        return 1;
                } else {
index 86cbb9ea2f269ee2532078dea529eebdb8cc0a9f..8ec1a9a0bb9ae007c69865b2599f07d3f23c99c8 100644 (file)
@@ -853,7 +853,9 @@ static int slip_open(struct tty_struct *tty)
        /* Done.  We have linked the TTY line to a channel. */
        rtnl_unlock();
        tty->receive_room = 65536;      /* We don't flow control */
-       return sl->dev->base_addr;
+
+       /* TTY layer expects 0 on success */
+       return 0;
 
 err_free_bufs:
        sl_free_bufs(sl);
index d65fab1ba790dfd0dba7af94bbf2506fc5566d7f..e25093510b0cd462af521f45aa5b3f43c98c0213 100644 (file)
@@ -26,9 +26,9 @@
 
 #undef DWMAC_DMA_DEBUG
 #ifdef DWMAC_DMA_DEBUG
-#define DBG(fmt, args...)  printk(fmt, ## args)
+#define DWMAC_LIB_DBG(fmt, args...)  printk(fmt, ## args)
 #else
-#define DBG(fmt, args...)  do { } while (0)
+#define DWMAC_LIB_DBG(fmt, args...)  do { } while (0)
 #endif
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
@@ -152,7 +152,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
        /* read the status register (CSR5) */
        u32 intr_status = readl(ioaddr + DMA_STATUS);
 
-       DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+       DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
 #ifdef DWMAC_DMA_DEBUG
        /* It displays the DMA process states (CSR5 register) */
        show_tx_process_state(intr_status);
@@ -160,43 +160,43 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
 #endif
        /* ABNORMAL interrupts */
        if (unlikely(intr_status & DMA_STATUS_AIS)) {
-               DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+               DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
                if (unlikely(intr_status & DMA_STATUS_UNF)) {
-                       DBG(INFO, "transmit underflow\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n");
                        ret = tx_hard_error_bump_tc;
                        x->tx_undeflow_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_TJT)) {
-                       DBG(INFO, "transmit jabber\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n");
                        x->tx_jabber_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_OVF)) {
-                       DBG(INFO, "recv overflow\n");
+                       DWMAC_LIB_DBG(KERN_INFO "recv overflow\n");
                        x->rx_overflow_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RU)) {
-                       DBG(INFO, "receive buffer unavailable\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n");
                        x->rx_buf_unav_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RPS)) {
-                       DBG(INFO, "receive process stopped\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n");
                        x->rx_process_stopped_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RWT)) {
-                       DBG(INFO, "receive watchdog\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n");
                        x->rx_watchdog_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_ETI)) {
-                       DBG(INFO, "transmit early interrupt\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n");
                        x->tx_early_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_TPS)) {
-                       DBG(INFO, "transmit process stopped\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n");
                        x->tx_process_stopped_irq++;
                        ret = tx_hard_error;
                }
                if (unlikely(intr_status & DMA_STATUS_FBI)) {
-                       DBG(INFO, "fatal bus error\n");
+                       DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n");
                        x->fatal_bus_error_irq++;
                        ret = tx_hard_error;
                }
@@ -215,7 +215,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
        /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
        writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
 
-       DBG(INFO, "\n\n");
+       DWMAC_LIB_DBG(KERN_INFO "\n\n");
        return ret;
 }
 
index 0e5f03135b50abd053712ca6ddaf1e14df76a241..cc973fc384052bc2a5315aa982237b5bbc31015f 100644 (file)
@@ -750,7 +750,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
                        priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
                        priv->xstats.threshold = tc;
                }
-               stmmac_tx_err(priv);
        } else if (unlikely(status == tx_hard_error))
                stmmac_tx_err(priv);
 }
@@ -781,21 +780,6 @@ static int stmmac_open(struct net_device *dev)
 
        stmmac_verify_args();
 
-       ret = stmmac_init_phy(dev);
-       if (unlikely(ret)) {
-               pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
-               return ret;
-       }
-
-       /* Request the IRQ lines */
-       ret = request_irq(dev->irq, stmmac_interrupt,
-                         IRQF_SHARED, dev->name, dev);
-       if (unlikely(ret < 0)) {
-               pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
-                      __func__, dev->irq, ret);
-               return ret;
-       }
-
 #ifdef CONFIG_STMMAC_TIMER
        priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
        if (unlikely(priv->tm == NULL)) {
@@ -814,6 +798,11 @@ static int stmmac_open(struct net_device *dev)
        } else
                priv->tm->enable = 1;
 #endif
+       ret = stmmac_init_phy(dev);
+       if (unlikely(ret)) {
+               pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+               goto open_error;
+       }
 
        /* Create and initialize the TX/RX descriptors chains. */
        priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
@@ -822,12 +811,11 @@ static int stmmac_open(struct net_device *dev)
        init_dma_desc_rings(dev);
 
        /* DMA initialization and SW reset */
-       if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
-                                        priv->dma_tx_phy,
-                                        priv->dma_rx_phy) < 0)) {
-
+       ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
+                                 priv->dma_tx_phy, priv->dma_rx_phy);
+       if (ret < 0) {
                pr_err("%s: DMA initialization failed\n", __func__);
-               return -1;
+               goto open_error;
        }
 
        /* Copy the MAC addr into the HW  */
@@ -848,6 +836,15 @@ static int stmmac_open(struct net_device *dev)
        writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
        writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
 
+       /* Request the IRQ lines */
+       ret = request_irq(dev->irq, stmmac_interrupt,
+                        IRQF_SHARED, dev->name, dev);
+       if (unlikely(ret < 0)) {
+               pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+                      __func__, dev->irq, ret);
+               goto open_error;
+       }
+
        /* Enable the MAC Rx/Tx */
        stmmac_enable_mac(priv->ioaddr);
 
@@ -878,7 +875,17 @@ static int stmmac_open(struct net_device *dev)
        napi_enable(&priv->napi);
        skb_queue_head_init(&priv->rx_recycle);
        netif_start_queue(dev);
+
        return 0;
+
+open_error:
+#ifdef CONFIG_STMMAC_TIMER
+       kfree(priv->tm);
+#endif
+       if (priv->phydev)
+               phy_disconnect(priv->phydev);
+
+       return ret;
 }
 
 /**
index eb4f59fb01e90cacc722a732e23ef46181747c61..bff2f7999ff0d36740632c8d35bdcbc067d9a756 100644 (file)
@@ -3237,15 +3237,18 @@ static void happy_meal_pci_exit(void)
 #endif
 
 #ifdef CONFIG_SBUS
+static const struct of_device_id hme_sbus_match[];
 static int __devinit hme_sbus_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        struct device_node *dp = op->dev.of_node;
        const char *model = of_get_property(dp, "model", NULL);
        int is_qfe;
 
-       if (!op->dev.of_match)
+       match = of_match_device(hme_sbus_match, &op->dev);
+       if (!match)
                return -EINVAL;
-       is_qfe = (op->dev.of_match->data != NULL);
+       is_qfe = (match->data != NULL);
 
        if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
                is_qfe = 1;
index b8c5f35577e45eb81e5f6a847b2831f9ce6f3619..7a5daefb6f3311e6e6d169113d7977e908045cbb 100644 (file)
@@ -12327,8 +12327,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if (val & VCPU_CFGSHDW_ASPM_DBNC)
                        tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
                if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
-                   (val & VCPU_CFGSHDW_WOL_MAGPKT))
+                   (val & VCPU_CFGSHDW_WOL_MAGPKT)) {
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
                goto done;
        }
 
@@ -12461,8 +12463,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
                if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
-                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
+                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)) {
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
 
                if (cfg2 & (1 << 17))
                        tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
index 8a3b191b195b8bc015694b5042fd67a340ecd421..ff32befd84433c98867a6b7a9d8824978e9e8557 100644 (file)
@@ -1251,7 +1251,7 @@ static netdev_tx_t xl_xmit(struct sk_buff *skb, struct net_device *dev)
 /* 
  * The NIC has told us that a packet has been downloaded onto the card, we must
  * find out which packet it has done, clear the skb and information for the packet
- * then advance around the ring for all tranmitted packets
+ * then advance around the ring for all transmitted packets
  */
 
 static void xl_dn_comp(struct net_device *dev) 
@@ -1568,7 +1568,7 @@ static void xl_arb_cmd(struct net_device *dev)
                        if (lan_status_diff & LSC_SOFT_ERR)
                                        printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN) 
-                                       printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+                                       printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
                        if (lan_status_diff & LSC_SS) 
                                        printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 5bd140704533f353fa6b7ee05a6cbd9445aec7ad..9354ca9da576c97f7ff54ed014480d29e877ec48 100644 (file)
@@ -1675,7 +1675,7 @@ drop_frame:
                        if (lan_status_diff & LSC_SOFT_ERR)
                                printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n", dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN)
-                               printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n", dev->name);
+                               printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n", dev->name);
                        if (lan_status_diff & LSC_SS)
                                printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 3d2fbe60b46e07f57e97f418ad62a903e908b26f..2684003b8ab6478037d1047328c61be4f02a8837 100644 (file)
@@ -1500,7 +1500,7 @@ drop_frame:
                        if (lan_status_diff & LSC_SOFT_ERR)
                                        printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN) 
-                                       printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+                                       printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
                        if (lan_status_diff & LSC_SS) 
                                        printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 341f7056a800ec2146c6187e3e9aca5ff6f7be5d..c924ea2bce07a4c06aa8d6ab5d9c23620b446915 100644 (file)
@@ -460,7 +460,7 @@ static const struct driver_info     cdc_info = {
        .manage_power = cdc_manage_power,
 };
 
-static const struct driver_info mbm_info = {
+static const struct driver_info wwan_info = {
        .description =  "Mobile Broadband Network Device",
        .flags =        FLAG_WWAN,
        .bind =         usbnet_cdc_bind,
@@ -471,6 +471,7 @@ static const struct driver_info mbm_info = {
 
 /*-------------------------------------------------------------------------*/
 
+#define HUAWEI_VENDOR_ID       0x12D1
 
 static const struct usb_device_id      products [] = {
 /*
@@ -566,7 +567,7 @@ static const struct usb_device_id   products [] = {
 {
        USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-       .driver_info            = 0,
+       .driver_info = (unsigned long)&wwan_info,
 },
 
 /*
@@ -587,8 +588,17 @@ static const struct usb_device_id  products [] = {
 }, {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
                        USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long)&mbm_info,
+       .driver_info = (unsigned long)&wwan_info,
 
+}, {
+       /* Various Huawei modems with a network port like the UMG1831 */
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = HUAWEI_VENDOR_ID,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = 255,
+       .driver_info = (unsigned long)&wwan_info,
 },
        { },            // END
 };
index 967371f04454205a1b147bddf27443a1e14f003a..1033ef6476a41a67ab0f8201dc0ad9218a8fe6de 100644 (file)
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
 
-#define        DRIVER_VERSION                          "7-Feb-2011"
+#define        DRIVER_VERSION                          "23-Apr-2011"
 
 /* CDC NCM subclass 3.2.1 */
 #define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
 
 /* Maximum NTB length */
-#define        CDC_NCM_NTB_MAX_SIZE_TX                 16384   /* bytes */
+#define        CDC_NCM_NTB_MAX_SIZE_TX                 (16384 + 4) /* bytes, must be short terminated */
 #define        CDC_NCM_NTB_MAX_SIZE_RX                 16384   /* bytes */
 
 /* Minimum value for MaxDatagramSize, ch. 6.2.9 */
index 7d42f9a2c06868027ac77c6265c76f9ce2288c27..81126ff85e0576e40b4d01aaf404044ffacfe1df 100644 (file)
@@ -65,6 +65,7 @@
 #define IPHETH_USBINTF_PROTO    1
 
 #define IPHETH_BUF_SIZE         1516
+#define IPHETH_IP_ALIGN                2       /* padding at front of URB */
 #define IPHETH_TX_TIMEOUT       (5 * HZ)
 
 #define IPHETH_INTFNUM          2
@@ -202,18 +203,21 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
                return;
        }
 
-       len = urb->actual_length;
-       buf = urb->transfer_buffer;
+       if (urb->actual_length <= IPHETH_IP_ALIGN) {
+               dev->net->stats.rx_length_errors++;
+               return;
+       }
+       len = urb->actual_length - IPHETH_IP_ALIGN;
+       buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
 
-       skb = dev_alloc_skb(NET_IP_ALIGN + len);
+       skb = dev_alloc_skb(len);
        if (!skb) {
                err("%s: dev_alloc_skb: -ENOMEM", __func__);
                dev->net->stats.rx_dropped++;
                return;
        }
 
-       skb_reserve(skb, NET_IP_ALIGN);
-       memcpy(skb_put(skb, len), buf + NET_IP_ALIGN, len - NET_IP_ALIGN);
+       memcpy(skb_put(skb, len), buf, len);
        skb->dev = dev->net;
        skb->protocol = eth_type_trans(skb, dev->net);
 
index 47a6c870b51fae361b39de950ee4a523ced52475..48d4efdb4959a61b6704d58178879593ca4edad2 100644 (file)
@@ -730,7 +730,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
                msleep(10);
                bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
                timeout++;
-       } while ((bmcr & MII_BMCR) && (timeout < 100));
+       } while ((bmcr & BMCR_RESET) && (timeout < 100));
 
        if (timeout >= 100) {
                netdev_warn(dev->net, "timeout on PHY Reset");
index 069c1cf0fdf73675dbb865b27ee4d673bd773840..9ab439d144ed0207758c8c5535d3fa1dcb3359b8 100644 (file)
@@ -645,6 +645,7 @@ int usbnet_stop (struct net_device *net)
        struct driver_info      *info = dev->driver_info;
        int                     retval;
 
+       clear_bit(EVENT_DEV_OPEN, &dev->flags);
        netif_stop_queue (net);
 
        netif_info(dev, ifdown, dev->net,
@@ -736,6 +737,7 @@ int usbnet_open (struct net_device *net)
                }
        }
 
+       set_bit(EVENT_DEV_OPEN, &dev->flags);
        netif_start_queue (net);
        netif_info(dev, ifup, dev->net,
                   "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n",
@@ -1259,6 +1261,9 @@ void usbnet_disconnect (struct usb_interface *intf)
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
+       usb_kill_urb(dev->interrupt);
+       usb_free_urb(dev->interrupt);
+
        free_netdev(net);
        usb_put_dev (xdev);
 }
@@ -1498,6 +1503,10 @@ int usbnet_resume (struct usb_interface *intf)
        int                     retval;
 
        if (!--dev->suspend_count) {
+               /* resume interrupt URBs */
+               if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags))
+                       usb_submit_urb(dev->interrupt, GFP_NOIO);
+
                spin_lock_irq(&dev->txq.lock);
                while ((res = usb_get_from_anchor(&dev->deferred))) {
 
@@ -1516,9 +1525,12 @@ int usbnet_resume (struct usb_interface *intf)
                smp_mb();
                clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
                spin_unlock_irq(&dev->txq.lock);
-               if (!(dev->txq.qlen >= TX_QLEN(dev)))
-                       netif_start_queue(dev->net);
-               tasklet_schedule (&dev->bh);
+
+               if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+                       if (!(dev->txq.qlen >= TX_QLEN(dev)))
+                               netif_start_queue(dev->net);
+                       tasklet_schedule (&dev->bh);
+               }
        }
        return 0;
 }
index 2de9b90c5f8f079859b695979acb4871c5a0ea08..3b99f64104fd528f7e1582931cacb58ff3bf7a92 100644 (file)
@@ -403,6 +403,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
        if (tb[IFLA_ADDRESS] == NULL)
                random_ether_addr(dev->dev_addr);
 
+       if (tb[IFLA_IFNAME])
+               nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
+       else
+               snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");
+
+       if (strchr(dev->name, '%')) {
+               err = dev_alloc_name(dev, dev->name);
+               if (err < 0)
+                       goto err_alloc_name;
+       }
+
        err = register_netdevice(dev);
        if (err < 0)
                goto err_register_dev;
@@ -422,6 +433,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 
 err_register_dev:
        /* nothing to do */
+err_alloc_name:
 err_configure_peer:
        unregister_netdevice(peer);
        return err;
index 0d47c3a0530788ab0e596836898eb399fd27e44c..c16ed961153a7705ff742a6212c7e322d28f76fd 100644 (file)
@@ -178,6 +178,7 @@ static void
 vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 {
        int i;
+       unsigned long flags;
        u32 events = le32_to_cpu(adapter->shared->ecr);
        if (!events)
                return;
@@ -190,10 +191,10 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 
        /* Check if there is an error on xmit/recv queues */
        if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
-               spin_lock(&adapter->cmd_lock);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
                VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
                                       VMXNET3_CMD_GET_QUEUE_STATUS);
-               spin_unlock(&adapter->cmd_lock);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
                for (i = 0; i < adapter->num_tx_queues; i++)
                        if (adapter->tqd_start[i].status.stopped)
@@ -2733,13 +2734,14 @@ static void
 vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 {
        u32 cfg;
+       unsigned long flags;
 
        /* intr settings */
-       spin_lock(&adapter->cmd_lock);
+       spin_lock_irqsave(&adapter->cmd_lock, flags);
        VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
                               VMXNET3_CMD_GET_CONF_INTR);
        cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
-       spin_unlock(&adapter->cmd_lock);
+       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
        adapter->intr.type = cfg & 0x3;
        adapter->intr.mask_mode = (cfg >> 2) & 0x3;
 
index 51f2ef142a5b635cca3f15239b830d2b554d6d6d..976467253d2006324af9355952e753d24c0ea301 100644 (file)
@@ -311,6 +311,9 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
                /* toggle the LRO feature*/
                netdev->features ^= NETIF_F_LRO;
 
+               /* Update private LRO flag */
+               adapter->lro = lro_requested;
+
                /* update harware LRO capability accordingly */
                if (lro_requested)
                        adapter->shared->devRead.misc.uptFeatures |=
index f1b8af64569cbdeea7d80316d071aea329eab494..2d10239ce8295e2633699c6680a9f1b7072703e1 100644 (file)
@@ -1040,7 +1040,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
        }
 
        ret = ath9k_htc_hw_init(hif_dev->htc_handle,
-                               &hif_dev->udev->dev, hif_dev->device_id,
+                               &interface->dev, hif_dev->device_id,
                                hif_dev->udev->product, id->driver_info);
        if (ret) {
                ret = -EINVAL;
@@ -1158,7 +1158,7 @@ fail_resume:
 #endif
 
 static struct usb_driver ath9k_hif_usb_driver = {
-       .name = "ath9k_hif_usb",
+       .name = KBUILD_MODNAME,
        .probe = ath9k_hif_usb_probe,
        .disconnect = ath9k_hif_usb_disconnect,
 #ifdef CONFIG_PM
index 1ec9bcd6b2815c28b34cfd4b2a232c8b055dd716..c95bc5cc1a1fbb4bad3d2e816477c5cfbe96fb97 100644 (file)
@@ -1254,15 +1254,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        ah->txchainmask = common->tx_chainmask;
        ah->rxchainmask = common->rx_chainmask;
 
-       if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) {
-               ath9k_hw_abortpcurecv(ah);
-               if (!ath9k_hw_stopdmarecv(ah)) {
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "Failed to stop receive dma\n");
-                       bChannelChange = false;
-               }
-       }
-
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
 
index 562257ac52cfecf77ee58cd7f1318507f14d9b75..edc1cbbfecaf6fbd153ce00237f1101f49096edc 100644 (file)
@@ -751,28 +751,47 @@ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
 
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
 {
 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
 #define AH_RX_TIME_QUANTUM     100     /* usec */
        struct ath_common *common = ath9k_hw_common(ah);
+       u32 mac_status, last_mac_status = 0;
        int i;
 
+       /* Enable access to the DMA observation bus */
+       REG_WRITE(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
        REG_WRITE(ah, AR_CR, AR_CR_RXD);
 
        /* Wait for rx enable bit to go low */
        for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
                if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
                        break;
+
+               if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+                       if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+                               *reset = true;
+                               break;
+                       }
+
+                       last_mac_status = mac_status;
+               }
+
                udelay(AH_TIME_QUANTUM);
        }
 
        if (i == 0) {
                ath_err(common,
-                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
                        AH_RX_STOP_DMA_TIMEOUT / 1000,
                        REG_READ(ah, AR_CR),
-                       REG_READ(ah, AR_DIAG_SW));
+                       REG_READ(ah, AR_DIAG_SW),
+                       REG_READ(ah, AR_DMADBG_7));
                return false;
        } else {
                return true;
index b2b2ff852c328142a55396801010c46e32c72432..c2a59386fb9cf05a7eabb12214e613103e0c08b0 100644 (file)
@@ -695,7 +695,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
 void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_abortpcurecv(struct ath_hw *ah);
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
 int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 /* Interrupt Handling */
index dddb85de622d2ea253152032ec8edf86df475754..1482fa6508334cdd32b979b5a0a22bf8e826082b 100644 (file)
@@ -1376,7 +1376,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 
        ath9k_calculate_iter_data(hw, vif, &iter_data);
 
-       ath9k_ps_wakeup(sc);
        /* Set BSSID mask. */
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
        ath_hw_setbssidmask(common);
@@ -1411,7 +1410,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
        }
 
        ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_ps_restore(sc);
 
        /* Set up ANI */
        if ((iter_data.naps + iter_data.nadhocs) > 0) {
@@ -1457,6 +1455,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        struct ath_vif *avp = (void *)vif->drv_priv;
        int ret = 0;
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        switch (vif->type) {
@@ -1503,6 +1502,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        ath9k_do_vif_add_setup(hw, vif);
 out:
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
        return ret;
 }
 
@@ -1517,6 +1517,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
 
        ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
        mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
 
        /* See if new interface type is valid. */
        if ((new_type == NL80211_IFTYPE_ADHOC) &&
@@ -1546,6 +1547,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
 
        ath9k_do_vif_add_setup(hw, vif);
 out:
+       ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
        return ret;
 }
@@ -1558,6 +1560,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 
        ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        sc->nvifs--;
@@ -1569,6 +1572,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        ath9k_calculate_summary_state(hw, NULL);
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 }
 
 static void ath9k_enable_ps(struct ath_softc *sc)
@@ -1809,6 +1813,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
        txq = sc->tx.txq_map[queue];
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1832,6 +1837,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
                        ath_beaconq_config(sc);
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 
        return ret;
 }
@@ -1894,6 +1900,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        int slottime;
        int error;
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        if (changed & BSS_CHANGED_BSSID) {
@@ -1994,6 +2001,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 }
 
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
@@ -2133,6 +2141,8 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
        int timeout = 200; /* ms */
        int i, j;
 
@@ -2141,6 +2151,12 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
 
        cancel_delayed_work_sync(&sc->tx_complete_work);
 
+       if (sc->sc_flags & SC_OP_INVALID) {
+               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+               mutex_unlock(&sc->mutex);
+               return;
+       }
+
        if (drop)
                timeout = 1;
 
index a9c3f4672aa0e12736a24c8ddb4e4c280d635d29..b29c80def35e89f10284ae794d267ca3a19d3e55 100644 (file)
@@ -486,12 +486,12 @@ start_recv:
 bool ath_stoprecv(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
-       bool stopped;
+       bool stopped, reset = false;
 
        spin_lock_bh(&sc->rx.rxbuflock);
        ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
-       stopped = ath9k_hw_stopdmarecv(ah);
+       stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
                ath_edma_stop_recv(sc);
@@ -506,7 +506,7 @@ bool ath_stoprecv(struct ath_softc *sc)
                        "confusing the DMA engine when we start RX up\n");
                ATH_DBG_WARN_ON_ONCE(!stopped);
        }
-       return stopped;
+       return stopped && !reset;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
index 248c670fdfbefe0bf06e3ace4e33b2e4bd43da05..5c2cfe6941524ccd7b05525a147b5ce6854c3133 100644 (file)
@@ -195,6 +195,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
        {APL9_WORLD, CTL_ETSI, CTL_ETSI},
 
        {APL3_FCCA, CTL_FCC, CTL_FCC},
+       {APL7_FCCA, CTL_FCC, CTL_FCC},
        {APL1_ETSIC, CTL_FCC, CTL_ETSI},
        {APL2_ETSIC, CTL_FCC, CTL_ETSI},
        {APL2_APLD, CTL_FCC, NO_CTL},
index d59b0168c14ad3b6c9b8b6c5ab40cbb524c0fb87..5af40d9170a096c4c598c9ae7c170cbb149c2f1a 100644 (file)
@@ -72,6 +72,7 @@ MODULE_FIRMWARE("b43/ucode11.fw");
 MODULE_FIRMWARE("b43/ucode13.fw");
 MODULE_FIRMWARE("b43/ucode14.fw");
 MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_mimo.fw");
 MODULE_FIRMWARE("b43/ucode5.fw");
 MODULE_FIRMWARE("b43/ucode9.fw");
 
index 2a45dd44cc127ba7abf3400012059ab90addcb73..aef65cd47661e39a62106b232eccb8054b382411 100644 (file)
@@ -1,6 +1,5 @@
 config IWLWIFI_LEGACY
-       tristate "Intel Wireless Wifi legacy devices"
-       depends on PCI && MAC80211
+       tristate
        select FW_LOADER
        select NEW_LEDS
        select LEDS_CLASS
@@ -65,7 +64,8 @@ endmenu
 
 config IWL4965
        tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
-       depends on IWLWIFI_LEGACY
+       depends on PCI && MAC80211
+       select IWLWIFI_LEGACY
        ---help---
          This option enables support for
 
@@ -92,7 +92,8 @@ config IWL4965
 
 config IWL3945
        tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
-       depends on IWLWIFI_LEGACY
+       depends on PCI && MAC80211
+       select IWLWIFI_LEGACY
        ---help---
          Select to build the driver supporting the:
 
index 779d3cb86e2c86ad9c15f207288032064bca9dcf..5c3a68d3af12e3e7c7fe137a536d2759416f2443 100644 (file)
@@ -74,8 +74,6 @@
 /* RSSI to dBm */
 #define IWL39_RSSI_OFFSET      95
 
-#define IWL_DEFAULT_TX_POWER   0x0F
-
 /*
  * EEPROM related constants, enums, and structures.
  */
index 08b189c8472d214d20ed132a3f0849e693136a29..fc6fa2886d9c38f05099516147dacc3088afb748 100644 (file)
@@ -804,9 +804,6 @@ struct iwl4965_scd_bc_tbl {
 
 #define IWL4965_DEFAULT_TX_RETRY  15
 
-/* Limit range of txpower output target to be between these values */
-#define IWL4965_TX_POWER_TARGET_POWER_MIN      (0)     /* 0 dBm: 1 milliwatt */
-
 /* EEPROM */
 #define IWL4965_FIRST_AMPDU_QUEUE      10
 
index 5c40502f869a89458545456870826236a27904d5..79ac081832fb771ff6ce607f37ce50e9bd5bc783 100644 (file)
@@ -316,12 +316,18 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        hdr_len = ieee80211_hdrlen(fc);
 
-       /* Find index into station table for destination station */
-       sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop_unlock;
+       /* For management frames use broadcast id to do not break aggregation */
+       if (!ieee80211_is_data(fc))
+               sta_id = ctx->bcast_sta_id;
+       else {
+               /* Find index into station table for destination station */
+               sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
+
+               if (sta_id == IWL_INVALID_STATION) {
+                       IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+                                      hdr->addr1);
+                       goto drop_unlock;
+               }
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -1127,12 +1133,16 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
             q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
                tx_info = &txq->txb[txq->q.read_ptr];
-               iwl4965_tx_status(priv, tx_info,
-                                txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
+
+               if (WARN_ON_ONCE(tx_info->skb == NULL))
+                       continue;
 
                hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-               if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+               if (ieee80211_is_data_qos(hdr->frame_control))
                        nfreed++;
+
+               iwl4965_tx_status(priv, tx_info,
+                                txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
                tx_info->skb = NULL;
 
                priv->cfg->ops->lib->txq_free_tfd(priv, txq);
index 7007d61bb6b5c904aa62af13183bc67b24eb635f..42db0fc8b921983d83bc244a8e4351ad207a0a0b 100644 (file)
@@ -160,6 +160,7 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
        struct ieee80211_channel *geo_ch;
        struct ieee80211_rate *rates;
        int i = 0;
+       s8 max_tx_power = 0;
 
        if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
            priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
@@ -235,8 +236,8 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
 
                        geo_ch->flags |= ch->ht40_extension_channel;
 
-                       if (ch->max_power_avg > priv->tx_power_device_lmt)
-                               priv->tx_power_device_lmt = ch->max_power_avg;
+                       if (ch->max_power_avg > max_tx_power)
+                               max_tx_power = ch->max_power_avg;
                } else {
                        geo_ch->flags |= IEEE80211_CHAN_DISABLED;
                }
@@ -249,6 +250,10 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
                                 geo_ch->flags);
        }
 
+       priv->tx_power_device_lmt = max_tx_power;
+       priv->tx_power_user_lmt = max_tx_power;
+       priv->tx_power_next = max_tx_power;
+
        if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
             priv->cfg->sku & IWL_SKU_A) {
                IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
@@ -1124,11 +1129,11 @@ int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
        if (!priv->cfg->ops->lib->send_tx_power)
                return -EOPNOTSUPP;
 
-       if (tx_power < IWL4965_TX_POWER_TARGET_POWER_MIN) {
+       /* 0 dBm mean 1 milliwatt */
+       if (tx_power < 0) {
                IWL_WARN(priv,
-                        "Requested user TXPOWER %d below lower limit %d.\n",
-                        tx_power,
-                        IWL4965_TX_POWER_TARGET_POWER_MIN);
+                        "Requested user TXPOWER %d below 1 mW.\n",
+                        tx_power);
                return -EINVAL;
        }
 
@@ -2150,6 +2155,13 @@ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
                        goto set_ch_out;
                }
 
+               if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+                   !iwl_legacy_is_channel_ibss(ch_info)) {
+                       IWL_DEBUG_MAC80211(priv, "leave - not IBSS channel\n");
+                       ret = -EINVAL;
+                       goto set_ch_out;
+               }
+
                spin_lock_irqsave(&priv->lock, flags);
 
                for_each_context(priv, ctx) {
index 9ee849d669f30532c8ddba597ef09d0827eb49b2..f43ac1eb901428371952d0e906dcfee849204e1f 100644 (file)
@@ -1411,6 +1411,12 @@ iwl_legacy_is_channel_passive(const struct iwl_channel_info *ch)
        return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
 }
 
+static inline int
+iwl_legacy_is_channel_ibss(const struct iwl_channel_info *ch)
+{
+       return (ch->flags & EEPROM_CHANNEL_IBSS) ? 1 : 0;
+}
+
 static inline void
 __iwl_legacy_free_pages(struct iwl_priv *priv, struct page *page)
 {
index 04c5648027df8db645aa57d4f5535267c5a15d3b..cb346d1a9ffa6e5f581b5b9c9c0a52f6ffafed3a 100644 (file)
@@ -471,13 +471,6 @@ int iwl_legacy_init_channel_map(struct iwl_priv *priv)
                                             flags & EEPROM_CHANNEL_RADAR))
                                       ? "" : "not ");
 
-                       /* Set the tx_power_user_lmt to the highest power
-                        * supported by any channel */
-                       if (eeprom_ch_info[ch].max_power_avg >
-                                               priv->tx_power_user_lmt)
-                               priv->tx_power_user_lmt =
-                                   eeprom_ch_info[ch].max_power_avg;
-
                        ch_info++;
                }
        }
index 15eb8b70715741c0a92e347b0d087964df2b32f9..bda0d61b2c0d1e5aefaea5b13fd4e25a84832ec1 100644 (file)
@@ -48,8 +48,21 @@ module_param(led_mode, int, S_IRUGO);
 MODULE_PARM_DESC(led_mode, "0=system default, "
                "1=On(RF On)/Off(RF Off), 2=blinking");
 
+/* Throughput          OFF time(ms)    ON time (ms)
+ *     >300                    25              25
+ *     >200 to 300             40              40
+ *     >100 to 200             55              55
+ *     >70 to 100              65              65
+ *     >50 to 70               75              75
+ *     >20 to 50               85              85
+ *     >10 to 20               95              95
+ *     >5 to 10                110             110
+ *     >1 to 5                 130             130
+ *     >0 to 1                 167             167
+ *     <=0                                     SOLID ON
+ */
 static const struct ieee80211_tpt_blink iwl_blink[] = {
-       { .throughput = 0 * 1024 - 1, .blink_time = 334 },
+       { .throughput = 0, .blink_time = 334 },
        { .throughput = 1 * 1024 - 1, .blink_time = 260 },
        { .throughput = 5 * 1024 - 1, .blink_time = 220 },
        { .throughput = 10 * 1024 - 1, .blink_time = 190 },
@@ -101,6 +114,11 @@ static int iwl_legacy_led_cmd(struct iwl_priv *priv,
        if (priv->blink_on == on && priv->blink_off == off)
                return 0;
 
+       if (off == 0) {
+               /* led is SOLID_ON */
+               on = IWL_LED_SOLID;
+       }
+
        IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
                        priv->cfg->base_params->led_compensation);
        led_cmd.on = iwl_legacy_blink_compensation(priv, on,
index 28eb3d885ba176874a0896bcfa03c5c4953f9af3..cc7ebcee60e5bd6e9d49f2a1ae8c17dee1c31f21 100644 (file)
@@ -3825,10 +3825,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->force_reset[IWL_FW_RESET].reset_duration =
                IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
-
-       priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
-       priv->tx_power_next = IWL_DEFAULT_TX_POWER;
-
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
                IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
                         eeprom->version);
index 91b3d8b9d7a5aceb2ecc0fbdc5d657dbe19a2cc8..a62fe24ee594cbbb5b462701ca3ec369b422a437 100644 (file)
@@ -2984,15 +2984,15 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                        txpower_work);
 
+       mutex_lock(&priv->mutex);
+
        /* If a scan happened to start before we got here
         * then just return; the statistics notification will
         * kick off another scheduled work to compensate for
         * any temperature delta we missed here. */
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
            test_bit(STATUS_SCANNING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
+               goto out;
 
        /* Regardless of if we are associated, we must reconfigure the
         * TX power since frames can be sent on non-radar channels while
@@ -3002,7 +3002,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
        /* Update last_temperature to keep is_calib_needed from running
         * when it isn't needed... */
        priv->last_temperature = priv->temperature;
-
+out:
        mutex_unlock(&priv->mutex);
 }
 
@@ -3140,12 +3140,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
 
        iwl_legacy_init_scan_params(priv);
 
-       /* Set the tx_power_user_lmt to the lowest power level
-        * this value will get overwritten by channel max power avg
-        * from eeprom */
-       priv->tx_power_user_lmt = IWL4965_TX_POWER_TARGET_POWER_MIN;
-       priv->tx_power_next = IWL4965_TX_POWER_TARGET_POWER_MIN;
-
        ret = iwl_legacy_init_channel_map(priv);
        if (ret) {
                IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
index 3ea31b659d1a5b620318d731c4036648e9ebd2b6..22e045b5bcee0a335baac193c8becdc8300314a1 100644 (file)
@@ -530,6 +530,9 @@ static struct iwl_ht_params iwl5000_ht_params = {
 struct iwl_cfg iwl5300_agn_cfg = {
        .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
        IWL_DEVICE_5000,
+       /* at least EEPROM 0x11A has wrong info */
+       .valid_tx_ant = ANT_ABC,        /* .cfg overwrite */
+       .valid_rx_ant = ANT_ABC,        /* .cfg overwrite */
        .ht_params = &iwl5000_ht_params,
 };
 
index dfdbea6e8f99530f05ce3c7fec062f2a6ff1a381..fbbde0712fa58ffb495f66e5e31d1265c95c162e 100644 (file)
@@ -335,7 +335,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
        struct ieee80211_channel *channel = conf->channel;
        const struct iwl_channel_info *ch_info;
        int ret = 0;
-       bool ht_changed[NUM_IWL_RXON_CTX] = {};
 
        IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
 
@@ -383,10 +382,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
 
                for_each_context(priv, ctx) {
                        /* Configure HT40 channels */
-                       if (ctx->ht.enabled != conf_is_ht(conf)) {
+                       if (ctx->ht.enabled != conf_is_ht(conf))
                                ctx->ht.enabled = conf_is_ht(conf);
-                               ht_changed[ctx->ctxid] = true;
-                       }
 
                        if (ctx->ht.enabled) {
                                if (conf_is_ht40_minus(conf)) {
@@ -455,8 +452,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
                if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
                        continue;
                iwlagn_commit_rxon(priv, ctx);
-               if (ht_changed[ctx->ctxid])
-                       iwlagn_update_qos(priv, ctx);
        }
  out:
        mutex_unlock(&priv->mutex);
index a709d05c5868f3e6a19d586bcdffd560cb69bf6f..0712b67283a4f7e1b4a4ae702623ba32fd61a933 100644 (file)
@@ -568,12 +568,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        hdr_len = ieee80211_hdrlen(fc);
 
-       /* Find index into station table for destination station */
-       sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop_unlock;
+       /* For management frames use broadcast id to do not break aggregation */
+       if (!ieee80211_is_data(fc))
+               sta_id = ctx->bcast_sta_id;
+       else {
+               /* Find index into station table for destination station */
+               sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+               if (sta_id == IWL_INVALID_STATION) {
+                       IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+                                      hdr->addr1);
+                       goto drop_unlock;
+               }
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -1224,12 +1229,16 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
                tx_info = &txq->txb[txq->q.read_ptr];
-               iwlagn_tx_status(priv, tx_info,
-                                txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
+
+               if (WARN_ON_ONCE(tx_info->skb == NULL))
+                       continue;
 
                hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-               if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+               if (ieee80211_is_data_qos(hdr->frame_control))
                        nfreed++;
+
+               iwlagn_tx_status(priv, tx_info,
+                                txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
                tx_info->skb = NULL;
 
                if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
index 7e8a658b7670ee580b5a8a84094beb9c6de86dd7..f3ac62431a3085c7eee695e98987ba140cb53d02 100644 (file)
@@ -1339,8 +1339,8 @@ int lbs_execute_next_command(struct lbs_private *priv)
                                    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
                                        lbs_deb_host(
                                               "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
-                                       list_del(&cmdnode->list);
                                        spin_lock_irqsave(&priv->driver_lock, flags);
+                                       list_del(&cmdnode->list);
                                        lbs_complete_command(priv, cmdnode, 0);
                                        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
@@ -1352,8 +1352,8 @@ int lbs_execute_next_command(struct lbs_private *priv)
                                    (priv->psstate == PS_STATE_PRE_SLEEP)) {
                                        lbs_deb_host(
                                               "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
-                                       list_del(&cmdnode->list);
                                        spin_lock_irqsave(&priv->driver_lock, flags);
+                                       list_del(&cmdnode->list);
                                        lbs_complete_command(priv, cmdnode, 0);
                                        spin_unlock_irqrestore(&priv->driver_lock, flags);
                                        priv->needtowakeup = 1;
@@ -1366,7 +1366,9 @@ int lbs_execute_next_command(struct lbs_private *priv)
                                       "EXEC_NEXT_CMD: sending EXIT_PS\n");
                        }
                }
+               spin_lock_irqsave(&priv->driver_lock, flags);
                list_del(&cmdnode->list);
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
                lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
                            le16_to_cpu(cmd->command));
                lbs_submit_command(priv, cmdnode);
index 36952274950e3cf7537834a132d5374f7b2b7322..c1ceb4b23971ea884577bb876432e4a764301446 100644 (file)
@@ -137,6 +137,7 @@ struct mwl8k_tx_queue {
 struct mwl8k_priv {
        struct ieee80211_hw *hw;
        struct pci_dev *pdev;
+       int irq;
 
        struct mwl8k_device_info *device_info;
 
@@ -3761,9 +3762,11 @@ static int mwl8k_start(struct ieee80211_hw *hw)
        rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
                         IRQF_SHARED, MWL8K_NAME, hw);
        if (rc) {
+               priv->irq = -1;
                wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
                return -EIO;
        }
+       priv->irq = priv->pdev->irq;
 
        /* Enable TX reclaim and RX tasklets.  */
        tasklet_enable(&priv->poll_tx_task);
@@ -3800,6 +3803,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
        if (rc) {
                iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
                free_irq(priv->pdev->irq, hw);
+               priv->irq = -1;
                tasklet_disable(&priv->poll_tx_task);
                tasklet_disable(&priv->poll_rx_task);
        }
@@ -3818,7 +3822,10 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
 
        /* Disable interrupts */
        iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-       free_irq(priv->pdev->irq, hw);
+       if (priv->irq != -1) {
+               free_irq(priv->pdev->irq, hw);
+               priv->irq = -1;
+       }
 
        /* Stop finalize join worker */
        cancel_work_sync(&priv->finalize_join_worker);
index 7834c26c295438e39ab1c63d3e1b0444ca81ef2f..042842e704de17945d7f61b9c6069072ad5230fe 100644 (file)
@@ -703,7 +703,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
        struct p54_tx_info *p54info;
        struct p54_hdr *hdr;
        struct p54_tx_data *txhdr;
-       unsigned int padding, len, extra_len;
+       unsigned int padding, len, extra_len = 0;
        int i, j, ridx;
        u16 hdr_flags = 0, aid = 0;
        u8 rate, queue = 0, crypt_offset = 0;
index b78a38d9172a52d8517faba9df5cb914d5215e1c..8c7c522a056acc76faa9e411b6231d10784432a7 100644 (file)
@@ -126,7 +126,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
 
     board = z->resource.start;
     ioaddr = board+cards[i].offset;
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
        return -ENOMEM;
     if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
@@ -146,15 +146,15 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
 static const struct net_device_ops zorro8390_netdev_ops = {
        .ndo_open               = zorro8390_open,
        .ndo_stop               = zorro8390_close,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
+       .ndo_poll_controller    = __ei_poll,
 #endif
 };
 
index a3755ffc03d468faf83d70e7a6a5a15a7214a6ac..bc8ce48f07781f00dccc0c856194926562af9cc3 100644 (file)
@@ -2550,7 +2550,6 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
                                         const struct parport_pc_via_data *via)
 {
        short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
-       struct resource *base_res;
        u32 ite8872set;
        u32 ite8872_lpt, ite8872_lpthi;
        u8 ite8872_irq, type;
@@ -2561,8 +2560,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
 
        /* make sure which one chip */
        for (i = 0; i < 5; i++) {
-               base_res = request_region(inta_addr[i], 32, "it887x");
-               if (base_res) {
+               if (request_region(inta_addr[i], 32, "it887x")) {
                        int test;
                        pci_write_config_dword(pdev, 0x60,
                                                0xe5000000 | inta_addr[i]);
@@ -2571,7 +2569,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
                        test = inb(inta_addr[i]);
                        if (test != 0xff)
                                break;
-                       release_region(inta_addr[i], 0x8);
+                       release_region(inta_addr[i], 32);
                }
        }
        if (i >= 5) {
@@ -2635,7 +2633,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
        /*
         * Release the resource so that parport_pc_probe_port can get it.
         */
-       release_resource(base_res);
+       release_region(inta_addr[i], 32);
        if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi,
                                   irq, PARPORT_DMA_NONE, &pdev->dev, 0)) {
                printk(KERN_INFO
index c8ff646c0b056e9fc8c81f3110fe53bb4b12df39..0fa466a91bf413995169f1751823e25784d70891 100644 (file)
@@ -88,4 +88,6 @@ config PCI_IOAPIC
        depends on HOTPLUG
        default y
 
-select NLS if (DMI || ACPI)
+config PCI_LABEL
+       def_bool y if (DMI || ACPI)
+       select NLS
index 98d61c8e984bc218c823fcaeecb02fdcf18183a3..c85f744270a56664cb91a720624cfc97dc29c6ee 100644 (file)
@@ -56,10 +56,10 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 # ACPI Related PCI FW Functions
 # ACPI _DSM provided firmware instance and string name
 #
-obj-$(CONFIG_ACPI)    += pci-acpi.o pci-label.o
+obj-$(CONFIG_ACPI)    += pci-acpi.o
 
 # SMBIOS provided firmware instance and labels
-obj-$(CONFIG_DMI)    += pci-label.o
+obj-$(CONFIG_PCI_LABEL) += pci-label.o
 
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
index 505c1c7075f011df2e94755b2fb88f632a4c148c..6af6b628175b459f03c2f0969f9b2be6d65dba48 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/tboot.h>
 #include <linux/dmi.h>
+#include <linux/pci-ats.h>
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
 #include "pci.h"
@@ -1299,7 +1300,7 @@ static void iommu_detach_domain(struct dmar_domain *domain,
 static struct iova_domain reserved_iova_list;
 static struct lock_class_key reserved_rbtree_key;
 
-static void dmar_init_reserved_ranges(void)
+static int dmar_init_reserved_ranges(void)
 {
        struct pci_dev *pdev = NULL;
        struct iova *iova;
@@ -1313,8 +1314,10 @@ static void dmar_init_reserved_ranges(void)
        /* IOAPIC ranges shouldn't be accessed by DMA */
        iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
                IOVA_PFN(IOAPIC_RANGE_END));
-       if (!iova)
+       if (!iova) {
                printk(KERN_ERR "Reserve IOAPIC range failed\n");
+               return -ENODEV;
+       }
 
        /* Reserve all PCI MMIO to avoid peer-to-peer access */
        for_each_pci_dev(pdev) {
@@ -1327,11 +1330,13 @@ static void dmar_init_reserved_ranges(void)
                        iova = reserve_iova(&reserved_iova_list,
                                            IOVA_PFN(r->start),
                                            IOVA_PFN(r->end));
-                       if (!iova)
+                       if (!iova) {
                                printk(KERN_ERR "Reserve iova failed\n");
+                               return -ENODEV;
+                       }
                }
        }
-
+       return 0;
 }
 
 static void domain_reserve_special_ranges(struct dmar_domain *domain)
@@ -1835,7 +1840,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
        ret = iommu_attach_domain(domain, iommu);
        if (ret) {
-               domain_exit(domain);
+               free_domain_mem(domain);
                goto error;
        }
 
@@ -2213,7 +2218,7 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
        return 0;
 }
 
-int __init init_dmars(void)
+static int __init init_dmars(int force_on)
 {
        struct dmar_drhd_unit *drhd;
        struct dmar_rmrr_unit *rmrr;
@@ -2393,8 +2398,15 @@ int __init init_dmars(void)
         *   enable translation
         */
        for_each_drhd_unit(drhd) {
-               if (drhd->ignored)
+               if (drhd->ignored) {
+                       /*
+                        * we always have to disable PMRs or DMA may fail on
+                        * this device
+                        */
+                       if (force_on)
+                               iommu_disable_protect_mem_regions(drhd->iommu);
                        continue;
+               }
                iommu = drhd->iommu;
 
                iommu_flush_write_buffer(iommu);
@@ -3240,9 +3252,15 @@ static int device_notifier(struct notifier_block *nb,
        if (!domain)
                return 0;
 
-       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
                domain_remove_one_dev_info(domain, pdev);
 
+               if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+                   !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+                   list_empty(&domain->devices))
+                       domain_exit(domain);
+       }
+
        return 0;
 }
 
@@ -3277,12 +3295,21 @@ int __init intel_iommu_init(void)
        if (no_iommu || dmar_disabled)
                return -ENODEV;
 
-       iommu_init_mempool();
-       dmar_init_reserved_ranges();
+       if (iommu_init_mempool()) {
+               if (force_on)
+                       panic("tboot: Failed to initialize iommu memory\n");
+               return  -ENODEV;
+       }
+
+       if (dmar_init_reserved_ranges()) {
+               if (force_on)
+                       panic("tboot: Failed to reserve iommu ranges\n");
+               return  -ENODEV;
+       }
 
        init_no_remapping_devices();
 
-       ret = init_dmars();
+       ret = init_dmars(force_on);
        if (ret) {
                if (force_on)
                        panic("tboot: Failed to initialize DMARs\n");
@@ -3391,6 +3418,11 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
                domain->iommu_count--;
                domain_update_iommu_cap(domain);
                spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+               spin_lock_irqsave(&iommu->lock, tmp_flags);
+               clear_bit(domain->id, iommu->domain_ids);
+               iommu->domains[domain->id] = NULL;
+               spin_unlock_irqrestore(&iommu->lock, tmp_flags);
        }
 
        spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3607,9 +3639,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 
                pte = dmar_domain->pgd;
                if (dma_pte_present(pte)) {
-                       free_pgtable_page(dmar_domain->pgd);
                        dmar_domain->pgd = (struct dma_pte *)
                                phys_to_virt(dma_pte_addr(pte));
+                       free_pgtable_page(pte);
                }
                dmar_domain->agaw--;
        }
index 553d8ee55c1c4aa3c9f6567867642d3505cf89df..42fae477651517ef8dd447427c39ea00d8955951 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/pci-ats.h>
 #include "pci.h"
 
 #define VIRTFN_ID_LEN  16
index a6ec200fe5ee4c187a103e2b19771e4e5e9a9f14..4020025f854e7686b314bdea89dd9add1f0ebe75 100644 (file)
@@ -250,15 +250,6 @@ struct pci_sriov {
        u8 __iomem *mstate;     /* VF Migration State Array */
 };
 
-/* Address Translation Service */
-struct pci_ats {
-       int pos;        /* capability position */
-       int stu;        /* Smallest Translation Unit */
-       int qdep;       /* Invalidate Queue Depth */
-       int ref_cnt;    /* Physical Function reference count */
-       unsigned int is_enabled:1;      /* Enable bit is set */
-};
-
 #ifdef CONFIG_PCI_IOV
 extern int pci_iov_init(struct pci_dev *dev);
 extern void pci_iov_release(struct pci_dev *dev);
@@ -269,19 +260,6 @@ extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
 extern void pci_restore_iov_state(struct pci_dev *dev);
 extern int pci_iov_bus_range(struct pci_bus *bus);
 
-extern int pci_enable_ats(struct pci_dev *dev, int ps);
-extern void pci_disable_ats(struct pci_dev *dev);
-extern int pci_ats_queue_depth(struct pci_dev *dev);
-/**
- * pci_ats_enabled - query the ATS status
- * @dev: the PCI device
- *
- * Returns 1 if ATS capability is enabled, or 0 if not.
- */
-static inline int pci_ats_enabled(struct pci_dev *dev)
-{
-       return dev->ats && dev->ats->is_enabled;
-}
 #else
 static inline int pci_iov_init(struct pci_dev *dev)
 {
@@ -304,21 +282,6 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
        return 0;
 }
 
-static inline int pci_enable_ats(struct pci_dev *dev, int ps)
-{
-       return -ENODEV;
-}
-static inline void pci_disable_ats(struct pci_dev *dev)
-{
-}
-static inline int pci_ats_queue_depth(struct pci_dev *dev)
-{
-       return -ENODEV;
-}
-static inline int pci_ats_enabled(struct pci_dev *dev)
-{
-       return 0;
-}
 #endif /* CONFIG_PCI_IOV */
 
 static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
index ebf51ad1b71478f08532edcdda8b3acf9d711bb7..a806cb321d2e25c2f896cda9aa4c329eb38a3051 100644 (file)
@@ -579,7 +579,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        }
        size0 = calculate_iosize(size, min_size, size1,
                        resource_size(b_res), 4096);
-       size1 = !add_size? size0:
+       size1 = (!add_head || (add_head && !add_size)) ? size0 :
                calculate_iosize(size, min_size+add_size, size1,
                        resource_size(b_res), 4096);
        if (!size0 && !size1) {
@@ -677,7 +677,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                align += aligns[order];
        }
        size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
-       size1 = !add_size ? size :
+       size1 = (!add_head || (add_head && !add_size)) ? size0 :
                calculate_memsize(size, min_size+add_size, 0,
                                resource_size(b_res), min_align);
        if (!size0 && !size1) {
index fe77e822384134b49e7da159aa5352826c8feb03..e8c19def1b0f501863008b3dc892d18bd4cdbe5c 100644 (file)
@@ -173,7 +173,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
        c = p_dev->function_config;
 
        if (!(c->state & CONFIG_LOCKED)) {
-               dev_dbg(&p_dev->dev, "Configuration isn't't locked\n");
+               dev_dbg(&p_dev->dev, "Configuration isn't locked\n");
                mutex_unlock(&s->ops_mutex);
                return -EACCES;
        }
index 5f2dd386152b52236991b73c60b61fa361555af9..2c1abf63957f23d0353c209af843f8e8bcf3c50c 100644 (file)
@@ -585,8 +585,9 @@ static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
        return true;
 }
 
-static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
+static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 {
+       struct pci_dev *port;
        struct pci_dev *dev;
        struct pci_bus *bus;
        bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
@@ -599,9 +600,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
        mutex_lock(&eeepc->hotplug_lock);
 
        if (eeepc->hotplug_slot) {
-               bus = pci_find_bus(0, 1);
+               port = acpi_get_pci_dev(handle);
+               if (!port) {
+                       pr_warning("Unable to find port\n");
+                       goto out_unlock;
+               }
+
+               bus = port->subordinate;
+
                if (!bus) {
-                       pr_warning("Unable to find PCI bus 1?\n");
+                       pr_warning("Unable to find PCI bus?\n");
                        goto out_unlock;
                }
 
@@ -609,6 +617,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
                        pr_err("Unable to read PCI config space?\n");
                        goto out_unlock;
                }
+
                absent = (l == 0xffffffff);
 
                if (blocked != absent) {
@@ -647,6 +656,17 @@ out_unlock:
        mutex_unlock(&eeepc->hotplug_lock);
 }
 
+static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
+{
+       acpi_status status = AE_OK;
+       acpi_handle handle;
+
+       status = acpi_get_handle(NULL, node, &handle);
+
+       if (ACPI_SUCCESS(status))
+               eeepc_rfkill_hotplug(eeepc, handle);
+}
+
 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 {
        struct eeepc_laptop *eeepc = data;
@@ -654,7 +674,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
        if (event != ACPI_NOTIFY_BUS_CHECK)
                return;
 
-       eeepc_rfkill_hotplug(eeepc);
+       eeepc_rfkill_hotplug(eeepc, handle);
 }
 
 static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
@@ -672,6 +692,11 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
                                                     eeepc);
                if (ACPI_FAILURE(status))
                        pr_warning("Failed to register notify on %s\n", node);
+               /*
+                * Refresh pci hotplug in case the rfkill state was
+                * changed during setup.
+                */
+               eeepc_rfkill_hotplug(eeepc, handle);
        } else
                return -ENODEV;
 
@@ -693,6 +718,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
                if (ACPI_FAILURE(status))
                        pr_err("Error removing rfkill notify handler %s\n",
                                node);
+                       /*
+                        * Refresh pci hotplug in case the rfkill
+                        * state was changed after
+                        * eeepc_unregister_rfkill_notifier()
+                        */
+               eeepc_rfkill_hotplug(eeepc, handle);
        }
 }
 
@@ -816,11 +847,7 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
                rfkill_destroy(eeepc->wlan_rfkill);
                eeepc->wlan_rfkill = NULL;
        }
-       /*
-        * Refresh pci hotplug in case the rfkill state was changed after
-        * eeepc_unregister_rfkill_notifier()
-        */
-       eeepc_rfkill_hotplug(eeepc);
+
        if (eeepc->hotplug_slot)
                pci_hp_deregister(eeepc->hotplug_slot);
 
@@ -889,11 +916,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
        eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
        eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
        eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
-       /*
-        * Refresh pci hotplug in case the rfkill state was changed during
-        * setup.
-        */
-       eeepc_rfkill_hotplug(eeepc);
 
 exit:
        if (result && result != -ENODEV)
@@ -928,8 +950,11 @@ static int eeepc_hotk_restore(struct device *device)
        struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 
        /* Refresh both wlan rfkill state and pci hotplug */
-       if (eeepc->wlan_rfkill)
-               eeepc_rfkill_hotplug(eeepc);
+       if (eeepc->wlan_rfkill) {
+               eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5");
+               eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6");
+               eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7");
+       }
 
        if (eeepc->bluetooth_rfkill)
                rfkill_set_sw_state(eeepc->bluetooth_rfkill,
index 8f709aec4da0ac2ebb81d09e19baea9932506f26..6fe8cd6e23b5f89fd1efc1145796a9e6c530aa8e 100644 (file)
@@ -934,6 +934,14 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
 /*
  * Backlight device
  */
+struct sony_backlight_props {
+       struct backlight_device *dev;
+       int                     handle;
+       u8                      offset;
+       u8                      maxlvl;
+};
+struct sony_backlight_props sony_bl_props;
+
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
        return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
@@ -954,21 +962,26 @@ static int sony_nc_get_brightness_ng(struct backlight_device *bd)
 {
        int result;
        int *handle = (int *)bl_get_data(bd);
+       struct sony_backlight_props *sdev =
+               (struct sony_backlight_props *)bl_get_data(bd);
 
-       sony_call_snc_handle(*handle, 0x0200, &result);
+       sony_call_snc_handle(sdev->handle, 0x0200, &result);
 
-       return result & 0xff;
+       return (result & 0xff) - sdev->offset;
 }
 
 static int sony_nc_update_status_ng(struct backlight_device *bd)
 {
        int value, result;
        int *handle = (int *)bl_get_data(bd);
+       struct sony_backlight_props *sdev =
+               (struct sony_backlight_props *)bl_get_data(bd);
 
-       value = bd->props.brightness;
-       sony_call_snc_handle(*handle, 0x0100 | (value << 16), &result);
+       value = bd->props.brightness + sdev->offset;
+       if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
+               return -EIO;
 
-       return sony_nc_get_brightness_ng(bd);
+       return value;
 }
 
 static const struct backlight_ops sony_backlight_ops = {
@@ -981,8 +994,6 @@ static const struct backlight_ops sony_backlight_ng_ops = {
        .update_status = sony_nc_update_status_ng,
        .get_brightness = sony_nc_get_brightness_ng,
 };
-static int backlight_ng_handle;
-static struct backlight_device *sony_backlight_device;
 
 /*
  * New SNC-only Vaios event mapping to driver known keys
@@ -1549,6 +1560,75 @@ static void sony_nc_kbd_backlight_resume(void)
                                &ignore);
 }
 
+static void sony_nc_backlight_ng_read_limits(int handle,
+               struct sony_backlight_props *props)
+{
+       int offset;
+       acpi_status status;
+       u8 brlvl, i;
+       u8 min = 0xff, max = 0x00;
+       struct acpi_object_list params;
+       union acpi_object in_obj;
+       union acpi_object *lvl_enum;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       props->handle = handle;
+       props->offset = 0;
+       props->maxlvl = 0xff;
+
+       offset = sony_find_snc_handle(handle);
+       if (offset < 0)
+               return;
+
+       /* try to read the boundaries from ACPI tables, if we fail the above
+        * defaults should be reasonable
+        */
+       params.count = 1;
+       params.pointer = &in_obj;
+       in_obj.type = ACPI_TYPE_INTEGER;
+       in_obj.integer.value = offset;
+       status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
+                       &buffer);
+       if (ACPI_FAILURE(status))
+               return;
+
+       lvl_enum = (union acpi_object *) buffer.pointer;
+       if (!lvl_enum) {
+               pr_err("No SN06 return object.");
+               return;
+       }
+       if (lvl_enum->type != ACPI_TYPE_BUFFER) {
+               pr_err("Invalid SN06 return object 0x%.2x\n",
+                      lvl_enum->type);
+               goto out_invalid;
+       }
+
+       /* the buffer lists brightness levels available, brightness levels are
+        * from 0 to 8 in the array, other values are used by ALS control.
+        */
+       for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
+
+               brlvl = *(lvl_enum->buffer.pointer + i);
+               dprintk("Brightness level: %d\n", brlvl);
+
+               if (!brlvl)
+                       break;
+
+               if (brlvl > max)
+                       max = brlvl;
+               if (brlvl < min)
+                       min = brlvl;
+       }
+       props->offset = min;
+       props->maxlvl = max;
+       dprintk("Brightness levels: min=%d max=%d\n", props->offset,
+                       props->maxlvl);
+
+out_invalid:
+       kfree(buffer.pointer);
+       return;
+}
+
 static void sony_nc_backlight_setup(void)
 {
        acpi_handle unused;
@@ -1557,14 +1637,14 @@ static void sony_nc_backlight_setup(void)
        struct backlight_properties props;
 
        if (sony_find_snc_handle(0x12f) != -1) {
-               backlight_ng_handle = 0x12f;
                ops = &sony_backlight_ng_ops;
-               max_brightness = 0xff;
+               sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
+               max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 
        } else if (sony_find_snc_handle(0x137) != -1) {
-               backlight_ng_handle = 0x137;
                ops = &sony_backlight_ng_ops;
-               max_brightness = 0xff;
+               sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
+               max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 
        } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
                                                &unused))) {
@@ -1577,22 +1657,22 @@ static void sony_nc_backlight_setup(void)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = max_brightness;
-       sony_backlight_device = backlight_device_register("sony", NULL,
-                                                         &backlight_ng_handle,
-                                                         ops, &props);
+       sony_bl_props.dev = backlight_device_register("sony", NULL,
+                                                     &sony_bl_props,
+                                                     ops, &props);
 
-       if (IS_ERR(sony_backlight_device)) {
-               pr_warning(DRV_PFX "unable to register backlight device\n");
-               sony_backlight_device = NULL;
+       if (IS_ERR(sony_bl_props.dev)) {
+               pr_warn(DRV_PFX "unable to register backlight device\n");
+               sony_bl_props.dev = NULL;
        } else
-               sony_backlight_device->props.brightness =
-                   ops->get_brightness(sony_backlight_device);
+               sony_bl_props.dev->props.brightness =
+                       ops->get_brightness(sony_bl_props.dev);
 }
 
 static void sony_nc_backlight_cleanup(void)
 {
-       if (sony_backlight_device)
-               backlight_device_unregister(sony_backlight_device);
+       if (sony_bl_props.dev)
+               backlight_device_unregister(sony_bl_props.dev);
 }
 
 static int sony_nc_add(struct acpi_device *device)
@@ -2590,7 +2670,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
        mutex_lock(&spic_dev.lock);
        switch (cmd) {
        case SONYPI_IOCGBRT:
-               if (sony_backlight_device == NULL) {
+               if (sony_bl_props.dev == NULL) {
                        ret = -EIO;
                        break;
                }
@@ -2603,7 +2683,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
                                ret = -EFAULT;
                break;
        case SONYPI_IOCSBRT:
-               if (sony_backlight_device == NULL) {
+               if (sony_bl_props.dev == NULL) {
                        ret = -EIO;
                        break;
                }
@@ -2617,8 +2697,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
                        break;
                }
                /* sync the backlight device status */
-               sony_backlight_device->props.brightness =
-                   sony_backlight_get_brightness(sony_backlight_device);
+               sony_bl_props.dev->props.brightness =
+                   sony_backlight_get_brightness(sony_bl_props.dev);
                break;
        case SONYPI_IOCGBAT1CAP:
                if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
index efb3b6b9bcdbe0746011c5762ec875218ac669ce..562fcf0dd2b5b083b7d45aeeb7e78a7c6809425f 100644 (file)
@@ -128,7 +128,8 @@ enum {
 };
 
 /* ACPI HIDs */
-#define TPACPI_ACPI_HKEY_HID           "IBM0068"
+#define TPACPI_ACPI_IBM_HKEY_HID       "IBM0068"
+#define TPACPI_ACPI_LENOVO_HKEY_HID    "LEN0068"
 #define TPACPI_ACPI_EC_HID             "PNP0C09"
 
 /* Input IDs */
@@ -3879,7 +3880,8 @@ errexit:
 }
 
 static const struct acpi_device_id ibm_htk_device_ids[] = {
-       {TPACPI_ACPI_HKEY_HID, 0},
+       {TPACPI_ACPI_IBM_HKEY_HID, 0},
+       {TPACPI_ACPI_LENOVO_HKEY_HID, 0},
        {"", 0},
 };
 
index ac2701b22e7133f8239a3136b18a5f85799f8578..043ee3136e408412c6d9a92db354bafce1ac78fe 100644 (file)
@@ -95,6 +95,9 @@ idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
        else
                table++;
 
+       if (route_port == RIO_INVALID_ROUTE)
+               route_port = IDT_DEFAULT_ROUTE;
+
        rio_mport_write_config_32(mport, destid, hopcount,
                                  LOCAL_RTE_CONF_DESTID_SEL, table);
 
@@ -411,6 +414,12 @@ static int idtg2_switch_init(struct rio_dev *rdev, int do_enum)
        rdev->rswitch->em_handle = idtg2_em_handler;
        rdev->rswitch->sw_sysfs = idtg2_sysfs;
 
+       if (do_enum) {
+               /* Ensure that default routing is disabled on startup */
+               rio_write_config_32(rdev,
+                                   RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE);
+       }
+
        return 0;
 }
 
index 3a971077e7bfc924da664209502fbc70ece30473..d06ee2d44b44794f08b23511b19339024bde2d4d 100644 (file)
@@ -26,6 +26,9 @@ idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
 {
        u32 result;
 
+       if (route_port == RIO_INVALID_ROUTE)
+               route_port = CPS_DEFAULT_ROUTE;
+
        if (table == RIO_GLOBAL_TABLE) {
                rio_mport_write_config_32(mport, destid, hopcount,
                                RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
@@ -130,6 +133,9 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum)
                /* set TVAL = ~50us */
                rio_write_config_32(rdev,
                        rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
+               /* Ensure that default routing is disabled on startup */
+               rio_write_config_32(rdev,
+                                   RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
        }
 
        return 0;
index 1a62934bfebc5f7982b0583b286268793a94d49f..db8b8028988d38216290a3e6021573f527d9ee55 100644 (file)
@@ -303,6 +303,12 @@ static int tsi57x_switch_init(struct rio_dev *rdev, int do_enum)
        rdev->rswitch->em_init = tsi57x_em_init;
        rdev->rswitch->em_handle = tsi57x_em_handler;
 
+       if (do_enum) {
+               /* Ensure that default routing is disabled on startup */
+               rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT,
+                                   RIO_INVALID_ROUTE);
+       }
+
        return 0;
 }
 
index e1878877399c42418e5b8d626337c285e3d9b12a..42891726ea7296ef867453e4423b9d4f0909fdad 100644 (file)
@@ -3,10 +3,10 @@
 #
 
 config RTC_LIB
-       tristate
+       bool
 
 menuconfig RTC_CLASS
-       tristate "Real Time Clock"
+       bool "Real Time Clock"
        default n
        depends on !S390
        select RTC_LIB
@@ -15,9 +15,6 @@ menuconfig RTC_CLASS
          be allowed to plug one or more RTCs to your system. You will
          probably want to enable one or more of the interfaces below.
 
-         This driver can also be built as a module. If so, the module
-         will be called rtc-core.
-
 if RTC_CLASS
 
 config RTC_HCTOSYS
index 39013867cbd6cf0deeffcd59cb4c43280cac4618..4194e59e14cd70398095224aefa059083f9b1a49 100644 (file)
@@ -41,26 +41,21 @@ static void rtc_device_release(struct device *dev)
  * system's wall clock; restore it on resume().
  */
 
-static struct timespec delta;
 static time_t          oldtime;
+static struct timespec oldts;
 
 static int rtc_suspend(struct device *dev, pm_message_t mesg)
 {
        struct rtc_device       *rtc = to_rtc_device(dev);
        struct rtc_time         tm;
-       struct timespec         ts = current_kernel_time();
 
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
                return 0;
 
        rtc_read_time(rtc, &tm);
+       ktime_get_ts(&oldts);
        rtc_tm_to_time(&tm, &oldtime);
 
-       /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
-       set_normalized_timespec(&delta,
-                               ts.tv_sec - oldtime,
-                               ts.tv_nsec - (NSEC_PER_SEC >> 1));
-
        return 0;
 }
 
@@ -70,10 +65,12 @@ static int rtc_resume(struct device *dev)
        struct rtc_time         tm;
        time_t                  newtime;
        struct timespec         time;
+       struct timespec         newts;
 
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
                return 0;
 
+       ktime_get_ts(&newts);
        rtc_read_time(rtc, &tm);
        if (rtc_valid_tm(&tm) != 0) {
                pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
@@ -85,15 +82,13 @@ static int rtc_resume(struct device *dev)
                        pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));
                return 0;
        }
+       /* calculate the RTC time delta */
+       set_normalized_timespec(&time, newtime - oldtime, 0);
 
-       /* restore wall clock using delta against this RTC;
-        * adjust again for avg 1/2 second RTC sampling error
-        */
-       set_normalized_timespec(&time,
-                               newtime + delta.tv_sec,
-                               (NSEC_PER_SEC >> 1) + delta.tv_nsec);
-       do_settimeofday(&time);
+       /* subtract kernel time between rtc_suspend to rtc_resume */
+       time = timespec_sub(time, timespec_sub(newts, oldts));
 
+       timekeeping_inject_sleeptime(&time);
        return 0;
 }
 
index 316f484999b55fb861667b5c6950654959ab7b75..80f9c88214c5e61987001d10479094cb8787f2a6 100644 (file)
@@ -220,6 +220,7 @@ static int __init coh901331_probe(struct platform_device *pdev)
        }
        clk_disable(rtap->clk);
 
+       platform_set_drvdata(pdev, rtap);
        rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops,
                                         THIS_MODULE);
        if (IS_ERR(rtap->rtc)) {
@@ -227,11 +228,10 @@ static int __init coh901331_probe(struct platform_device *pdev)
                goto out_no_rtc;
        }
 
-       platform_set_drvdata(pdev, rtap);
-
        return 0;
 
  out_no_rtc:
+       platform_set_drvdata(pdev, NULL);
  out_no_clk_enable:
        clk_put(rtap->clk);
  out_no_clk:
index 8d46838dff8a0aaac95e032211bd9945f2ced1c4..755e1fe914af46911bedf6897cb553240a0e0e3d 100644 (file)
@@ -524,6 +524,8 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
                goto fail2;
        }
 
+       platform_set_drvdata(pdev, davinci_rtc);
+
        davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
                                    &davinci_rtc_ops, THIS_MODULE);
        if (IS_ERR(davinci_rtc->rtc)) {
@@ -553,8 +555,6 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 
        rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL);
 
-       platform_set_drvdata(pdev, davinci_rtc);
-
        device_init_wakeup(&pdev->dev, 0);
 
        return 0;
@@ -562,6 +562,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 fail4:
        rtc_device_unregister(davinci_rtc->rtc);
 fail3:
+       platform_set_drvdata(pdev, NULL);
        iounmap(davinci_rtc->base);
 fail2:
        release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
index 60ce69600828237e63175a7aed8962a6d463a86e..47e681df31e280d27f4ce1a926b0f1c5bedbc13e 100644 (file)
@@ -355,6 +355,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev)
                goto out;
        }
        spin_lock_init(&priv->lock);
+       platform_set_drvdata(pdev, priv);
        rtc = rtc_device_register("ds1286", &pdev->dev,
                                  &ds1286_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -362,7 +363,6 @@ static int __devinit ds1286_probe(struct platform_device *pdev)
                goto out;
        }
        priv->rtc = rtc;
-       platform_set_drvdata(pdev, priv);
        return 0;
 
 out:
index 11ae64dcbf3c7b1a365853ae16cb095cbb38ea9f..335551d333b24f10a428c4f332792190181ec82f 100644 (file)
@@ -151,6 +151,7 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
                return -ENXIO;
 
        pdev->dev.platform_data = ep93xx_rtc;
+       platform_set_drvdata(pdev, rtc);
 
        rtc = rtc_device_register(pdev->name,
                                &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
@@ -159,8 +160,6 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
                goto exit;
        }
 
-       platform_set_drvdata(pdev, rtc);
-
        err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
        if (err)
                goto fail;
@@ -168,9 +167,9 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
        return 0;
 
 fail:
-       platform_set_drvdata(pdev, NULL);
        rtc_device_unregister(rtc);
 exit:
+       platform_set_drvdata(pdev, NULL);
        pdev->dev.platform_data = NULL;
        return err;
 }
index 69fe664a2228a801ede6c1cae5973b551a89f258..eda128fc1d38729ebb1a385c10fd30e6345e852b 100644 (file)
@@ -783,6 +783,9 @@ static int m41t80_probe(struct i2c_client *client,
                goto exit;
        }
 
+       clientdata->features = id->driver_data;
+       i2c_set_clientdata(client, clientdata);
+
        rtc = rtc_device_register(client->name, &client->dev,
                                  &m41t80_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -792,8 +795,6 @@ static int m41t80_probe(struct i2c_client *client,
        }
 
        clientdata->rtc = rtc;
-       clientdata->features = id->driver_data;
-       i2c_set_clientdata(client, clientdata);
 
        /* Make sure HT (Halt Update) bit is cleared */
        rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
index 174036dda78652ce106afc23d12699f1d310000b..3bc046f427e04c373465a0ac25f9125d0e89043f 100644 (file)
@@ -257,6 +257,10 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
                goto out_irq;
        }
 
+       dev_set_drvdata(&pdev->dev, info);
+       /* XXX - isn't this redundant? */
+       platform_set_drvdata(pdev, info);
+
        info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
                                        &max8925_rtc_ops, THIS_MODULE);
        ret = PTR_ERR(info->rtc_dev);
@@ -265,11 +269,9 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
                goto out_rtc;
        }
 
-       dev_set_drvdata(&pdev->dev, info);
-       platform_set_drvdata(pdev, info);
-
        return 0;
 out_rtc:
+       platform_set_drvdata(pdev, NULL);
        free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
 out_irq:
        kfree(info);
index 3f7bc6b9fefa94186c020503e8614304606d336b..2e48aa604273ad8e93f737888de136ec549467b5 100644 (file)
@@ -265,6 +265,8 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
        info->rtc = max8998->rtc;
        info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0;
 
+       platform_set_drvdata(pdev, info);
+
        info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev,
                        &max8998_rtc_ops, THIS_MODULE);
 
@@ -274,8 +276,6 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
                goto out_rtc;
        }
 
-       platform_set_drvdata(pdev, info);
-
        ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0,
                        "rtc-alarm0", info);
 
@@ -293,6 +293,7 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
        return 0;
 
 out_rtc:
+       platform_set_drvdata(pdev, NULL);
        kfree(info);
        return ret;
 }
index c5ac03793e7910fec863f70130496cd3a3d60e9c..a1a278bc340dbfd0ff6814c8bcfec577f6137c85 100644 (file)
@@ -349,11 +349,15 @@ static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev)
        if (ret)
                goto err_alarm_irq_request;
 
+       mc13xxx_unlock(mc13xxx);
+
        priv->rtc = rtc_device_register(pdev->name,
                        &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE);
        if (IS_ERR(priv->rtc)) {
                ret = PTR_ERR(priv->rtc);
 
+               mc13xxx_lock(mc13xxx);
+
                mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
 err_alarm_irq_request:
 
@@ -365,12 +369,12 @@ err_reset_irq_status:
                mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 err_reset_irq_request:
 
+               mc13xxx_unlock(mc13xxx);
+
                platform_set_drvdata(pdev, NULL);
                kfree(priv);
        }
 
-       mc13xxx_unlock(mc13xxx);
-
        return ret;
 }
 
index 67820626e18fa7fe4f7d889c614336db2533f5c7..fcb113c11122b7a762abd88f700bd53dc1713a15 100644 (file)
@@ -214,6 +214,7 @@ static int __init msm6242_rtc_probe(struct platform_device *dev)
                error = -ENOMEM;
                goto out_free_priv;
        }
+       platform_set_drvdata(dev, priv);
 
        rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops,
                                  THIS_MODULE);
@@ -223,10 +224,10 @@ static int __init msm6242_rtc_probe(struct platform_device *dev)
        }
 
        priv->rtc = rtc;
-       platform_set_drvdata(dev, priv);
        return 0;
 
 out_unmap:
+       platform_set_drvdata(dev, NULL);
        iounmap(priv->regs);
 out_free_priv:
        kfree(priv);
index 826ab64a8fa91d1a4524e7e3e7a2ae2ce565fec8..d814417bee8c08b68224fafcbeb39e7ca405fd5d 100644 (file)
@@ -418,14 +418,6 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
                goto exit_put_clk;
        }
 
-       rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
-                                 THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               goto exit_put_clk;
-       }
-
-       pdata->rtc = rtc;
        platform_set_drvdata(pdev, pdata);
 
        /* Configure and enable the RTC */
@@ -438,8 +430,19 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
                pdata->irq = -1;
        }
 
+       rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
+                                 THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto exit_clr_drvdata;
+       }
+
+       pdata->rtc = rtc;
+
        return 0;
 
+exit_clr_drvdata:
+       platform_set_drvdata(pdev, NULL);
 exit_put_clk:
        clk_disable(pdata->clk);
        clk_put(pdata->clk);
index de0dd7b1f146e0e7fff07bd30487b1da9add0ca1..bcae8dd41496ab089d43e6639fedfd4272dca035 100644 (file)
@@ -394,7 +394,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        return 0;
 
 fail2:
-       free_irq(omap_rtc_timer, NULL);
+       free_irq(omap_rtc_timer, rtc);
 fail1:
        rtc_device_unregister(rtc);
 fail0:
index a633abc428966a91384d92f2613113a3a8861eab..cd4f198cc2eff921b364eaa1d66ae8b97e7cf5a1 100644 (file)
@@ -151,6 +151,8 @@ static int __devinit pcap_rtc_probe(struct platform_device *pdev)
 
        pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent);
 
+       platform_set_drvdata(pdev, pcap_rtc);
+
        pcap_rtc->rtc = rtc_device_register("pcap", &pdev->dev,
                                  &pcap_rtc_ops, THIS_MODULE);
        if (IS_ERR(pcap_rtc->rtc)) {
@@ -158,7 +160,6 @@ static int __devinit pcap_rtc_probe(struct platform_device *pdev)
                goto fail_rtc;
        }
 
-       platform_set_drvdata(pdev, pcap_rtc);
 
        timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ);
        alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA);
@@ -177,6 +178,7 @@ fail_alarm:
 fail_timer:
        rtc_device_unregister(pcap_rtc->rtc);
 fail_rtc:
+       platform_set_drvdata(pdev, NULL);
        kfree(pcap_rtc);
        return err;
 }
index 694da39b6dd25ff7c8bfb9830c2a5405d7aa47e0..359da6d020b98c99318dddcc1a007e1be7d452ba 100644 (file)
@@ -249,15 +249,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
 
        spin_lock_init(&priv->lock);
 
+       platform_set_drvdata(dev, priv);
+
        rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops,
                                  THIS_MODULE);
        if (IS_ERR(rtc)) {
                error = PTR_ERR(rtc);
                goto out_unmap;
        }
-
        priv->rtc = rtc;
-       platform_set_drvdata(dev, priv);
 
        error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr);
        if (error)
@@ -268,6 +268,7 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
 out_unregister:
        rtc_device_unregister(rtc);
 out_unmap:
+       platform_set_drvdata(dev, NULL);
        iounmap(priv->regs);
 out_free_priv:
        kfree(priv);
index b3466c491cd35cbbd93a64df0f1dbcf070c84e6c..16512ecae31a384fef42e743884b5b0c8d905d7d 100644 (file)
@@ -46,6 +46,7 @@ static struct clk *rtc_clk;
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
 static int s3c_rtc_tickno  = NO_IRQ;
+static bool wake_en;
 static enum s3c_cpu_type s3c_rtc_cpu_type;
 
 static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
@@ -562,8 +563,12 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
        }
        s3c_rtc_enable(pdev, 0);
 
-       if (device_may_wakeup(&pdev->dev))
-               enable_irq_wake(s3c_rtc_alarmno);
+       if (device_may_wakeup(&pdev->dev) && !wake_en) {
+               if (enable_irq_wake(s3c_rtc_alarmno) == 0)
+                       wake_en = true;
+               else
+                       dev_err(&pdev->dev, "enable_irq_wake failed\n");
+       }
 
        return 0;
 }
@@ -579,8 +584,10 @@ static int s3c_rtc_resume(struct platform_device *pdev)
                writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
        }
 
-       if (device_may_wakeup(&pdev->dev))
+       if (device_may_wakeup(&pdev->dev) && wake_en) {
                disable_irq_wake(s3c_rtc_alarmno);
+               wake_en = false;
+       }
 
        return 0;
 }
index 4d2df2f76ea0daa718215c179e88fe2b45249516..86b6f1cc1b10c56277f49ec439b893daf2c25f33 100644 (file)
@@ -1742,11 +1742,20 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
 static inline int _dasd_term_running_cqr(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
+       int rc;
 
        if (list_empty(&device->ccw_queue))
                return 0;
        cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
-       return device->discipline->term_IO(cqr);
+       rc = device->discipline->term_IO(cqr);
+       if (!rc)
+               /*
+                * CQR terminated because a more important request is pending.
+                * Undo decreasing of retry counter because this is
+                * not an error case.
+                */
+               cqr->retries++;
+       return rc;
 }
 
 int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
@@ -2314,15 +2323,14 @@ static void dasd_flush_request_queue(struct dasd_block *block)
 
 static int dasd_open(struct block_device *bdev, fmode_t mode)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
        struct dasd_device *base;
        int rc;
 
-       if (!block)
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
                return -ENODEV;
 
-       base = block->base;
-       atomic_inc(&block->open_count);
+       atomic_inc(&base->block->open_count);
        if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
                rc = -ENODEV;
                goto unlock;
@@ -2355,21 +2363,28 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
                goto out;
        }
 
+       dasd_put_device(base);
        return 0;
 
 out:
        module_put(base->discipline->owner);
 unlock:
-       atomic_dec(&block->open_count);
+       atomic_dec(&base->block->open_count);
+       dasd_put_device(base);
        return rc;
 }
 
 static int dasd_release(struct gendisk *disk, fmode_t mode)
 {
-       struct dasd_block *block = disk->private_data;
+       struct dasd_device *base;
 
-       atomic_dec(&block->open_count);
-       module_put(block->base->discipline->owner);
+       base = dasd_device_from_gendisk(disk);
+       if (!base)
+               return -ENODEV;
+
+       atomic_dec(&base->block->open_count);
+       module_put(base->discipline->owner);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -2378,20 +2393,20 @@ static int dasd_release(struct gendisk *disk, fmode_t mode)
  */
 static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct dasd_block *block;
        struct dasd_device *base;
 
-       block = bdev->bd_disk->private_data;
-       if (!block)
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
                return -ENODEV;
-       base = block->base;
 
        if (!base->discipline ||
-           !base->discipline->fill_geometry)
+           !base->discipline->fill_geometry) {
+               dasd_put_device(base);
                return -EINVAL;
-
-       base->discipline->fill_geometry(block, geo);
-       geo->start = get_start_sect(bdev) >> block->s2b_shift;
+       }
+       base->discipline->fill_geometry(base->block, geo);
+       geo->start = get_start_sect(bdev) >> base->block->s2b_shift;
+       dasd_put_device(base);
        return 0;
 }
 
@@ -2528,7 +2543,6 @@ void dasd_generic_remove(struct ccw_device *cdev)
        dasd_set_target_state(device, DASD_STATE_NEW);
        /* dasd_delete_device destroys the device reference. */
        block = device->block;
-       device->block = NULL;
        dasd_delete_device(device);
        /*
         * life cycle of block is bound to device, so delete it after
@@ -2650,7 +2664,6 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
        dasd_set_target_state(device, DASD_STATE_NEW);
        /* dasd_delete_device destroys the device reference. */
        block = device->block;
-       device->block = NULL;
        dasd_delete_device(device);
        /*
         * life cycle of block is bound to device, so delete it after
index 42e1bf35f6893d53e3374eba20673b1d27d095f7..d71511c7850a8560014ceee03c468e4da24c361a 100644 (file)
@@ -674,6 +674,36 @@ dasd_device_from_cdev(struct ccw_device *cdev)
        return device;
 }
 
+void dasd_add_link_to_gendisk(struct gendisk *gdp, struct dasd_device *device)
+{
+       struct dasd_devmap *devmap;
+
+       devmap = dasd_find_busid(dev_name(&device->cdev->dev));
+       if (IS_ERR(devmap))
+               return;
+       spin_lock(&dasd_devmap_lock);
+       gdp->private_data = devmap;
+       spin_unlock(&dasd_devmap_lock);
+}
+
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *gdp)
+{
+       struct dasd_device *device;
+       struct dasd_devmap *devmap;
+
+       if (!gdp->private_data)
+               return NULL;
+       device = NULL;
+       spin_lock(&dasd_devmap_lock);
+       devmap = gdp->private_data;
+       if (devmap && devmap->device) {
+               device = devmap->device;
+               dasd_get_device(device);
+       }
+       spin_unlock(&dasd_devmap_lock);
+       return device;
+}
+
 /*
  * SECTION: files in sysfs
  */
index 29143eda9dd903b4a8f897ade5eee20dcaecaf91..85dddb1e4126be512d843ceef08123fd86cc1b0d 100644 (file)
@@ -239,7 +239,6 @@ static void dasd_ext_handler(unsigned int ext_int_code,
        addr_t ip;
        int rc;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
        switch (ext_int_code >> 24) {
        case DASD_DIAG_CODE_31BIT:
                ip = (addr_t) param32;
@@ -250,6 +249,7 @@ static void dasd_ext_handler(unsigned int ext_int_code,
        default:
                return;
        }
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
        if (!ip) {              /* no intparm: unsolicited interrupt */
                DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
                              "interrupt");
index db8005d9f2fd2fe2effb667659228e4f3d38ba9f..3ebdf5f92f8f945fabad2e9744fa82f106b8a33b 100644 (file)
@@ -2037,7 +2037,7 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
                return;
 
        /* summary unit check */
-       if ((sense[7] == 0x0D) &&
+       if ((sense[27] & DASD_SENSE_BIT_0) && (sense[7] == 0x0D) &&
            (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
                dasd_alias_handle_summary_unit_check(device, irb);
                return;
@@ -2053,7 +2053,8 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
        /* loss of device reservation is handled via base devices only
         * as alias devices may be used with several bases
         */
-       if (device->block && (sense[7] == 0x3F) &&
+       if (device->block && (sense[27] & DASD_SENSE_BIT_0) &&
+           (sense[7] == 0x3F) &&
            (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
            test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) {
                if (device->features & DASD_FEATURE_FAILONSLCK)
index 5505bc07e1e7cccccb84549943d89b772533d199..19a1ff03d65ef25c5320585c04064916827a41bb 100644 (file)
@@ -73,7 +73,7 @@ int dasd_gendisk_alloc(struct dasd_block *block)
        if (base->features & DASD_FEATURE_READONLY ||
            test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
                set_disk_ro(gdp, 1);
-       gdp->private_data = block;
+       dasd_add_link_to_gendisk(gdp, base);
        gdp->queue = block->request_queue;
        block->gdp = gdp;
        set_capacity(block->gdp, 0);
index df9f6999411def84414938e65df42d699b33bfcc..d1e4f2c1264c54225a70307b0830343a5e5c5f0c 100644 (file)
@@ -686,6 +686,9 @@ struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
 struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
 struct dasd_device *dasd_device_from_devindex(int);
 
+void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *);
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *);
+
 int dasd_parse(void);
 int dasd_busid_known(const char *);
 
index 26075e95b1bad786db8ff7b0e8504521fe8f3d68..72261e4c516de89e836a2afb3d646d24b947ecfd 100644 (file)
@@ -42,16 +42,22 @@ dasd_ioctl_api_version(void __user *argp)
 static int
 dasd_ioctl_enable(struct block_device *bdev)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       dasd_enable_device(block->base);
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+
+       dasd_enable_device(base);
        /* Formatting the dasd device can change the capacity. */
        mutex_lock(&bdev->bd_mutex);
-       i_size_write(bdev->bd_inode, (loff_t)get_capacity(block->gdp) << 9);
+       i_size_write(bdev->bd_inode,
+                    (loff_t)get_capacity(base->block->gdp) << 9);
        mutex_unlock(&bdev->bd_mutex);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -62,11 +68,14 @@ dasd_ioctl_enable(struct block_device *bdev)
 static int
 dasd_ioctl_disable(struct block_device *bdev)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
        /*
         * Man this is sick. We don't do a real disable but only downgrade
         * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
@@ -75,7 +84,7 @@ dasd_ioctl_disable(struct block_device *bdev)
         * using the BIODASDFMT ioctl. Therefore the correct state for the
         * device is DASD_STATE_BASIC that allows to do basic i/o.
         */
-       dasd_set_target_state(block->base, DASD_STATE_BASIC);
+       dasd_set_target_state(base, DASD_STATE_BASIC);
        /*
         * Set i_size to zero, since read, write, etc. check against this
         * value.
@@ -83,6 +92,7 @@ dasd_ioctl_disable(struct block_device *bdev)
        mutex_lock(&bdev->bd_mutex);
        i_size_write(bdev->bd_inode, 0);
        mutex_unlock(&bdev->bd_mutex);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -191,26 +201,36 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
 static int
 dasd_ioctl_format(struct block_device *bdev, void __user *argp)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
        struct format_data_t fdata;
+       int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (!argp)
                return -EINVAL;
-
-       if (block->base->features & DASD_FEATURE_READONLY ||
-           test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       if (base->features & DASD_FEATURE_READONLY ||
+           test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+               dasd_put_device(base);
                return -EROFS;
-       if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
+       }
+       if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
+               dasd_put_device(base);
                return -EFAULT;
+       }
        if (bdev != bdev->bd_contains) {
                pr_warning("%s: The specified DASD is a partition and cannot "
                           "be formatted\n",
-                          dev_name(&block->base->cdev->dev));
+                          dev_name(&base->cdev->dev));
+               dasd_put_device(base);
                return -EINVAL;
        }
-       return dasd_format(block, &fdata);
+       rc = dasd_format(base->block, &fdata);
+       dasd_put_device(base);
+       return rc;
 }
 
 #ifdef CONFIG_DASD_PROFILE
@@ -340,8 +360,8 @@ static int dasd_ioctl_information(struct dasd_block *block,
 static int
 dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
 {
-       struct dasd_block *block =  bdev->bd_disk->private_data;
-       int intval;
+       struct dasd_device *base;
+       int intval, rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -350,10 +370,17 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
                return -EINVAL;
        if (get_user(intval, (int __user *)argp))
                return -EFAULT;
-       if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+               dasd_put_device(base);
                return -EROFS;
+       }
        set_disk_ro(bdev->bd_disk, intval);
-       return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
+       rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
+       dasd_put_device(base);
+       return rc;
 }
 
 static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
@@ -372,59 +399,78 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
 int dasd_ioctl(struct block_device *bdev, fmode_t mode,
               unsigned int cmd, unsigned long arg)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_block *block;
+       struct dasd_device *base;
        void __user *argp;
+       int rc;
 
        if (is_compat_task())
                argp = compat_ptr(arg);
        else
                argp = (void __user *)arg;
 
-       if (!block)
-                return -ENODEV;
-
        if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
                PRINT_DEBUG("empty data ptr");
                return -EINVAL;
        }
 
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       block = base->block;
+       rc = 0;
        switch (cmd) {
        case BIODASDDISABLE:
-               return dasd_ioctl_disable(bdev);
+               rc = dasd_ioctl_disable(bdev);
+               break;
        case BIODASDENABLE:
-               return dasd_ioctl_enable(bdev);
+               rc = dasd_ioctl_enable(bdev);
+               break;
        case BIODASDQUIESCE:
-               return dasd_ioctl_quiesce(block);
+               rc = dasd_ioctl_quiesce(block);
+               break;
        case BIODASDRESUME:
-               return dasd_ioctl_resume(block);
+               rc = dasd_ioctl_resume(block);
+               break;
        case BIODASDFMT:
-               return dasd_ioctl_format(bdev, argp);
+               rc = dasd_ioctl_format(bdev, argp);
+               break;
        case BIODASDINFO:
-               return dasd_ioctl_information(block, cmd, argp);
+               rc = dasd_ioctl_information(block, cmd, argp);
+               break;
        case BIODASDINFO2:
-               return dasd_ioctl_information(block, cmd, argp);
+               rc = dasd_ioctl_information(block, cmd, argp);
+               break;
        case BIODASDPRRD:
-               return dasd_ioctl_read_profile(block, argp);
+               rc = dasd_ioctl_read_profile(block, argp);
+               break;
        case BIODASDPRRST:
-               return dasd_ioctl_reset_profile(block);
+               rc = dasd_ioctl_reset_profile(block);
+               break;
        case BLKROSET:
-               return dasd_ioctl_set_ro(bdev, argp);
+               rc = dasd_ioctl_set_ro(bdev, argp);
+               break;
        case DASDAPIVER:
-               return dasd_ioctl_api_version(argp);
+               rc = dasd_ioctl_api_version(argp);
+               break;
        case BIODASDCMFENABLE:
-               return enable_cmf(block->base->cdev);
+               rc = enable_cmf(base->cdev);
+               break;
        case BIODASDCMFDISABLE:
-               return disable_cmf(block->base->cdev);
+               rc = disable_cmf(base->cdev);
+               break;
        case BIODASDREADALLCMB:
-               return dasd_ioctl_readall_cmb(block, cmd, argp);
+               rc = dasd_ioctl_readall_cmb(block, cmd, argp);
+               break;
        default:
                /* if the discipline has an ioctl method try it. */
-               if (block->base->discipline->ioctl) {
-                       int rval = block->base->discipline->ioctl(block, cmd, argp);
-                       if (rval != -ENOIOCTLCMD)
-                               return rval;
-               }
-
-               return -EINVAL;
+               if (base->discipline->ioctl) {
+                       rc = base->discipline->ioctl(block, cmd, argp);
+                       if (rc == -ENOIOCTLCMD)
+                               rc = -EINVAL;
+               } else
+                       rc = -EINVAL;
        }
+       dasd_put_device(base);
+       return rc;
 }
index 4b60ede07f0e0f9738d22c70d53c3393eff1b37e..be55fb2b1b1c58f78a3df48ad8ac7be544f3ec51 100644 (file)
@@ -518,6 +518,8 @@ static void __init insert_increment(u16 rn, int standby, int assigned)
                return;
        new_incr->rn = rn;
        new_incr->standby = standby;
+       if (!standby)
+               new_incr->usecount = 1;
        last_rn = 0;
        prev = &sclp_mem_list;
        list_for_each_entry(incr, &sclp_mem_list, list) {
index 83cea9a55e2f8c10df077710a66f23760a7431e6..1b3924c2fffd9b87cdaede8204ffab3cbbe7d129 100644 (file)
@@ -236,7 +236,6 @@ tapeblock_setup_device(struct tape_device * device)
        disk->major = tapeblock_major;
        disk->first_minor = device->first_minor;
        disk->fops = &tapeblock_fops;
-       disk->events = DISK_EVENT_MEDIA_CHANGE;
        disk->private_data = tape_get_device(device);
        disk->queue = blkdat->request_queue;
        set_capacity(disk, 0);
index c532ba929ccde2c0c802edcf4ad870a7a78cf484..e8f267eb88873b2a65e8d0cb05bcce3dc5c2c33c 100644 (file)
@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count)
        q->q_stats.nr_sbals[pos]++;
 }
 
-static void announce_buffer_error(struct qdio_q *q, int count)
+static void process_buffer_error(struct qdio_q *q, int count)
 {
+       unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
+                                       SLSB_P_OUTPUT_NOT_INIT;
+
        q->qdio_error |= QDIO_ERROR_SLSB_STATE;
 
        /* special handling for no target buffer empty */
@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count)
        DBF_ERROR("F14:%2x F15:%2x",
                  q->sbal[q->first_to_check]->element[14].flags & 0xff,
                  q->sbal[q->first_to_check]->element[15].flags & 0xff);
+
+       /*
+        * Interrupts may be avoided as long as the error is present
+        * so change the buffer state immediately to avoid starvation.
+        */
+       set_buf_states(q, q->first_to_check, state, count);
 }
 
 static inline void inbound_primed(struct qdio_q *q, int count)
@@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
                        account_sbals(q, count);
                break;
        case SLSB_P_INPUT_ERROR:
-               announce_buffer_error(q, count);
-               /* process the buffer, the upper layer will take care of it */
+               process_buffer_error(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
                atomic_sub(count, &q->nr_buf_used);
                if (q->irq_ptr->perf_stat_enabled)
@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
                        account_sbals(q, count);
                break;
        case SLSB_P_OUTPUT_ERROR:
-               announce_buffer_error(q, count);
-               /* process the buffer, the upper layer will take care of it */
+               process_buffer_error(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
                atomic_sub(count, &q->nr_buf_used);
                if (q->irq_ptr->perf_stat_enabled)
index 414427d64a8ff6f46b3b7e375c7db97a95a66dac..607998f0b7d8580c05c4fec47cf672bfad9d3c14 100644 (file)
@@ -381,10 +381,10 @@ static void kvm_extint_handler(unsigned int ext_int_code,
        u16 subcode;
        u32 param;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
        subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
                return;
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
 
        /* The LSB might be overloaded, we have to mask it */
        vq = (struct virtqueue *)(param64 & ~1UL);
index 564e6ecd17c2d1feb7e9330aa129464f8b714bf0..0119b814779744ccfc448bceddcaac3a7e195fcc 100644 (file)
@@ -394,12 +394,14 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
        unsigned long flags;
        struct scsi_device *sdev;
        struct scsi_device_handler *scsi_dh = NULL;
+       struct device *dev = NULL;
 
        spin_lock_irqsave(q->queue_lock, flags);
        sdev = q->queuedata;
        if (sdev && sdev->scsi_dh_data)
                scsi_dh = sdev->scsi_dh_data->scsi_dh;
-       if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+       dev = get_device(&sdev->sdev_gendev);
+       if (!scsi_dh || !dev ||
            sdev->sdev_state == SDEV_CANCEL ||
            sdev->sdev_state == SDEV_DEL)
                err = SCSI_DH_NOSYS;
@@ -410,12 +412,13 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
        if (err) {
                if (fn)
                        fn(data, err);
-               return err;
+               goto out;
        }
 
        if (scsi_dh->activate)
                err = scsi_dh->activate(sdev, fn, data);
-       put_device(&sdev->sdev_gendev);
+out:
+       put_device(dev);
        return err;
 }
 EXPORT_SYMBOL_GPL(scsi_dh_activate);
index 1c6d2b405eefb49e9913b48c2015c12028161971..d72f1f2b1392eb5c49ba5efd5f3fae06e69b0b3d 100644 (file)
@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                goto out;
        }
 
+       /* Check for overflow and wraparound */
+       if (karg.data_sge_offset * 4 > ioc->request_sz ||
+           karg.data_sge_offset > (UINT_MAX / 4)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        /* copy in request message frame from user */
        if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        Mpi2DiagBufferPostReply_t *mpi_reply;
        int rc, i;
        u8 buffer_type;
-       unsigned long timeleft;
+       unsigned long timeleft, request_size, copy_size;
        u16 smid;
        u16 ioc_status;
        u8 issue_reset = 0;
@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
                return -ENOMEM;
        }
 
+       request_size = ioc->diag_buffer_sz[buffer_type];
+
        if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
                printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
                    "or bytes_to_read are not 4 byte aligned\n", ioc->name,
@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
                return -EINVAL;
        }
 
+       if (karg.starting_offset > request_size)
+               return -EINVAL;
+
        diag_data = (void *)(request_data + karg.starting_offset);
        dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
            "offset(%d), sz(%d)\n", ioc->name, __func__,
            diag_data, karg.starting_offset, karg.bytes_to_read));
 
+       /* Truncate data on requests that are too large */
+       if ((diag_data + karg.bytes_to_read < diag_data) ||
+           (diag_data + karg.bytes_to_read > request_data + request_size))
+               copy_size = request_size - karg.starting_offset;
+       else
+               copy_size = karg.bytes_to_read;
+
        if (copy_to_user((void __user *)uarg->diagnostic_data,
-           diag_data, karg.bytes_to_read)) {
+           diag_data, copy_size)) {
                printk(MPT2SAS_ERR_FMT "%s: Unable to write "
                    "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
                    __func__, diag_data);
index 96d5ad0c1e420ed61c8f2b673997284e3b65bf4b..7f636b118287a7bb0f9e3ac7d1cdecb27ed0598d 100644 (file)
@@ -3814,6 +3814,9 @@ static long pmcraid_ioctl_passthrough(
                        rc = -EFAULT;
                        goto out_free_buffer;
                }
+       } else if (request_size < 0) {
+               rc = -EINVAL;
+               goto out_free_buffer;
        }
 
        /* check if we have any additional command parameters */
index e2d45c91b8e8fa9d99d2d6abc17739aff12e6012..9689d41c788887f4f3fb12e43c87b0c67ae1aa39 100644 (file)
@@ -1292,8 +1292,10 @@ static struct scsi_host_template qpti_template = {
        .use_clustering         = ENABLE_CLUSTERING,
 };
 
+static const struct of_device_id qpti_match[];
 static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
+       const struct of_device_id *match;
        struct scsi_host_template *tpnt;
        struct device_node *dp = op->dev.of_node;
        struct Scsi_Host *host;
@@ -1301,9 +1303,10 @@ static int __devinit qpti_sbus_probe(struct platform_device *op)
        static int nqptis;
        const char *fcode;
 
-       if (!op->dev.of_match)
+       match = of_match_device(qpti_match, &op->dev);
+       if (!match)
                return -EINVAL;
-       tpnt = op->dev.of_match->data;
+       tpnt = match->data;
 
        /* Sometimes Antares cards come up not completely
         * setup, and we get a report of a zero IRQ.
index ab55c2fa7ce209563f99691a7201122fb619fdd9..ec1803a48723dc950f56eb3fddb33456ea8d9a61 100644 (file)
@@ -74,8 +74,6 @@ struct kmem_cache *scsi_sdb_cache;
  */
 #define SCSI_QUEUE_DELAY       3
 
-static void scsi_run_queue(struct request_queue *q);
-
 /*
  * Function:   scsi_unprep_request()
  *
@@ -161,7 +159,7 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
        blk_requeue_request(q, cmd->request);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
-       scsi_run_queue(q);
+       kblockd_schedule_work(q, &device->requeue_work);
 
        return 0;
 }
@@ -400,10 +398,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost)
 static void scsi_run_queue(struct request_queue *q)
 {
        struct scsi_device *sdev = q->queuedata;
-       struct Scsi_Host *shost = sdev->host;
+       struct Scsi_Host *shost;
        LIST_HEAD(starved_list);
        unsigned long flags;
 
+       /* if the device is dead, sdev will be NULL, so no queue to run */
+       if (!sdev)
+               return;
+
+       shost = sdev->host;
        if (scsi_target(sdev)->single_lun)
                scsi_single_lun_run(sdev);
 
@@ -411,8 +414,6 @@ static void scsi_run_queue(struct request_queue *q)
        list_splice_init(&shost->starved_list, &starved_list);
 
        while (!list_empty(&starved_list)) {
-               int flagset;
-
                /*
                 * As long as shost is accepting commands and we have
                 * starved queues, call blk_run_queue. scsi_request_fn
@@ -436,18 +437,9 @@ static void scsi_run_queue(struct request_queue *q)
                }
 
                spin_unlock(shost->host_lock);
-
                spin_lock(sdev->request_queue->queue_lock);
-               flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
-                               !test_bit(QUEUE_FLAG_REENTER,
-                                       &sdev->request_queue->queue_flags);
-               if (flagset)
-                       queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
                __blk_run_queue(sdev->request_queue);
-               if (flagset)
-                       queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
                spin_unlock(sdev->request_queue->queue_lock);
-
                spin_lock(shost->host_lock);
        }
        /* put any unprocessed entries back */
@@ -457,6 +449,16 @@ static void scsi_run_queue(struct request_queue *q)
        blk_run_queue(q);
 }
 
+void scsi_requeue_run_queue(struct work_struct *work)
+{
+       struct scsi_device *sdev;
+       struct request_queue *q;
+
+       sdev = container_of(work, struct scsi_device, requeue_work);
+       q = sdev->request_queue;
+       scsi_run_queue(q);
+}
+
 /*
  * Function:   scsi_requeue_command()
  *
index 087821fac8fe76d64b50b0beaad7b1dd3c2dff0c..58584dc0724ade4fb4b2d5fc12d48b962d2b91bd 100644 (file)
@@ -242,6 +242,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        int display_failure_msg = 1, ret;
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        extern void scsi_evt_thread(struct work_struct *work);
+       extern void scsi_requeue_run_queue(struct work_struct *work);
 
        sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
                       GFP_ATOMIC);
@@ -264,6 +265,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        INIT_LIST_HEAD(&sdev->event_list);
        spin_lock_init(&sdev->list_lock);
        INIT_WORK(&sdev->event_work, scsi_evt_thread);
+       INIT_WORK(&sdev->requeue_work, scsi_requeue_run_queue);
 
        sdev->sdev_gendev.parent = get_device(&starget->dev);
        sdev->sdev_target = starget;
index e44ff64233fd5fbe00a4aa675081bcac319739af..e63912510fb9349b31ede55df1c0b20011b6235e 100644 (file)
@@ -322,14 +322,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
                kfree(evt);
        }
 
-       if (sdev->request_queue) {
-               sdev->request_queue->queuedata = NULL;
-               /* user context needed to free queue */
-               scsi_free_queue(sdev->request_queue);
-               /* temporary expedient, try to catch use of queue lock
-                * after free of sdev */
-               sdev->request_queue = NULL;
-       }
+       /* NULL queue means the device can't be used */
+       sdev->request_queue = NULL;
 
        scsi_target_reap(scsi_target(sdev));
 
@@ -937,6 +931,12 @@ void __scsi_remove_device(struct scsi_device *sdev)
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(dev);
+
+       /* cause the request function to reject all I/O requests */
+       sdev->request_queue->queuedata = NULL;
+
+       /* Freeing the queue signals to block that we're done */
+       scsi_free_queue(sdev->request_queue);
        put_device(dev);
 }
 
index 28c33506e4ada98b560f020410f9bcff803a074e..815069d13f9b57edc5ddaf22dbb223c452d74811 100644 (file)
@@ -3816,28 +3816,17 @@ fail_host_msg:
 static void
 fc_bsg_goose_queue(struct fc_rport *rport)
 {
-       int flagset;
-       unsigned long flags;
-
        if (!rport->rqst_q)
                return;
 
+       /*
+        * This get/put dance makes no sense
+        */
        get_device(&rport->dev);
-
-       spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
-       flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
-                 !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
-       if (flagset)
-               queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q);
-       __blk_run_queue(rport->rqst_q);
-       if (flagset)
-               queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
-       spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
-
+       blk_run_queue_async(rport->rqst_q);
        put_device(&rport->dev);
 }
 
-
 /**
  * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
  * @q:         rport request queue
index 6f34963b3c6445f7a0417bd76a6123bc62106233..7ad48585c5e6c0cc0ad9c0593ae3ad24394b0314 100644 (file)
@@ -662,7 +662,6 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 static int ssb_pci_sprom_get(struct ssb_bus *bus,
                             struct ssb_sprom *sprom)
 {
-       const struct ssb_sprom *fallback;
        int err;
        u16 *buf;
 
@@ -707,10 +706,17 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                if (err) {
                        /* All CRC attempts failed.
                         * Maybe there is no SPROM on the device?
-                        * If we have a fallback, use that. */
-                       fallback = ssb_get_fallback_sprom();
-                       if (fallback) {
-                               memcpy(sprom, fallback, sizeof(*sprom));
+                        * Now we ask the arch code if there is some sprom
+                        * available for this device in some other storage */
+                       err = ssb_fill_sprom_with_fallback(bus, sprom);
+                       if (err) {
+                               ssb_printk(KERN_WARNING PFX "WARNING: Using"
+                                          " fallback SPROM failed (err %d)\n",
+                                          err);
+                       } else {
+                               ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
+                                           " revision %d provided by"
+                                           " platform.\n", sprom->revision);
                                err = 0;
                                goto out_free;
                        }
index 5f34d7a3e3a5eb08aa89ba6c616ed431c1cc57ee..45ff0e3a3828df3de8f9188dc5043df3152e24b5 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 
 
-static const struct ssb_sprom *fallback_sprom;
+static int(*get_fallback_sprom)(struct ssb_bus *dev, struct ssb_sprom *out);
 
 
 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
@@ -145,36 +145,43 @@ out:
 }
 
 /**
- * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found.
+ * ssb_arch_register_fallback_sprom - Registers a method providing a
+ * fallback SPROM if no SPROM is found.
  *
- * @sprom: The SPROM data structure to register.
+ * @sprom_callback: The callback function.
  *
- * With this function the architecture implementation may register a fallback
- * SPROM data structure. The fallback is only used for PCI based SSB devices,
- * where no valid SPROM can be found in the shadow registers.
+ * With this function the architecture implementation may register a
+ * callback handler which fills the SPROM data structure. The fallback is
+ * only used for PCI based SSB devices, where no valid SPROM can be found
+ * in the shadow registers.
  *
- * This function is useful for weird architectures that have a half-assed SSB device
- * hardwired to their PCI bus.
+ * This function is useful for weird architectures that have a half-assed
+ * SSB device hardwired to their PCI bus.
  *
- * Note that it does only work with PCI attached SSB devices. PCMCIA devices currently
- * don't use this fallback.
- * Architectures must provide the SPROM for native SSB devices anyway,
- * so the fallback also isn't used for native devices.
+ * Note that it does only work with PCI attached SSB devices. PCMCIA
+ * devices currently don't use this fallback.
+ * Architectures must provide the SPROM for native SSB devices anyway, so
+ * the fallback also isn't used for native devices.
  *
- * This function is available for architecture code, only. So it is not exported.
+ * This function is available for architecture code, only. So it is not
+ * exported.
  */
-int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom)
+int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus,
+                                    struct ssb_sprom *out))
 {
-       if (fallback_sprom)
+       if (get_fallback_sprom)
                return -EEXIST;
-       fallback_sprom = sprom;
+       get_fallback_sprom = sprom_callback;
 
        return 0;
 }
 
-const struct ssb_sprom *ssb_get_fallback_sprom(void)
+int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, struct ssb_sprom *out)
 {
-       return fallback_sprom;
+       if (!get_fallback_sprom)
+               return -ENOENT;
+
+       return get_fallback_sprom(bus, out);
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
index 0331139a726fb2dd44cd30c41985cfa866b2f1f2..77653014db0b8f997a61dec98a26933cacb874d1 100644 (file)
@@ -171,7 +171,8 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
                             const char *buf, size_t count,
                             int (*sprom_check_crc)(const u16 *sprom, size_t size),
                             int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
-extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
+extern int ssb_fill_sprom_with_fallback(struct ssb_bus *bus,
+                                       struct ssb_sprom *out);
 
 
 /* core.c */
index eeb7dd43f9a8ef9128487fd977761d1fae8fbdf7..830822f86e410183c77641bddc9fbe6a29e54194 100644 (file)
@@ -2288,7 +2288,3 @@ err_dev:
        free_netdev(dev);
        return NULL;
 }
-
-EXPORT_SYMBOL(init_ft1000_card);
-EXPORT_SYMBOL(stop_ft1000_card);
-EXPORT_SYMBOL(flarion_ft1000_cnt);
index 935608e72007e25cb075f10f2940ba0977ea3ff0..bdfb1aec58df8a52eb7e42b60d698086abe19825 100644 (file)
@@ -214,6 +214,3 @@ void ft1000CleanupProc(struct net_device *dev)
        remove_proc_entry(FT1000_PROC, init_net.proc_net);
        unregister_netdevice_notifier(&ft1000_netdev_notifier);
 }
-
-EXPORT_SYMBOL(ft1000InitProc);
-EXPORT_SYMBOL(ft1000CleanupProc);
index 5501eb9b3355050eb33526829c51e0e9c94d2fa3..ce8bedaeaac21589f84768e4788bbc4939b36488 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_PSB
        tristate "Intel GMA500 KMS Framebuffer"
-       depends on DRM && PCI
+       depends on DRM && PCI && X86
        select FB_CFB_COPYAREA
         select FB_CFB_FILLRECT
         select FB_CFB_IMAGEBLIT
index 9cc15c1c18d48277f95d8debb8065e46ec541f59..1ea81421805940acca598367a5fe6d3bba43d945 100644 (file)
@@ -28,6 +28,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <linux/file.h>
 #include <asm/mrst.h>
 #include <sound/pcm.h>
index 26d815a67eb836906cd72b3c7553b07fc85ab77b..3c6b3abff3c3e3757fadc8b9a0f43b2895ff8bb6 100644 (file)
@@ -29,6 +29,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <linux/file.h>
 #include "intel_sst.h"
 #include "intelmid_snd_control.h"
index b5d21f6497f9ef14aa4176550615a6203c6a11c8..22c04eabed4116768959b10681c4c880c0940c7c 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/cs5535.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <asm/olpc.h>
 
 #include "olpc_dcon.h"
index bef0bbd8cef75f17027768416388be2424d93233..f01a51c381f1d9e218b65ff79724bfb966250050 100644 (file)
@@ -444,7 +444,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
                        return (NDIS_STATUS_FAILURE);
                }
        }
-       /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */
+       /* Drop not U2M frames, can't drop here because we will drop beacon in this case */
        /* I am kind of doubting the U2M bit operation */
        /* if (pRxD->U2M == 0) */
        /*      return(NDIS_STATUS_FAILURE); */
index 5637857ae9eb7c7ab9b304857291e1ea6e1785da..83a62faa7e5731255f793bbe873b52f2f95d54fc 100644 (file)
@@ -860,7 +860,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
                DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
                return NDIS_STATUS_FAILURE;
        }
-       /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */
+       /* Drop not U2M frames, can't drop here because we will drop beacon in this case */
        /* I am kind of doubting the U2M bit operation */
        /* if (pRxD->U2M == 0) */
        /*      return(NDIS_STATUS_FAILURE); */
index e1408b0e7ae4e33a90a49af8d202d51683f81cca..ab305be96fb5d34e78117b5f4ecddab263adc2a4 100644 (file)
@@ -28,7 +28,7 @@
 
 #define RTSX_STOR "rts_pstor: "
 
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
 #define RTSX_DEBUGP(x...) printk(KERN_DEBUG RTSX_STOR x)
 #define RTSX_DEBUGPN(x...) printk(KERN_DEBUG x)
 #define RTSX_DEBUGPX(x...) printk(x)
index 810e170894f58c3d3180047084dacc31014ec6cd..d89795c6a3ac2545be028198604443b3f37debe0 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index d2f1c715a684201eae59e646ead22096bb154033..4e60780ea80412b7992e1a46b37da22b284ea214 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
@@ -1311,11 +1312,11 @@ void rtsx_polling_func(struct rtsx_chip *chip)
 
 #ifdef SUPPORT_OCP
        if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-               #if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) {
                        RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
                }
-               #endif
+#endif
 
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
                        if (chip->card_exist & SD_CARD) {
index 20c2464a20f9cf7f421d600d7326f5ccb802b5b7..7de1fae443fce559780a97af49cf32352dc3205e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index 8d066bd428c4ad94e4785a974c2b98c2acceddb0..b1277a6c7a8b857dd602ee610a764ab7810ec099 100644 (file)
@@ -909,7 +909,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
                RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
                RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
        } else {
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
                rtsx_read_register(chip, SD_VP_CTL, &val);
                RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
                rtsx_read_register(chip, SD_DCMPS_CTL, &val);
@@ -958,7 +958,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
        return STATUS_SUCCESS;
 
 Fail:
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
        rtsx_read_register(chip, SD_VP_CTL, &val);
        RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
        rtsx_read_register(chip, SD_DCMPS_CTL, &val);
index 2c668bae6ff47ea66afc3d74f7897ba06b4aafa6..bc83b49a4eb4a975cdc286c484b08e4d4698a39e 100644 (file)
@@ -82,7 +82,7 @@ do {                                                                                                  \
 #define TRACE_GOTO(chip, label)        goto label
 #endif
 
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
 static inline void rtsx_dump(u8 *buf, int buf_len)
 {
        int i;
index 7bcd468b8f2c2f15fff7e53cae3ce63b322c0bf6..9f3add1e8f59d885564703688df6d76554d228c6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index 2cf77c9408602964a2c5dfe527bc7dc0d316da4f..03dcac4ea4d064a291d28476de2eb8c71b2d8cdb 100644 (file)
@@ -2,6 +2,7 @@ config SOLO6X10
        tristate "Softlogic 6x10 MPEG codec cards"
        depends on PCI && VIDEO_DEV && SND && I2C
        select VIDEOBUF_DMA_SG
+       select SND_PCM
        ---help---
          This driver supports the Softlogic based MPEG-4 and h.264 codec
          codec cards.
index 20dae73d3b78347064608e1ebdb4c7cd639f68f5..506547b603e1fb0724e703a943193bfb559b9a8c 100644 (file)
@@ -653,7 +653,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
        }
        dev->queue->queuedata = dev;
 
-       /* As Linux block layer does't support >4KB hardware sector,  */
+       /* As Linux block layer doesn't support >4KB hardware sector,  */
        /* Here we force report 512 byte hardware sector size to Kernel */
        blk_queue_logical_block_size(dev->queue, 512);
 
index 5cecd237e3f68cae3a1f5cc52ff63b85bb80b285..fe1ef0addb09e4da2cf73f7fe36fac818b2bb436 100644 (file)
@@ -718,7 +718,7 @@ static void dload_symbols(struct dload_state *dlthis)
         * as a temporary for .dllview record construction.
         * Allocate storage for the whole table.  Add 1 to the section count
         * in case a trampoline section is auto-generated as well as the
-        * size of the trampoline section name so DLLView does't get lost.
+        * size of the trampoline section name so DLLView doesn't get lost.
         */
 
        siz = sym_count * sizeof(struct local_symbol);
index cb24c6d999db0b4fc76160c48cf6952921a56c87..5c3598ec74560c56ce1a33115b1e95e14220a81b 100644 (file)
@@ -978,7 +978,7 @@ static void sx_change_speed(struct specialix_board *bp,
        spin_lock_irqsave(&bp->lock, flags);
        sx_out(bp, CD186x_CAR, port_No(port));
 
-       /* The Specialix board does't implement the RTS lines.
+       /* The Specialix board doesn't implement the RTS lines.
           They are used to set the IRQ level. Don't touch them. */
        if (sx_crtscts(tty))
                port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
index 0f02a4b12ae4a29b05b68710d178686251acd713..4f4f13321f403866c579dfda8a10451b443ea73c 100644 (file)
@@ -876,8 +876,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
        }
 
        /* kill threads related to this sdev, if v.c. exists */
-       kthread_stop(vdev->ud.tcp_rx);
-       kthread_stop(vdev->ud.tcp_tx);
+       if (vdev->ud.tcp_rx)
+               kthread_stop(vdev->ud.tcp_rx);
+       if (vdev->ud.tcp_tx)
+               kthread_stop(vdev->ud.tcp_tx);
 
        usbip_uinfo("stop threads\n");
 
@@ -949,9 +951,6 @@ static void vhci_device_init(struct vhci_device *vdev)
 {
        memset(vdev, 0, sizeof(*vdev));
 
-       vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
-       vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
-
        vdev->ud.side   = USBIP_VHCI;
        vdev->ud.status = VDEV_ST_NULL;
        /* vdev->ud.lock   = SPIN_LOCK_UNLOCKED; */
@@ -1139,7 +1138,7 @@ static int vhci_hcd_probe(struct platform_device *pdev)
                usbip_uerr("create hcd failed\n");
                return -ENOMEM;
        }
-
+       hcd->has_tt = 1;
 
        /* this is private data for vhci_hcd */
        the_controller = hcd_to_vhci(hcd);
index 3f2459f30415ef5ec03e84eedf0417bb712d93e1..e2dadbd5ef1e2707956faa774f3c42ec44c039d4 100644 (file)
@@ -21,6 +21,7 @@
 #include "vhci.h"
 
 #include <linux/in.h>
+#include <linux/kthread.h>
 
 /* TODO: refine locking ?*/
 
@@ -220,13 +221,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
        vdev->ud.tcp_socket = socket;
        vdev->ud.status     = VDEV_ST_NOTASSIGNED;
 
-       wake_up_process(vdev->ud.tcp_rx);
-       wake_up_process(vdev->ud.tcp_tx);
-
        spin_unlock(&vdev->ud.lock);
        spin_unlock(&the_controller->lock);
        /* end the lock */
 
+       vdev->ud.tcp_rx = kthread_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
+       vdev->ud.tcp_tx = kthread_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
+
        rh_port_connect(rhport, speed);
 
        return count;
index 6a71f52c59b1f0a575b8ba69aeac20a9fd2c733a..76378397b763355c059ace7b5fe6bdd09abaf80c 100644 (file)
@@ -273,7 +273,7 @@ exit:
 }
 
 int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
-                          u8 key_index)
+                          u8 key_index, bool unicast, bool multicast)
 {
        wlandevice_t *wlandev = dev->ml_priv;
 
index 47f8cdb207f14089fcb2eaa3f284cdb11f58228c..74273e638c0dfce1d0350a14d57502a5692ee7d9 100644 (file)
@@ -1658,8 +1658,12 @@ static void gsm_queue(struct gsm_mux *gsm)
 
        if ((gsm->control & ~PF) == UI)
                gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
-       /* generate final CRC with received FCS */
-       gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
+       if (gsm->encoding == 0){
+               /* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only.
+                           In this case it contain the last piece of data
+                           required to generate final CRC */
+               gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
+       }
        if (gsm->fcs != GOOD_FCS) {
                gsm->bad_fcs++;
                if (debug & 4)
index 80484af781e1338590e18389ec5198dedc855e7b..b1f0f83b870d43d186a125e709a5d6ac097e0760 100644 (file)
@@ -1391,6 +1391,14 @@ config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
        help
          Support for Console on the NWP serial ports.
 
+config SERIAL_LANTIQ
+       bool "Lantiq serial driver"
+       depends on LANTIQ
+       select SERIAL_CORE
+       select SERIAL_CORE_CONSOLE
+       help
+         Support for console and UART on Lantiq SoCs.
+
 config SERIAL_QE
        tristate "Freescale QUICC Engine serial port support"
        depends on QUICC_ENGINE
index fee0690ef8e330c8048913fb510c37897093d494..35276043d9d12589a10346085246c8f6e39e75e0 100644 (file)
@@ -94,3 +94,4 @@ obj-$(CONFIG_SERIAL_IFX6X60)          += ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)  += pch_uart.o
 obj-$(CONFIG_SERIAL_MSM_SMD)   += msm_smd_tty.o
 obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
+obj-$(CONFIG_SERIAL_LANTIQ)    += lantiq.o
index cb36b0d4ef3c8305aa7b4aaa0abb543b0b752dd8..62df72d9f0aa32bef8a58a19f447dea922bdd18a 100644 (file)
@@ -382,12 +382,13 @@ static void imx_start_tx(struct uart_port *port)
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
        struct imx_port *sport = dev_id;
-       unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
+       unsigned int val;
        unsigned long flags;
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
        writel(USR1_RTSD, sport->port.membase + USR1);
+       val = readl(sport->port.membase + USR1) & USR1_RTSS;
        uart_handle_cts_change(&sport->port, !!val);
        wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
new file mode 100644 (file)
index 0000000..58cf279
--- /dev/null
@@ -0,0 +1,756 @@
+/*
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) 2004 Infineon IFAP DC COM CPE
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <lantiq_soc.h>
+
+#define PORT_LTQ_ASC           111
+#define MAXPORTS               2
+#define UART_DUMMY_UER_RX      1
+#define DRVNAME                        "ltq_asc"
+#ifdef __BIG_ENDIAN
+#define LTQ_ASC_TBUF           (0x0020 + 3)
+#define LTQ_ASC_RBUF           (0x0024 + 3)
+#else
+#define LTQ_ASC_TBUF           0x0020
+#define LTQ_ASC_RBUF           0x0024
+#endif
+#define LTQ_ASC_FSTAT          0x0048
+#define LTQ_ASC_WHBSTATE       0x0018
+#define LTQ_ASC_STATE          0x0014
+#define LTQ_ASC_IRNCR          0x00F8
+#define LTQ_ASC_CLC            0x0000
+#define LTQ_ASC_ID             0x0008
+#define LTQ_ASC_PISEL          0x0004
+#define LTQ_ASC_TXFCON         0x0044
+#define LTQ_ASC_RXFCON         0x0040
+#define LTQ_ASC_CON            0x0010
+#define LTQ_ASC_BG             0x0050
+#define LTQ_ASC_IRNREN         0x00F4
+
+#define ASC_IRNREN_TX          0x1
+#define ASC_IRNREN_RX          0x2
+#define ASC_IRNREN_ERR         0x4
+#define ASC_IRNREN_TX_BUF      0x8
+#define ASC_IRNCR_TIR          0x1
+#define ASC_IRNCR_RIR          0x2
+#define ASC_IRNCR_EIR          0x4
+
+#define ASCOPT_CSIZE           0x3
+#define TXFIFO_FL              1
+#define RXFIFO_FL              1
+#define ASCCLC_DISS            0x2
+#define ASCCLC_RMCMASK         0x0000FF00
+#define ASCCLC_RMCOFFSET       8
+#define ASCCON_M_8ASYNC                0x0
+#define ASCCON_M_7ASYNC                0x2
+#define ASCCON_ODD             0x00000020
+#define ASCCON_STP             0x00000080
+#define ASCCON_BRS             0x00000100
+#define ASCCON_FDE             0x00000200
+#define ASCCON_R               0x00008000
+#define ASCCON_FEN             0x00020000
+#define ASCCON_ROEN            0x00080000
+#define ASCCON_TOEN            0x00100000
+#define ASCSTATE_PE            0x00010000
+#define ASCSTATE_FE            0x00020000
+#define ASCSTATE_ROE           0x00080000
+#define ASCSTATE_ANY           (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
+#define ASCWHBSTATE_CLRREN     0x00000001
+#define ASCWHBSTATE_SETREN     0x00000002
+#define ASCWHBSTATE_CLRPE      0x00000004
+#define ASCWHBSTATE_CLRFE      0x00000008
+#define ASCWHBSTATE_CLRROE     0x00000020
+#define ASCTXFCON_TXFEN                0x0001
+#define ASCTXFCON_TXFFLU       0x0002
+#define ASCTXFCON_TXFITLMASK   0x3F00
+#define ASCTXFCON_TXFITLOFF    8
+#define ASCRXFCON_RXFEN                0x0001
+#define ASCRXFCON_RXFFLU       0x0002
+#define ASCRXFCON_RXFITLMASK   0x3F00
+#define ASCRXFCON_RXFITLOFF    8
+#define ASCFSTAT_RXFFLMASK     0x003F
+#define ASCFSTAT_TXFFLMASK     0x3F00
+#define ASCFSTAT_TXFREEMASK    0x3F000000
+#define ASCFSTAT_TXFREEOFF     24
+
+static void lqasc_tx_chars(struct uart_port *port);
+static struct ltq_uart_port *lqasc_port[MAXPORTS];
+static struct uart_driver lqasc_reg;
+static DEFINE_SPINLOCK(ltq_asc_lock);
+
+struct ltq_uart_port {
+       struct uart_port        port;
+       struct clk              *clk;
+       unsigned int            tx_irq;
+       unsigned int            rx_irq;
+       unsigned int            err_irq;
+};
+
+static inline struct
+ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
+{
+       return container_of(port, struct ltq_uart_port, port);
+}
+
+static void
+lqasc_stop_tx(struct uart_port *port)
+{
+       return;
+}
+
+static void
+lqasc_start_tx(struct uart_port *port)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+       lqasc_tx_chars(port);
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+       return;
+}
+
+static void
+lqasc_stop_rx(struct uart_port *port)
+{
+       ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+}
+
+static void
+lqasc_enable_ms(struct uart_port *port)
+{
+}
+
+static int
+lqasc_rx_chars(struct uart_port *port)
+{
+       struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+       unsigned int ch = 0, rsr = 0, fifocnt;
+
+       if (!tty) {
+               dev_dbg(port->dev, "%s:tty is busy now", __func__);
+               return -EBUSY;
+       }
+       fifocnt =
+               ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+       while (fifocnt--) {
+               u8 flag = TTY_NORMAL;
+               ch = ltq_r8(port->membase + LTQ_ASC_RBUF);
+               rsr = (ltq_r32(port->membase + LTQ_ASC_STATE)
+                       & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
+               tty_flip_buffer_push(tty);
+               port->icount.rx++;
+
+               /*
+                * Note that the error handling code is
+                * out of the main execution path
+                */
+               if (rsr & ASCSTATE_ANY) {
+                       if (rsr & ASCSTATE_PE) {
+                               port->icount.parity++;
+                               ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
+                                       port->membase + LTQ_ASC_WHBSTATE);
+                       } else if (rsr & ASCSTATE_FE) {
+                               port->icount.frame++;
+                               ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
+                                       port->membase + LTQ_ASC_WHBSTATE);
+                       }
+                       if (rsr & ASCSTATE_ROE) {
+                               port->icount.overrun++;
+                               ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
+                                       port->membase + LTQ_ASC_WHBSTATE);
+                       }
+
+                       rsr &= port->read_status_mask;
+
+                       if (rsr & ASCSTATE_PE)
+                               flag = TTY_PARITY;
+                       else if (rsr & ASCSTATE_FE)
+                               flag = TTY_FRAME;
+               }
+
+               if ((rsr & port->ignore_status_mask) == 0)
+                       tty_insert_flip_char(tty, ch, flag);
+
+               if (rsr & ASCSTATE_ROE)
+                       /*
+                        * Overrun is special, since it's reported
+                        * immediately, and doesn't affect the current
+                        * character
+                        */
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+       }
+       if (ch != 0)
+               tty_flip_buffer_push(tty);
+       tty_kref_put(tty);
+       return 0;
+}
+
+static void
+lqasc_tx_chars(struct uart_port *port)
+{
+       struct circ_buf *xmit = &port->state->xmit;
+       if (uart_tx_stopped(port)) {
+               lqasc_stop_tx(port);
+               return;
+       }
+
+       while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
+               ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
+               if (port->x_char) {
+                       ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
+                       port->icount.tx++;
+                       port->x_char = 0;
+                       continue;
+               }
+
+               if (uart_circ_empty(xmit))
+                       break;
+
+               ltq_w8(port->state->xmit.buf[port->state->xmit.tail],
+                       port->membase + LTQ_ASC_TBUF);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               port->icount.tx++;
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+}
+
+static irqreturn_t
+lqasc_tx_int(int irq, void *_port)
+{
+       unsigned long flags;
+       struct uart_port *port = (struct uart_port *)_port;
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+       ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+       lqasc_start_tx(port);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+lqasc_err_int(int irq, void *_port)
+{
+       unsigned long flags;
+       struct uart_port *port = (struct uart_port *)_port;
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+       /* clear any pending interrupts */
+       ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
+               ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+lqasc_rx_int(int irq, void *_port)
+{
+       unsigned long flags;
+       struct uart_port *port = (struct uart_port *)_port;
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+       ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+       lqasc_rx_chars(port);
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+       return IRQ_HANDLED;
+}
+
+static unsigned int
+lqasc_tx_empty(struct uart_port *port)
+{
+       int status;
+       status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+       return status ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int
+lqasc_get_mctrl(struct uart_port *port)
+{
+       return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
+}
+
+static void
+lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+}
+
+static void
+lqasc_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static int
+lqasc_startup(struct uart_port *port)
+{
+       struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+       int retval;
+
+       port->uartclk = clk_get_rate(ltq_port->clk);
+
+       ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
+               port->membase + LTQ_ASC_CLC);
+
+       ltq_w32(0, port->membase + LTQ_ASC_PISEL);
+       ltq_w32(
+               ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
+               ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
+               port->membase + LTQ_ASC_TXFCON);
+       ltq_w32(
+               ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
+               | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
+               port->membase + LTQ_ASC_RXFCON);
+       /* make sure other settings are written to hardware before
+        * setting enable bits
+        */
+       wmb();
+       ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
+               ASCCON_ROEN, port->membase + LTQ_ASC_CON);
+
+       retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
+               IRQF_DISABLED, "asc_tx", port);
+       if (retval) {
+               pr_err("failed to request lqasc_tx_int\n");
+               return retval;
+       }
+
+       retval = request_irq(ltq_port->rx_irq, lqasc_rx_int,
+               IRQF_DISABLED, "asc_rx", port);
+       if (retval) {
+               pr_err("failed to request lqasc_rx_int\n");
+               goto err1;
+       }
+
+       retval = request_irq(ltq_port->err_irq, lqasc_err_int,
+               IRQF_DISABLED, "asc_err", port);
+       if (retval) {
+               pr_err("failed to request lqasc_err_int\n");
+               goto err2;
+       }
+
+       ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+               port->membase + LTQ_ASC_IRNREN);
+       return 0;
+
+err2:
+       free_irq(ltq_port->rx_irq, port);
+err1:
+       free_irq(ltq_port->tx_irq, port);
+       return retval;
+}
+
+static void
+lqasc_shutdown(struct uart_port *port)
+{
+       struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+       free_irq(ltq_port->tx_irq, port);
+       free_irq(ltq_port->rx_irq, port);
+       free_irq(ltq_port->err_irq, port);
+
+       ltq_w32(0, port->membase + LTQ_ASC_CON);
+       ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
+               port->membase + LTQ_ASC_RXFCON);
+       ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
+               port->membase + LTQ_ASC_TXFCON);
+}
+
+static void
+lqasc_set_termios(struct uart_port *port,
+       struct ktermios *new, struct ktermios *old)
+{
+       unsigned int cflag;
+       unsigned int iflag;
+       unsigned int divisor;
+       unsigned int baud;
+       unsigned int con = 0;
+       unsigned long flags;
+
+       cflag = new->c_cflag;
+       iflag = new->c_iflag;
+
+       switch (cflag & CSIZE) {
+       case CS7:
+               con = ASCCON_M_7ASYNC;
+               break;
+
+       case CS5:
+       case CS6:
+       default:
+               new->c_cflag &= ~ CSIZE;
+               new->c_cflag |= CS8;
+               con = ASCCON_M_8ASYNC;
+               break;
+       }
+
+       cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
+
+       if (cflag & CSTOPB)
+               con |= ASCCON_STP;
+
+       if (cflag & PARENB) {
+               if (!(cflag & PARODD))
+                       con &= ~ASCCON_ODD;
+               else
+                       con |= ASCCON_ODD;
+       }
+
+       port->read_status_mask = ASCSTATE_ROE;
+       if (iflag & INPCK)
+               port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
+
+       port->ignore_status_mask = 0;
+       if (iflag & IGNPAR)
+               port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
+
+       if (iflag & IGNBRK) {
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (iflag & IGNPAR)
+                       port->ignore_status_mask |= ASCSTATE_ROE;
+       }
+
+       if ((cflag & CREAD) == 0)
+               port->ignore_status_mask |= UART_DUMMY_UER_RX;
+
+       /* set error signals  - framing, parity  and overrun, enable receiver */
+       con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
+
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+
+       /* set up CON */
+       ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON);
+
+       /* Set baud rate - take a divider of 2 into account */
+       baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+       divisor = uart_get_divisor(port, baud);
+       divisor = divisor / 2 - 1;
+
+       /* disable the baudrate generator */
+       ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
+
+       /* make sure the fractional divider is off */
+       ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
+
+       /* set up to use divisor of 2 */
+       ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
+
+       /* now we can write the new baudrate into the register */
+       ltq_w32(divisor, port->membase + LTQ_ASC_BG);
+
+       /* turn the baudrate generator back on */
+       ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
+
+       /* enable rx */
+       ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+
+       /* Don't rewrite B0 */
+        if (tty_termios_baud_rate(new))
+               tty_termios_encode_baud_rate(new, baud, baud);
+}
+
+static const char*
+lqasc_type(struct uart_port *port)
+{
+       if (port->type == PORT_LTQ_ASC)
+               return DRVNAME;
+       else
+               return NULL;
+}
+
+static void
+lqasc_release_port(struct uart_port *port)
+{
+       if (port->flags & UPF_IOREMAP) {
+               iounmap(port->membase);
+               port->membase = NULL;
+       }
+}
+
+static int
+lqasc_request_port(struct uart_port *port)
+{
+       struct platform_device *pdev = to_platform_device(port->dev);
+       struct resource *res;
+       int size;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "cannot obtain I/O memory region");
+               return -ENODEV;
+       }
+       size = resource_size(res);
+
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               size, dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev, "cannot request I/O memory region");
+               return -EBUSY;
+       }
+
+       if (port->flags & UPF_IOREMAP) {
+               port->membase = devm_ioremap_nocache(&pdev->dev,
+                       port->mapbase, size);
+               if (port->membase == NULL)
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+static void
+lqasc_config_port(struct uart_port *port, int flags)
+{
+       if (flags & UART_CONFIG_TYPE) {
+               port->type = PORT_LTQ_ASC;
+               lqasc_request_port(port);
+       }
+}
+
+static int
+lqasc_verify_port(struct uart_port *port,
+       struct serial_struct *ser)
+{
+       int ret = 0;
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
+               ret = -EINVAL;
+       if (ser->irq < 0 || ser->irq >= NR_IRQS)
+               ret = -EINVAL;
+       if (ser->baud_base < 9600)
+               ret = -EINVAL;
+       return ret;
+}
+
+static struct uart_ops lqasc_pops = {
+       .tx_empty =     lqasc_tx_empty,
+       .set_mctrl =    lqasc_set_mctrl,
+       .get_mctrl =    lqasc_get_mctrl,
+       .stop_tx =      lqasc_stop_tx,
+       .start_tx =     lqasc_start_tx,
+       .stop_rx =      lqasc_stop_rx,
+       .enable_ms =    lqasc_enable_ms,
+       .break_ctl =    lqasc_break_ctl,
+       .startup =      lqasc_startup,
+       .shutdown =     lqasc_shutdown,
+       .set_termios =  lqasc_set_termios,
+       .type =         lqasc_type,
+       .release_port = lqasc_release_port,
+       .request_port = lqasc_request_port,
+       .config_port =  lqasc_config_port,
+       .verify_port =  lqasc_verify_port,
+};
+
+static void
+lqasc_console_putchar(struct uart_port *port, int ch)
+{
+       int fifofree;
+
+       if (!port->membase)
+               return;
+
+       do {
+               fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
+                       & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
+       } while (fifofree == 0);
+       ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
+}
+
+
+static void
+lqasc_console_write(struct console *co, const char *s, u_int count)
+{
+       struct ltq_uart_port *ltq_port;
+       struct uart_port *port;
+       unsigned long flags;
+
+       if (co->index >= MAXPORTS)
+               return;
+
+       ltq_port = lqasc_port[co->index];
+       if (!ltq_port)
+               return;
+
+       port = &ltq_port->port;
+
+       spin_lock_irqsave(&ltq_asc_lock, flags);
+       uart_console_write(port, s, count, lqasc_console_putchar);
+       spin_unlock_irqrestore(&ltq_asc_lock, flags);
+}
+
+static int __init
+lqasc_console_setup(struct console *co, char *options)
+{
+       struct ltq_uart_port *ltq_port;
+       struct uart_port *port;
+       int baud = 115200;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (co->index >= MAXPORTS)
+               return -ENODEV;
+
+       ltq_port = lqasc_port[co->index];
+       if (!ltq_port)
+               return -ENODEV;
+
+       port = &ltq_port->port;
+
+       port->uartclk = clk_get_rate(ltq_port->clk);
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct console lqasc_console = {
+       .name =         "ttyLTQ",
+       .write =        lqasc_console_write,
+       .device =       uart_console_device,
+       .setup =        lqasc_console_setup,
+       .flags =        CON_PRINTBUFFER,
+       .index =        -1,
+       .data =         &lqasc_reg,
+};
+
+static int __init
+lqasc_console_init(void)
+{
+       register_console(&lqasc_console);
+       return 0;
+}
+console_initcall(lqasc_console_init);
+
+static struct uart_driver lqasc_reg = {
+       .owner =        THIS_MODULE,
+       .driver_name =  DRVNAME,
+       .dev_name =     "ttyLTQ",
+       .major =        0,
+       .minor =        0,
+       .nr =           MAXPORTS,
+       .cons =         &lqasc_console,
+};
+
+static int __init
+lqasc_probe(struct platform_device *pdev)
+{
+       struct ltq_uart_port *ltq_port;
+       struct uart_port *port;
+       struct resource *mmres, *irqres;
+       int tx_irq, rx_irq, err_irq;
+       struct clk *clk;
+       int ret;
+
+       mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!mmres || !irqres)
+               return -ENODEV;
+
+       if (pdev->id >= MAXPORTS)
+               return -EBUSY;
+
+       if (lqasc_port[pdev->id] != NULL)
+               return -EBUSY;
+
+       clk = clk_get(&pdev->dev, "fpi");
+       if (IS_ERR(clk)) {
+               pr_err("failed to get fpi clk\n");
+               return -ENOENT;
+       }
+
+       tx_irq = platform_get_irq_byname(pdev, "tx");
+       rx_irq = platform_get_irq_byname(pdev, "rx");
+       err_irq = platform_get_irq_byname(pdev, "err");
+       if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0))
+               return -ENODEV;
+
+       ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
+       if (!ltq_port)
+               return -ENOMEM;
+
+       port = &ltq_port->port;
+
+       port->iotype    = SERIAL_IO_MEM;
+       port->flags     = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
+       port->ops       = &lqasc_pops;
+       port->fifosize  = 16;
+       port->type      = PORT_LTQ_ASC,
+       port->line      = pdev->id;
+       port->dev       = &pdev->dev;
+
+       port->irq       = tx_irq; /* unused, just to be backward-compatibe */
+       port->mapbase   = mmres->start;
+
+       ltq_port->clk   = clk;
+
+       ltq_port->tx_irq = tx_irq;
+       ltq_port->rx_irq = rx_irq;
+       ltq_port->err_irq = err_irq;
+
+       lqasc_port[pdev->id] = ltq_port;
+       platform_set_drvdata(pdev, ltq_port);
+
+       ret = uart_add_one_port(&lqasc_reg, port);
+
+       return ret;
+}
+
+static struct platform_driver lqasc_driver = {
+       .driver         = {
+               .name   = DRVNAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+int __init
+init_lqasc(void)
+{
+       int ret;
+
+       ret = uart_register_driver(&lqasc_reg);
+       if (ret != 0)
+               return ret;
+
+       ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
+       if (ret != 0)
+               uart_unregister_driver(&lqasc_reg);
+
+       return ret;
+}
+
+module_init(init_lqasc);
+
+MODULE_DESCRIPTION("Lantiq serial port driver");
+MODULE_LICENSE("GPL");
index 0e8eec516df4d94f0395842a3f4573cd036dbfdc..c911b2419abb8a664f3bfad7d258a94c1363fa5b 100644 (file)
@@ -80,14 +80,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 /*
  * Try to register a serial port
  */
+static struct of_device_id of_platform_serial_table[];
 static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct of_serial_info *info;
        struct uart_port port;
        int port_type;
        int ret;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(of_platform_serial_table, &ofdev->dev);
+       if (!match)
                return -EINVAL;
 
        if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
@@ -97,7 +100,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
        if (info == NULL)
                return -ENOMEM;
 
-       port_type = (unsigned long)ofdev->dev.of_match->data;
+       port_type = (unsigned long)match->data;
        ret = of_platform_serial_setup(ofdev, port_type, &port);
        if (ret)
                goto out;
index 36613b37c50442c96a3bad47449365aaf31b1e89..3a68e09309f750107528451f7d2b4c40d645f1b1 100644 (file)
@@ -2539,15 +2539,18 @@ static void qe_udc_release(struct device *dev)
 }
 
 /* Driver probe functions */
+static const struct of_device_id qe_udc_match[];
 static int __devinit qe_udc_probe(struct platform_device *ofdev)
 {
+       const struct of_device_id *match;
        struct device_node *np = ofdev->dev.of_node;
        struct qe_ep *ep;
        unsigned int ret = 0;
        unsigned int i;
        const void *prop;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(qe_udc_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
 
        prop = of_get_property(np, "mode", NULL);
@@ -2561,7 +2564,7 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
                return -ENOMEM;
        }
 
-       udc_controller->soc_type = (unsigned long)ofdev->dev.of_match->data;
+       udc_controller->soc_type = (unsigned long)match->data;
        udc_controller->usb_regs = of_iomap(np, 0);
        if (!udc_controller->usb_regs) {
                ret = -ENOMEM;
index 7e41a95c5ceb6a9aa70ed437b737eabebf379a4a..627f3a678759a1e007a70a520262a41b48327339 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
 #include <plat/usb.h>
+#include <linux/regulator/consumer.h>
 
 /* EHCI Register Set */
 #define EHCI_INSNREG04                                 (0xA0)
@@ -118,6 +119,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        struct ehci_hcd                         *omap_ehci;
        int                                     ret = -ENODEV;
        int                                     irq;
+       int                                     i;
+       char                                    supply[7];
 
        if (usb_disabled())
                return -ENODEV;
@@ -158,6 +161,23 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        hcd->rsrc_len = resource_size(res);
        hcd->regs = regs;
 
+       /* get ehci regulator and enable */
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
+                       pdata->regulator[i] = NULL;
+                       continue;
+               }
+               snprintf(supply, sizeof(supply), "hsusb%d", i);
+               pdata->regulator[i] = regulator_get(dev, supply);
+               if (IS_ERR(pdata->regulator[i])) {
+                       pdata->regulator[i] = NULL;
+                       dev_dbg(dev,
+                       "failed to get ehci port%d regulator\n", i);
+               } else {
+                       regulator_enable(pdata->regulator[i]);
+               }
+       }
+
        ret = omap_usbhs_enable(dev);
        if (ret) {
                dev_err(dev, "failed to start usbhs with err %d\n", ret);
index 795345ad45e62881fb8e28a1abce639a3088cac8..7b2e69aa2e98fdf2e803bb9d1c26d25ba74cb63e 100644 (file)
@@ -1633,6 +1633,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        ints[i].qh = NULL;
                        ints[i].qtd = NULL;
 
+                       urb->status = status;
                        isp1760_urb_done(hcd, urb);
                        if (qtd)
                                pe(hcd, qh, qtd);
index a78f2ebd11b785aabf235bf6dd4e76a529506319..73f75d26436c48635bca66c68a777891287b36c9 100644 (file)
@@ -777,7 +777,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                if (t1 != t2)
                        xhci_writel(xhci, t2, port_array[port_index]);
 
-               if (DEV_HIGHSPEED(t1)) {
+               if (hcd->speed != HCD_USB3) {
                        /* enable remote wake up for USB 2.0 */
                        u32 __iomem *addr;
                        u32 tmp;
@@ -866,6 +866,21 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                                temp |= PORT_LINK_STROBE | XDEV_U0;
                                xhci_writel(xhci, temp, port_array[port_index]);
                        }
+                       /* wait for the port to enter U0 and report port link
+                        * state change.
+                        */
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       msleep(20);
+                       spin_lock_irqsave(&xhci->lock, flags);
+
+                       /* Clear PLC */
+                       temp = xhci_readl(xhci, port_array[port_index]);
+                       if (temp & PORT_PLC) {
+                               temp = xhci_port_state_to_neutral(temp);
+                               temp |= PORT_PLC;
+                               xhci_writel(xhci, temp, port_array[port_index]);
+                       }
+
                        slot_id = xhci_find_slot_id_by_port(hcd,
                                        xhci, port_index + 1);
                        if (slot_id)
@@ -873,7 +888,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                } else
                        xhci_writel(xhci, temp, port_array[port_index]);
 
-               if (DEV_HIGHSPEED(temp)) {
+               if (hcd->speed != HCD_USB3) {
                        /* disable remote wake up for USB 2.0 */
                        u32 __iomem *addr;
                        u32 tmp;
index 6dfbf9ffd7a63660ef472b6b3a932ecf22fd0341..f47c20197c61aa3c8882f25a064c83e6890ff9cb 100644 (file)
@@ -1887,11 +1887,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
                        otg_set_vbus(musb->xceiv, 1);
 
                hcd->self.uses_pio_for_control = 1;
-
-               if (musb->xceiv->last_event == USB_EVENT_NONE)
-                       pm_runtime_put(musb->controller);
-
        }
+       if (musb->xceiv->last_event == USB_EVENT_NONE)
+               pm_runtime_put(musb->controller);
 
        return 0;
 
index 57a27fa954b41fdd7b0fba880fd3c9da2b64b19c..e9e60b6e058394c3bdcdad9af873e6f25e9c21d8 100644 (file)
@@ -270,7 +270,7 @@ static int musb_otg_notifications(struct notifier_block *nb,
                DBG(4, "VBUS Disconnect\n");
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
-               if (is_otg_enabled(musb))
+               if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
                        if (musb->gadget_driver)
 #endif
                        {
index 2ab291241635d94278ff9f417b19223c265a044c..7aa4eea930f1310077012eeab05a511bd1febdfe 100644 (file)
@@ -4,7 +4,7 @@
  * Author: Michael S. Tsirkin <mst@redhat.com>
  *
  * Inspiration, some code, and most witty comments come from
- * Documentation/lguest/lguest.c, by Rusty Russell
+ * Documentation/virtual/lguest/lguest.c, by Rusty Russell
  *
  * This work is licensed under the terms of the GNU GPL, version 2.
  *
index 82acb8dc4aa144dab7888e567238a1ce332e49c8..6183a57eb69d8b913abcde29af3bbdb24714e725 100644 (file)
@@ -66,7 +66,7 @@
  * have.  Allow 1% either way on the nominal for TVs.
  */
 #define NR_MONTYPES    6
-static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
+static struct fb_monspecs monspecs[NR_MONTYPES] __devinitdata = {
        {       /* TV           */
                .hfmin  = 15469,
                .hfmax  = 15781,
@@ -873,7 +873,7 @@ static struct fb_ops acornfb_ops = {
 /*
  * Everything after here is initialisation!!!
  */
-static struct fb_videomode modedb[] __initdata = {
+static struct fb_videomode modedb[] __devinitdata = {
        {       /* 320x256 @ 50Hz */
                NULL, 50,  320,  256, 125000,  92,  62,  35, 19,  38, 2,
                FB_SYNC_COMP_HIGH_ACT,
@@ -925,8 +925,7 @@ static struct fb_videomode modedb[] __initdata = {
        }
 };
 
-static struct fb_videomode __initdata
-acornfb_default_mode = {
+static struct fb_videomode acornfb_default_mode __devinitdata = {
        .name =         NULL,
        .refresh =      60,
        .xres =         640,
@@ -942,7 +941,7 @@ acornfb_default_mode = {
        .vmode =        FB_VMODE_NONINTERLACED
 };
 
-static void __init acornfb_init_fbinfo(void)
+static void __devinit acornfb_init_fbinfo(void)
 {
        static int first = 1;
 
@@ -1018,8 +1017,7 @@ static void __init acornfb_init_fbinfo(void)
  *     size can optionally be followed by 'M' or 'K' for
  *     MB or KB respectively.
  */
-static void __init
-acornfb_parse_mon(char *opt)
+static void __devinit acornfb_parse_mon(char *opt)
 {
        char *p = opt;
 
@@ -1066,8 +1064,7 @@ bad:
        current_par.montype = -1;
 }
 
-static void __init
-acornfb_parse_montype(char *opt)
+static void __devinit acornfb_parse_montype(char *opt)
 {
        current_par.montype = -2;
 
@@ -1108,8 +1105,7 @@ acornfb_parse_montype(char *opt)
        }
 }
 
-static void __init
-acornfb_parse_dram(char *opt)
+static void __devinit acornfb_parse_dram(char *opt)
 {
        unsigned int size;
 
@@ -1134,15 +1130,14 @@ acornfb_parse_dram(char *opt)
 static struct options {
        char *name;
        void (*parse)(char *opt);
-} opt_table[] __initdata = {
+} opt_table[] __devinitdata = {
        { "mon",     acornfb_parse_mon     },
        { "montype", acornfb_parse_montype },
        { "dram",    acornfb_parse_dram    },
        { NULL, NULL }
 };
 
-int __init
-acornfb_setup(char *options)
+static int __devinit acornfb_setup(char *options)
 {
        struct options *optp;
        char *opt;
@@ -1179,8 +1174,7 @@ acornfb_setup(char *options)
  * Detect type of monitor connected
  *  For now, we just assume SVGA
  */
-static int __init
-acornfb_detect_monitortype(void)
+static int __devinit acornfb_detect_monitortype(void)
 {
        return 4;
 }
index 5b2b5ef4edba9dba4e125e4dc01ba304dbbb5dfe..64e41f5448c4fcd5a3f3c0bf2324d0efb90f4778 100644 (file)
@@ -3117,7 +3117,7 @@ int __init atafb_init(void)
                        atafb_ops.fb_setcolreg = &falcon_setcolreg;
                        error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
                                            IRQ_TYPE_PRIO,
-                                           "framebuffer/modeswitch",
+                                           "framebuffer:modeswitch",
                                            falcon_vbl_switcher);
                        if (error)
                                return error;
index e0c2284924b63b4a390aa8a4eb862fcfddac2609..5aac00eb1830c1724ed521f2bcc91693d9dbe646 100644 (file)
 
 #define FBPIXMAPSIZE   (1024 * 8)
 
+static DEFINE_MUTEX(registration_lock);
 struct fb_info *registered_fb[FB_MAX] __read_mostly;
 int num_registered_fb __read_mostly;
 
+static struct fb_info *get_fb_info(unsigned int idx)
+{
+       struct fb_info *fb_info;
+
+       if (idx >= FB_MAX)
+               return ERR_PTR(-ENODEV);
+
+       mutex_lock(&registration_lock);
+       fb_info = registered_fb[idx];
+       if (fb_info)
+               atomic_inc(&fb_info->count);
+       mutex_unlock(&registration_lock);
+
+       return fb_info;
+}
+
+static void put_fb_info(struct fb_info *fb_info)
+{
+       if (!atomic_dec_and_test(&fb_info->count))
+               return;
+       if (fb_info->fbops->fb_destroy)
+               fb_info->fbops->fb_destroy(fb_info);
+}
+
 int lock_fb_info(struct fb_info *info)
 {
        mutex_lock(&info->lock);
@@ -647,6 +672,7 @@ int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
 
 static void *fb_seq_start(struct seq_file *m, loff_t *pos)
 {
+       mutex_lock(&registration_lock);
        return (*pos < FB_MAX) ? pos : NULL;
 }
 
@@ -658,6 +684,7 @@ static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void fb_seq_stop(struct seq_file *m, void *v)
 {
+       mutex_unlock(&registration_lock);
 }
 
 static int fb_seq_show(struct seq_file *m, void *v)
@@ -690,13 +717,30 @@ static const struct file_operations fb_proc_fops = {
        .release        = seq_release,
 };
 
-static ssize_t
-fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+/*
+ * We hold a reference to the fb_info in file->private_data,
+ * but if the current registered fb has changed, we don't
+ * actually want to use it.
+ *
+ * So look up the fb_info using the inode minor number,
+ * and just verify it against the reference we have.
+ */
+static struct fb_info *file_fb_info(struct file *file)
 {
-       unsigned long p = *ppos;
        struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
+
+       if (info != file->private_data)
+               info = NULL;
+       return info;
+}
+
+static ssize_t
+fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       struct fb_info *info = file_fb_info(file);
        u8 *buffer, *dst;
        u8 __iomem *src;
        int c, cnt = 0, err = 0;
@@ -761,9 +805,7 @@ static ssize_t
 fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
+       struct fb_info *info = file_fb_info(file);
        u8 *buffer, *src;
        u8 __iomem *dst;
        int c, cnt = 0, err = 0;
@@ -1141,10 +1183,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
 
 static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
+       struct fb_info *info = file_fb_info(file);
 
+       if (!info)
+               return -ENODEV;
        return do_fb_ioctl(info, cmd, arg);
 }
 
@@ -1265,12 +1307,13 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
 static long fb_compat_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
-       struct fb_ops *fb = info->fbops;
+       struct fb_info *info = file_fb_info(file);
+       struct fb_ops *fb;
        long ret = -ENOIOCTLCMD;
 
+       if (!info)
+               return -ENODEV;
+       fb = info->fbops;
        switch(cmd) {
        case FBIOGET_VSCREENINFO:
        case FBIOPUT_VSCREENINFO:
@@ -1303,16 +1346,18 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
 static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
-       int fbidx = iminor(file->f_path.dentry->d_inode);
-       struct fb_info *info = registered_fb[fbidx];
-       struct fb_ops *fb = info->fbops;
+       struct fb_info *info = file_fb_info(file);
+       struct fb_ops *fb;
        unsigned long off;
        unsigned long start;
        u32 len;
 
+       if (!info)
+               return -ENODEV;
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
                return -EINVAL;
        off = vma->vm_pgoff << PAGE_SHIFT;
+       fb = info->fbops;
        if (!fb)
                return -ENODEV;
        mutex_lock(&info->mm_lock);
@@ -1361,14 +1406,16 @@ __releases(&info->lock)
        struct fb_info *info;
        int res = 0;
 
-       if (fbidx >= FB_MAX)
-               return -ENODEV;
-       info = registered_fb[fbidx];
-       if (!info)
+       info = get_fb_info(fbidx);
+       if (!info) {
                request_module("fb%d", fbidx);
-       info = registered_fb[fbidx];
-       if (!info)
-               return -ENODEV;
+               info = get_fb_info(fbidx);
+               if (!info)
+                       return -ENODEV;
+       }
+       if (IS_ERR(info))
+               return PTR_ERR(info);
+
        mutex_lock(&info->lock);
        if (!try_module_get(info->fbops->owner)) {
                res = -ENODEV;
@@ -1386,6 +1433,8 @@ __releases(&info->lock)
 #endif
 out:
        mutex_unlock(&info->lock);
+       if (res)
+               put_fb_info(info);
        return res;
 }
 
@@ -1401,6 +1450,7 @@ __releases(&info->lock)
                info->fbops->fb_release(info,1);
        module_put(info->fbops->owner);
        mutex_unlock(&info->lock);
+       put_fb_info(info);
        return 0;
 }
 
@@ -1487,8 +1537,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
        return false;
 }
 
+static int do_unregister_framebuffer(struct fb_info *fb_info);
+
 #define VGA_FB_PHYS 0xA0000
-void remove_conflicting_framebuffers(struct apertures_struct *a,
+static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
                                     const char *name, bool primary)
 {
        int i;
@@ -1510,43 +1562,32 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
                        printk(KERN_INFO "fb: conflicting fb hw usage "
                               "%s vs %s - removing generic driver\n",
                               name, registered_fb[i]->fix.id);
-                       unregister_framebuffer(registered_fb[i]);
+                       do_unregister_framebuffer(registered_fb[i]);
                }
        }
 }
-EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
-/**
- *     register_framebuffer - registers a frame buffer device
- *     @fb_info: frame buffer info structure
- *
- *     Registers a frame buffer device @fb_info.
- *
- *     Returns negative errno on error, or zero for success.
- *
- */
-
-int
-register_framebuffer(struct fb_info *fb_info)
+static int do_register_framebuffer(struct fb_info *fb_info)
 {
        int i;
        struct fb_event event;
        struct fb_videomode mode;
 
-       if (num_registered_fb == FB_MAX)
-               return -ENXIO;
-
        if (fb_check_foreignness(fb_info))
                return -ENOSYS;
 
-       remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
+       do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
                                         fb_is_primary_device(fb_info));
 
+       if (num_registered_fb == FB_MAX)
+               return -ENXIO;
+
        num_registered_fb++;
        for (i = 0 ; i < FB_MAX; i++)
                if (!registered_fb[i])
                        break;
        fb_info->node = i;
+       atomic_set(&fb_info->count, 1);
        mutex_init(&fb_info->lock);
        mutex_init(&fb_info->mm_lock);
 
@@ -1592,36 +1633,14 @@ register_framebuffer(struct fb_info *fb_info)
        return 0;
 }
 
-
-/**
- *     unregister_framebuffer - releases a frame buffer device
- *     @fb_info: frame buffer info structure
- *
- *     Unregisters a frame buffer device @fb_info.
- *
- *     Returns negative errno on error, or zero for success.
- *
- *      This function will also notify the framebuffer console
- *      to release the driver.
- *
- *      This is meant to be called within a driver's module_exit()
- *      function. If this is called outside module_exit(), ensure
- *      that the driver implements fb_open() and fb_release() to
- *      check that no processes are using the device.
- */
-
-int
-unregister_framebuffer(struct fb_info *fb_info)
+static int do_unregister_framebuffer(struct fb_info *fb_info)
 {
        struct fb_event event;
        int i, ret = 0;
 
        i = fb_info->node;
-       if (!registered_fb[i]) {
-               ret = -EINVAL;
-               goto done;
-       }
-
+       if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+               return -EINVAL;
 
        if (!lock_fb_info(fb_info))
                return -ENODEV;
@@ -1629,16 +1648,14 @@ unregister_framebuffer(struct fb_info *fb_info)
        ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
        unlock_fb_info(fb_info);
 
-       if (ret) {
-               ret = -EINVAL;
-               goto done;
-       }
+       if (ret)
+               return -EINVAL;
 
        if (fb_info->pixmap.addr &&
            (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
                kfree(fb_info->pixmap.addr);
        fb_destroy_modelist(&fb_info->modelist);
-       registered_fb[i]=NULL;
+       registered_fb[i] = NULL;
        num_registered_fb--;
        fb_cleanup_device(fb_info);
        device_destroy(fb_class, MKDEV(FB_MAJOR, i));
@@ -1646,9 +1663,65 @@ unregister_framebuffer(struct fb_info *fb_info)
        fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
 
        /* this may free fb info */
-       if (fb_info->fbops->fb_destroy)
-               fb_info->fbops->fb_destroy(fb_info);
-done:
+       put_fb_info(fb_info);
+       return 0;
+}
+
+void remove_conflicting_framebuffers(struct apertures_struct *a,
+                                    const char *name, bool primary)
+{
+       mutex_lock(&registration_lock);
+       do_remove_conflicting_framebuffers(a, name, primary);
+       mutex_unlock(&registration_lock);
+}
+EXPORT_SYMBOL(remove_conflicting_framebuffers);
+
+/**
+ *     register_framebuffer - registers a frame buffer device
+ *     @fb_info: frame buffer info structure
+ *
+ *     Registers a frame buffer device @fb_info.
+ *
+ *     Returns negative errno on error, or zero for success.
+ *
+ */
+int
+register_framebuffer(struct fb_info *fb_info)
+{
+       int ret;
+
+       mutex_lock(&registration_lock);
+       ret = do_register_framebuffer(fb_info);
+       mutex_unlock(&registration_lock);
+
+       return ret;
+}
+
+/**
+ *     unregister_framebuffer - releases a frame buffer device
+ *     @fb_info: frame buffer info structure
+ *
+ *     Unregisters a frame buffer device @fb_info.
+ *
+ *     Returns negative errno on error, or zero for success.
+ *
+ *      This function will also notify the framebuffer console
+ *      to release the driver.
+ *
+ *      This is meant to be called within a driver's module_exit()
+ *      function. If this is called outside module_exit(), ensure
+ *      that the driver implements fb_open() and fb_release() to
+ *      check that no processes are using the device.
+ */
+int
+unregister_framebuffer(struct fb_info *fb_info)
+{
+       int ret;
+
+       mutex_lock(&registration_lock);
+       ret = do_unregister_framebuffer(fb_info);
+       mutex_unlock(&registration_lock);
+
        return ret;
 }
 
index 4fb5b2bf23486c0bee03f0dd3de196aff7f40549..4bcc8b82640be13af193478aaa2c4699bc609d2b 100644 (file)
@@ -590,15 +590,10 @@ static struct virtio_config_ops virtio_pci_config_ops = {
 
 static void virtio_pci_release_dev(struct device *_d)
 {
-       struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
+       struct virtio_device *dev = container_of(_d, struct virtio_device,
+                                                dev);
        struct virtio_pci_device *vp_dev = to_vp_device(dev);
-       struct pci_dev *pci_dev = vp_dev->pci_dev;
 
-       vp_del_vqs(dev);
-       pci_set_drvdata(pci_dev, NULL);
-       pci_iounmap(pci_dev, vp_dev->ioaddr);
-       pci_release_regions(pci_dev);
-       pci_disable_device(pci_dev);
        kfree(vp_dev);
 }
 
@@ -681,6 +676,12 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
        struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
 
        unregister_virtio_device(&vp_dev->vdev);
+
+       vp_del_vqs(&vp_dev->vdev);
+       pci_set_drvdata(pci_dev, NULL);
+       pci_iounmap(pci_dev, vp_dev->ioaddr);
+       pci_release_regions(pci_dev);
+       pci_disable_device(pci_dev);
 }
 
 #ifdef CONFIG_PM
index cc2f73e03475b620053765b373c8b1a39fc08762..b0043fb26a4d5dd8fcc9a2b7b66a18b3b44053b0 100644 (file)
@@ -371,6 +371,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
                /* detach_buf clears data, so grab it now. */
                buf = vq->data[i];
                detach_buf(vq, i);
+               vq->vring.avail->idx--;
                END_USE(vq);
                return buf;
        }
index 1b0f98bc51b5fbdaa9288bbc436fd4316dea38a0..022f9eb0b7bf01546479d8da03a98394f73299c6 100644 (file)
@@ -990,6 +990,12 @@ config BCM63XX_WDT
          To compile this driver as a loadable module, choose M here.
          The module will be called bcm63xx_wdt.
 
+config LANTIQ_WDT
+       tristate "Lantiq SoC watchdog"
+       depends on LANTIQ
+       help
+         Hardware driver for the Lantiq SoC Watchdog Timer.
+
 # PARISC Architecture
 
 # POWERPC Architecture
index 3f8608b922a7df6531b948de47437961ad8223be..ed26f7094e470ac8cd06317136305ea1a01ea2a8 100644 (file)
@@ -123,6 +123,7 @@ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
 obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
+obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
 
 # PARISC Architecture
 
index 35a0d12dad7351340fdd1cfc8b84cb221556e059..5fd020da7c5534f32f7823d966ee49610ac9d31a 100644 (file)
@@ -35,6 +35,7 @@
  *     document number 324645-001, 324646-001: Cougar Point (CPT)
  *     document number TBD                   : Patsburg (PBG)
  *     document number TBD                   : DH89xxCC
+ *     document number TBD                   : Panther Point
  */
 
 /*
@@ -153,6 +154,38 @@ enum iTCO_chipsets {
        TCO_PBG1,       /* Patsburg */
        TCO_PBG2,       /* Patsburg */
        TCO_DH89XXCC,   /* DH89xxCC */
+       TCO_PPT0,       /* Panther Point */
+       TCO_PPT1,       /* Panther Point */
+       TCO_PPT2,       /* Panther Point */
+       TCO_PPT3,       /* Panther Point */
+       TCO_PPT4,       /* Panther Point */
+       TCO_PPT5,       /* Panther Point */
+       TCO_PPT6,       /* Panther Point */
+       TCO_PPT7,       /* Panther Point */
+       TCO_PPT8,       /* Panther Point */
+       TCO_PPT9,       /* Panther Point */
+       TCO_PPT10,      /* Panther Point */
+       TCO_PPT11,      /* Panther Point */
+       TCO_PPT12,      /* Panther Point */
+       TCO_PPT13,      /* Panther Point */
+       TCO_PPT14,      /* Panther Point */
+       TCO_PPT15,      /* Panther Point */
+       TCO_PPT16,      /* Panther Point */
+       TCO_PPT17,      /* Panther Point */
+       TCO_PPT18,      /* Panther Point */
+       TCO_PPT19,      /* Panther Point */
+       TCO_PPT20,      /* Panther Point */
+       TCO_PPT21,      /* Panther Point */
+       TCO_PPT22,      /* Panther Point */
+       TCO_PPT23,      /* Panther Point */
+       TCO_PPT24,      /* Panther Point */
+       TCO_PPT25,      /* Panther Point */
+       TCO_PPT26,      /* Panther Point */
+       TCO_PPT27,      /* Panther Point */
+       TCO_PPT28,      /* Panther Point */
+       TCO_PPT29,      /* Panther Point */
+       TCO_PPT30,      /* Panther Point */
+       TCO_PPT31,      /* Panther Point */
 };
 
 static struct {
@@ -244,6 +277,38 @@ static struct {
        {"Patsburg", 2},
        {"Patsburg", 2},
        {"DH89xxCC", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
        {NULL, 0}
 };
 
@@ -363,6 +428,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
        { ITCO_PCI_DEVICE(0x1d40,                               TCO_PBG1)},
        { ITCO_PCI_DEVICE(0x1d41,                               TCO_PBG2)},
        { ITCO_PCI_DEVICE(0x2310,                               TCO_DH89XXCC)},
+       { ITCO_PCI_DEVICE(0x1e40,                               TCO_PPT0)},
+       { ITCO_PCI_DEVICE(0x1e41,                               TCO_PPT1)},
+       { ITCO_PCI_DEVICE(0x1e42,                               TCO_PPT2)},
+       { ITCO_PCI_DEVICE(0x1e43,                               TCO_PPT3)},
+       { ITCO_PCI_DEVICE(0x1e44,                               TCO_PPT4)},
+       { ITCO_PCI_DEVICE(0x1e45,                               TCO_PPT5)},
+       { ITCO_PCI_DEVICE(0x1e46,                               TCO_PPT6)},
+       { ITCO_PCI_DEVICE(0x1e47,                               TCO_PPT7)},
+       { ITCO_PCI_DEVICE(0x1e48,                               TCO_PPT8)},
+       { ITCO_PCI_DEVICE(0x1e49,                               TCO_PPT9)},
+       { ITCO_PCI_DEVICE(0x1e4a,                               TCO_PPT10)},
+       { ITCO_PCI_DEVICE(0x1e4b,                               TCO_PPT11)},
+       { ITCO_PCI_DEVICE(0x1e4c,                               TCO_PPT12)},
+       { ITCO_PCI_DEVICE(0x1e4d,                               TCO_PPT13)},
+       { ITCO_PCI_DEVICE(0x1e4e,                               TCO_PPT14)},
+       { ITCO_PCI_DEVICE(0x1e4f,                               TCO_PPT15)},
+       { ITCO_PCI_DEVICE(0x1e50,                               TCO_PPT16)},
+       { ITCO_PCI_DEVICE(0x1e51,                               TCO_PPT17)},
+       { ITCO_PCI_DEVICE(0x1e52,                               TCO_PPT18)},
+       { ITCO_PCI_DEVICE(0x1e53,                               TCO_PPT19)},
+       { ITCO_PCI_DEVICE(0x1e54,                               TCO_PPT20)},
+       { ITCO_PCI_DEVICE(0x1e55,                               TCO_PPT21)},
+       { ITCO_PCI_DEVICE(0x1e56,                               TCO_PPT22)},
+       { ITCO_PCI_DEVICE(0x1e57,                               TCO_PPT23)},
+       { ITCO_PCI_DEVICE(0x1e58,                               TCO_PPT24)},
+       { ITCO_PCI_DEVICE(0x1e59,                               TCO_PPT25)},
+       { ITCO_PCI_DEVICE(0x1e5a,                               TCO_PPT26)},
+       { ITCO_PCI_DEVICE(0x1e5b,                               TCO_PPT27)},
+       { ITCO_PCI_DEVICE(0x1e5c,                               TCO_PPT28)},
+       { ITCO_PCI_DEVICE(0x1e5d,                               TCO_PPT29)},
+       { ITCO_PCI_DEVICE(0x1e5e,                               TCO_PPT30)},
+       { ITCO_PCI_DEVICE(0x1e5f,                               TCO_PPT31)},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
new file mode 100644 (file)
index 0000000..7d82ada
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Based on EP93xx wdt driver
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <lantiq.h>
+
+/* Section 3.4 of the datasheet
+ * The password sequence protects the WDT control register from unintended
+ * write actions, which might cause malfunction of the WDT.
+ *
+ * essentially the following two magic passwords need to be written to allow
+ * IO access to the WDT core
+ */
+#define LTQ_WDT_PW1            0x00BE0000
+#define LTQ_WDT_PW2            0x00DC0000
+
+#define LTQ_WDT_CR             0x0     /* watchdog control register */
+#define LTQ_WDT_SR             0x8     /* watchdog status register */
+
+#define LTQ_WDT_SR_EN          (0x1 << 31)     /* enable bit */
+#define LTQ_WDT_SR_PWD         (0x3 << 26)     /* turn on power */
+#define LTQ_WDT_SR_CLKDIV      (0x3 << 24)     /* turn on clock and set */
+                                               /* divider to 0x40000 */
+#define LTQ_WDT_DIVIDER                0x40000
+#define LTQ_MAX_TIMEOUT                ((1 << 16) - 1) /* the reload field is 16 bit */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static void __iomem *ltq_wdt_membase;
+static unsigned long ltq_io_region_clk_rate;
+
+static unsigned long ltq_wdt_bootstatus;
+static unsigned long ltq_wdt_in_use;
+static int ltq_wdt_timeout = 30;
+static int ltq_wdt_ok_to_close;
+
+static void
+ltq_wdt_enable(void)
+{
+       ltq_wdt_timeout = ltq_wdt_timeout *
+                       (ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
+       if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
+               ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
+
+       /* write the first password magic */
+       ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
+       /* write the second magic plus the configuration and new timeout */
+       ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
+               LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
+}
+
+static void
+ltq_wdt_disable(void)
+{
+       /* write the first password magic */
+       ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
+       /* write the second password magic with no config
+        * this turns the watchdog off
+        */
+       ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
+}
+
+static ssize_t
+ltq_wdt_write(struct file *file, const char __user *data,
+               size_t len, loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       ltq_wdt_ok_to_close = 0;
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       ltq_wdt_ok_to_close = 1;
+                               else
+                                       ltq_wdt_ok_to_close = 0;
+                       }
+               }
+               ltq_wdt_enable();
+       }
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+                       WDIOF_CARDRESET,
+       .identity = "ltq_wdt",
+};
+
+static long
+ltq_wdt_ioctl(struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       int ret = -ENOTTY;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+                               sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(ltq_wdt_bootstatus, (int __user *)arg);
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int __user *)arg);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(ltq_wdt_timeout, (int __user *)arg);
+               if (!ret)
+                       ltq_wdt_enable();
+               /* intentional drop through */
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(ltq_wdt_timeout, (int __user *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               ltq_wdt_enable();
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+static int
+ltq_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &ltq_wdt_in_use))
+               return -EBUSY;
+       ltq_wdt_in_use = 1;
+       ltq_wdt_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int
+ltq_wdt_release(struct inode *inode, struct file *file)
+{
+       if (ltq_wdt_ok_to_close)
+               ltq_wdt_disable();
+       else
+               pr_err("ltq_wdt: watchdog closed without warning\n");
+       ltq_wdt_ok_to_close = 0;
+       clear_bit(0, &ltq_wdt_in_use);
+
+       return 0;
+}
+
+static const struct file_operations ltq_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .write          = ltq_wdt_write,
+       .unlocked_ioctl = ltq_wdt_ioctl,
+       .open           = ltq_wdt_open,
+       .release        = ltq_wdt_release,
+       .llseek         = no_llseek,
+};
+
+static struct miscdevice ltq_wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &ltq_wdt_fops,
+};
+
+static int __init
+ltq_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct clk *clk;
+
+       if (!res) {
+               dev_err(&pdev->dev, "cannot obtain I/O memory region");
+               return -ENOENT;
+       }
+       res = devm_request_mem_region(&pdev->dev, res->start,
+               resource_size(res), dev_name(&pdev->dev));
+       if (!res) {
+               dev_err(&pdev->dev, "cannot request I/O memory region");
+               return -EBUSY;
+       }
+       ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+               resource_size(res));
+       if (!ltq_wdt_membase) {
+               dev_err(&pdev->dev, "cannot remap I/O memory region\n");
+               return -ENOMEM;
+       }
+
+       /* we do not need to enable the clock as it is always running */
+       clk = clk_get(&pdev->dev, "io");
+       WARN_ON(!clk);
+       ltq_io_region_clk_rate = clk_get_rate(clk);
+       clk_put(clk);
+
+       if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
+               ltq_wdt_bootstatus = WDIOF_CARDRESET;
+
+       return misc_register(&ltq_wdt_miscdev);
+}
+
+static int __devexit
+ltq_wdt_remove(struct platform_device *pdev)
+{
+       misc_deregister(&ltq_wdt_miscdev);
+
+       if (ltq_wdt_membase)
+               iounmap(ltq_wdt_membase);
+
+       return 0;
+}
+
+
+static struct platform_driver ltq_wdt_driver = {
+       .remove = __devexit_p(ltq_wdt_remove),
+       .driver = {
+               .name = "ltq_wdt",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init
+init_ltq_wdt(void)
+{
+       return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
+}
+
+static void __exit
+exit_ltq_wdt(void)
+{
+       return platform_driver_unregister(&ltq_wdt_driver);
+}
+
+module_init(init_ltq_wdt);
+module_exit(exit_ltq_wdt);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 528bceb220fd5783383d8575e99ff2099fdbdd95..eed5436ffb512dd75b54f3c10a97040f71a0c71d 100644 (file)
@@ -185,17 +185,20 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
        .fops   = &mpc8xxx_wdt_fops,
 };
 
+static const struct of_device_id mpc8xxx_wdt_match[];
 static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
 {
        int ret;
+       const struct of_device_id *match;
        struct device_node *np = ofdev->dev.of_node;
        struct mpc8xxx_wdt_type *wdt_type;
        u32 freq = fsl_get_sys_freq();
        bool enabled;
 
-       if (!ofdev->dev.of_match)
+       match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev);
+       if (!match)
                return -EINVAL;
-       wdt_type = ofdev->dev.of_match->data;
+       wdt_type = match->data;
 
        if (!freq || freq == -1)
                return -EINVAL;
index 5ec5ac1f78782296c5343ac07ec43932f25ad14e..1479dc4d612922327e5c2314862ace3b99922a74 100644 (file)
@@ -66,6 +66,7 @@ static struct {
        int default_ticks;
        unsigned long inuse;
        unsigned gpio;
+       int gstate;
 } mtx1_wdt_device;
 
 static void mtx1_wdt_trigger(unsigned long unused)
@@ -75,13 +76,13 @@ static void mtx1_wdt_trigger(unsigned long unused)
        spin_lock(&mtx1_wdt_device.lock);
        if (mtx1_wdt_device.running)
                ticks--;
-       /*
-        * toggle GPIO2_15
-        */
-       tmp = au_readl(GPIO2_DIR);
-       tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) |
-             ((~tmp) & (1 << mtx1_wdt_device.gpio));
-       au_writel(tmp, GPIO2_DIR);
+
+       /* toggle wdt gpio */
+       mtx1_wdt_device.gstate = ~mtx1_wdt_device.gstate;
+       if (mtx1_wdt_device.gstate)
+               gpio_direction_output(mtx1_wdt_device.gpio, 1);
+       else
+               gpio_direction_input(mtx1_wdt_device.gpio);
 
        if (mtx1_wdt_device.queue && ticks)
                mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
@@ -103,7 +104,8 @@ static void mtx1_wdt_start(void)
        spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
        if (!mtx1_wdt_device.queue) {
                mtx1_wdt_device.queue = 1;
-               gpio_set_value(mtx1_wdt_device.gpio, 1);
+               mtx1_wdt_device.gstate = 1;
+               gpio_direction_output(mtx1_wdt_device.gpio, 1);
                mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
        }
        mtx1_wdt_device.running++;
@@ -117,7 +119,8 @@ static int mtx1_wdt_stop(void)
        spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
        if (mtx1_wdt_device.queue) {
                mtx1_wdt_device.queue = 0;
-               gpio_set_value(mtx1_wdt_device.gpio, 0);
+               mtx1_wdt_device.gstate = 0;
+               gpio_direction_output(mtx1_wdt_device.gpio, 0);
        }
        ticks = mtx1_wdt_device.default_ticks;
        spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags);
index f420f1ff7f137c7be0e85f7f102e50f42a1d1a25..4781f806701d93c1e1a81917cdb2130d79d491b4 100644 (file)
@@ -4,21 +4,21 @@ obj-y += xenbus/
 nostackp := $(call cc-option, -fno-stack-protector)
 CFLAGS_features.o                      := $(nostackp)
 
-obj-$(CONFIG_BLOCK)            += biomerge.o
-obj-$(CONFIG_HOTPLUG_CPU)      += cpu_hotplug.o
-obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o
-obj-$(CONFIG_XEN_BALLOON)      += xen-balloon.o
-obj-$(CONFIG_XEN_DEV_EVTCHN)   += xen-evtchn.o
-obj-$(CONFIG_XEN_GNTDEV)       += xen-gntdev.o
+obj-$(CONFIG_BLOCK)                    += biomerge.o
+obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
+obj-$(CONFIG_XEN_XENCOMM)              += xencomm.o
+obj-$(CONFIG_XEN_BALLOON)              += xen-balloon.o
+obj-$(CONFIG_XEN_DEV_EVTCHN)           += xen-evtchn.o
+obj-$(CONFIG_XEN_GNTDEV)               += xen-gntdev.o
 obj-$(CONFIG_XEN_GRANT_DEV_ALLOC)      += xen-gntalloc.o
-obj-$(CONFIG_XENFS)            += xenfs/
+obj-$(CONFIG_XENFS)                    += xenfs/
 obj-$(CONFIG_XEN_SYS_HYPERVISOR)       += sys-hypervisor.o
-obj-$(CONFIG_XEN_PLATFORM_PCI) += xen-platform-pci.o
-obj-$(CONFIG_SWIOTLB_XEN)      += swiotlb-xen.o
-obj-$(CONFIG_XEN_DOM0)         += pci.o
+obj-$(CONFIG_XEN_PLATFORM_PCI)         += xen-platform-pci.o
+obj-$(CONFIG_SWIOTLB_XEN)              += swiotlb-xen.o
+obj-$(CONFIG_XEN_DOM0)                 += pci.o
 
-xen-evtchn-y                   := evtchn.o
+xen-evtchn-y                           := evtchn.o
 xen-gntdev-y                           := gntdev.o
 xen-gntalloc-y                         := gntalloc.o
 
-xen-platform-pci-y             := platform-pci.o
+xen-platform-pci-y                     := platform-pci.o
index 043af8ad6b601058418147f224b417c2eb74447d..f54290baa3dbd84317350a41aaab720649dc1baf 100644 (file)
@@ -114,7 +114,6 @@ static void __balloon_append(struct page *page)
        if (PageHighMem(page)) {
                list_add_tail(&page->lru, &ballooned_pages);
                balloon_stats.balloon_high++;
-               dec_totalhigh_pages();
        } else {
                list_add(&page->lru, &ballooned_pages);
                balloon_stats.balloon_low++;
@@ -124,6 +123,8 @@ static void __balloon_append(struct page *page)
 static void balloon_append(struct page *page)
 {
        __balloon_append(page);
+       if (PageHighMem(page))
+               dec_totalhigh_pages();
        totalram_pages--;
 }
 
@@ -193,7 +194,7 @@ static enum bp_state update_schedule(enum bp_state state)
        return BP_EAGAIN;
 }
 
-static unsigned long current_target(void)
+static long current_credit(void)
 {
        unsigned long target = balloon_stats.target_pages;
 
@@ -202,7 +203,7 @@ static unsigned long current_target(void)
                     balloon_stats.balloon_low +
                     balloon_stats.balloon_high);
 
-       return target;
+       return target - balloon_stats.current_pages;
 }
 
 static enum bp_state increase_reservation(unsigned long nr_pages)
@@ -246,7 +247,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
                set_phys_to_machine(pfn, frame_list[i]);
 
                /* Link back into the page tables if not highmem. */
-               if (!xen_hvm_domain() && pfn < max_low_pfn) {
+               if (xen_pv_domain() && !PageHighMem(page)) {
                        int ret;
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)__va(pfn << PAGE_SHIFT),
@@ -293,7 +294,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
-               if (!xen_hvm_domain() && !PageHighMem(page)) {
+               if (xen_pv_domain() && !PageHighMem(page)) {
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)__va(pfn << PAGE_SHIFT),
                                __pte_ma(0), 0);
@@ -337,7 +338,7 @@ static void balloon_process(struct work_struct *work)
        mutex_lock(&balloon_mutex);
 
        do {
-               credit = current_target() - balloon_stats.current_pages;
+               credit = current_credit();
 
                if (credit > 0)
                        state = increase_reservation(credit);
@@ -420,7 +421,7 @@ void free_xenballooned_pages(int nr_pages, struct page** pages)
        }
 
        /* The balloon may be too large now. Shrink it if needed. */
-       if (current_target() != balloon_stats.current_pages)
+       if (current_credit())
                schedule_delayed_work(&balloon_worker, 0);
 
        mutex_unlock(&balloon_mutex);
@@ -429,7 +430,7 @@ EXPORT_SYMBOL(free_xenballooned_pages);
 
 static int __init balloon_init(void)
 {
-       unsigned long pfn, nr_pages, extra_pfn_end;
+       unsigned long pfn, extra_pfn_end;
        struct page *page;
 
        if (!xen_domain())
@@ -437,11 +438,7 @@ static int __init balloon_init(void)
 
        pr_info("xen/balloon: Initialising balloon driver.\n");
 
-       if (xen_pv_domain())
-               nr_pages = xen_start_info->nr_pages;
-       else
-               nr_pages = max_pfn;
-       balloon_stats.current_pages = min(nr_pages, max_pfn);
+       balloon_stats.current_pages = xen_pv_domain() ? min(xen_start_info->nr_pages, max_pfn) : max_pfn;
        balloon_stats.target_pages  = balloon_stats.current_pages;
        balloon_stats.balloon_low   = 0;
        balloon_stats.balloon_high  = 0;
@@ -466,7 +463,7 @@ static int __init balloon_init(void)
             pfn < extra_pfn_end;
             pfn++) {
                page = pfn_to_page(pfn);
-               /* totalram_pages doesn't include the boot-time
+               /* totalram_pages and totalhigh_pages do not include the boot-time
                   balloon extension, so don't subtract from it. */
                __balloon_append(page);
        }
index 33167b43ac7e4ad9ae981b53ad6ee9069d453296..3ff822b481454847487b2c3eeaaa18d354f33721 100644 (file)
@@ -101,6 +101,7 @@ struct irq_info
                        unsigned short gsi;
                        unsigned char vector;
                        unsigned char flags;
+                       uint16_t domid;
                } pirq;
        } u;
 };
@@ -118,6 +119,8 @@ static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
 static struct irq_chip xen_dynamic_chip;
 static struct irq_chip xen_percpu_chip;
 static struct irq_chip xen_pirq_chip;
+static void enable_dynirq(struct irq_data *data);
+static void disable_dynirq(struct irq_data *data);
 
 /* Get info for IRQ */
 static struct irq_info *info_for_irq(unsigned irq)
@@ -184,6 +187,7 @@ static void xen_irq_info_pirq_init(unsigned irq,
                                   unsigned short pirq,
                                   unsigned short gsi,
                                   unsigned short vector,
+                                  uint16_t domid,
                                   unsigned char flags)
 {
        struct irq_info *info = info_for_irq(irq);
@@ -193,6 +197,7 @@ static void xen_irq_info_pirq_init(unsigned irq,
        info->u.pirq.pirq = pirq;
        info->u.pirq.gsi = gsi;
        info->u.pirq.vector = vector;
+       info->u.pirq.domid = domid;
        info->u.pirq.flags = flags;
 }
 
@@ -473,16 +478,6 @@ static void xen_free_irq(unsigned irq)
        irq_free_desc(irq);
 }
 
-static void pirq_unmask_notify(int irq)
-{
-       struct physdev_eoi eoi = { .irq = pirq_from_irq(irq) };
-
-       if (unlikely(pirq_needs_eoi(irq))) {
-               int rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
-               WARN_ON(rc);
-       }
-}
-
 static void pirq_query_unmask(int irq)
 {
        struct physdev_irq_status_query irq_status;
@@ -506,6 +501,29 @@ static bool probing_irq(int irq)
        return desc && desc->action == NULL;
 }
 
+static void eoi_pirq(struct irq_data *data)
+{
+       int evtchn = evtchn_from_irq(data->irq);
+       struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) };
+       int rc = 0;
+
+       irq_move_irq(data);
+
+       if (VALID_EVTCHN(evtchn))
+               clear_evtchn(evtchn);
+
+       if (pirq_needs_eoi(data->irq)) {
+               rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
+               WARN_ON(rc);
+       }
+}
+
+static void mask_ack_pirq(struct irq_data *data)
+{
+       disable_dynirq(data);
+       eoi_pirq(data);
+}
+
 static unsigned int __startup_pirq(unsigned int irq)
 {
        struct evtchn_bind_pirq bind_pirq;
@@ -539,7 +557,7 @@ static unsigned int __startup_pirq(unsigned int irq)
 
 out:
        unmask_evtchn(evtchn);
-       pirq_unmask_notify(irq);
+       eoi_pirq(irq_get_irq_data(irq));
 
        return 0;
 }
@@ -579,18 +597,7 @@ static void enable_pirq(struct irq_data *data)
 
 static void disable_pirq(struct irq_data *data)
 {
-}
-
-static void ack_pirq(struct irq_data *data)
-{
-       int evtchn = evtchn_from_irq(data->irq);
-
-       irq_move_irq(data);
-
-       if (VALID_EVTCHN(evtchn)) {
-               mask_evtchn(evtchn);
-               clear_evtchn(evtchn);
-       }
+       disable_dynirq(data);
 }
 
 static int find_irq_by_gsi(unsigned gsi)
@@ -639,9 +646,6 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
        if (irq < 0)
                goto out;
 
-       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
-                                     name);
-
        irq_op.irq = irq;
        irq_op.vector = 0;
 
@@ -655,9 +659,35 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
                goto out;
        }
 
-       xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector,
+       xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF,
                               shareable ? PIRQ_SHAREABLE : 0);
 
+       pirq_query_unmask(irq);
+       /* We try to use the handler with the appropriate semantic for the
+        * type of interrupt: if the interrupt doesn't need an eoi
+        * (pirq_needs_eoi returns false), we treat it like an edge
+        * triggered interrupt so we use handle_edge_irq.
+        * As a matter of fact this only happens when the corresponding
+        * physical interrupt is edge triggered or an msi.
+        *
+        * On the other hand if the interrupt needs an eoi (pirq_needs_eoi
+        * returns true) we treat it like a level triggered interrupt so we
+        * use handle_fasteoi_irq like the native code does for this kind of
+        * interrupts.
+        * Depending on the Xen version, pirq_needs_eoi might return true
+        * not only for level triggered interrupts but for edge triggered
+        * interrupts too. In any case Xen always honors the eoi mechanism,
+        * not injecting any more pirqs of the same kind if the first one
+        * hasn't received an eoi yet. Therefore using the fasteoi handler
+        * is the right choice either way.
+        */
+       if (pirq_needs_eoi(irq))
+               irq_set_chip_and_handler_name(irq, &xen_pirq_chip,
+                               handle_fasteoi_irq, name);
+       else
+               irq_set_chip_and_handler_name(irq, &xen_pirq_chip,
+                               handle_edge_irq, name);
+
 out:
        spin_unlock(&irq_mapping_update_lock);
 
@@ -680,7 +710,8 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
 }
 
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-                            int pirq, int vector, const char *name)
+                            int pirq, int vector, const char *name,
+                            domid_t domid)
 {
        int irq, ret;
 
@@ -690,10 +721,10 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
        if (irq == -1)
                goto out;
 
-       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
-                                     name);
+       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
+                       name);
 
-       xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
+       xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0);
        ret = irq_set_msi_desc(irq, msidesc);
        if (ret < 0)
                goto error_irq;
@@ -722,9 +753,16 @@ int xen_destroy_irq(int irq)
 
        if (xen_initial_domain()) {
                unmap_irq.pirq = info->u.pirq.pirq;
-               unmap_irq.domid = DOMID_SELF;
+               unmap_irq.domid = info->u.pirq.domid;
                rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
-               if (rc) {
+               /* If another domain quits without making the pci_disable_msix
+                * call, the Xen hypervisor takes care of freeing the PIRQs
+                * (free_domain_pirqs).
+                */
+               if ((rc == -ESRCH && info->u.pirq.domid != DOMID_SELF))
+                       printk(KERN_INFO "domain %d does not have %d anymore\n",
+                               info->u.pirq.domid, info->u.pirq.pirq);
+               else if (rc) {
                        printk(KERN_WARNING "unmap irq failed %d\n", rc);
                        goto out;
                }
@@ -759,6 +797,12 @@ out:
        return irq;
 }
 
+
+int xen_pirq_from_irq(unsigned irq)
+{
+       return pirq_from_irq(irq);
+}
+EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
 int bind_evtchn_to_irq(unsigned int evtchn)
 {
        int irq;
@@ -773,7 +817,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
                        goto out;
 
                irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
-                                             handle_fasteoi_irq, "event");
+                                             handle_edge_irq, "event");
 
                xen_irq_info_evtchn_init(irq, evtchn);
        }
@@ -1179,9 +1223,6 @@ static void __xen_evtchn_do_upcall(void)
                                port = (word_idx * BITS_PER_LONG) + bit_idx;
                                irq = evtchn_to_irq[port];
 
-                               mask_evtchn(port);
-                               clear_evtchn(port);
-
                                if (irq != -1) {
                                        desc = irq_to_desc(irq);
                                        if (desc)
@@ -1337,10 +1378,16 @@ static void ack_dynirq(struct irq_data *data)
 {
        int evtchn = evtchn_from_irq(data->irq);
 
-       irq_move_masked_irq(data);
+       irq_move_irq(data);
 
        if (VALID_EVTCHN(evtchn))
-               unmask_evtchn(evtchn);
+               clear_evtchn(evtchn);
+}
+
+static void mask_ack_dynirq(struct irq_data *data)
+{
+       disable_dynirq(data);
+       ack_dynirq(data);
 }
 
 static int retrigger_dynirq(struct irq_data *data)
@@ -1502,6 +1549,18 @@ void xen_poll_irq(int irq)
        xen_poll_irq_timeout(irq, 0 /* no timeout */);
 }
 
+/* Check whether the IRQ line is shared with other guests. */
+int xen_test_irq_shared(int irq)
+{
+       struct irq_info *info = info_for_irq(irq);
+       struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
+
+       if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+               return 0;
+       return !(irq_status.flags & XENIRQSTAT_shared);
+}
+EXPORT_SYMBOL_GPL(xen_test_irq_shared);
+
 void xen_irq_resume(void)
 {
        unsigned int cpu, evtchn;
@@ -1535,7 +1594,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
        .irq_mask               = disable_dynirq,
        .irq_unmask             = enable_dynirq,
 
-       .irq_eoi                = ack_dynirq,
+       .irq_ack                = ack_dynirq,
+       .irq_mask_ack           = mask_ack_dynirq,
+
        .irq_set_affinity       = set_affinity_irq,
        .irq_retrigger          = retrigger_dynirq,
 };
@@ -1545,14 +1606,15 @@ static struct irq_chip xen_pirq_chip __read_mostly = {
 
        .irq_startup            = startup_pirq,
        .irq_shutdown           = shutdown_pirq,
-
        .irq_enable             = enable_pirq,
-       .irq_unmask             = enable_pirq,
-
        .irq_disable            = disable_pirq,
-       .irq_mask               = disable_pirq,
 
-       .irq_ack                = ack_pirq,
+       .irq_mask               = disable_dynirq,
+       .irq_unmask             = enable_dynirq,
+
+       .irq_ack                = eoi_pirq,
+       .irq_eoi                = eoi_pirq,
+       .irq_mask_ack           = mask_ack_pirq,
 
        .irq_set_affinity       = set_affinity_irq,
 
index a7ffdfe19fc9b06141792bde2d3ee10f61f10dbb..f6832f46aea4a4861368465321cc8423f997cdfc 100644 (file)
@@ -427,6 +427,17 @@ static long gntalloc_ioctl(struct file *filp, unsigned int cmd,
        return 0;
 }
 
+static void gntalloc_vma_open(struct vm_area_struct *vma)
+{
+       struct gntalloc_gref *gref = vma->vm_private_data;
+       if (!gref)
+               return;
+
+       spin_lock(&gref_lock);
+       gref->users++;
+       spin_unlock(&gref_lock);
+}
+
 static void gntalloc_vma_close(struct vm_area_struct *vma)
 {
        struct gntalloc_gref *gref = vma->vm_private_data;
@@ -441,6 +452,7 @@ static void gntalloc_vma_close(struct vm_area_struct *vma)
 }
 
 static struct vm_operations_struct gntalloc_vmops = {
+       .open = gntalloc_vma_open,
        .close = gntalloc_vma_close,
 };
 
@@ -471,8 +483,6 @@ static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma)
        vma->vm_private_data = gref;
 
        vma->vm_flags |= VM_RESERVED;
-       vma->vm_flags |= VM_DONTCOPY;
-       vma->vm_flags |= VM_PFNMAP | VM_PFN_AT_MMAP;
 
        vma->vm_ops = &gntalloc_vmops;
 
index b0f9e8fb005255d0f49ddf9e2aa3584dbbbd9d7b..f914b26cf0c2efdfac05b8af9e6d9b8a37124dfc 100644 (file)
@@ -330,17 +330,26 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
 
 /* ------------------------------------------------------------------ */
 
+static void gntdev_vma_open(struct vm_area_struct *vma)
+{
+       struct grant_map *map = vma->vm_private_data;
+
+       pr_debug("gntdev_vma_open %p\n", vma);
+       atomic_inc(&map->users);
+}
+
 static void gntdev_vma_close(struct vm_area_struct *vma)
 {
        struct grant_map *map = vma->vm_private_data;
 
-       pr_debug("close %p\n", vma);
+       pr_debug("gntdev_vma_close %p\n", vma);
        map->vma = NULL;
        vma->vm_private_data = NULL;
        gntdev_put_map(map);
 }
 
 static struct vm_operations_struct gntdev_vmops = {
+       .open = gntdev_vma_open,
        .close = gntdev_vma_close,
 };
 
@@ -652,7 +661,10 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 
        vma->vm_ops = &gntdev_vmops;
 
-       vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP;
+       vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
+
+       if (use_ptemod)
+               vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP;
 
        vma->vm_private_data = map;
 
index 3745a318defce26400eeb53f390385cb3a3af217..fd725cde6ad174bc7048c2e6dd9aa268b061ae6d 100644 (file)
@@ -466,13 +466,30 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                if (map_ops[i].status)
                        continue;
 
-               /* m2p override only supported for GNTMAP_contains_pte mappings */
-               if (!(map_ops[i].flags & GNTMAP_contains_pte))
-                       continue;
-               pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
+               if (map_ops[i].flags & GNTMAP_contains_pte) {
+                       pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
                                (map_ops[i].host_addr & ~PAGE_MASK));
-               mfn = pte_mfn(*pte);
-               ret = m2p_add_override(mfn, pages[i]);
+                       mfn = pte_mfn(*pte);
+               } else {
+                       /* If you really wanted to do this:
+                        * mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
+                        *
+                        * The reason we do not implement it is b/c on the
+                        * unmap path (gnttab_unmap_refs) we have no means of
+                        * checking whether the page is !GNTMAP_contains_pte.
+                        *
+                        * That is without some extra data-structure to carry
+                        * the struct page, bool clear_pte, and list_head next
+                        * tuples and deal with allocation/delallocation, etc.
+                        *
+                        * The users of this API set the GNTMAP_contains_pte
+                        * flag so lets just return not supported until it
+                        * becomes neccessary to implement.
+                        */
+                       return -EOPNOTSUPP;
+               }
+               ret = m2p_add_override(mfn, pages[i],
+                                      map_ops[i].flags & GNTMAP_contains_pte);
                if (ret)
                        return ret;
        }
@@ -494,7 +511,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                return ret;
 
        for (i = 0; i < count; i++) {
-               ret = m2p_remove_override(pages[i]);
+               ret = m2p_remove_override(pages[i], true /* clear the PTE */);
                if (ret)
                        return ret;
        }
index 1ac94125bf93c38bb98342828490e9633a12c75f..0b5366b5be2017dc90aab1c6ed869908556fd954 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sysrq.h>
 #include <linux/stop_machine.h>
 #include <linux/freezer.h>
+#include <linux/syscore_ops.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -69,9 +70,9 @@ static int xen_suspend(void *data)
 
        BUG_ON(!irqs_disabled());
 
-       err = sysdev_suspend(PMSG_FREEZE);
+       err = syscore_suspend();
        if (err) {
-               printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
+               printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
                        err);
                return err;
        }
@@ -95,7 +96,7 @@ static int xen_suspend(void *data)
                xen_timer_resume();
        }
 
-       sysdev_resume();
+       syscore_resume();
 
        return 0;
 }
index 60f1827a32cb7fc56b70a8ec829fc3c9fcaaee3c..1e0fe01eb6705dee98acd115be1ab781cdabbc10 100644 (file)
@@ -215,7 +215,7 @@ static struct attribute_group xen_compilation_group = {
        .attrs = xen_compile_attrs,
 };
 
-int __init static xen_compilation_init(void)
+static int __init xen_compilation_init(void)
 {
        return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
 }
index 5147bdd3b8e1cc0c86ae9ac4f32d1bcaa596d4b7..257b00e9842808721780d1af1c09aa2f35558d35 100644 (file)
@@ -1102,6 +1102,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                        if (!bdev->bd_part)
                                goto out_clear;
 
+                       ret = 0;
                        if (disk->fops->open) {
                                ret = disk->fops->open(bdev, mode);
                                if (ret == -ERESTARTSYS) {
@@ -1118,9 +1119,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                        put_disk(disk);
                                        goto restart;
                                }
-                               if (ret)
-                                       goto out_clear;
                        }
+                       /*
+                        * If the device is invalidated, rescan partition
+                        * if open succeeded or failed with -ENOMEDIUM.
+                        * The latter is necessary to prevent ghost
+                        * partitions on a removed medium.
+                        */
+                       if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
+                               rescan_partitions(disk, bdev);
+                       if (ret)
+                               goto out_clear;
+
                        if (!bdev->bd_openers) {
                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
                                bdi = blk_get_backing_dev_info(bdev);
@@ -1128,8 +1138,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                        bdi = &default_backing_dev_info;
                                bdev_inode_switch_bdi(bdev->bd_inode, bdi);
                        }
-                       if (bdev->bd_invalidated)
-                               rescan_partitions(disk, bdev);
                } else {
                        struct block_device *whole;
                        whole = bdget_disk(disk, 0);
@@ -1153,13 +1161,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                }
        } else {
                if (bdev->bd_contains == bdev) {
-                       if (bdev->bd_disk->fops->open) {
+                       ret = 0;
+                       if (bdev->bd_disk->fops->open)
                                ret = bdev->bd_disk->fops->open(bdev, mode);
-                               if (ret)
-                                       goto out_unlock_bdev;
-                       }
-                       if (bdev->bd_invalidated)
+                       /* the same as first opener case, read comment there */
+                       if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
                                rescan_partitions(bdev->bd_disk, bdev);
+                       if (ret)
+                               goto out_unlock_bdev;
                }
                /* only one opener holds refs to the module and disk */
                module_put(disk->fops->owner);
index 5d505aaa72fb8326eb451687590b336c2e04052a..44ea5b92e1ba891181235a24ba53785ff7acbfa0 100644 (file)
@@ -178,12 +178,13 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
 
        if (value) {
                acl = posix_acl_from_xattr(value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+
                if (acl) {
                        ret = posix_acl_valid(acl);
                        if (ret)
                                goto out;
-               } else if (IS_ERR(acl)) {
-                       return PTR_ERR(acl);
                }
        }
 
index 2e61fe1b6b8cc76111f62c3f4b4aded03f7a0cce..8f4b81de3ae2a0ffb21b57080de5649d9a3785ff 100644 (file)
@@ -718,7 +718,7 @@ struct btrfs_space_info {
        u64 total_bytes;        /* total bytes in the space,
                                   this doesn't take mirrors into account */
        u64 bytes_used;         /* total bytes used,
-                                  this does't take mirrors into account */
+                                  this doesn't take mirrors into account */
        u64 bytes_pinned;       /* total bytes pinned, will be freed when the
                                   transaction finishes */
        u64 bytes_reserved;     /* total bytes the allocator has reserved for
index 68c84c8c24bdd3f77762b230ccb7efd614e3cab5..228cf36ece8351475d5075f74e15624e4276e112 100644 (file)
@@ -2824,6 +2824,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
 
        spin_lock(&delayed_refs->lock);
        if (delayed_refs->num_entries == 0) {
+               spin_unlock(&delayed_refs->lock);
                printk(KERN_INFO "delayed_refs has NO entry\n");
                return ret;
        }
index 31f33ba56fe823d40ecf308f32eb777315548376..9ee6bd55e16c5ea4cc9e2f1e31289ba6591730b1 100644 (file)
@@ -8059,6 +8059,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
                                u64 group_start = group->key.objectid;
                                new_extents = kmalloc(sizeof(*new_extents),
                                                      GFP_NOFS);
+                               if (!new_extents) {
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
                                nr_extents = 1;
                                ret = get_new_locations(reloc_inode,
                                                        extent_key,
@@ -8852,23 +8856,38 @@ out:
 int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_space_info *space_info;
+       struct btrfs_super_block *disk_super;
+       u64 features;
+       u64 flags;
+       int mixed = 0;
        int ret;
 
-       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0,
-                                                                &space_info);
-       if (ret)
-               return ret;
+       disk_super = &fs_info->super_copy;
+       if (!btrfs_super_root(disk_super))
+               return 1;
 
-       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0,
-                                                                &space_info);
-       if (ret)
-               return ret;
+       features = btrfs_super_incompat_flags(disk_super);
+       if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
+               mixed = 1;
 
-       ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0,
-                                                                &space_info);
+       flags = BTRFS_BLOCK_GROUP_SYSTEM;
+       ret = update_space_info(fs_info, flags, 0, 0, &space_info);
        if (ret)
-               return ret;
+               goto out;
 
+       if (mixed) {
+               flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
+               ret = update_space_info(fs_info, flags, 0, 0, &space_info);
+       } else {
+               flags = BTRFS_BLOCK_GROUP_METADATA;
+               ret = update_space_info(fs_info, flags, 0, 0, &space_info);
+               if (ret)
+                       goto out;
+
+               flags = BTRFS_BLOCK_GROUP_DATA;
+               ret = update_space_info(fs_info, flags, 0, 0, &space_info);
+       }
+out:
        return ret;
 }
 
index 31513860508829b352ae7679003c7832777196e8..ba41da59e31b1d93348622d7b47655234f5ff930 100644 (file)
@@ -2681,7 +2681,7 @@ int extent_readpages(struct extent_io_tree *tree,
                prefetchw(&page->flags);
                list_del(&page->lru);
                if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
+                                       page->index, GFP_NOFS)) {
                        __extent_read_full_page(tree, page, get_extent,
                                                &bio, 0, &bio_flags);
                }
index 11d2e9cea09e95b329cfe4e37aec5b50bcc46135..63731a1fb0a1f9004e892a31e121ae977a9eff3a 100644 (file)
@@ -1768,10 +1768,13 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
 
        while ((node = rb_last(&block_group->free_space_offset)) != NULL) {
                info = rb_entry(node, struct btrfs_free_space, offset_index);
-               unlink_free_space(block_group, info);
-               if (info->bitmap)
-                       kfree(info->bitmap);
-               kmem_cache_free(btrfs_free_space_cachep, info);
+               if (!info->bitmap) {
+                       unlink_free_space(block_group, info);
+                       kmem_cache_free(btrfs_free_space_cachep, info);
+               } else {
+                       free_bitmap(block_group, info);
+               }
+
                if (need_resched()) {
                        spin_unlock(&block_group->tree_lock);
                        cond_resched();
@@ -2301,7 +2304,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
                        start = entry->offset;
                        bytes = min(entry->bytes, end - start);
                        unlink_free_space(block_group, entry);
-                       kfree(entry);
+                       kmem_cache_free(btrfs_free_space_cachep, entry);
                }
 
                spin_unlock(&block_group->tree_lock);
index fcd66b6a80864c9612975163473240c4e8cb34fd..7cd8ab0ef04d5b3e95ccd572f96ca858457e8c18 100644 (file)
@@ -954,6 +954,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
                         1, 0, NULL, GFP_NOFS);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
+               BUG_ON(!async_cow);
                async_cow->inode = inode;
                async_cow->root = root;
                async_cow->locked_page = locked_page;
@@ -4731,9 +4732,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
@@ -4792,9 +4794,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
@@ -4999,6 +5002,8 @@ static noinline int uncompress_inline(struct btrfs_path *path,
        inline_size = btrfs_file_extent_inline_item_len(leaf,
                                        btrfs_item_nr(leaf, path->slots[0]));
        tmp = kmalloc(inline_size, GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
        ptr = btrfs_file_extent_inline_start(item);
 
        read_extent_buffer(leaf, tmp, ptr, inline_size);
@@ -6036,7 +6041,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        ret = btrfs_map_block(map_tree, READ, start_sector << 9,
                              &map_length, NULL, 0);
        if (ret) {
-               bio_put(bio);
+               bio_put(orig_bio);
                return -EIO;
        }
 
@@ -7273,9 +7278,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
                                &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
index ffb48d6c54334ab8fe0d29ae4d69cfa1b22d613c..2616f7ed47996a21df8b0c5de224c4b6c1aebf70 100644 (file)
@@ -81,6 +81,13 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
                iflags |= FS_NOATIME_FL;
        if (flags & BTRFS_INODE_DIRSYNC)
                iflags |= FS_DIRSYNC_FL;
+       if (flags & BTRFS_INODE_NODATACOW)
+               iflags |= FS_NOCOW_FL;
+
+       if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS))
+               iflags |= FS_COMPR_FL;
+       else if (flags & BTRFS_INODE_NOCOMPRESS)
+               iflags |= FS_NOCOMP_FL;
 
        return iflags;
 }
@@ -144,16 +151,13 @@ static int check_flags(unsigned int flags)
        if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
                      FS_NOATIME_FL | FS_NODUMP_FL | \
                      FS_SYNC_FL | FS_DIRSYNC_FL | \
-                     FS_NOCOMP_FL | FS_COMPR_FL | \
-                     FS_NOCOW_FL | FS_COW_FL))
+                     FS_NOCOMP_FL | FS_COMPR_FL |
+                     FS_NOCOW_FL))
                return -EOPNOTSUPP;
 
        if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
                return -EINVAL;
 
-       if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL))
-               return -EINVAL;
-
        return 0;
 }
 
@@ -218,6 +222,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
                ip->flags |= BTRFS_INODE_DIRSYNC;
        else
                ip->flags &= ~BTRFS_INODE_DIRSYNC;
+       if (flags & FS_NOCOW_FL)
+               ip->flags |= BTRFS_INODE_NODATACOW;
+       else
+               ip->flags &= ~BTRFS_INODE_NODATACOW;
 
        /*
         * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
@@ -230,11 +238,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        } else if (flags & FS_COMPR_FL) {
                ip->flags |= BTRFS_INODE_COMPRESS;
                ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
+       } else {
+               ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
        }
-       if (flags & FS_NOCOW_FL)
-               ip->flags |= BTRFS_INODE_NODATACOW;
-       else if (flags & FS_COW_FL)
-               ip->flags &= ~BTRFS_INODE_NODATACOW;
 
        trans = btrfs_join_transaction(root, 1);
        BUG_ON(IS_ERR(trans));
index c50271ad3157675059656d8113e9804cf3872dfb..f997ec0c1ba4b8efb6b46f88160de43cda3da4f2 100644 (file)
@@ -2209,8 +2209,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
 
        log = root->log_root;
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               err = -ENOMEM;
+               goto out_unlock;
+       }
 
        di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
                                   name, name_len, -1);
@@ -2271,6 +2273,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
        }
 fail:
        btrfs_free_path(path);
+out_unlock:
        mutex_unlock(&BTRFS_I(dir)->log_mutex);
        if (ret == -ENOSPC) {
                root->fs_info->last_trans_log_full_commit = trans->transid;
index 309a57b9fc85e3a6f09809da14d0cd9e1df55fb5..c7367ae5a3e6d9427add05ebf8a594ae92e81d5b 100644 (file)
@@ -155,6 +155,15 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
        unsigned long limit;
        unsigned long last_waited = 0;
        int force_reg = 0;
+       struct blk_plug plug;
+
+       /*
+        * this function runs all the bios we've collected for
+        * a particular device.  We don't want to wander off to
+        * another device without first sending all of these down.
+        * So, setup a plug here and finish it off before we return
+        */
+       blk_start_plug(&plug);
 
        bdi = blk_get_backing_dev_info(device->bdev);
        fs_info = device->dev_root->fs_info;
@@ -294,6 +303,7 @@ loop_lock:
        spin_unlock(&device->io_lock);
 
 done:
+       blk_finish_plug(&plug);
        return 0;
 }
 
index e159c529fd2bbc845bbd893f645ac7633d91b9eb..38b8ab554924cd2d4a9ddf11ce3a79efe3d411cd 100644 (file)
@@ -775,6 +775,13 @@ get_more_pages:
                                            ci->i_truncate_seq,
                                            ci->i_truncate_size,
                                            &inode->i_mtime, true, 1, 0);
+
+                               if (!req) {
+                                       rc = -ENOMEM;
+                                       unlock_page(page);
+                                       break;
+                               }
+
                                max_pages = req->r_num_pages;
 
                                alloc_page_vec(fsc, req);
index 5323c330bbf3d4acad87fe6a48701b9ee7f27589..2a5404c1c42f4efd1be78f5d24eed337c24429e3 100644 (file)
@@ -819,7 +819,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci)
                used |= CEPH_CAP_FILE_CACHE;
        if (ci->i_wr_ref)
                used |= CEPH_CAP_FILE_WR;
-       if (ci->i_wrbuffer_ref)
+       if (ci->i_wb_ref || ci->i_wrbuffer_ref)
                used |= CEPH_CAP_FILE_BUFFER;
        return used;
 }
@@ -1331,10 +1331,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
 }
 
 /*
- * Mark caps dirty.  If inode is newly dirty, add to the global dirty
- * list.
+ * Mark caps dirty.  If inode is newly dirty, return the dirty flags.
+ * Caller is then responsible for calling __mark_inode_dirty with the
+ * returned flags value.
  */
-void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
+int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
 {
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
@@ -1357,7 +1358,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
                list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
                spin_unlock(&mdsc->cap_dirty_lock);
                if (ci->i_flushing_caps == 0) {
-                       igrab(inode);
+                       ihold(inode);
                        dirty |= I_DIRTY_SYNC;
                }
        }
@@ -1365,9 +1366,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
        if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) &&
            (mask & CEPH_CAP_FILE_BUFFER))
                dirty |= I_DIRTY_DATASYNC;
-       if (dirty)
-               __mark_inode_dirty(inode, dirty);
        __cap_delay_requeue(mdsc, ci);
+       return dirty;
 }
 
 /*
@@ -1990,11 +1990,11 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got)
        if (got & CEPH_CAP_FILE_WR)
                ci->i_wr_ref++;
        if (got & CEPH_CAP_FILE_BUFFER) {
-               if (ci->i_wrbuffer_ref == 0)
-                       igrab(&ci->vfs_inode);
-               ci->i_wrbuffer_ref++;
-               dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n",
-                    &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref);
+               if (ci->i_wb_ref == 0)
+                       ihold(&ci->vfs_inode);
+               ci->i_wb_ref++;
+               dout("__take_cap_refs %p wb %d -> %d (?)\n",
+                    &ci->vfs_inode, ci->i_wb_ref-1, ci->i_wb_ref);
        }
 }
 
@@ -2169,12 +2169,12 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
                if (--ci->i_rdcache_ref == 0)
                        last++;
        if (had & CEPH_CAP_FILE_BUFFER) {
-               if (--ci->i_wrbuffer_ref == 0) {
+               if (--ci->i_wb_ref == 0) {
                        last++;
                        put++;
                }
-               dout("put_cap_refs %p wrbuffer %d -> %d (?)\n",
-                    inode, ci->i_wrbuffer_ref+1, ci->i_wrbuffer_ref);
+               dout("put_cap_refs %p wb %d -> %d (?)\n",
+                    inode, ci->i_wb_ref+1, ci->i_wb_ref);
        }
        if (had & CEPH_CAP_FILE_WR)
                if (--ci->i_wr_ref == 0) {
index 159b512d5a271379abf0bde217fd46feeb38c79b..203252d88d9fa6509d1dd7bfed3e4198c414d906 100644 (file)
@@ -734,9 +734,12 @@ retry_snap:
                }
        }
        if (ret >= 0) {
+               int dirty;
                spin_lock(&inode->i_lock);
-               __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
                spin_unlock(&inode->i_lock);
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
        }
 
 out:
index b54c97da1c43fd8a4d52238d469c0aa6cb904772..70b6a4839c386be5fa4b40b48c3bf6521eda7ca7 100644 (file)
@@ -355,6 +355,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
        ci->i_rd_ref = 0;
        ci->i_rdcache_ref = 0;
        ci->i_wr_ref = 0;
+       ci->i_wb_ref = 0;
        ci->i_wrbuffer_ref = 0;
        ci->i_wrbuffer_ref_head = 0;
        ci->i_shared_gen = 0;
@@ -1567,6 +1568,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        int release = 0, dirtied = 0;
        int mask = 0;
        int err = 0;
+       int inode_dirty_flags = 0;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -1725,13 +1727,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
                dout("setattr %p ATTR_FILE ... hrm!\n", inode);
 
        if (dirtied) {
-               __ceph_mark_dirty_caps(ci, dirtied);
+               inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied);
                inode->i_ctime = CURRENT_TIME;
        }
 
        release &= issued;
        spin_unlock(&inode->i_lock);
 
+       if (inode_dirty_flags)
+               __mark_inode_dirty(inode, inode_dirty_flags);
+
        if (mask) {
                req->r_inode = igrab(inode);
                req->r_inode_drop = release;
index f60b07b0feb075042e91c3cdabea569bd01ee158..d0fae4ce9ba55b704ccedadbfd3f298e3a00cfb4 100644 (file)
@@ -3304,8 +3304,8 @@ static void con_put(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
 
+       dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref) - 1);
        ceph_put_mds_session(s);
-       dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref));
 }
 
 /*
index e86ec1155f8f401ec2722f6b8ae005f48c6d9a42..24067d68a5549769df4be2c2a2574c36d6dcf702 100644 (file)
@@ -206,7 +206,7 @@ void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
                up_write(&mdsc->snap_rwsem);
        } else {
                spin_lock(&mdsc->snap_empty_lock);
-               list_add(&mdsc->snap_empty, &realm->empty_item);
+               list_add(&realm->empty_item, &mdsc->snap_empty);
                spin_unlock(&mdsc->snap_empty_lock);
        }
 }
index 619fe719968ff124771de1811b80ba165a54c2b3..f5cabefa98dc03cee37b12e8c961a4f208e970a4 100644 (file)
@@ -293,7 +293,7 @@ struct ceph_inode_info {
 
        /* held references to caps */
        int i_pin_ref;
-       int i_rd_ref, i_rdcache_ref, i_wr_ref;
+       int i_rd_ref, i_rdcache_ref, i_wr_ref, i_wb_ref;
        int i_wrbuffer_ref, i_wrbuffer_ref_head;
        u32 i_shared_gen;       /* increment each time we get FILE_SHARED */
        u32 i_rdcache_gen;      /* incremented each time we get FILE_CACHE. */
@@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci)
 {
        return ci->i_dirty_caps | ci->i_flushing_caps;
 }
-extern void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask);
+extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask);
 
 extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
 extern int __ceph_caps_used(struct ceph_inode_info *ci);
index 8c9eba6ef9df4999ce4894893900984d943695e5..f2b628696180e93d69bae9c72464ed4b795d694e 100644 (file)
@@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
        struct ceph_inode_xattr *xattr = NULL;
        int issued;
        int required_blob_size;
+       int dirty;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -763,11 +764,12 @@ retry:
        dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
        err = __set_xattr(ci, newname, name_len, newval,
                          val_len, 1, 1, 1, &xattr);
-       __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
        ci->i_xattrs.dirty = true;
        inode->i_ctime = CURRENT_TIME;
        spin_unlock(&inode->i_lock);
-
+       if (dirty)
+               __mark_inode_dirty(inode, dirty);
        return err;
 
 do_sync:
@@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
        struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
        int issued;
        int err;
+       int dirty;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
                goto do_sync;
 
        err = __remove_xattr_by_name(ceph_inode(inode), name);
-       __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
        ci->i_xattrs.dirty = true;
        inode->i_ctime = CURRENT_TIME;
 
        spin_unlock(&inode->i_lock);
-
+       if (dirty)
+               __mark_inode_dirty(inode, dirty);
        return err;
 do_sync:
        spin_unlock(&inode->i_lock);
index 23d43cde4306042407dcd3df76d78ab81b793db7..1b2e180b018dd01e9d65041c6eb8cc288974b2c3 100644 (file)
@@ -277,6 +277,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 
        for (i = 0, j = 0; i < srclen; j++) {
                src_char = source[i];
+               charlen = 1;
                switch (src_char) {
                case 0:
                        put_unaligned(0, &target[j]);
@@ -316,16 +317,13 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
                                dst_char = cpu_to_le16(0x003f);
                                charlen = 1;
                        }
-                       /*
-                        * character may take more than one byte in the source
-                        * string, but will take exactly two bytes in the
-                        * target string
-                        */
-                       i += charlen;
-                       continue;
                }
+               /*
+                * character may take more than one byte in the source string,
+                * but will take exactly two bytes in the target string
+                */
+               i += charlen;
                put_unaligned(dst_char, &target[j]);
-               i++; /* move to next char in source string */
        }
 
 ctoUCS_out:
index db9d55b507d0afe36b816889165975edd3a7198b..277262a8e82f282d4a32b0ddd4a244bc55e99472 100644 (file)
@@ -274,7 +274,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
        char *data_area_of_target;
        char *data_area_of_buf2;
        int remaining;
-       __u16 byte_count, total_data_size, total_in_buf, total_in_buf2;
+       unsigned int byte_count, total_in_buf;
+       __u16 total_data_size, total_in_buf2;
 
        total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
 
@@ -287,7 +288,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
        remaining = total_data_size - total_in_buf;
 
        if (remaining < 0)
-               return -EINVAL;
+               return -EPROTO;
 
        if (remaining == 0) /* nothing to do, ignore */
                return 0;
@@ -308,20 +309,29 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
        data_area_of_target += total_in_buf;
 
        /* copy second buffer into end of first buffer */
-       memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
        total_in_buf += total_in_buf2;
+       /* is the result too big for the field? */
+       if (total_in_buf > USHRT_MAX)
+               return -EPROTO;
        put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
+
+       /* fix up the BCC */
        byte_count = get_bcc_le(pTargetSMB);
        byte_count += total_in_buf2;
+       /* is the result too big for the field? */
+       if (byte_count > USHRT_MAX)
+               return -EPROTO;
        put_bcc_le(byte_count, pTargetSMB);
 
        byte_count = pTargetSMB->smb_buf_length;
        byte_count += total_in_buf2;
-
-       /* BB also add check that we are not beyond maximum buffer size */
-
+       /* don't allow buffer to overflow */
+       if (byte_count > CIFSMaxBufSize)
+               return -ENOBUFS;
        pTargetSMB->smb_buf_length = byte_count;
 
+       memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
+
        if (remaining == total_in_buf2) {
                cFYI(1, "found the last secondary response");
                return 0; /* we are done */
@@ -607,59 +617,63 @@ incomplete_rcv:
                list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
                        mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 
-                       if ((mid_entry->mid == smb_buffer->Mid) &&
-                           (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
-                           (mid_entry->command == smb_buffer->Command)) {
-                               if (length == 0 &&
-                                  check2ndT2(smb_buffer, server->maxBuf) > 0) {
-                                       /* We have a multipart transact2 resp */
-                                       isMultiRsp = true;
-                                       if (mid_entry->resp_buf) {
-                                               /* merge response - fix up 1st*/
-                                               if (coalesce_t2(smb_buffer,
-                                                       mid_entry->resp_buf)) {
-                                                       mid_entry->multiRsp =
-                                                                true;
-                                                       break;
-                                               } else {
-                                                       /* all parts received */
-                                                       mid_entry->multiEnd =
-                                                                true;
-                                                       goto multi_t2_fnd;
-                                               }
+                       if (mid_entry->mid != smb_buffer->Mid ||
+                           mid_entry->midState != MID_REQUEST_SUBMITTED ||
+                           mid_entry->command != smb_buffer->Command) {
+                               mid_entry = NULL;
+                               continue;
+                       }
+
+                       if (length == 0 &&
+                           check2ndT2(smb_buffer, server->maxBuf) > 0) {
+                               /* We have a multipart transact2 resp */
+                               isMultiRsp = true;
+                               if (mid_entry->resp_buf) {
+                                       /* merge response - fix up 1st*/
+                                       length = coalesce_t2(smb_buffer,
+                                                       mid_entry->resp_buf);
+                                       if (length > 0) {
+                                               length = 0;
+                                               mid_entry->multiRsp = true;
+                                               break;
                                        } else {
-                                               if (!isLargeBuf) {
-                                                       cERROR(1, "1st trans2 resp needs bigbuf");
-                                       /* BB maybe we can fix this up,  switch
-                                          to already allocated large buffer? */
-                                               } else {
-                                                       /* Have first buffer */
-                                                       mid_entry->resp_buf =
-                                                                smb_buffer;
-                                                       mid_entry->largeBuf =
-                                                                true;
-                                                       bigbuf = NULL;
-                                               }
+                                               /* all parts received or
+                                                * packet is malformed
+                                                */
+                                               mid_entry->multiEnd = true;
+                                               goto multi_t2_fnd;
+                                       }
+                               } else {
+                                       if (!isLargeBuf) {
+                                               /*
+                                                * FIXME: switch to already
+                                                *        allocated largebuf?
+                                                */
+                                               cERROR(1, "1st trans2 resp "
+                                                         "needs bigbuf");
+                                       } else {
+                                               /* Have first buffer */
+                                               mid_entry->resp_buf =
+                                                        smb_buffer;
+                                               mid_entry->largeBuf = true;
+                                               bigbuf = NULL;
                                        }
-                                       break;
                                }
-                               mid_entry->resp_buf = smb_buffer;
-                               mid_entry->largeBuf = isLargeBuf;
+                               break;
+                       }
+                       mid_entry->resp_buf = smb_buffer;
+                       mid_entry->largeBuf = isLargeBuf;
 multi_t2_fnd:
-                               if (length == 0)
-                                       mid_entry->midState =
-                                                       MID_RESPONSE_RECEIVED;
-                               else
-                                       mid_entry->midState =
-                                                       MID_RESPONSE_MALFORMED;
+                       if (length == 0)
+                               mid_entry->midState = MID_RESPONSE_RECEIVED;
+                       else
+                               mid_entry->midState = MID_RESPONSE_MALFORMED;
 #ifdef CONFIG_CIFS_STATS2
-                               mid_entry->when_received = jiffies;
+                       mid_entry->when_received = jiffies;
 #endif
-                               list_del_init(&mid_entry->qhead);
-                               mid_entry->callback(mid_entry);
-                               break;
-                       }
-                       mid_entry = NULL;
+                       list_del_init(&mid_entry->qhead);
+                       mid_entry->callback(mid_entry);
+                       break;
                }
                spin_unlock(&GlobalMid_Lock);
 
@@ -807,8 +821,7 @@ static int
 cifs_parse_mount_options(char *options, const char *devname,
                         struct smb_vol *vol)
 {
-       char *value;
-       char *data;
+       char *value, *data, *end;
        unsigned int  temp_len, i, j;
        char separator[2];
        short int override_uid = -1;
@@ -851,6 +864,7 @@ cifs_parse_mount_options(char *options, const char *devname,
        if (!options)
                return 1;
 
+       end = options + strlen(options);
        if (strncmp(options, "sep=", 4) == 0) {
                if (options[4] != 0) {
                        separator[0] = options[4];
@@ -916,6 +930,7 @@ cifs_parse_mount_options(char *options, const char *devname,
                        the only illegal character in a password is null */
 
                        if ((value[temp_len] == 0) &&
+                           (value + temp_len < end) &&
                            (value[temp_len+1] == separator[0])) {
                                /* reinsert comma */
                                value[temp_len] = separator[0];
@@ -2658,6 +2673,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon,
                              0 /* not legacy */, cifs_sb->local_nls,
                              cifs_sb->mnt_cifs_flags &
                                CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+       if (rc == -EOPNOTSUPP || rc == -EINVAL)
+               rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
        kfree(pfile_info);
        return rc;
 }
index f6728eb6f4b94774431136a8700ce9e96b4d2940..645114ad0a10031e08ad9beaa815a720b9fe50b0 100644 (file)
@@ -276,7 +276,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
 }
 
 static void
-decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses,
+decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
                      const struct nls_table *nls_cp)
 {
        int len;
@@ -284,19 +284,6 @@ decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses,
 
        cFYI(1, "bleft %d", bleft);
 
-       /*
-        * Windows servers do not always double null terminate their final
-        * Unicode string. Check to see if there are an uneven number of bytes
-        * left. If so, then add an extra NULL pad byte to the end of the
-        * response.
-        *
-        * See section 2.7.2 in "Implementing CIFS" for details
-        */
-       if (bleft % 2) {
-               data[bleft] = 0;
-               ++bleft;
-       }
-
        kfree(ses->serverOS);
        ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
        cFYI(1, "serverOS=%s", ses->serverOS);
@@ -929,7 +916,9 @@ ssetup_ntlmssp_authenticate:
        }
 
        /* BB check if Unicode and decode strings */
-       if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+       if (bytes_remaining == 0) {
+               /* no string area to decode, do nothing */
+       } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
                /* unicode string area must be word-aligned */
                if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
                        ++bcc_ptr;
index 3313dd19f543841d7e4689cfd18da028e4522892..9a37a9b6de3a23f026f6dc0d9c2906e07b1f8bf0 100644 (file)
@@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock);
 static void configfs_d_iput(struct dentry * dentry,
                            struct inode * inode)
 {
-       struct configfs_dirent * sd = dentry->d_fsdata;
+       struct configfs_dirent *sd = dentry->d_fsdata;
 
        if (sd) {
                BUG_ON(sd->s_dentry != dentry);
+               /* Coordinate with configfs_readdir */
+               spin_lock(&configfs_dirent_lock);
                sd->s_dentry = NULL;
+               spin_unlock(&configfs_dirent_lock);
                configfs_put(sd);
        }
        iput(inode);
@@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group,
                        sd = child->d_fsdata;
                        sd->s_type |= CONFIGFS_USET_DEFAULT;
                } else {
-                       d_delete(child);
+                       BUG_ON(child->d_inode);
+                       d_drop(child);
                        dput(child);
                }
        }
@@ -1545,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
        struct configfs_dirent * parent_sd = dentry->d_fsdata;
        struct configfs_dirent *cursor = filp->private_data;
        struct list_head *p, *q = &cursor->s_sibling;
-       ino_t ino;
+       ino_t ino = 0;
        int i = filp->f_pos;
 
        switch (i) {
@@ -1573,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
                                struct configfs_dirent *next;
                                const char * name;
                                int len;
+                               struct inode *inode = NULL;
 
                                next = list_entry(p, struct configfs_dirent,
                                                   s_sibling);
@@ -1581,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
 
                                name = configfs_get_name(next);
                                len = strlen(name);
-                               if (next->s_dentry)
-                                       ino = next->s_dentry->d_inode->i_ino;
-                               else
+
+                               /*
+                                * We'll have a dentry and an inode for
+                                * PINNED items and for open attribute
+                                * files.  We lock here to prevent a race
+                                * with configfs_d_iput() clearing
+                                * s_dentry before calling iput().
+                                *
+                                * Why do we go to the trouble?  If
+                                * someone has an attribute file open,
+                                * the inode number should match until
+                                * they close it.  Beyond that, we don't
+                                * care.
+                                */
+                               spin_lock(&configfs_dirent_lock);
+                               dentry = next->s_dentry;
+                               if (dentry)
+                                       inode = dentry->d_inode;
+                               if (inode)
+                                       ino = inode->i_ino;
+                               spin_unlock(&configfs_dirent_lock);
+                               if (!inode)
                                        ino = iunique(configfs_sb, 2);
 
                                if (filldir(dirent, name, len, filp->f_pos, ino,
@@ -1683,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
                err = configfs_attach_group(sd->s_element, &group->cg_item,
                                            dentry);
                if (err) {
-                       d_delete(dentry);
+                       BUG_ON(dentry->d_inode);
+                       d_drop(dentry);
                        dput(dentry);
                } else {
                        spin_lock(&configfs_dirent_lock);
index 129a357309946291b62f670e4ebdf978c7d8b947..22a0ef41bad1b1cd17fc6ce84023d52f65096ba5 100644 (file)
@@ -99,12 +99,9 @@ static struct kmem_cache *dentry_cache __read_mostly;
 static unsigned int d_hash_mask __read_mostly;
 static unsigned int d_hash_shift __read_mostly;
 
-struct dcache_hash_bucket {
-       struct hlist_bl_head head;
-};
-static struct dcache_hash_bucket *dentry_hashtable __read_mostly;
+static struct hlist_bl_head *dentry_hashtable __read_mostly;
 
-static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
+static inline struct hlist_bl_head *d_hash(struct dentry *parent,
                                        unsigned long hash)
 {
        hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
@@ -112,16 +109,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
        return dentry_hashtable + (hash & D_HASHMASK);
 }
 
-static inline void spin_lock_bucket(struct dcache_hash_bucket *b)
-{
-       bit_spin_lock(0, (unsigned long *)&b->head.first);
-}
-
-static inline void spin_unlock_bucket(struct dcache_hash_bucket *b)
-{
-       __bit_spin_unlock(0, (unsigned long *)&b->head.first);
-}
-
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
@@ -167,8 +154,8 @@ static void d_free(struct dentry *dentry)
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
 
-       /* if dentry was never inserted into hash, immediate free is OK */
-       if (hlist_bl_unhashed(&dentry->d_hash))
+       /* if dentry was never visible to RCU, immediate free is OK */
+       if (!(dentry->d_flags & DCACHE_RCUACCESS))
                __d_free(&dentry->d_u.d_rcu);
        else
                call_rcu(&dentry->d_u.d_rcu, __d_free);
@@ -330,28 +317,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
  */
 void __d_drop(struct dentry *dentry)
 {
-       if (!(dentry->d_flags & DCACHE_UNHASHED)) {
-               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) {
-                       bit_spin_lock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_init(&dentry->d_hash);
-                       __bit_spin_unlock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-               } else {
-                       struct dcache_hash_bucket *b;
+       if (!d_unhashed(dentry)) {
+               struct hlist_bl_head *b;
+               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
+                       b = &dentry->d_sb->s_anon;
+               else
                        b = d_hash(dentry->d_parent, dentry->d_name.hash);
-                       spin_lock_bucket(b);
-                       /*
-                        * We may not actually need to put DCACHE_UNHASHED
-                        * manipulations under the hash lock, but follow
-                        * the principle of least surprise.
-                        */
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_rcu(&dentry->d_hash);
-                       spin_unlock_bucket(b);
-                       dentry_rcuwalk_barrier(dentry);
-               }
+
+               hlist_bl_lock(b);
+               __hlist_bl_del(&dentry->d_hash);
+               dentry->d_hash.pprev = NULL;
+               hlist_bl_unlock(b);
+
+               dentry_rcuwalk_barrier(dentry);
        }
 }
 EXPORT_SYMBOL(__d_drop);
@@ -1304,7 +1282,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        dname[name->len] = 0;
 
        dentry->d_count = 1;
-       dentry->d_flags = DCACHE_UNHASHED;
+       dentry->d_flags = 0;
        spin_lock_init(&dentry->d_lock);
        seqcount_init(&dentry->d_seq);
        dentry->d_inode = NULL;
@@ -1606,10 +1584,9 @@ struct dentry *d_obtain_alias(struct inode *inode)
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
        list_add(&tmp->d_alias, &inode->i_dentry);
-       bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
-       tmp->d_flags &= ~DCACHE_UNHASHED;
+       hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
-       __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
+       hlist_bl_unlock(&tmp->d_sb->s_anon);
        spin_unlock(&tmp->d_lock);
        spin_unlock(&inode->i_lock);
        security_d_instantiate(tmp, inode);
@@ -1789,7 +1766,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *dentry;
 
@@ -1813,7 +1790,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
         *
         * See Documentation/filesystems/path-lookup.txt for more details.
         */
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
                struct inode *i;
                const char *tname;
                int tlen;
@@ -1908,7 +1885,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *found = NULL;
        struct dentry *dentry;
@@ -1935,7 +1912,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
         */
        rcu_read_lock();
        
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
                const char *tname;
                int tlen;
 
@@ -2086,13 +2063,13 @@ again:
 }
 EXPORT_SYMBOL(d_delete);
 
-static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b)
+static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
 {
        BUG_ON(!d_unhashed(entry));
-       spin_lock_bucket(b);
-       entry->d_flags &= ~DCACHE_UNHASHED;
-       hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
-       spin_unlock_bucket(b);
+       hlist_bl_lock(b);
+       entry->d_flags |= DCACHE_RCUACCESS;
+       hlist_bl_add_head_rcu(&entry->d_hash, b);
+       hlist_bl_unlock(b);
 }
 
 static void _d_rehash(struct dentry * entry)
@@ -3025,7 +3002,7 @@ static void __init dcache_init_early(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        HASH_EARLY,
@@ -3034,7 +3011,7 @@ static void __init dcache_init_early(void)
                                        0);
 
        for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 static void __init dcache_init(void)
@@ -3057,7 +3034,7 @@ static void __init dcache_init(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        0,
@@ -3066,7 +3043,7 @@ static void __init dcache_init(void)
                                        0);
 
        for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 /* SLAB cache for __getname() consumers */
index d2a70a4561f91257fe44d7cb867e9d14ec1ff908..b8d5c8091024cd1a66d8f36cf9d8fde25f3d2052 100644 (file)
@@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
        crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 }
 
+void ecryptfs_i_size_init(const char *page_virt, struct inode *inode)
+{
+       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+       struct ecryptfs_crypt_stat *crypt_stat;
+       u64 file_size;
+
+       crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+       mount_crypt_stat =
+               &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
+       if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
+               file_size = i_size_read(ecryptfs_inode_to_lower(inode));
+               if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+                       file_size += crypt_stat->metadata_size;
+       } else
+               file_size = get_unaligned_be64(page_virt);
+       i_size_write(inode, (loff_t)file_size);
+       crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED;
+}
+
 /**
  * ecryptfs_read_headers_virt
  * @page_virt: The virtual address into which to read the headers
@@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt,
                rc = -EINVAL;
                goto out;
        }
+       if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED))
+               ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
        offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
        rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
                                    &bytes_read);
index bd3cafd0949de6d22179ca5f91115edf18f38fda..e70282775e2c193f11da232c897f6859a2e4334b 100644 (file)
@@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800
 #define ECRYPTFS_ENCFN_USE_FEK        0x00001000
 #define ECRYPTFS_UNLINK_SIGS          0x00002000
+#define ECRYPTFS_I_SIZE_INITIALIZED   0x00004000
        u32 flags;
        unsigned int file_version;
        size_t iv_bytes;
@@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat {
 struct ecryptfs_inode_info {
        struct inode vfs_inode;
        struct inode *wii_inode;
+       struct mutex lower_file_mutex;
+       atomic_t lower_file_count;
        struct file *lower_file;
        struct ecryptfs_crypt_stat crypt_stat;
 };
@@ -626,6 +629,7 @@ struct ecryptfs_open_req {
 int ecryptfs_interpose(struct dentry *hidden_dentry,
                       struct dentry *this_dentry, struct super_block *sb,
                       u32 flags);
+void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                                        struct dentry *lower_dentry,
                                        struct inode *ecryptfs_dir_inode);
@@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
                             struct dentry *lower_dentry,
                             struct vfsmount *lower_mnt,
                             const struct cred *cred);
-int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
+int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry);
+void ecryptfs_put_lower_file(struct inode *inode);
 int
 ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
                             size_t *packet_size,
index cedc913d11ba908f62be8711190a0883f4e95fbe..566e5472f78c3d6dae8e5008689eef281cba37ab 100644 (file)
@@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                                      | ECRYPTFS_ENCRYPTED);
        }
        mutex_unlock(&crypt_stat->cs_mutex);
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out_free;
@@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
        if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
            == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) {
                rc = -EPERM;
-               printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+               printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "
                       "file must hence be opened RO\n", __func__);
-               goto out_free;
+               goto out_put;
        }
        ecryptfs_set_file_lower(
                file, ecryptfs_inode_to_private(inode)->lower_file);
@@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                                       "Plaintext passthrough mode is not "
                                       "enabled; returning -EIO\n");
                                mutex_unlock(&crypt_stat->cs_mutex);
-                               goto out_free;
+                               goto out_put;
                        }
                        rc = 0;
-                       crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+                       crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+                                              | ECRYPTFS_ENCRYPTED);
                        mutex_unlock(&crypt_stat->cs_mutex);
                        goto out;
                }
@@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                        "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
                        (unsigned long long)i_size_read(inode));
        goto out;
+out_put:
+       ecryptfs_put_lower_file(inode);
 out_free:
        kmem_cache_free(ecryptfs_file_info_cache,
                        ecryptfs_file_to_private(file));
@@ -254,17 +257,13 @@ out:
 
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
-       int rc = 0;
-       struct file *lower_file = NULL;
-
-       lower_file = ecryptfs_file_to_lower(file);
-       if (lower_file->f_op && lower_file->f_op->flush)
-               rc = lower_file->f_op->flush(lower_file, td);
-       return rc;
+       return file->f_mode & FMODE_WRITE
+              ? filemap_write_and_wait(file->f_mapping) : 0;
 }
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
 {
+       ecryptfs_put_lower_file(inode);
        kmem_cache_free(ecryptfs_file_info_cache,
                        ecryptfs_file_to_private(file));
        return 0;
index f99051b7adab1e7e107cc40e40bb39d57e20e5c1..4d4cc6a90cd57f18b330674f8e5320205cc2a5e6 100644 (file)
@@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                                "context; rc = [%d]\n", rc);
                goto out;
        }
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out;
        }
        rc = ecryptfs_write_metadata(ecryptfs_dentry);
-       if (rc) {
+       if (rc)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
-               goto out;
-       }
+       ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
 out:
        return rc;
 }
@@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
        struct dentry *lower_dir_dentry;
        struct vfsmount *lower_mnt;
        struct inode *lower_inode;
-       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        struct ecryptfs_crypt_stat *crypt_stat;
        char *page_virt = NULL;
-       u64 file_size;
-       int rc = 0;
+       int put_lower = 0, rc = 0;
 
        lower_dir_dentry = lower_dentry->d_parent;
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
@@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                rc = -ENOMEM;
                goto out;
        }
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out_free_kmem;
        }
+       put_lower = 1;
        crypt_stat = &ecryptfs_inode_to_private(
                                        ecryptfs_dentry->d_inode)->crypt_stat;
        /* TODO: lock for crypt_stat comparison */
@@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                }
                crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
        }
-       mount_crypt_stat = &ecryptfs_superblock_to_private(
-               ecryptfs_dentry->d_sb)->mount_crypt_stat;
-       if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
-               if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-                       file_size = (crypt_stat->metadata_size
-                                    + i_size_read(lower_dentry->d_inode));
-               else
-                       file_size = i_size_read(lower_dentry->d_inode);
-       } else {
-               file_size = get_unaligned_be64(page_virt);
-       }
-       i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size);
+       ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
 out_free_kmem:
        kmem_cache_free(ecryptfs_header_cache_2, page_virt);
        goto out;
@@ -322,6 +309,8 @@ out_put:
        mntput(lower_mnt);
        d_drop(ecryptfs_dentry);
 out:
+       if (put_lower)
+               ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
        return rc;
 }
 
@@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
        dget(lower_dentry);
        rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
        dput(lower_dentry);
-       if (!rc)
-               d_delete(lower_dentry);
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
        unlock_dir(lower_dir_dentry);
@@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-       dput(lower_new_dentry->d_parent);
-       dput(lower_old_dentry->d_parent);
+       dput(lower_new_dir_dentry);
+       dput(lower_old_dir_dentry);
        dput(lower_new_dentry);
        dput(lower_old_dentry);
        return rc;
@@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
 
        if (unlikely((ia->ia_size == i_size))) {
                lower_ia->ia_valid &= ~ATTR_SIZE;
-               goto out;
+               return 0;
        }
+       rc = ecryptfs_get_lower_file(dentry);
+       if (rc)
+               return rc;
        crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
        /* Switch on growing or shrinking file */
        if (ia->ia_size > i_size) {
@@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                        lower_ia->ia_valid &= ~ATTR_SIZE;
        }
 out:
+       ecryptfs_put_lower_file(inode);
        return rc;
 }
 
@@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
 
                mount_crypt_stat = &ecryptfs_superblock_to_private(
                        dentry->d_sb)->mount_crypt_stat;
+               rc = ecryptfs_get_lower_file(dentry);
+               if (rc) {
+                       mutex_unlock(&crypt_stat->cs_mutex);
+                       goto out;
+               }
                rc = ecryptfs_read_metadata(dentry);
+               ecryptfs_put_lower_file(inode);
                if (rc) {
                        if (!(mount_crypt_stat->flags
                              & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
@@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
                                goto out;
                        }
                        rc = 0;
-                       crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+                       crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+                                              | ECRYPTFS_ENCRYPTED);
                }
        }
        mutex_unlock(&crypt_stat->cs_mutex);
+       if (S_ISREG(inode->i_mode)) {
+               rc = filemap_write_and_wait(inode->i_mapping);
+               if (rc)
+                       goto out;
+               fsstack_copy_attr_all(inode, lower_inode);
+       }
        memcpy(&lower_ia, ia, sizeof(lower_ia));
        if (ia->ia_valid & ATTR_FILE)
                lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
index 0851ab6980f54038b8f0ed9239712fea573622c5..69f994a7d5249589bf594adaa4780bca967f08b2 100644 (file)
@@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread;
  * @ignored: ignored
  *
  * The eCryptfs kernel thread that has the responsibility of getting
- * the lower persistent file with RW permissions.
+ * the lower file with RW permissions.
  *
  * Returns zero on success; non-zero otherwise
  */
@@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
        int rc = 0;
 
        /* Corresponding dput() and mntput() are done when the
-        * persistent file is fput() when the eCryptfs inode is
-        * destroyed. */
+        * lower file is fput() when all eCryptfs files for the inode are
+        * released. */
        dget(lower_dentry);
        mntget(lower_mnt);
        flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
index fdb2eb0ad09e447d3701dcc31a9da29cc8619cbe..89b93389af8ee0a69b44cbfe709f4f766156a6c0 100644 (file)
@@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)
 }
 
 /**
- * ecryptfs_init_persistent_file
+ * ecryptfs_init_lower_file
  * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
  *                   the lower dentry and the lower mount set
  *
@@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...)
  * inode. All I/O operations to the lower inode occur through that
  * file. When the first eCryptfs dentry that interposes with the first
  * lower dentry for that inode is created, this function creates the
- * persistent file struct and associates it with the eCryptfs
- * inode. When the eCryptfs inode is destroyed, the file is closed.
+ * lower file struct and associates it with the eCryptfs
+ * inode. When all eCryptfs files associated with the inode are released, the
+ * file is closed.
  *
- * The persistent file will be opened with read/write permissions, if
+ * The lower file will be opened with read/write permissions, if
  * possible. Otherwise, it is opened read-only.
  *
- * This function does nothing if a lower persistent file is already
+ * This function does nothing if a lower file is already
  * associated with the eCryptfs inode.
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_init_lower_file(struct dentry *dentry,
+                                   struct file **lower_file)
 {
        const struct cred *cred = current_cred();
-       struct ecryptfs_inode_info *inode_info =
-               ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-       int rc = 0;
+       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+       struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+       int rc;
 
-       if (!inode_info->lower_file) {
-               struct dentry *lower_dentry;
-               struct vfsmount *lower_mnt =
-                       ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
+       rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
+                                     cred);
+       if (rc) {
+               printk(KERN_ERR "Error opening lower file "
+                      "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
+                      "rc = [%d]\n", lower_dentry, lower_mnt, rc);
+               (*lower_file) = NULL;
+       }
+       return rc;
+}
 
-               lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-               rc = ecryptfs_privileged_open(&inode_info->lower_file,
-                                             lower_dentry, lower_mnt, cred);
-               if (rc) {
-                       printk(KERN_ERR "Error opening lower persistent file "
-                              "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
-                              "rc = [%d]\n", lower_dentry, lower_mnt, rc);
-                       inode_info->lower_file = NULL;
-               }
+int ecryptfs_get_lower_file(struct dentry *dentry)
+{
+       struct ecryptfs_inode_info *inode_info =
+               ecryptfs_inode_to_private(dentry->d_inode);
+       int count, rc = 0;
+
+       mutex_lock(&inode_info->lower_file_mutex);
+       count = atomic_inc_return(&inode_info->lower_file_count);
+       if (WARN_ON_ONCE(count < 1))
+               rc = -EINVAL;
+       else if (count == 1) {
+               rc = ecryptfs_init_lower_file(dentry,
+                                             &inode_info->lower_file);
+               if (rc)
+                       atomic_set(&inode_info->lower_file_count, 0);
        }
+       mutex_unlock(&inode_info->lower_file_mutex);
        return rc;
 }
 
+void ecryptfs_put_lower_file(struct inode *inode)
+{
+       struct ecryptfs_inode_info *inode_info;
+
+       inode_info = ecryptfs_inode_to_private(inode);
+       if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
+                                     &inode_info->lower_file_mutex)) {
+               fput(inode_info->lower_file);
+               inode_info->lower_file = NULL;
+               mutex_unlock(&inode_info->lower_file_mutex);
+       }
+}
+
 static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
                       struct super_block *sb)
 {
index bacc882e1ae40454f7623ac81e78968155d9ae55..245b517bf1b65ec5dc5dfa294891e40038d201d7 100644 (file)
@@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
        if (unlikely(!inode_info))
                goto out;
        ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
+       mutex_init(&inode_info->lower_file_mutex);
+       atomic_set(&inode_info->lower_file_count, 0);
        inode_info->lower_file = NULL;
        inode = &inode_info->vfs_inode;
 out:
@@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head)
  *
  * This is used during the final destruction of the inode.  All
  * allocation of memory related to the inode, including allocated
- * memory in the crypt_stat struct, will be released here. This
- * function also fput()'s the persistent file for the lower inode.
+ * memory in the crypt_stat struct, will be released here.
  * There should be no chance that this deallocation will be missed.
  */
 static void ecryptfs_destroy_inode(struct inode *inode)
@@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode)
        struct ecryptfs_inode_info *inode_info;
 
        inode_info = ecryptfs_inode_to_private(inode);
-       if (inode_info->lower_file) {
-               struct dentry *lower_dentry =
-                       inode_info->lower_file->f_dentry;
-
-               BUG_ON(!lower_dentry);
-               if (lower_dentry->d_inode) {
-                       fput(inode_info->lower_file);
-                       inode_info->lower_file = NULL;
-               }
-       }
+       BUG_ON(inode_info->lower_file);
        ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
        call_rcu(&inode->i_rcu, ecryptfs_i_callback);
 }
index 0be344755c020e8de53d26ff89f60d8a4778cf91..4c6992d8f3ba1e3056645e805ddcb4c879d82f93 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/mmzone.h>
 #include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -39,14 +40,17 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */
  */
 static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
-static inline void *alloc_fdmem(unsigned int size)
+static void *alloc_fdmem(unsigned int size)
 {
-       void *data;
-
-       data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
-       if (data != NULL)
-               return data;
-
+       /*
+        * Very large allocations can stress page reclaim, so fall back to
+        * vmalloc() if the allocation size will be considered "large" by the VM.
+        */
+       if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+               void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
+               if (data != NULL)
+                       return data;
+       }
        return vmalloc(size);
 }
 
index c6ba49bd95b34136d04bae30b83342933c35ce7a..b32eb29a4e6ff4f8dd892b1af9ea74d712f148ee 100644 (file)
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                if (!inode)
                        return 0;
 
-               if (nd->flags & LOOKUP_RCU)
+               if (nd && (nd->flags & LOOKUP_RCU))
                        return -ECHILD;
 
                fc = get_fuse_conn(inode);
index c71995b111bf6f4347ffb313692c4ee66ff6f74e..0f5c4f9d5d62beee06937a8d0c98bd015f7dc5ee 100644 (file)
@@ -884,8 +884,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
        }
 
        brelse(dibh);
-       gfs2_trans_end(sdp);
 failed:
+       gfs2_trans_end(sdp);
        if (al) {
                gfs2_inplace_release(ip);
                gfs2_quota_unlock(ip);
index 5c356d09c321c10133afc7cf93aba2eddd1cb3c1..f789c5732b7c5fc695c7fdb97183402613dfd3c5 100644 (file)
@@ -1506,7 +1506,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
                inode = gfs2_inode_lookup(dir->i_sb, 
                                be16_to_cpu(dent->de_type),
                                be64_to_cpu(dent->de_inum.no_addr),
-                               be64_to_cpu(dent->de_inum.no_formal_ino));
+                               be64_to_cpu(dent->de_inum.no_formal_ino), 0);
                brelse(bh);
                return inode;
        }
index b2682e073eee0a593b1ab43c74291aa08e6af674..e48310885c48e8866c35647f7ea242e702df4ab2 100644 (file)
@@ -617,18 +617,51 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        return generic_file_aio_write(iocb, iov, nr_segs, pos);
 }
 
-static void empty_write_end(struct page *page, unsigned from,
-                          unsigned to)
+static int empty_write_end(struct page *page, unsigned from,
+                          unsigned to, int mode)
 {
-       struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+       struct inode *inode = page->mapping->host;
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct buffer_head *bh;
+       unsigned offset, blksize = 1 << inode->i_blkbits;
+       pgoff_t end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
 
        zero_user(page, from, to-from);
        mark_page_accessed(page);
 
-       if (!gfs2_is_writeback(ip))
-               gfs2_page_add_databufs(ip, page, from, to);
+       if (page->index < end_index || !(mode & FALLOC_FL_KEEP_SIZE)) {
+               if (!gfs2_is_writeback(ip))
+                       gfs2_page_add_databufs(ip, page, from, to);
+
+               block_commit_write(page, from, to);
+               return 0;
+       }
+
+       offset = 0;
+       bh = page_buffers(page);
+       while (offset < to) {
+               if (offset >= from) {
+                       set_buffer_uptodate(bh);
+                       mark_buffer_dirty(bh);
+                       clear_buffer_new(bh);
+                       write_dirty_buffer(bh, WRITE);
+               }
+               offset += blksize;
+               bh = bh->b_this_page;
+       }
 
-       block_commit_write(page, from, to);
+       offset = 0;
+       bh = page_buffers(page);
+       while (offset < to) {
+               if (offset >= from) {
+                       wait_on_buffer(bh);
+                       if (!buffer_uptodate(bh))
+                               return -EIO;
+               }
+               offset += blksize;
+               bh = bh->b_this_page;
+       }
+       return 0;
 }
 
 static int needs_empty_write(sector_t block, struct inode *inode)
@@ -643,7 +676,8 @@ static int needs_empty_write(sector_t block, struct inode *inode)
        return !buffer_mapped(&bh_map);
 }
 
-static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+static int write_empty_blocks(struct page *page, unsigned from, unsigned to,
+                             int mode)
 {
        struct inode *inode = page->mapping->host;
        unsigned start, end, next, blksize;
@@ -668,7 +702,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
                                                          gfs2_block_map);
                                if (unlikely(ret))
                                        return ret;
-                               empty_write_end(page, start, end);
+                               ret = empty_write_end(page, start, end, mode);
+                               if (unlikely(ret))
+                                       return ret;
                                end = 0;
                        }
                        start = next;
@@ -682,7 +718,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
                ret = __block_write_begin(page, start, end - start, gfs2_block_map);
                if (unlikely(ret))
                        return ret;
-               empty_write_end(page, start, end);
+               ret = empty_write_end(page, start, end, mode);
+               if (unlikely(ret))
+                       return ret;
        }
 
        return 0;
@@ -731,7 +769,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
 
                if (curr == end)
                        to = end_offset;
-               error = write_empty_blocks(page, from, to);
+               error = write_empty_blocks(page, from, to, mode);
                if (!error && offset + to > inode->i_size &&
                    !(mode & FALLOC_FL_KEEP_SIZE)) {
                        i_size_write(inode, offset + to);
index f07643e21bfa20a46a541aaf160d164784ddcbe4..7a4fb630a320ef2f4aea4816ecbceefee07ad96d 100644 (file)
@@ -93,14 +93,12 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp,
 
 static inline void spin_lock_bucket(unsigned int hash)
 {
-       struct hlist_bl_head *bl = &gl_hash_table[hash];
-       bit_spin_lock(0, (unsigned long *)bl);
+       hlist_bl_lock(&gl_hash_table[hash]);
 }
 
 static inline void spin_unlock_bucket(unsigned int hash)
 {
-       struct hlist_bl_head *bl = &gl_hash_table[hash];
-       __bit_spin_unlock(0, (unsigned long *)bl);
+       hlist_bl_unlock(&gl_hash_table[hash]);
 }
 
 static void gfs2_glock_dealloc(struct rcu_head *rcu)
index 3754e3cbf02bce2bf04b683bc9d36d48ec6a8bbe..25eeb2bcee47e4e10d289510718d7c08539a3acb 100644 (file)
@@ -385,6 +385,10 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl)
 static void iopen_go_callback(struct gfs2_glock *gl)
 {
        struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+
+       if (sdp->sd_vfs->s_flags & MS_RDONLY)
+               return;
 
        if (gl->gl_demote_state == LM_ST_UNLOCKED &&
            gl->gl_state == LM_ST_SHARED && ip) {
index 97d54a28776a1851a004b62a7b7ecc41a84d0e04..9134dcb894790adfd487101565703e4e24a37075 100644 (file)
@@ -40,37 +40,61 @@ struct gfs2_inum_range_host {
        u64 ir_length;
 };
 
+struct gfs2_skip_data {
+       u64 no_addr;
+       int skipped;
+       int non_block;
+};
+
 static int iget_test(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       u64 *no_addr = opaque;
+       struct gfs2_skip_data *data = opaque;
 
-       if (ip->i_no_addr == *no_addr)
+       if (ip->i_no_addr == data->no_addr) {
+               if (data->non_block &&
+                   inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
+                       data->skipped = 1;
+                       return 0;
+               }
                return 1;
-
+       }
        return 0;
 }
 
 static int iget_set(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       u64 *no_addr = opaque;
+       struct gfs2_skip_data *data = opaque;
 
-       inode->i_ino = (unsigned long)*no_addr;
-       ip->i_no_addr = *no_addr;
+       if (data->skipped)
+               return -ENOENT;
+       inode->i_ino = (unsigned long)(data->no_addr);
+       ip->i_no_addr = data->no_addr;
        return 0;
 }
 
 struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
 {
        unsigned long hash = (unsigned long)no_addr;
-       return ilookup5(sb, hash, iget_test, &no_addr);
+       struct gfs2_skip_data data;
+
+       data.no_addr = no_addr;
+       data.skipped = 0;
+       data.non_block = 0;
+       return ilookup5(sb, hash, iget_test, &data);
 }
 
-static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr,
+                              int non_block)
 {
+       struct gfs2_skip_data data;
        unsigned long hash = (unsigned long)no_addr;
-       return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
+
+       data.no_addr = no_addr;
+       data.skipped = 0;
+       data.non_block = non_block;
+       return iget5_locked(sb, hash, iget_test, iget_set, &data);
 }
 
 /**
@@ -111,19 +135,20 @@ static void gfs2_set_iop(struct inode *inode)
  * @sb: The super block
  * @no_addr: The inode number
  * @type: The type of the inode
+ * non_block: Can we block on inodes that are being freed?
  *
  * Returns: A VFS inode, or an error
  */
 
 struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
-                               u64 no_addr, u64 no_formal_ino)
+                               u64 no_addr, u64 no_formal_ino, int non_block)
 {
        struct inode *inode;
        struct gfs2_inode *ip;
        struct gfs2_glock *io_gl = NULL;
        int error;
 
-       inode = gfs2_iget(sb, no_addr);
+       inode = gfs2_iget(sb, no_addr, non_block);
        ip = GFS2_I(inode);
 
        if (!inode)
@@ -185,11 +210,12 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
 {
        struct super_block *sb = sdp->sd_vfs;
        struct gfs2_holder i_gh;
-       struct inode *inode;
+       struct inode *inode = NULL;
        int error;
 
+       /* Must not read in block until block type is verified */
        error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops,
-                                 LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+                                 LM_ST_EXCLUSIVE, GL_SKIP, &i_gh);
        if (error)
                return ERR_PTR(error);
 
@@ -197,7 +223,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
        if (error)
                goto fail;
 
-       inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0);
+       inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1);
        if (IS_ERR(inode))
                goto fail;
 
@@ -843,7 +869,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
                goto fail_gunlock2;
 
        inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
-                                 inum.no_formal_ino);
+                                 inum.no_formal_ino, 0);
        if (IS_ERR(inode))
                goto fail_gunlock2;
 
index 3e00a66e7cbd04c707ce22686647e5800c7621a4..099ca305e518d25c8251e5163456635087b26828 100644 (file)
@@ -97,7 +97,8 @@ err:
 }
 
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
-                                      u64 no_addr, u64 no_formal_ino);
+                                      u64 no_addr, u64 no_formal_ino,
+                                      int non_block);
 extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
                                         u64 *no_formal_ino,
                                         unsigned int blktype);
index 42ef24355afbdb112e366269d3835cc40b37cff6..d3c69eb91c74e29c05af120f3938bffb9ebb1d75 100644 (file)
@@ -430,7 +430,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
        struct dentry *dentry;
        struct inode *inode;
 
-       inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
+       inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0);
        if (IS_ERR(inode)) {
                fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode));
                return PTR_ERR(inode);
index cf930cd9664af9ca0c351e08c0d852f52c52417d..6fcae8469f6d76a178710ee2ece82108c8ec2ba1 100644 (file)
@@ -945,7 +945,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
                /* rgblk_search can return a block < goal, so we need to
                   keep it marching forward. */
                no_addr = block + rgd->rd_data0;
-               goal++;
+               goal = max(block + 1, goal + 1);
                if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked)
                        continue;
                if (no_addr == skip)
@@ -971,7 +971,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
                        found++;
 
                /* Limit reclaim to sensible number of tasks */
-               if (found > 2*NR_CPUS)
+               if (found > NR_CPUS)
                        return;
        }
 
index a4e23d68a39862f08848c8a7d19136c1d6bb881e..b9f28e66dad190af29b389b2830f1ff66efff024 100644 (file)
@@ -1318,15 +1318,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
 
 static void gfs2_evict_inode(struct inode *inode)
 {
-       struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+       struct super_block *sb = inode->i_sb;
+       struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
 
-       if (inode->i_nlink)
+       if (inode->i_nlink || (sb->s_flags & MS_RDONLY))
                goto out;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+       /* Must not read inode block until block type has been verified */
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
        if (unlikely(error)) {
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
                goto out;
@@ -1336,6 +1338,12 @@ static void gfs2_evict_inode(struct inode *inode)
        if (error)
                goto out_truncate;
 
+       if (test_bit(GIF_INVALID, &ip->i_flags)) {
+               error = gfs2_inode_refresh(ip);
+               if (error)
+                       goto out_truncate;
+       }
+
        ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
        gfs2_glock_dq_wait(&ip->i_iopen_gh);
        gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
index 0c39dc3ef7d71473a0a951612fd54e82a63cf3a2..56bd15c5bf6cffee6cdd2e36c379eeb42c22d604 100644 (file)
@@ -1,7 +1,6 @@
 config HPFS_FS
        tristate "OS/2 HPFS file system support"
        depends on BLOCK
-       depends on BROKEN || !PREEMPT
        help
          OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
          is the file system used for organizing files on OS/2 hard disk
index 5503e2c28910102bb0a2a22b97d8e2a7bf20cbad..7a5eb2c718c854206d6db419abe4ce7bc61d12c7 100644 (file)
@@ -8,8 +8,6 @@
 
 #include "hpfs_fn.h"
 
-static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);
-
 /*
  * Check if a sector is allocated in bitmap
  * This is really slow. Turned on only if chk==2
@@ -18,9 +16,9 @@ static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);
 static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
 {
        struct quad_buffer_head qbh;
-       unsigned *bmp;
+       u32 *bmp;
        if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail;
-       if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f)) & 1) {
+       if ((cpu_to_le32(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) {
                hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec);
                goto fail1;
        }
@@ -28,7 +26,7 @@ static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
        if (sec >= hpfs_sb(s)->sb_dirband_start && sec < hpfs_sb(s)->sb_dirband_start + hpfs_sb(s)->sb_dirband_size) {
                unsigned ssec = (sec - hpfs_sb(s)->sb_dirband_start) / 4;
                if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto fail;
-               if ((bmp[ssec >> 5] >> (ssec & 0x1f)) & 1) {
+               if ((le32_to_cpu(bmp[ssec >> 5]) >> (ssec & 0x1f)) & 1) {
                        hpfs_error(s, "sector '%s' - %08x not allocated in directory bitmap", msg, sec);
                        goto fail1;
                }
@@ -75,7 +73,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
                hpfs_error(s, "Bad allocation size: %d", n);
                return 0;
        }
-       lock_super(s);
        if (bs != ~0x3fff) {
                if (!(bmp = hpfs_map_bitmap(s, near >> 14, &qbh, "aib"))) goto uls;
        } else {
@@ -85,10 +82,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
                ret = bs + nr;
                goto rt;
        }
-       /*if (!tstbits(bmp, nr + n, n + forward)) {
-               ret = bs + nr + n;
-               goto rt;
-       }*/
        q = nr + n; b = 0;
        while ((a = tstbits(bmp, q, n + forward)) != 0) {
                q += a;
@@ -105,14 +98,14 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
                goto rt;
        }
        nr >>= 5;
-       /*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/
+       /*for (i = nr + 1; i != nr; i++, i &= 0x1ff) */
        i = nr;
        do {
-               if (!bmp[i]) goto cont;
-               if (n + forward >= 0x3f && bmp[i] != -1) goto cont;
+               if (!le32_to_cpu(bmp[i])) goto cont;
+               if (n + forward >= 0x3f && le32_to_cpu(bmp[i]) != 0xffffffff) goto cont;
                q = i<<5;
                if (i > 0) {
-                       unsigned k = bmp[i-1];
+                       unsigned k = le32_to_cpu(bmp[i-1]);
                        while (k & 0x80000000) {
                                q--; k <<= 1;
                        }
@@ -132,18 +125,17 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
        } while (i != nr);
        rt:
        if (ret) {
-               if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {
+               if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (le32_to_cpu(bmp[(ret & 0x3fff) >> 5]) | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {
                        hpfs_error(s, "Allocation doesn't work! Wanted %d, allocated at %08x", n, ret);
                        ret = 0;
                        goto b;
                }
-               bmp[(ret & 0x3fff) >> 5] &= ~(((1 << n) - 1) << (ret & 0x1f));
+               bmp[(ret & 0x3fff) >> 5] &= cpu_to_le32(~(((1 << n) - 1) << (ret & 0x1f)));
                hpfs_mark_4buffers_dirty(&qbh);
        }
        b:
        hpfs_brelse4(&qbh);
        uls:
-       unlock_super(s);
        return ret;
 }
 
@@ -155,7 +147,7 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
  *                             sectors
  */
 
-secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock)
+secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward)
 {
        secno sec;
        int i;
@@ -167,7 +159,6 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa
                forward = -forward;
                f_p = 1;
        }
-       if (lock) hpfs_lock_creation(s);
        n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14;
        if (near && near < sbi->sb_fs_size) {
                if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret;
@@ -214,18 +205,17 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa
        ret:
        if (sec && f_p) {
                for (i = 0; i < forward; i++) {
-                       if (!hpfs_alloc_if_possible_nolock(s, sec + i + 1)) {
+                       if (!hpfs_alloc_if_possible(s, sec + i + 1)) {
                                hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);
                                sec = 0;
                                break;
                        }
                }
        }
-       if (lock) hpfs_unlock_creation(s);
        return sec;
 }
 
-static secno alloc_in_dirband(struct super_block *s, secno near, int lock)
+static secno alloc_in_dirband(struct super_block *s, secno near)
 {
        unsigned nr = near;
        secno sec;
@@ -236,49 +226,35 @@ static secno alloc_in_dirband(struct super_block *s, secno near, int lock)
                nr = sbi->sb_dirband_start + sbi->sb_dirband_size - 4;
        nr -= sbi->sb_dirband_start;
        nr >>= 2;
-       if (lock) hpfs_lock_creation(s);
        sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0);
-       if (lock) hpfs_unlock_creation(s);
        if (!sec) return 0;
        return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;
 }
 
 /* Alloc sector if it's free */
 
-static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec)
+int hpfs_alloc_if_possible(struct super_block *s, secno sec)
 {
        struct quad_buffer_head qbh;
-       unsigned *bmp;
-       lock_super(s);
+       u32 *bmp;
        if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end;
-       if (bmp[(sec & 0x3fff) >> 5] & (1 << (sec & 0x1f))) {
-               bmp[(sec & 0x3fff) >> 5] &= ~(1 << (sec & 0x1f));
+       if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) {
+               bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
-               unlock_super(s);
                return 1;
        }
        hpfs_brelse4(&qbh);
        end:
-       unlock_super(s);
        return 0;
 }
 
-int hpfs_alloc_if_possible(struct super_block *s, secno sec)
-{
-       int r;
-       hpfs_lock_creation(s);
-       r = hpfs_alloc_if_possible_nolock(s, sec);
-       hpfs_unlock_creation(s);
-       return r;
-}
-
 /* Free sectors in bitmaps */
 
 void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
 {
        struct quad_buffer_head qbh;
-       unsigned *bmp;
+       u32 *bmp;
        struct hpfs_sb_info *sbi = hpfs_sb(s);
        /*printk("2 - ");*/
        if (!n) return;
@@ -286,26 +262,22 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
                hpfs_error(s, "Trying to free reserved sector %08x", sec);
                return;
        }
-       lock_super(s);
        sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n;
        if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff;
        new_map:
        if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) {
-               unlock_super(s);
                return;
        }       
        new_tst:
-       if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f) & 1)) {
+       if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f) & 1)) {
                hpfs_error(s, "sector %08x not allocated", sec);
                hpfs_brelse4(&qbh);
-               unlock_super(s);
                return;
        }
-       bmp[(sec & 0x3fff) >> 5] |= 1 << (sec & 0x1f);
+       bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f));
        if (!--n) {
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
-               unlock_super(s);
                return;
        }       
        if (!(++sec & 0x3fff)) {
@@ -327,13 +299,13 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)
        int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14;
        int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;
        int i, j;
-       unsigned *bmp;
+       u32 *bmp;
        struct quad_buffer_head qbh;
        if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
                for (j = 0; j < 512; j++) {
                        unsigned k;
-                       if (!bmp[j]) continue;
-                       for (k = bmp[j]; k; k >>= 1) if (k & 1) if (!--n) {
+                       if (!le32_to_cpu(bmp[j])) continue;
+                       for (k = le32_to_cpu(bmp[j]); k; k >>= 1) if (k & 1) if (!--n) {
                                hpfs_brelse4(&qbh);
                                return 0;
                        }
@@ -352,10 +324,10 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)
        chk_bmp:
        if (bmp) {
                for (j = 0; j < 512; j++) {
-                       unsigned k;
-                       if (!bmp[j]) continue;
+                       u32 k;
+                       if (!le32_to_cpu(bmp[j])) continue;
                        for (k = 0xf; k; k <<= 4)
-                               if ((bmp[j] & k) == k) {
+                               if ((le32_to_cpu(bmp[j]) & k) == k) {
                                        if (!--n) {
                                                hpfs_brelse4(&qbh);
                                                return 0;
@@ -379,44 +351,40 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)
                hpfs_free_sectors(s, dno, 4);
        } else {
                struct quad_buffer_head qbh;
-               unsigned *bmp;
+               u32 *bmp;
                unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4;
-               lock_super(s);
                if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
-                       unlock_super(s);
                        return;
                }
-               bmp[ssec >> 5] |= 1 << (ssec & 0x1f);
+               bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
-               unlock_super(s);
        }
 }
 
 struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near,
-                        dnode_secno *dno, struct quad_buffer_head *qbh,
-                        int lock)
+                        dnode_secno *dno, struct quad_buffer_head *qbh)
 {
        struct dnode *d;
        if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) {
-               if (!(*dno = alloc_in_dirband(s, near, lock)))
-                       if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL;
+               if (!(*dno = alloc_in_dirband(s, near)))
+                       if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;
        } else {
-               if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock)))
-                       if (!(*dno = alloc_in_dirband(s, near, lock))) return NULL;
+               if (!(*dno = hpfs_alloc_sector(s, near, 4, 0)))
+                       if (!(*dno = alloc_in_dirband(s, near))) return NULL;
        }
        if (!(d = hpfs_get_4sectors(s, *dno, qbh))) {
                hpfs_free_dnode(s, *dno);
                return NULL;
        }
        memset(d, 0, 2048);
-       d->magic = DNODE_MAGIC;
-       d->first_free = 52;
+       d->magic = cpu_to_le32(DNODE_MAGIC);
+       d->first_free = cpu_to_le32(52);
        d->dirent[0] = 32;
        d->dirent[2] = 8;
        d->dirent[30] = 1;
        d->dirent[31] = 255;
-       d->self = *dno;
+       d->self = cpu_to_le32(*dno);
        return d;
 }
 
@@ -424,16 +392,16 @@ struct fnode *hpfs_alloc_fnode(struct super_block *s, secno near, fnode_secno *f
                          struct buffer_head **bh)
 {
        struct fnode *f;
-       if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD, 1))) return NULL;
+       if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD))) return NULL;
        if (!(f = hpfs_get_sector(s, *fno, bh))) {
                hpfs_free_sectors(s, *fno, 1);
                return NULL;
        }       
        memset(f, 0, 512);
-       f->magic = FNODE_MAGIC;
-       f->ea_offs = 0xc4;
+       f->magic = cpu_to_le32(FNODE_MAGIC);
+       f->ea_offs = cpu_to_le16(0xc4);
        f->btree.n_free_nodes = 8;
-       f->btree.first_free = 8;
+       f->btree.first_free = cpu_to_le16(8);
        return f;
 }
 
@@ -441,16 +409,16 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a
                          struct buffer_head **bh)
 {
        struct anode *a;
-       if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD, 1))) return NULL;
+       if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD))) return NULL;
        if (!(a = hpfs_get_sector(s, *ano, bh))) {
                hpfs_free_sectors(s, *ano, 1);
                return NULL;
        }
        memset(a, 0, 512);
-       a->magic = ANODE_MAGIC;
-       a->self = *ano;
+       a->magic = cpu_to_le32(ANODE_MAGIC);
+       a->self = cpu_to_le32(*ano);
        a->btree.n_free_nodes = 40;
        a->btree.n_used_nodes = 0;
-       a->btree.first_free = 8;
+       a->btree.first_free = cpu_to_le16(8);
        return a;
 }
index 6a2f04bf3df007249047523e10a098fd2b43c603..08b503e8ed29ec610a098cb9658e1a2ecaa1779c 100644 (file)
@@ -22,8 +22,8 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
        if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
        if (btree->internal) {
                for (i = 0; i < btree->n_used_nodes; i++)
-                       if (btree->u.internal[i].file_secno > sec) {
-                               a = btree->u.internal[i].down;
+                       if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
+                               a = le32_to_cpu(btree->u.internal[i].down);
                                brelse(bh);
                                if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;
                                btree = &anode->btree;
@@ -34,18 +34,18 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
                return -1;
        }
        for (i = 0; i < btree->n_used_nodes; i++)
-               if (btree->u.external[i].file_secno <= sec &&
-                   btree->u.external[i].file_secno + btree->u.external[i].length > sec) {
-                       a = btree->u.external[i].disk_secno + sec - btree->u.external[i].file_secno;
+               if (le32_to_cpu(btree->u.external[i].file_secno) <= sec &&
+                   le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > sec) {
+                       a = le32_to_cpu(btree->u.external[i].disk_secno) + sec - le32_to_cpu(btree->u.external[i].file_secno);
                        if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, a, 1, "data")) {
                                brelse(bh);
                                return -1;
                        }
                        if (inode) {
                                struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
-                               hpfs_inode->i_file_sec = btree->u.external[i].file_secno;
-                               hpfs_inode->i_disk_sec = btree->u.external[i].disk_secno;
-                               hpfs_inode->i_n_secs = btree->u.external[i].length;
+                               hpfs_inode->i_file_sec = le32_to_cpu(btree->u.external[i].file_secno);
+                               hpfs_inode->i_disk_sec = le32_to_cpu(btree->u.external[i].disk_secno);
+                               hpfs_inode->i_n_secs = le32_to_cpu(btree->u.external[i].length);
                        }
                        brelse(bh);
                        return a;
@@ -83,8 +83,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                return -1;
        }
        if (btree->internal) {
-               a = btree->u.internal[n].down;
-               btree->u.internal[n].file_secno = -1;
+               a = le32_to_cpu(btree->u.internal[n].down);
+               btree->u.internal[n].file_secno = cpu_to_le32(-1);
                mark_buffer_dirty(bh);
                brelse(bh);
                if (hpfs_sb(s)->sb_chk)
@@ -94,15 +94,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                goto go_down;
        }
        if (n >= 0) {
-               if (btree->u.external[n].file_secno + btree->u.external[n].length != fsecno) {
+               if (le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length) != fsecno) {
                        hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x",
-                               btree->u.external[n].file_secno + btree->u.external[n].length, fsecno,
+                               le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length), fsecno,
                                fnod?'f':'a', node);
                        brelse(bh);
                        return -1;
                }
-               if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) {
-                       btree->u.external[n].length++;
+               if (hpfs_alloc_if_possible(s, se = le32_to_cpu(btree->u.external[n].disk_secno) + le32_to_cpu(btree->u.external[n].length))) {
+                       btree->u.external[n].length = cpu_to_le32(le32_to_cpu(btree->u.external[n].length) + 1);
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        return se;
@@ -115,20 +115,20 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                }
                se = !fnod ? node : (node + 16384) & ~16383;
        }       
-       if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) {
+       if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M))) {
                brelse(bh);
                return -1;
        }
-       fs = n < 0 ? 0 : btree->u.external[n].file_secno + btree->u.external[n].length;
+       fs = n < 0 ? 0 : le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length);
        if (!btree->n_free_nodes) {
-               up = a != node ? anode->up : -1;
+               up = a != node ? le32_to_cpu(anode->up) : -1;
                if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) {
                        brelse(bh);
                        hpfs_free_sectors(s, se, 1);
                        return -1;
                }
                if (a == node && fnod) {
-                       anode->up = node;
+                       anode->up = cpu_to_le32(node);
                        anode->btree.fnode_parent = 1;
                        anode->btree.n_used_nodes = btree->n_used_nodes;
                        anode->btree.first_free = btree->first_free;
@@ -137,9 +137,9 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                        btree->internal = 1;
                        btree->n_free_nodes = 11;
                        btree->n_used_nodes = 1;
-                       btree->first_free = (char *)&(btree->u.internal[1]) - (char *)btree;
-                       btree->u.internal[0].file_secno = -1;
-                       btree->u.internal[0].down = na;
+                       btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree);
+                       btree->u.internal[0].file_secno = cpu_to_le32(-1);
+                       btree->u.internal[0].down = cpu_to_le32(na);
                        mark_buffer_dirty(bh);
                } else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) {
                        brelse(bh);
@@ -153,15 +153,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                btree = &anode->btree;
        }
        btree->n_free_nodes--; n = btree->n_used_nodes++;
-       btree->first_free += 12;
-       btree->u.external[n].disk_secno = se;
-       btree->u.external[n].file_secno = fs;
-       btree->u.external[n].length = 1;
+       btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 12);
+       btree->u.external[n].disk_secno = cpu_to_le32(se);
+       btree->u.external[n].file_secno = cpu_to_le32(fs);
+       btree->u.external[n].length = cpu_to_le32(1);
        mark_buffer_dirty(bh);
        brelse(bh);
        if ((a == node && fnod) || na == -1) return se;
        c2 = 0;
-       while (up != -1) {
+       while (up != (anode_secno)-1) {
                struct anode *new_anode;
                if (hpfs_sb(s)->sb_chk)
                        if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1;
@@ -174,47 +174,47 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                }
                if (btree->n_free_nodes) {
                        btree->n_free_nodes--; n = btree->n_used_nodes++;
-                       btree->first_free += 8;
-                       btree->u.internal[n].file_secno = -1;
-                       btree->u.internal[n].down = na;
-                       btree->u.internal[n-1].file_secno = fs;
+                       btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 8);
+                       btree->u.internal[n].file_secno = cpu_to_le32(-1);
+                       btree->u.internal[n].down = cpu_to_le32(na);
+                       btree->u.internal[n-1].file_secno = cpu_to_le32(fs);
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        brelse(bh2);
                        hpfs_free_sectors(s, ra, 1);
                        if ((anode = hpfs_map_anode(s, na, &bh))) {
-                               anode->up = up;
+                               anode->up = cpu_to_le32(up);
                                anode->btree.fnode_parent = up == node && fnod;
                                mark_buffer_dirty(bh);
                                brelse(bh);
                        }
                        return se;
                }
-               up = up != node ? anode->up : -1;
-               btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1;
+               up = up != node ? le32_to_cpu(anode->up) : -1;
+               btree->u.internal[btree->n_used_nodes - 1].file_secno = cpu_to_le32(/*fs*/-1);
                mark_buffer_dirty(bh);
                brelse(bh);
                a = na;
                if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {
                        anode = new_anode;
-                       /*anode->up = up != -1 ? up : ra;*/
+                       /*anode->up = cpu_to_le32(up != -1 ? up : ra);*/
                        anode->btree.internal = 1;
                        anode->btree.n_used_nodes = 1;
                        anode->btree.n_free_nodes = 59;
-                       anode->btree.first_free = 16;
-                       anode->btree.u.internal[0].down = a;
-                       anode->btree.u.internal[0].file_secno = -1;
+                       anode->btree.first_free = cpu_to_le16(16);
+                       anode->btree.u.internal[0].down = cpu_to_le32(a);
+                       anode->btree.u.internal[0].file_secno = cpu_to_le32(-1);
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        if ((anode = hpfs_map_anode(s, a, &bh))) {
-                               anode->up = na;
+                               anode->up = cpu_to_le32(na);
                                mark_buffer_dirty(bh);
                                brelse(bh);
                        }
                } else na = a;
        }
        if ((anode = hpfs_map_anode(s, na, &bh))) {
-               anode->up = node;
+               anode->up = cpu_to_le32(node);
                if (fnod) anode->btree.fnode_parent = 1;
                mark_buffer_dirty(bh);
                brelse(bh);
@@ -232,14 +232,14 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                }
                btree = &fnode->btree;
        }
-       ranode->up = node;
-       memcpy(&ranode->btree, btree, btree->first_free);
+       ranode->up = cpu_to_le32(node);
+       memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
        if (fnod) ranode->btree.fnode_parent = 1;
        ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
        if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
                struct anode *unode;
-               if ((unode = hpfs_map_anode(s, ranode->u.internal[n].down, &bh1))) {
-                       unode->up = ra;
+               if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
+                       unode->up = cpu_to_le32(ra);
                        unode->btree.fnode_parent = 0;
                        mark_buffer_dirty(bh1);
                        brelse(bh1);
@@ -248,11 +248,11 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
        btree->internal = 1;
        btree->n_free_nodes = fnod ? 10 : 58;
        btree->n_used_nodes = 2;
-       btree->first_free = (char *)&btree->u.internal[2] - (char *)btree;
-       btree->u.internal[0].file_secno = fs;
-       btree->u.internal[0].down = ra;
-       btree->u.internal[1].file_secno = -1;
-       btree->u.internal[1].down = na;
+       btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree);
+       btree->u.internal[0].file_secno = cpu_to_le32(fs);
+       btree->u.internal[0].down = cpu_to_le32(ra);
+       btree->u.internal[1].file_secno = cpu_to_le32(-1);
+       btree->u.internal[1].down = cpu_to_le32(na);
        mark_buffer_dirty(bh);
        brelse(bh);
        mark_buffer_dirty(bh2);
@@ -279,7 +279,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
        go_down:
        d2 = 0;
        while (btree1->internal) {
-               ano = btree1->u.internal[pos].down;
+               ano = le32_to_cpu(btree1->u.internal[pos].down);
                if (level) brelse(bh);
                if (hpfs_sb(s)->sb_chk)
                        if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1"))
@@ -290,7 +290,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
                pos = 0;
        }
        for (i = 0; i < btree1->n_used_nodes; i++)
-               hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length);
+               hpfs_free_sectors(s, le32_to_cpu(btree1->u.external[i].disk_secno), le32_to_cpu(btree1->u.external[i].length));
        go_up:
        if (!level) return;
        brelse(bh);
@@ -298,13 +298,13 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
                if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return;
        hpfs_free_sectors(s, ano, 1);
        oano = ano;
-       ano = anode->up;
+       ano = le32_to_cpu(anode->up);
        if (--level) {
                if (!(anode = hpfs_map_anode(s, ano, &bh))) return;
                btree1 = &anode->btree;
        } else btree1 = btree;
        for (i = 0; i < btree1->n_used_nodes; i++) {
-               if (btree1->u.internal[i].down == oano) {
+               if (le32_to_cpu(btree1->u.internal[i].down) == oano) {
                        if ((pos = i + 1) < btree1->n_used_nodes)
                                goto go_down;
                        else
@@ -411,7 +411,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
                if (fno) {
                        btree->n_free_nodes = 8;
                        btree->n_used_nodes = 0;
-                       btree->first_free = 8;
+                       btree->first_free = cpu_to_le16(8);
                        btree->internal = 0;
                        mark_buffer_dirty(bh);
                } else hpfs_free_sectors(s, f, 1);
@@ -421,22 +421,22 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
        while (btree->internal) {
                nodes = btree->n_used_nodes + btree->n_free_nodes;
                for (i = 0; i < btree->n_used_nodes; i++)
-                       if (btree->u.internal[i].file_secno >= secs) goto f;
+                       if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
                brelse(bh);
                hpfs_error(s, "internal btree %08x doesn't end with -1", node);
                return;
                f:
                for (j = i + 1; j < btree->n_used_nodes; j++)
-                       hpfs_ea_remove(s, btree->u.internal[j].down, 1, 0);
+                       hpfs_ea_remove(s, le32_to_cpu(btree->u.internal[j].down), 1, 0);
                btree->n_used_nodes = i + 1;
                btree->n_free_nodes = nodes - btree->n_used_nodes;
-               btree->first_free = 8 + 8 * btree->n_used_nodes;
+               btree->first_free = cpu_to_le16(8 + 8 * btree->n_used_nodes);
                mark_buffer_dirty(bh);
-               if (btree->u.internal[i].file_secno == secs) {
+               if (btree->u.internal[i].file_secno == cpu_to_le32(secs)) {
                        brelse(bh);
                        return;
                }
-               node = btree->u.internal[i].down;
+               node = le32_to_cpu(btree->u.internal[i].down);
                brelse(bh);
                if (hpfs_sb(s)->sb_chk)
                        if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree"))
@@ -446,25 +446,25 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
        }       
        nodes = btree->n_used_nodes + btree->n_free_nodes;
        for (i = 0; i < btree->n_used_nodes; i++)
-               if (btree->u.external[i].file_secno + btree->u.external[i].length >= secs) goto ff;
+               if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) >= secs) goto ff;
        brelse(bh);
        return;
        ff:
-       if (secs <= btree->u.external[i].file_secno) {
+       if (secs <= le32_to_cpu(btree->u.external[i].file_secno)) {
                hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs);
                if (i) i--;
        }
-       else if (btree->u.external[i].file_secno + btree->u.external[i].length > secs) {
-               hpfs_free_sectors(s, btree->u.external[i].disk_secno + secs -
-                       btree->u.external[i].file_secno, btree->u.external[i].length
-                       - secs + btree->u.external[i].file_secno); /* I hope gcc optimizes this :-) */
-               btree->u.external[i].length = secs - btree->u.external[i].file_secno;
+       else if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > secs) {
+               hpfs_free_sectors(s, le32_to_cpu(btree->u.external[i].disk_secno) + secs -
+                       le32_to_cpu(btree->u.external[i].file_secno), le32_to_cpu(btree->u.external[i].length)
+                       - secs + le32_to_cpu(btree->u.external[i].file_secno)); /* I hope gcc optimizes this :-) */
+               btree->u.external[i].length = cpu_to_le32(secs - le32_to_cpu(btree->u.external[i].file_secno));
        }
        for (j = i + 1; j < btree->n_used_nodes; j++)
-               hpfs_free_sectors(s, btree->u.external[j].disk_secno, btree->u.external[j].length);
+               hpfs_free_sectors(s, le32_to_cpu(btree->u.external[j].disk_secno), le32_to_cpu(btree->u.external[j].length));
        btree->n_used_nodes = i + 1;
        btree->n_free_nodes = nodes - btree->n_used_nodes;
-       btree->first_free = 8 + 12 * btree->n_used_nodes;
+       btree->first_free = cpu_to_le16(8 + 12 * btree->n_used_nodes);
        mark_buffer_dirty(bh);
        brelse(bh);
 }
@@ -480,12 +480,12 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno)
        struct extended_attribute *ea_end;
        if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return;
        if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree);
-       else hpfs_remove_dtree(s, fnode->u.external[0].disk_secno);
+       else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno));
        ea_end = fnode_end_ea(fnode);
        for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
                if (ea->indirect)
                        hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
-       hpfs_ea_ext_remove(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l);
+       hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l));
        brelse(bh);
        hpfs_free_sectors(s, fno, 1);
 }
index 793cb9d943d21a70584958c27fba6b2f97b37f93..9ecde27d1e297ed3d42a742352f469f1bf2dfb9a 100644 (file)
@@ -9,22 +9,6 @@
 #include <linux/slab.h>
 #include "hpfs_fn.h"
 
-void hpfs_lock_creation(struct super_block *s)
-{
-#ifdef DEBUG_LOCKS
-       printk("lock creation\n");
-#endif
-       mutex_lock(&hpfs_sb(s)->hpfs_creation_de);
-}
-
-void hpfs_unlock_creation(struct super_block *s)
-{
-#ifdef DEBUG_LOCKS
-       printk("unlock creation\n");
-#endif
-       mutex_unlock(&hpfs_sb(s)->hpfs_creation_de);
-}
-
 /* Map a sector into a buffer and return pointers to it and to the buffer. */
 
 void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
@@ -32,6 +16,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
 {
        struct buffer_head *bh;
 
+       hpfs_lock_assert(s);
+
        cond_resched();
 
        *bhp = bh = sb_bread(s, secno);
@@ -50,6 +36,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
        struct buffer_head *bh;
        /*return hpfs_map_sector(s, secno, bhp, 0);*/
 
+       hpfs_lock_assert(s);
+
        cond_resched();
 
        if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
@@ -70,6 +58,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
        struct buffer_head *bh;
        char *data;
 
+       hpfs_lock_assert(s);
+
        cond_resched();
 
        if (secno & 3) {
@@ -125,6 +115,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
 {
        cond_resched();
 
+       hpfs_lock_assert(s);
+
        if (secno & 3) {
                printk("HPFS: hpfs_get_4sectors: unaligned read\n");
                return NULL;
index b3d7c0ddb60971e2cb4217afb0bf22d4683c2988..f46ae025bfb58bc172716efcb66772add1daac43 100644 (file)
@@ -88,9 +88,9 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
                                        (unsigned long)inode->i_ino);
                }
-               if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) {
+               if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {
                        e = 1;
-                       hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, fno->u.external[0].disk_secno);
+                       hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno));
                }
                brelse(bh);
                if (e) {
@@ -156,7 +156,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        goto again;
                }
                tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
-               if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
+               if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) {
                        filp->f_pos = old_pos;
                        if (tempname != de->name) kfree(tempname);
                        hpfs_brelse4(&qbh);
@@ -221,7 +221,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
         * Get inode number, what we're after.
         */
 
-       ino = de->fnode;
+       ino = le32_to_cpu(de->fnode);
 
        /*
         * Go find or make an inode.
@@ -236,7 +236,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
                hpfs_init_inode(result);
                if (de->directory)
                        hpfs_read_inode(result);
-               else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas)
+               else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)
                        hpfs_read_inode(result);
                else {
                        result->i_mode |= S_IFREG;
@@ -250,8 +250,6 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
        hpfs_result = hpfs_i(result);
        if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
 
-       hpfs_decide_conv(result, name, len);
-
        if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
                hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
                goto bail1;
@@ -263,19 +261,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
         */
 
        if (!result->i_ctime.tv_sec) {
-               if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date)))
+               if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date))))
                        result->i_ctime.tv_sec = 1;
                result->i_ctime.tv_nsec = 0;
-               result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date);
+               result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date));
                result->i_mtime.tv_nsec = 0;
-               result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date);
+               result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date));
                result->i_atime.tv_nsec = 0;
-               hpfs_result->i_ea_size = de->ea_size;
+               hpfs_result->i_ea_size = le32_to_cpu(de->ea_size);
                if (!hpfs_result->i_ea_mode && de->read_only)
                        result->i_mode &= ~0222;
                if (!de->directory) {
                        if (result->i_size == -1) {
-                               result->i_size = de->file_size;
+                               result->i_size = le32_to_cpu(de->file_size);
                                result->i_data.a_ops = &hpfs_aops;
                                hpfs_i(result)->mmu_private = result->i_size;
                        /*
index 9b2ffadfc8c42dd9a39f86a0bdedb6a8dbbd0df5..1e0e2ac30fd3be93f8e5b7a97618f19a52220ec4 100644 (file)
@@ -14,11 +14,11 @@ static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde)
        struct hpfs_dirent *de_end = dnode_end_de(d);
        int i = 1;
        for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
-               if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i;
+               if (de == fde) return ((loff_t) le32_to_cpu(d->self) << 4) | (loff_t)i;
                i++;
        }
        printk("HPFS: get_pos: not_found\n");
-       return ((loff_t)d->self << 4) | (loff_t)1;
+       return ((loff_t)le32_to_cpu(d->self) << 4) | (loff_t)1;
 }
 
 void hpfs_add_pos(struct inode *inode, loff_t *pos)
@@ -130,29 +130,30 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno
 {
        struct hpfs_dirent *de;
        if (!(de = dnode_last_de(d))) {
-               hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self);
+               hpfs_error(s, "set_last_pointer: empty dnode %08x", le32_to_cpu(d->self));
                return;
        }
        if (hpfs_sb(s)->sb_chk) {
                if (de->down) {
                        hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x",
-                               d->self, de_down_pointer(de));
+                               le32_to_cpu(d->self), de_down_pointer(de));
                        return;
                }
-               if (de->length != 32) {
-                       hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self);
+               if (le16_to_cpu(de->length) != 32) {
+                       hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", le32_to_cpu(d->self));
                        return;
                }
        }
        if (ptr) {
-               if ((d->first_free += 4) > 2048) {
-                       hpfs_error(s,"set_last_pointer: too long dnode %08x", d->self);
-                       d->first_free -= 4;
+               d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + 4);
+               if (le32_to_cpu(d->first_free) > 2048) {
+                       hpfs_error(s, "set_last_pointer: too long dnode %08x", le32_to_cpu(d->self));
+                       d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - 4);
                        return;
                }
-               de->length = 36;
+               de->length = cpu_to_le16(36);
                de->down = 1;
-               *(dnode_secno *)((char *)de + 32) = ptr;
+               *(dnode_secno *)((char *)de + 32) = cpu_to_le32(ptr);
        }
 }
 
@@ -168,7 +169,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
        for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
                int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last);
                if (!c) {
-                       hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self);
+                       hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, le32_to_cpu(d->self));
                        return NULL;
                }
                if (c < 0) break;
@@ -176,15 +177,14 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
        memmove((char *)de + d_size, de, (char *)de_end - (char *)de);
        memset(de, 0, d_size);
        if (down_ptr) {
-               *(int *)((char *)de + d_size - 4) = down_ptr;
+               *(dnode_secno *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr);
                de->down = 1;
        }
-       de->length = d_size;
-       if (down_ptr) de->down = 1;
+       de->length = cpu_to_le16(d_size);
        de->not_8x3 = hpfs_is_name_long(name, namelen);
        de->namelen = namelen;
        memcpy(de->name, name, namelen);
-       d->first_free += d_size;
+       d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + d_size);
        return de;
 }
 
@@ -194,25 +194,25 @@ static void hpfs_delete_de(struct super_block *s, struct dnode *d,
                           struct hpfs_dirent *de)
 {
        if (de->last) {
-               hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self);
+               hpfs_error(s, "attempt to delete last dirent in dnode %08x", le32_to_cpu(d->self));
                return;
        }
-       d->first_free -= de->length;
-       memmove(de, de_next_de(de), d->first_free + (char *)d - (char *)de);
+       d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - le16_to_cpu(de->length));
+       memmove(de, de_next_de(de), le32_to_cpu(d->first_free) + (char *)d - (char *)de);
 }
 
 static void fix_up_ptrs(struct super_block *s, struct dnode *d)
 {
        struct hpfs_dirent *de;
        struct hpfs_dirent *de_end = dnode_end_de(d);
-       dnode_secno dno = d->self;
+       dnode_secno dno = le32_to_cpu(d->self);
        for (de = dnode_first_de(d); de < de_end; de = de_next_de(de))
                if (de->down) {
                        struct quad_buffer_head qbh;
                        struct dnode *dd;
                        if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) {
-                               if (dd->up != dno || dd->root_dnode) {
-                                       dd->up = dno;
+                               if (le32_to_cpu(dd->up) != dno || dd->root_dnode) {
+                                       dd->up = cpu_to_le32(dno);
                                        dd->root_dnode = 0;
                                        hpfs_mark_4buffers_dirty(&qbh);
                                }
@@ -262,7 +262,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
                        kfree(nname);
                        return 1;
                }
-       if (d->first_free + de_size(namelen, down_ptr) <= 2048) {
+       if (le32_to_cpu(d->first_free) + de_size(namelen, down_ptr) <= 2048) {
                loff_t t;
                copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de);
                t = get_pos(d, de);
@@ -286,11 +286,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
                kfree(nname);
                return 1;
        }       
-       memcpy(nd, d, d->first_free);
+       memcpy(nd, d, le32_to_cpu(d->first_free));
        copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de);
        for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1);
        h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10;
-       if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1, 0))) {
+       if (!(ad = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &adno, &qbh1))) {
                hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
                hpfs_brelse4(&qbh);
                kfree(nd);
@@ -313,20 +313,21 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
        down_ptr = adno;
        set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
        de = de_next_de(de);
-       memmove((char *)nd + 20, de, nd->first_free + (char *)nd - (char *)de);
-       nd->first_free -= (char *)de - (char *)nd - 20;
-       memcpy(d, nd, nd->first_free);
+       memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de);
+       nd->first_free = cpu_to_le32(le32_to_cpu(nd->first_free) - ((char *)de - (char *)nd - 20));
+       memcpy(d, nd, le32_to_cpu(nd->first_free));
        for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos);
        fix_up_ptrs(i->i_sb, ad);
        if (!d->root_dnode) {
-               dno = ad->up = d->up;
+               ad->up = d->up;
+               dno = le32_to_cpu(ad->up);
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
                hpfs_mark_4buffers_dirty(&qbh1);
                hpfs_brelse4(&qbh1);
                goto go_up;
        }
-       if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2, 0))) {
+       if (!(rd = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &rdno, &qbh2))) {
                hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
                hpfs_brelse4(&qbh);
                hpfs_brelse4(&qbh1);
@@ -338,7 +339,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
        i->i_blocks += 4;
        rd->root_dnode = 1;
        rd->up = d->up;
-       if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) {
+       if (!(fnode = hpfs_map_fnode(i->i_sb, le32_to_cpu(d->up), &bh))) {
                hpfs_free_dnode(i->i_sb, rdno);
                hpfs_brelse4(&qbh);
                hpfs_brelse4(&qbh1);
@@ -347,10 +348,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
                kfree(nname);
                return 1;
        }
-       fnode->u.external[0].disk_secno = rdno;
+       fnode->u.external[0].disk_secno = cpu_to_le32(rdno);
        mark_buffer_dirty(bh);
        brelse(bh);
-       d->up = ad->up = hpfs_i(i)->i_dno = rdno;
+       hpfs_i(i)->i_dno = rdno;
+       d->up = ad->up = cpu_to_le32(rdno);
        d->root_dnode = ad->root_dnode = 0;
        hpfs_mark_4buffers_dirty(&qbh);
        hpfs_brelse4(&qbh);
@@ -373,7 +375,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
 
 int hpfs_add_dirent(struct inode *i,
                    const unsigned char *name, unsigned namelen,
-                   struct hpfs_dirent *new_de, int cdepth)
+                   struct hpfs_dirent *new_de)
 {
        struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
        struct dnode *d;
@@ -403,7 +405,6 @@ int hpfs_add_dirent(struct inode *i,
                }
        }
        hpfs_brelse4(&qbh);
-       if (!cdepth) hpfs_lock_creation(i->i_sb);
        if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) {
                c = 1;
                goto ret;
@@ -411,7 +412,6 @@ int hpfs_add_dirent(struct inode *i,
        i->i_version++;
        c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0);
        ret:
-       if (!cdepth) hpfs_unlock_creation(i->i_sb);
        return c;
 }
 
@@ -437,9 +437,9 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
                                return 0;
                if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0;
                if (hpfs_sb(i->i_sb)->sb_chk) {
-                       if (dnode->up != chk_up) {
+                       if (le32_to_cpu(dnode->up) != chk_up) {
                                hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x",
-                                       dno, chk_up, dnode->up);
+                                       dno, chk_up, le32_to_cpu(dnode->up));
                                hpfs_brelse4(&qbh);
                                return 0;
                        }
@@ -455,7 +455,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
                hpfs_brelse4(&qbh);
        }
        while (!(de = dnode_pre_last_de(dnode))) {
-               dnode_secno up = dnode->up;
+               dnode_secno up = le32_to_cpu(dnode->up);
                hpfs_brelse4(&qbh);
                hpfs_free_dnode(i->i_sb, dno);
                i->i_size -= 2048;
@@ -474,8 +474,8 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
                        hpfs_brelse4(&qbh);
                        return 0;
                }
-               dnode->first_free -= 4;
-               de->length -= 4;
+               dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
+               de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
                de->down = 0;
                hpfs_mark_4buffers_dirty(&qbh);
                dno = up;
@@ -483,12 +483,12 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
        t = get_pos(dnode, de);
        for_all_poss(i, hpfs_pos_subst, t, 4);
        for_all_poss(i, hpfs_pos_subst, t + 1, 5);
-       if (!(nde = kmalloc(de->length, GFP_NOFS))) {
+       if (!(nde = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) {
                hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted");
                hpfs_brelse4(&qbh);
                return 0;
        }
-       memcpy(nde, de, de->length);
+       memcpy(nde, de, le16_to_cpu(de->length));
        ddno = de->down ? de_down_pointer(de) : 0;
        hpfs_delete_de(i->i_sb, dnode, de);
        set_last_pointer(i->i_sb, dnode, ddno);
@@ -517,11 +517,11 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
        try_it_again:
        if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return;
        if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return;
-       if (dnode->first_free > 56) goto end;
-       if (dnode->first_free == 52 || dnode->first_free == 56) {
+       if (le32_to_cpu(dnode->first_free) > 56) goto end;
+       if (le32_to_cpu(dnode->first_free) == 52 || le32_to_cpu(dnode->first_free) == 56) {
                struct hpfs_dirent *de_end;
                int root = dnode->root_dnode;
-               up = dnode->up;
+               up = le32_to_cpu(dnode->up);
                de = dnode_first_de(dnode);
                down = de->down ? de_down_pointer(de) : 0;
                if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) {
@@ -545,13 +545,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                                return;
                            }
                        if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
-                               d1->up = up;
+                               d1->up = cpu_to_le32(up);
                                d1->root_dnode = 1;
                                hpfs_mark_4buffers_dirty(&qbh1);
                                hpfs_brelse4(&qbh1);
                        }
                        if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) {
-                               fnode->u.external[0].disk_secno = down;
+                               fnode->u.external[0].disk_secno = cpu_to_le32(down);
                                mark_buffer_dirty(bh);
                                brelse(bh);
                        }
@@ -570,22 +570,22 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p);
                if (!down) {
                        de->down = 0;
-                       de->length -= 4;
-                       dnode->first_free -= 4;
+                       de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
+                       dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
                        memmove(de_next_de(de), (char *)de_next_de(de) + 4,
-                               (char *)dnode + dnode->first_free - (char *)de_next_de(de));
+                               (char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de));
                } else {
                        struct dnode *d1;
                        struct quad_buffer_head qbh1;
-                       *(dnode_secno *) ((void *) de + de->length - 4) = down;
+                       *(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4) = down;
                        if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
-                               d1->up = up;
+                               d1->up = cpu_to_le32(up);
                                hpfs_mark_4buffers_dirty(&qbh1);
                                hpfs_brelse4(&qbh1);
                        }
                }
        } else {
-               hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, dnode->first_free);
+               hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, le32_to_cpu(dnode->first_free));
                goto end;
        }
 
@@ -596,18 +596,18 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                struct quad_buffer_head qbh1;
                if (!de_next->down) goto endm;
                ndown = de_down_pointer(de_next);
-               if (!(de_cp = kmalloc(de->length, GFP_NOFS))) {
+               if (!(de_cp = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) {
                        printk("HPFS: out of memory for dtree balancing\n");
                        goto endm;
                }
-               memcpy(de_cp, de, de->length);
+               memcpy(de_cp, de, le16_to_cpu(de->length));
                hpfs_delete_de(i->i_sb, dnode, de);
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
                for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4);
                for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1);
                if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) {
-                       d1->up = ndown;
+                       d1->up = cpu_to_le32(ndown);
                        hpfs_mark_4buffers_dirty(&qbh1);
                        hpfs_brelse4(&qbh1);
                }
@@ -635,7 +635,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                        struct hpfs_dirent *del = dnode_last_de(d1);
                        dlp = del->down ? de_down_pointer(del) : 0;
                        if (!dlp && down) {
-                               if (d1->first_free > 2044) {
+                               if (le32_to_cpu(d1->first_free) > 2044) {
                                        if (hpfs_sb(i->i_sb)->sb_chk >= 2) {
                                                printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
                                                printk("HPFS: warning: terminating balancing operation\n");
@@ -647,38 +647,38 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                                        printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
                                        printk("HPFS: warning: goin'on\n");
                                }
-                               del->length += 4;
+                               del->length = cpu_to_le16(le16_to_cpu(del->length) + 4);
                                del->down = 1;
-                               d1->first_free += 4;
+                               d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) + 4);
                        }
                        if (dlp && !down) {
-                               del->length -= 4;
+                               del->length = cpu_to_le16(le16_to_cpu(del->length) - 4);
                                del->down = 0;
-                               d1->first_free -= 4;
+                               d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
                        } else if (down)
-                               *(dnode_secno *) ((void *) del + del->length - 4) = down;
+                               *(dnode_secno *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);
                } else goto endm;
-               if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) {
+               if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) {
                        printk("HPFS: out of memory for dtree balancing\n");
                        hpfs_brelse4(&qbh1);
                        goto endm;
                }
                hpfs_mark_4buffers_dirty(&qbh1);
                hpfs_brelse4(&qbh1);
-               memcpy(de_cp, de_prev, de_prev->length);
+               memcpy(de_cp, de_prev, le16_to_cpu(de_prev->length));
                hpfs_delete_de(i->i_sb, dnode, de_prev);
                if (!de_prev->down) {
-                       de_prev->length += 4;
+                       de_prev->length = cpu_to_le16(le16_to_cpu(de_prev->length) + 4);
                        de_prev->down = 1;
-                       dnode->first_free += 4;
+                       dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
                }
-               *(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown;
+               *(dnode_secno *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
                for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);
                for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1));
                if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) {
-                       d1->up = ndown;
+                       d1->up = cpu_to_le32(ndown);
                        hpfs_mark_4buffers_dirty(&qbh1);
                        hpfs_brelse4(&qbh1);
                }
@@ -701,7 +701,6 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
 {
        struct dnode *dnode = qbh->data;
        dnode_secno down = 0;
-       int lock = 0;
        loff_t t;
        if (de->first || de->last) {
                hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno);
@@ -710,11 +709,8 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
        }
        if (de->down) down = de_down_pointer(de);
        if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) {
-               lock = 1;
-               hpfs_lock_creation(i->i_sb);
                if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) {
                        hpfs_brelse4(qbh);
-                       hpfs_unlock_creation(i->i_sb);
                        return 2;
                }
        }
@@ -727,11 +723,9 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
                dnode_secno a = move_to_top(i, down, dno);
                for_all_poss(i, hpfs_pos_subst, 5, t);
                if (a) delete_empty_dnode(i, a);
-               if (lock) hpfs_unlock_creation(i->i_sb);
                return !a;
        }
        delete_empty_dnode(i, dno);
-       if (lock) hpfs_unlock_creation(i->i_sb);
        return 0;
 }
 
@@ -751,8 +745,8 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,
        ptr = 0;
        go_up:
        if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return;
-       if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno)
-               hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up);
+       if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && le32_to_cpu(dnode->up) != odno)
+               hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, le32_to_cpu(dnode->up));
        de = dnode_first_de(dnode);
        if (ptr) while(1) {
                if (de->down) if (de_down_pointer(de) == ptr) goto process_de;
@@ -776,7 +770,7 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,
        if (!de->first && !de->last && n_items) (*n_items)++;
        if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de;
        ptr = dno;
-       dno = dnode->up;
+       dno = le32_to_cpu(dnode->up);
        if (dnode->root_dnode) {
                hpfs_brelse4(&qbh);
                return;
@@ -824,8 +818,8 @@ dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno)
                        return d;
        if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno;
        if (hpfs_sb(s)->sb_chk)
-               if (up && ((struct dnode *)qbh.data)->up != up)
-                       hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up);
+               if (up && le32_to_cpu(((struct dnode *)qbh.data)->up) != up)
+                       hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, le32_to_cpu(((struct dnode *)qbh.data)->up));
        if (!de->down) {
                hpfs_brelse4(&qbh);
                return d;
@@ -874,7 +868,7 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
        /* Going up */
        if (dnode->root_dnode) goto bail;
 
-       if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0)))
+       if (!(up_dnode = hpfs_map_dnode(inode->i_sb, le32_to_cpu(dnode->up), &qbh0)))
                goto bail;
 
        end_up_de = dnode_end_de(up_dnode);
@@ -882,16 +876,16 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
        for (up_de = dnode_first_de(up_dnode); up_de < end_up_de;
             up_de = de_next_de(up_de)) {
                if (!(++c & 077)) hpfs_error(inode->i_sb,
-                       "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up);
+                       "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", le32_to_cpu(dnode->up));
                if (up_de->down && de_down_pointer(up_de) == dno) {
-                       *posp = ((loff_t) dnode->up << 4) + c;
+                       *posp = ((loff_t) le32_to_cpu(dnode->up) << 4) + c;
                        hpfs_brelse4(&qbh0);
                        return de;
                }
        }
        
        hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x",
-               dno, dnode->up);
+               dno, le32_to_cpu(dnode->up));
        hpfs_brelse4(&qbh0);
        
        bail:
@@ -1017,17 +1011,17 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
                /*name2[15] = 0xff;*/
                name1len = 15; name2len = 256;
        }
-       if (!(upf = hpfs_map_fnode(s, f->up, &bh))) {
+       if (!(upf = hpfs_map_fnode(s, le32_to_cpu(f->up), &bh))) {
                kfree(name2);
                return NULL;
        }       
        if (!upf->dirflag) {
                brelse(bh);
-               hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up);
+               hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));
                kfree(name2);
                return NULL;
        }
-       dno = upf->u.external[0].disk_secno;
+       dno = le32_to_cpu(upf->u.external[0].disk_secno);
        brelse(bh);
        go_down:
        downd = 0;
@@ -1049,7 +1043,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
                return NULL;
        }
        next_de:
-       if (de->fnode == fno) {
+       if (le32_to_cpu(de->fnode) == fno) {
                kfree(name2);
                return de;
        }
@@ -1065,7 +1059,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
                goto go_down;
        }
        f:
-       if (de->fnode == fno) {
+       if (le32_to_cpu(de->fnode) == fno) {
                kfree(name2);
                return de;
        }
@@ -1074,7 +1068,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
        if ((de = de_next_de(de)) < de_end) goto next_de;
        if (d->root_dnode) goto not_found;
        downd = dno;
-       dno = d->up;
+       dno = le32_to_cpu(d->up);
        hpfs_brelse4(qbh);
        if (hpfs_sb(s)->sb_chk)
                if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) {
index 45e53d972b42ed27e931c5fa01ae5fb194b0c5f2..d8b84d113c891bbcfd8416d3f35153983b0549a7 100644 (file)
@@ -24,7 +24,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
                }
                if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
                if (ea->indirect) {
-                       if (ea->valuelen != 8) {
+                       if (ea_valuelen(ea) != 8) {
                                hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x",
                                        ano ? "anode" : "sectors", a, pos);
                                return;
@@ -33,7 +33,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
                                return;
                        hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
                }
-               pos += ea->namelen + ea->valuelen + 5;
+               pos += ea->namelen + ea_valuelen(ea) + 5;
        }
        if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);
        else {
@@ -76,24 +76,24 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
        unsigned pos;
        int ano, len;
        secno a;
+       char ex[4 + 255 + 1 + 8];
        struct extended_attribute *ea;
        struct extended_attribute *ea_end = fnode_end_ea(fnode);
        for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
                if (!strcmp(ea->name, key)) {
                        if (ea->indirect)
                                goto indirect;
-                       if (ea->valuelen >= size)
+                       if (ea_valuelen(ea) >= size)
                                return -EINVAL;
-                       memcpy(buf, ea_data(ea), ea->valuelen);
-                       buf[ea->valuelen] = 0;
+                       memcpy(buf, ea_data(ea), ea_valuelen(ea));
+                       buf[ea_valuelen(ea)] = 0;
                        return 0;
                }
-       a = fnode->ea_secno;
-       len = fnode->ea_size_l;
+       a = le32_to_cpu(fnode->ea_secno);
+       len = le32_to_cpu(fnode->ea_size_l);
        ano = fnode->ea_anode;
        pos = 0;
        while (pos < len) {
-               char ex[4 + 255 + 1 + 8];
                ea = (struct extended_attribute *)ex;
                if (pos + 4 > len) {
                        hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
@@ -106,14 +106,14 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
                if (!strcmp(ea->name, key)) {
                        if (ea->indirect)
                                goto indirect;
-                       if (ea->valuelen >= size)
+                       if (ea_valuelen(ea) >= size)
                                return -EINVAL;
-                       if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
+                       if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf))
                                return -EIO;
-                       buf[ea->valuelen] = 0;
+                       buf[ea_valuelen(ea)] = 0;
                        return 0;
                }
-               pos += ea->namelen + ea->valuelen + 5;
+               pos += ea->namelen + ea_valuelen(ea) + 5;
        }
        return -ENOENT;
 indirect:
@@ -138,16 +138,16 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
                if (!strcmp(ea->name, key)) {
                        if (ea->indirect)
                                return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
-                       if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
+                       if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
                                printk("HPFS: out of memory for EA\n");
                                return NULL;
                        }
-                       memcpy(ret, ea_data(ea), ea->valuelen);
-                       ret[ea->valuelen] = 0;
+                       memcpy(ret, ea_data(ea), ea_valuelen(ea));
+                       ret[ea_valuelen(ea)] = 0;
                        return ret;
                }
-       a = fnode->ea_secno;
-       len = fnode->ea_size_l;
+       a = le32_to_cpu(fnode->ea_secno);
+       len = le32_to_cpu(fnode->ea_size_l);
        ano = fnode->ea_anode;
        pos = 0;
        while (pos < len) {
@@ -164,18 +164,18 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
                if (!strcmp(ea->name, key)) {
                        if (ea->indirect)
                                return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
-                       if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
+                       if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
                                printk("HPFS: out of memory for EA\n");
                                return NULL;
                        }
-                       if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, ret)) {
+                       if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) {
                                kfree(ret);
                                return NULL;
                        }
-                       ret[ea->valuelen] = 0;
+                       ret[ea_valuelen(ea)] = 0;
                        return ret;
                }
-               pos += ea->namelen + ea->valuelen + 5;
+               pos += ea->namelen + ea_valuelen(ea) + 5;
        }
        return NULL;
 }
@@ -202,13 +202,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
                        if (ea->indirect) {
                                if (ea_len(ea) == size)
                                        set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
-                       } else if (ea->valuelen == size) {
+                       } else if (ea_valuelen(ea) == size) {
                                memcpy(ea_data(ea), data, size);
                        }
                        return;
                }
-       a = fnode->ea_secno;
-       len = fnode->ea_size_l;
+       a = le32_to_cpu(fnode->ea_secno);
+       len = le32_to_cpu(fnode->ea_size_l);
        ano = fnode->ea_anode;
        pos = 0;
        while (pos < len) {
@@ -228,68 +228,70 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
                                        set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
                        }
                        else {
-                               if (ea->valuelen == size)
+                               if (ea_valuelen(ea) == size)
                                        hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
                        }
                        return;
                }
-               pos += ea->namelen + ea->valuelen + 5;
+               pos += ea->namelen + ea_valuelen(ea) + 5;
        }
-       if (!fnode->ea_offs) {
-               /*if (fnode->ea_size_s) {
+       if (!le16_to_cpu(fnode->ea_offs)) {
+               /*if (le16_to_cpu(fnode->ea_size_s)) {
                        hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
-                               inode->i_ino, fnode->ea_size_s);
+                               inode->i_ino, le16_to_cpu(fnode->ea_size_s));
                        return;
                }*/
-               fnode->ea_offs = 0xc4;
+               fnode->ea_offs = cpu_to_le16(0xc4);
        }
-       if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) {
+       if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) {
                hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
                        (unsigned long)inode->i_ino,
-                       fnode->ea_offs, fnode->ea_size_s);
+                       le32_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
                return;
        }
-       if ((fnode->ea_size_s || !fnode->ea_size_l) &&
-            fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
+       if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
+            le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5 <= 0x200) {
                ea = fnode_end_ea(fnode);
                *(char *)ea = 0;
                ea->namelen = strlen(key);
-               ea->valuelen = size;
+               ea->valuelen_lo = size;
+               ea->valuelen_hi = size >> 8;
                strcpy(ea->name, key);
                memcpy(ea_data(ea), data, size);
-               fnode->ea_size_s += strlen(key) + size + 5;
+               fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5);
                goto ret;
        }
        /* Most the code here is 99.9993422% unused. I hope there are no bugs.
           But what .. HPFS.IFS has also bugs in ea management. */
-       if (fnode->ea_size_s && !fnode->ea_size_l) {
+       if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) {
                secno n;
                struct buffer_head *bh;
                char *data;
-               if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return;
+               if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return;
                if (!(data = hpfs_get_sector(s, n, &bh))) {
                        hpfs_free_sectors(s, n, 1);
                        return;
                }
-               memcpy(data, fnode_ea(fnode), fnode->ea_size_s);
-               fnode->ea_size_l = fnode->ea_size_s;
-               fnode->ea_size_s = 0;
-               fnode->ea_secno = n;
-               fnode->ea_anode = 0;
+               memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s));
+               fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
+               fnode->ea_size_s = cpu_to_le16(0);
+               fnode->ea_secno = cpu_to_le32(n);
+               fnode->ea_anode = cpu_to_le32(0);
                mark_buffer_dirty(bh);
                brelse(bh);
        }
-       pos = fnode->ea_size_l + 5 + strlen(key) + size;
-       len = (fnode->ea_size_l + 511) >> 9;
+       pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size;
+       len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9;
        if (pos >= 30000) goto bail;
        while (((pos + 511) >> 9) > len) {
                if (!len) {
-                       if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1)))
-                               goto bail;
+                       secno q = hpfs_alloc_sector(s, fno, 1, 0);
+                       if (!q) goto bail;
+                       fnode->ea_secno = cpu_to_le32(q);
                        fnode->ea_anode = 0;
                        len++;
                } else if (!fnode->ea_anode) {
-                       if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) {
+                       if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
                                len++;
                        } else {
                                /* Aargh... don't know how to create ea anodes :-( */
@@ -298,26 +300,26 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
                                anode_secno a_s;
                                if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
                                        goto bail;
-                               anode->up = fno;
+                               anode->up = cpu_to_le32(fno);
                                anode->btree.fnode_parent = 1;
                                anode->btree.n_free_nodes--;
                                anode->btree.n_used_nodes++;
-                               anode->btree.first_free += 12;
-                               anode->u.external[0].disk_secno = fnode->ea_secno;
-                               anode->u.external[0].file_secno = 0;
-                               anode->u.external[0].length = len;
+                               anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12);
+                               anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno));
+                               anode->u.external[0].file_secno = cpu_to_le32(0);
+                               anode->u.external[0].length = cpu_to_le32(len);
                                mark_buffer_dirty(bh);
                                brelse(bh);
                                fnode->ea_anode = 1;
-                               fnode->ea_secno = a_s;*/
+                               fnode->ea_secno = cpu_to_le32(a_s);*/
                                secno new_sec;
                                int i;
-                               if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1)))
+                               if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9))))
                                        goto bail;
                                for (i = 0; i < len; i++) {
                                        struct buffer_head *bh1, *bh2;
                                        void *b1, *b2;
-                                       if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) {
+                                       if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) {
                                                hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
                                                goto bail;
                                        }
@@ -331,13 +333,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
                                        mark_buffer_dirty(bh2);
                                        brelse(bh2);
                                }
-                               hpfs_free_sectors(s, fnode->ea_secno, len);
-                               fnode->ea_secno = new_sec;
+                               hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len);
+                               fnode->ea_secno = cpu_to_le32(new_sec);
                                len = (pos + 511) >> 9;
                        }
                }
                if (fnode->ea_anode) {
-                       if (hpfs_add_sector_to_btree(s, fnode->ea_secno,
+                       if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
                                                     0, len) != -1) {
                                len++;
                        } else {
@@ -349,17 +351,17 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
        h[1] = strlen(key);
        h[2] = size & 0xff;
        h[3] = size >> 8;
-       if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail;
-       if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail;
-       if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail;
-       fnode->ea_size_l = pos;
+       if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail;
+       if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail;
+       if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail;
+       fnode->ea_size_l = cpu_to_le32(pos);
        ret:
        hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
        return;
        bail:
-       if (fnode->ea_secno)
-               if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9);
-               else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9));
-       else fnode->ea_secno = fnode->ea_size_l = 0;
+       if (le32_to_cpu(fnode->ea_secno))
+               if (fnode->ea_anode) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9);
+               else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9));
+       else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);
 }
        
index 9b9eb6933e43d8620a38ec744f77d4d8712e3b9a..89c500ee521382c2250c0a818a3c18c773025ac8 100644 (file)
@@ -20,8 +20,8 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
 
 int hpfs_file_fsync(struct file *file, int datasync)
 {
-       /*return file_fsync(file, datasync);*/
-       return 0; /* Don't fsync :-) */
+       struct inode *inode = file->f_mapping->host;
+       return sync_blockdev(inode->i_sb->s_bdev);
 }
 
 /*
@@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
 static void hpfs_truncate(struct inode *i)
 {
        if (IS_IMMUTABLE(i)) return /*-EPERM*/;
-       hpfs_lock(i->i_sb);
+       hpfs_lock_assert(i->i_sb);
+
        hpfs_i(i)->i_n_secs = 0;
        i->i_blocks = 1 + ((i->i_size + 511) >> 9);
        hpfs_i(i)->mmu_private = i->i_size;
        hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
        hpfs_write_inode(i);
        hpfs_i(i)->i_n_secs = 0;
-       hpfs_unlock(i->i_sb);
 }
 
 static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
 {
+       int r;
        secno s;
+       hpfs_lock(inode->i_sb);
        s = hpfs_bmap(inode, iblock);
        if (s) {
                map_bh(bh_result, inode->i_sb, s);
-               return 0;
+               goto ret_0;
        }
-       if (!create) return 0;
+       if (!create) goto ret_0;
        if (iblock<<9 != hpfs_i(inode)->mmu_private) {
                BUG();
-               return -EIO;
+               r = -EIO;
+               goto ret_r;
        }
        if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
                hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
-               return -ENOSPC;
+               r = -ENOSPC;
+               goto ret_r;
        }
        inode->i_blocks++;
        hpfs_i(inode)->mmu_private += 512;
        set_buffer_new(bh_result);
        map_bh(bh_result, inode->i_sb, s);
-       return 0;
+       ret_0:
+       r = 0;
+       ret_r:
+       hpfs_unlock(inode->i_sb);
+       return r;
 }
 
 static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
@@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
        ssize_t retval;
 
        retval = do_sync_write(file, buf, count, ppos);
-       if (retval > 0)
+       if (retval > 0) {
+               hpfs_lock(file->f_path.dentry->d_sb);
                hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
+               hpfs_unlock(file->f_path.dentry->d_sb);
+       }
        return retval;
 }
 
index 0e84c73cd9c4ea88514e6d145bb6a753a3205c03..8b0650aae32812bac9abbb581439b592d64949d2 100644 (file)
    For definitive information on HPFS, ask somebody else -- this is guesswork.
    There are certain to be many mistakes. */
 
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error unknown endian
+#endif
+
 /* Notation */
 
-typedef unsigned secno;                        /* sector number, partition relative */
+typedef u32 secno;                     /* sector number, partition relative */
 
 typedef secno dnode_secno;             /* sector number of a dnode */
 typedef secno fnode_secno;             /* sector number of an fnode */
@@ -38,28 +42,28 @@ typedef u32 time32_t;               /* 32-bit time_t type */
 
 struct hpfs_boot_block
 {
-  unsigned char jmp[3];
-  unsigned char oem_id[8];
-  unsigned char bytes_per_sector[2];   /* 512 */
-  unsigned char sectors_per_cluster;
-  unsigned char n_reserved_sectors[2];
-  unsigned char n_fats;
-  unsigned char n_rootdir_entries[2];
-  unsigned char n_sectors_s[2];
-  unsigned char media_byte;
-  unsigned short sectors_per_fat;
-  unsigned short sectors_per_track;
-  unsigned short heads_per_cyl;
-  unsigned int n_hidden_sectors;
-  unsigned int n_sectors_l;            /* size of partition */
-  unsigned char drive_number;
-  unsigned char mbz;
-  unsigned char sig_28h;               /* 28h */
-  unsigned char vol_serno[4];
-  unsigned char vol_label[11];
-  unsigned char sig_hpfs[8];           /* "HPFS    " */
-  unsigned char pad[448];
-  unsigned short magic;                        /* aa55 */
+  u8 jmp[3];
+  u8 oem_id[8];
+  u8 bytes_per_sector[2];      /* 512 */
+  u8 sectors_per_cluster;
+  u8 n_reserved_sectors[2];
+  u8 n_fats;
+  u8 n_rootdir_entries[2];
+  u8 n_sectors_s[2];
+  u8 media_byte;
+  u16 sectors_per_fat;
+  u16 sectors_per_track;
+  u16 heads_per_cyl;
+  u32 n_hidden_sectors;
+  u32 n_sectors_l;             /* size of partition */
+  u8 drive_number;
+  u8 mbz;
+  u8 sig_28h;                  /* 28h */
+  u8 vol_serno[4];
+  u8 vol_label[11];
+  u8 sig_hpfs[8];              /* "HPFS    " */
+  u8 pad[448];
+  u16 magic;                   /* aa55 */
 };
 
 
@@ -71,31 +75,29 @@ struct hpfs_boot_block
 
 struct hpfs_super_block
 {
-  unsigned magic;                      /* f995 e849 */
-  unsigned magic1;                     /* fa53 e9c5, more magic? */
-  /*unsigned huh202;*/                 /* ?? 202 = N. of B. in 1.00390625 S.*/
-  char version;                                /* version of a filesystem  usually 2 */
-  char funcversion;                    /* functional version - oldest version
+  u32 magic;                           /* f995 e849 */
+  u32 magic1;                          /* fa53 e9c5, more magic? */
+  u8 version;                          /* version of a filesystem  usually 2 */
+  u8 funcversion;                      /* functional version - oldest version
                                           of filesystem that can understand
                                           this disk */
-  unsigned short int zero;             /* 0 */
+  u16 zero;                            /* 0 */
   fnode_secno root;                    /* fnode of root directory */
   secno n_sectors;                     /* size of filesystem */
-  unsigned n_badblocks;                        /* number of bad blocks */
+  u32 n_badblocks;                     /* number of bad blocks */
   secno bitmaps;                       /* pointers to free space bit maps */
-  unsigned zero1;                      /* 0 */
+  u32 zero1;                           /* 0 */
   secno badblocks;                     /* bad block list */
-  unsigned zero3;                      /* 0 */
+  u32 zero3;                           /* 0 */
   time32_t last_chkdsk;                        /* date last checked, 0 if never */
-  /*unsigned zero4;*/                  /* 0 */
-  time32_t last_optimize;                      /* date last optimized, 0 if never */
+  time32_t last_optimize;              /* date last optimized, 0 if never */
   secno n_dir_band;                    /* number of sectors in dir band */
   secno dir_band_start;                        /* first sector in dir band */
   secno dir_band_end;                  /* last sector in dir band */
   secno dir_band_bitmap;               /* free space map, 1 dnode per bit */
-  char volume_name[32];                        /* not used */
+  u8 volume_name[32];                  /* not used */
   secno user_id_table;                 /* 8 preallocated sectors - user id */
-  unsigned zero6[103];                 /* 0 */
+  u32 zero6[103];                      /* 0 */
 };
 
 
@@ -107,44 +109,65 @@ struct hpfs_super_block
 
 struct hpfs_spare_block
 {
-  unsigned magic;                      /* f991 1849 */
-  unsigned magic1;                     /* fa52 29c5, more magic? */
-
-  unsigned dirty: 1;                   /* 0 clean, 1 "improperly stopped" */
-  /*unsigned flag1234: 4;*/            /* unknown flags */
-  unsigned sparedir_used: 1;           /* spare dirblks used */
-  unsigned hotfixes_used: 1;           /* hotfixes used */
-  unsigned bad_sector: 1;              /* bad sector, corrupted disk (???) */
-  unsigned bad_bitmap: 1;              /* bad bitmap */
-  unsigned fast: 1;                    /* partition was fast formatted */
-  unsigned old_wrote: 1;               /* old version wrote to partion */
-  unsigned old_wrote_1: 1;             /* old version wrote to partion (?) */
-  unsigned install_dasd_limits: 1;     /* HPFS386 flags */
-  unsigned resynch_dasd_limits: 1;
-  unsigned dasd_limits_operational: 1;
-  unsigned multimedia_active: 1;
-  unsigned dce_acls_active: 1;
-  unsigned dasd_limits_dirty: 1;
-  unsigned flag67: 2;
-  unsigned char mm_contlgulty;
-  unsigned char unused;
+  u32 magic;                           /* f991 1849 */
+  u32 magic1;                          /* fa52 29c5, more magic? */
+
+#ifdef __LITTLE_ENDIAN
+  u8 dirty: 1;                         /* 0 clean, 1 "improperly stopped" */
+  u8 sparedir_used: 1;                 /* spare dirblks used */
+  u8 hotfixes_used: 1;                 /* hotfixes used */
+  u8 bad_sector: 1;                    /* bad sector, corrupted disk (???) */
+  u8 bad_bitmap: 1;                    /* bad bitmap */
+  u8 fast: 1;                          /* partition was fast formatted */
+  u8 old_wrote: 1;                     /* old version wrote to partion */
+  u8 old_wrote_1: 1;                   /* old version wrote to partion (?) */
+#else
+  u8 old_wrote_1: 1;                   /* old version wrote to partion (?) */
+  u8 old_wrote: 1;                     /* old version wrote to partion */
+  u8 fast: 1;                          /* partition was fast formatted */
+  u8 bad_bitmap: 1;                    /* bad bitmap */
+  u8 bad_sector: 1;                    /* bad sector, corrupted disk (???) */
+  u8 hotfixes_used: 1;                 /* hotfixes used */
+  u8 sparedir_used: 1;                 /* spare dirblks used */
+  u8 dirty: 1;                         /* 0 clean, 1 "improperly stopped" */
+#endif
+
+#ifdef __LITTLE_ENDIAN
+  u8 install_dasd_limits: 1;           /* HPFS386 flags */
+  u8 resynch_dasd_limits: 1;
+  u8 dasd_limits_operational: 1;
+  u8 multimedia_active: 1;
+  u8 dce_acls_active: 1;
+  u8 dasd_limits_dirty: 1;
+  u8 flag67: 2;
+#else
+  u8 flag67: 2;
+  u8 dasd_limits_dirty: 1;
+  u8 dce_acls_active: 1;
+  u8 multimedia_active: 1;
+  u8 dasd_limits_operational: 1;
+  u8 resynch_dasd_limits: 1;
+  u8 install_dasd_limits: 1;           /* HPFS386 flags */
+#endif
+
+  u8 mm_contlgulty;
+  u8 unused;
 
   secno hotfix_map;                    /* info about remapped bad sectors */
-  unsigned n_spares_used;              /* number of hotfixes */
-  unsigned n_spares;                   /* number of spares in hotfix map */
-  unsigned n_dnode_spares_free;                /* spare dnodes unused */
-  unsigned n_dnode_spares;             /* length of spare_dnodes[] list,
+  u32 n_spares_used;                   /* number of hotfixes */
+  u32 n_spares;                                /* number of spares in hotfix map */
+  u32 n_dnode_spares_free;             /* spare dnodes unused */
+  u32 n_dnode_spares;                  /* length of spare_dnodes[] list,
                                           follows in this block*/
   secno code_page_dir;                 /* code page directory block */
-  unsigned n_code_pages;               /* number of code pages */
-  /*unsigned large_numbers[2];*/       /* ?? */
-  unsigned super_crc;                  /* on HPFS386 and LAN Server this is
+  u32 n_code_pages;                    /* number of code pages */
+  u32 super_crc;                       /* on HPFS386 and LAN Server this is
                                           checksum of superblock, on normal
                                           OS/2 unused */
-  unsigned spare_crc;                  /* on HPFS386 checksum of spareblock */
-  unsigned zero1[15];                  /* unused */
+  u32 spare_crc;                       /* on HPFS386 checksum of spareblock */
+  u32 zero1[15];                       /* unused */
   dnode_secno spare_dnodes[100];       /* emergency free dnode list */
-  unsigned zero2[1];                   /* room for more? */
+  u32 zero2[1];                                /* room for more? */
 };
 
 /* The bad block list is 4 sectors long.  The first word must be zero,
@@ -179,18 +202,18 @@ struct hpfs_spare_block
 
 struct code_page_directory
 {
-  unsigned magic;                      /* 4945 21f7 */
-  unsigned n_code_pages;               /* number of pointers following */
-  unsigned zero1[2];
+  u32 magic;                           /* 4945 21f7 */
+  u32 n_code_pages;                    /* number of pointers following */
+  u32 zero1[2];
   struct {
-    unsigned short ix;                 /* index */
-    unsigned short code_page_number;   /* code page number */
-    unsigned bounds;                   /* matches corresponding word
+    u16 ix;                            /* index */
+    u16 code_page_number;              /* code page number */
+    u32 bounds;                                /* matches corresponding word
                                           in data block */
     secno code_page_data;              /* sector number of a code_page_data
                                           containing c.p. array */
-    unsigned short index;              /* index in c.p. array in that sector*/
-    unsigned short unknown;            /* some unknown value; usually 0;
+    u16 index;                         /* index in c.p. array in that sector*/
+    u16 unknown;                       /* some unknown value; usually 0;
                                           2 in Japanese version */
   } array[31];                         /* unknown length */
 };
@@ -201,21 +224,21 @@ struct code_page_directory
 
 struct code_page_data
 {
-  unsigned magic;                      /* 8945 21f7 */
-  unsigned n_used;                     /* # elements used in c_p_data[] */
-  unsigned bounds[3];                  /* looks a bit like
+  u32 magic;                           /* 8945 21f7 */
+  u32 n_used;                          /* # elements used in c_p_data[] */
+  u32 bounds[3];                       /* looks a bit like
                                             (beg1,end1), (beg2,end2)
                                           one byte each */
-  unsigned short offs[3];              /* offsets from start of sector
+  u16 offs[3];                         /* offsets from start of sector
                                           to start of c_p_data[ix] */
   struct {
-    unsigned short ix;                 /* index */
-    unsigned short code_page_number;   /* code page number */
-    unsigned short unknown;            /* the same as in cp directory */
-    unsigned char map[128];            /* upcase table for chars 80..ff */
-    unsigned short zero2;
+    u16 ix;                            /* index */
+    u16 code_page_number;              /* code page number */
+    u16 unknown;                       /* the same as in cp directory */
+    u8 map[128];                       /* upcase table for chars 80..ff */
+    u16 zero2;
   } code_page[3];
-  unsigned char incognita[78];
+  u8 incognita[78];
 };
 
 
@@ -255,50 +278,84 @@ struct code_page_data
 #define DNODE_MAGIC   0x77e40aae
 
 struct dnode {
-  unsigned magic;                      /* 77e4 0aae */
-  unsigned first_free;                 /* offset from start of dnode to
+  u32 magic;                           /* 77e4 0aae */
+  u32 first_free;                      /* offset from start of dnode to
                                           first free dir entry */
-  unsigned root_dnode:1;               /* Is it root dnode? */
-  unsigned increment_me:31;            /* some kind of activity counter?
-                                          Neither HPFS.IFS nor CHKDSK cares
+#ifdef __LITTLE_ENDIAN
+  u8 root_dnode: 1;                    /* Is it root dnode? */
+  u8 increment_me: 7;                  /* some kind of activity counter? */
+                                       /* Neither HPFS.IFS nor CHKDSK cares
+                                          if you change this word */
+#else
+  u8 increment_me: 7;                  /* some kind of activity counter? */
+                                       /* Neither HPFS.IFS nor CHKDSK cares
                                           if you change this word */
+  u8 root_dnode: 1;                    /* Is it root dnode? */
+#endif
+  u8 increment_me2[3];
   secno up;                            /* (root dnode) directory's fnode
                                           (nonroot) parent dnode */
   dnode_secno self;                    /* pointer to this dnode */
-  unsigned char dirent[2028];          /* one or more dirents */
+  u8 dirent[2028];                     /* one or more dirents */
 };
 
 struct hpfs_dirent {
-  unsigned short length;               /* offset to next dirent */
-  unsigned first: 1;                   /* set on phony ^A^A (".") entry */
-  unsigned has_acl: 1;
-  unsigned down: 1;                    /* down pointer present (after name) */
-  unsigned last: 1;                    /* set on phony \377 entry */
-  unsigned has_ea: 1;                  /* entry has EA */
-  unsigned has_xtd_perm: 1;            /* has extended perm list (???) */
-  unsigned has_explicit_acl: 1;
-  unsigned has_needea: 1;              /* ?? some EA has NEEDEA set
+  u16 length;                          /* offset to next dirent */
+
+#ifdef __LITTLE_ENDIAN
+  u8 first: 1;                         /* set on phony ^A^A (".") entry */
+  u8 has_acl: 1;
+  u8 down: 1;                          /* down pointer present (after name) */
+  u8 last: 1;                          /* set on phony \377 entry */
+  u8 has_ea: 1;                                /* entry has EA */
+  u8 has_xtd_perm: 1;                  /* has extended perm list (???) */
+  u8 has_explicit_acl: 1;
+  u8 has_needea: 1;                    /* ?? some EA has NEEDEA set
+                                          I have no idea why this is
+                                          interesting in a dir entry */
+#else
+  u8 has_needea: 1;                    /* ?? some EA has NEEDEA set
                                           I have no idea why this is
                                           interesting in a dir entry */
-  unsigned read_only: 1;               /* dos attrib */
-  unsigned hidden: 1;                  /* dos attrib */
-  unsigned system: 1;                  /* dos attrib */
-  unsigned flag11: 1;                  /* would be volume label dos attrib */
-  unsigned directory: 1;               /* dos attrib */
-  unsigned archive: 1;                 /* dos attrib */
-  unsigned not_8x3: 1;                 /* name is not 8.3 */
-  unsigned flag15: 1;
+  u8 has_explicit_acl: 1;
+  u8 has_xtd_perm: 1;                  /* has extended perm list (???) */
+  u8 has_ea: 1;                                /* entry has EA */
+  u8 last: 1;                          /* set on phony \377 entry */
+  u8 down: 1;                          /* down pointer present (after name) */
+  u8 has_acl: 1;
+  u8 first: 1;                         /* set on phony ^A^A (".") entry */
+#endif
+
+#ifdef __LITTLE_ENDIAN
+  u8 read_only: 1;                     /* dos attrib */
+  u8 hidden: 1;                                /* dos attrib */
+  u8 system: 1;                                /* dos attrib */
+  u8 flag11: 1;                                /* would be volume label dos attrib */
+  u8 directory: 1;                     /* dos attrib */
+  u8 archive: 1;                       /* dos attrib */
+  u8 not_8x3: 1;                       /* name is not 8.3 */
+  u8 flag15: 1;
+#else
+  u8 flag15: 1;
+  u8 not_8x3: 1;                       /* name is not 8.3 */
+  u8 archive: 1;                       /* dos attrib */
+  u8 directory: 1;                     /* dos attrib */
+  u8 flag11: 1;                                /* would be volume label dos attrib */
+  u8 system: 1;                                /* dos attrib */
+  u8 hidden: 1;                                /* dos attrib */
+  u8 read_only: 1;                     /* dos attrib */
+#endif
+
   fnode_secno fnode;                   /* fnode giving allocation info */
   time32_t write_date;                 /* mtime */
-  unsigned file_size;                  /* file length, bytes */
+  u32 file_size;                       /* file length, bytes */
   time32_t read_date;                  /* atime */
   time32_t creation_date;                      /* ctime */
-  unsigned ea_size;                    /* total EA length, bytes */
-  unsigned char no_of_acls : 3;                /* number of ACL's */
-  unsigned char reserver : 5;
-  unsigned char ix;                    /* code page index (of filename), see
+  u32 ea_size;                         /* total EA length, bytes */
+  u8 no_of_acls;                       /* number of ACL's (low 3 bits) */
+  u8 ix;                               /* code page index (of filename), see
                                           struct code_page_data */
-  unsigned char namelen, name[1];      /* file name */
+  u8 namelen, name[1];                 /* file name */
   /* dnode_secno down;   btree down pointer, if present,
                          follows name on next word boundary, or maybe it
                          precedes next dirent, which is on a word boundary. */
@@ -318,38 +375,50 @@ struct hpfs_dirent {
 
 struct bplus_leaf_node
 {
-  unsigned file_secno;                 /* first file sector in extent */
-  unsigned length;                     /* length, sectors */
+  u32 file_secno;                      /* first file sector in extent */
+  u32 length;                          /* length, sectors */
   secno disk_secno;                    /* first corresponding disk sector */
 };
 
 struct bplus_internal_node
 {
-  unsigned file_secno;                 /* subtree maps sectors < this  */
+  u32 file_secno;                      /* subtree maps sectors < this  */
   anode_secno down;                    /* pointer to subtree */
 };
 
 struct bplus_header
 {
-  unsigned hbff: 1;    /* high bit of first free entry offset */
-  unsigned flag1: 1;
-  unsigned flag2: 1;
-  unsigned flag3: 1;
-  unsigned flag4: 1;
-  unsigned fnode_parent: 1;            /* ? we're pointed to by an fnode,
+#ifdef __LITTLE_ENDIAN
+  u8 hbff: 1;                  /* high bit of first free entry offset */
+  u8 flag1234: 4;
+  u8 fnode_parent: 1;                  /* ? we're pointed to by an fnode,
                                           the data btree or some ea or the
                                           main ea bootage pointer ea_secno */
                                        /* also can get set in fnodes, which
                                           may be a chkdsk glitch or may mean
                                           this bit is irrelevant in fnodes,
                                           or this interpretation is all wet */
-  unsigned binary_search: 1;           /* suggest binary search (unused) */
-  unsigned internal: 1;                        /* 1 -> (internal) tree of anodes
+  u8 binary_search: 1;                 /* suggest binary search (unused) */
+  u8 internal: 1;                      /* 1 -> (internal) tree of anodes
+                                          0 -> (leaf) list of extents */
+#else
+  u8 internal: 1;                      /* 1 -> (internal) tree of anodes
                                           0 -> (leaf) list of extents */
-  unsigned char fill[3];
-  unsigned char n_free_nodes;          /* free nodes in following array */
-  unsigned char n_used_nodes;          /* used nodes in following array */
-  unsigned short first_free;           /* offset from start of header to
+  u8 binary_search: 1;                 /* suggest binary search (unused) */
+  u8 fnode_parent: 1;                  /* ? we're pointed to by an fnode,
+                                          the data btree or some ea or the
+                                          main ea bootage pointer ea_secno */
+                                       /* also can get set in fnodes, which
+                                          may be a chkdsk glitch or may mean
+                                          this bit is irrelevant in fnodes,
+                                          or this interpretation is all wet */
+  u8 flag1234: 4;
+  u8 hbff: 1;                  /* high bit of first free entry offset */
+#endif
+  u8 fill[3];
+  u8 n_free_nodes;                     /* free nodes in following array */
+  u8 n_used_nodes;                     /* used nodes in following array */
+  u16 first_free;                      /* offset from start of header to
                                           first free node in array */
   union {
     struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
@@ -369,37 +438,38 @@ struct bplus_header
 
 struct fnode
 {
-  unsigned magic;                      /* f7e4 0aae */
-  unsigned zero1[2];                   /* read history */
-  unsigned char len, name[15];         /* true length, truncated name */
+  u32 magic;                           /* f7e4 0aae */
+  u32 zero1[2];                                /* read history */
+  u8 len, name[15];                    /* true length, truncated name */
   fnode_secno up;                      /* pointer to file's directory fnode */
-  /*unsigned zero2[3];*/
   secno acl_size_l;
   secno acl_secno;
-  unsigned short acl_size_s;
-  char acl_anode;
-  char zero2;                          /* history bit count */
-  unsigned ea_size_l;                  /* length of disk-resident ea's */
+  u16 acl_size_s;
+  u8 acl_anode;
+  u8 zero2;                            /* history bit count */
+  u32 ea_size_l;                       /* length of disk-resident ea's */
   secno ea_secno;                      /* first sector of disk-resident ea's*/
-  unsigned short ea_size_s;            /* length of fnode-resident ea's */
-
-  unsigned flag0: 1;
-  unsigned ea_anode: 1;                        /* 1 -> ea_secno is an anode */
-  unsigned flag2: 1;
-  unsigned flag3: 1;
-  unsigned flag4: 1;
-  unsigned flag5: 1;
-  unsigned flag6: 1;
-  unsigned flag7: 1;
-  unsigned dirflag: 1;                 /* 1 -> directory.  first & only extent
+  u16 ea_size_s;                       /* length of fnode-resident ea's */
+
+#ifdef __LITTLE_ENDIAN
+  u8 flag0: 1;
+  u8 ea_anode: 1;                      /* 1 -> ea_secno is an anode */
+  u8 flag234567: 6;
+#else
+  u8 flag234567: 6;
+  u8 ea_anode: 1;                      /* 1 -> ea_secno is an anode */
+  u8 flag0: 1;
+#endif
+
+#ifdef __LITTLE_ENDIAN
+  u8 dirflag: 1;                       /* 1 -> directory.  first & only extent
                                           points to dnode. */
-  unsigned flag9: 1;
-  unsigned flag10: 1;
-  unsigned flag11: 1;
-  unsigned flag12: 1;
-  unsigned flag13: 1;
-  unsigned flag14: 1;
-  unsigned flag15: 1;
+  u8 flag9012345: 7;
+#else
+  u8 flag9012345: 7;
+  u8 dirflag: 1;                       /* 1 -> directory.  first & only extent
+                                          points to dnode. */
+#endif
 
   struct bplus_header btree;           /* b+ tree, 8 extents or 12 subtrees */
   union {
@@ -407,17 +477,16 @@ struct fnode
     struct bplus_internal_node internal[12];
   } u;
 
-  unsigned file_size;                  /* file length, bytes */
-  unsigned n_needea;                   /* number of EA's with NEEDEA set */
-  char user_id[16];                    /* unused */
-  unsigned short ea_offs;              /* offset from start of fnode
+  u32 file_size;                       /* file length, bytes */
+  u32 n_needea;                                /* number of EA's with NEEDEA set */
+  u8 user_id[16];                      /* unused */
+  u16 ea_offs;                         /* offset from start of fnode
                                           to first fnode-resident ea */
-  char dasd_limit_treshhold;
-  char dasd_limit_delta;
-  unsigned dasd_limit;
-  unsigned dasd_usage;
-  /*unsigned zero5[2];*/
-  unsigned char ea[316];               /* zero or more EA's, packed together
+  u8 dasd_limit_treshhold;
+  u8 dasd_limit_delta;
+  u32 dasd_limit;
+  u32 dasd_usage;
+  u8 ea[316];                          /* zero or more EA's, packed together
                                           with no alignment padding.
                                           (Do not use this name, get here
                                           via fnode + ea_offs. I think.) */
@@ -430,7 +499,7 @@ struct fnode
 
 struct anode
 {
-  unsigned magic;                      /* 37e4 0aae */
+  u32 magic;                           /* 37e4 0aae */
   anode_secno self;                    /* pointer to this anode */
   secno up;                            /* parent anode or fnode */
 
@@ -440,7 +509,7 @@ struct anode
     struct bplus_internal_node internal[60];
   } u;
 
-  unsigned fill[3];                    /* unused */
+  u32 fill[3];                         /* unused */
 };
 
 
@@ -461,25 +530,31 @@ struct anode
 
 struct extended_attribute
 {
-  unsigned indirect: 1;                        /* 1 -> value gives sector number
+#ifdef __LITTLE_ENDIAN
+  u8 indirect: 1;                      /* 1 -> value gives sector number
                                           where real value starts */
-  unsigned anode: 1;                   /* 1 -> sector is an anode
+  u8 anode: 1;                         /* 1 -> sector is an anode
+                                          that points to fragmented value */
+  u8 flag23456: 5;
+  u8 needea: 1;                                /* required ea */
+#else
+  u8 needea: 1;                                /* required ea */
+  u8 flag23456: 5;
+  u8 anode: 1;                         /* 1 -> sector is an anode
                                           that points to fragmented value */
-  unsigned flag2: 1;
-  unsigned flag3: 1;
-  unsigned flag4: 1;
-  unsigned flag5: 1;
-  unsigned flag6: 1;
-  unsigned needea: 1;                  /* required ea */
-  unsigned char namelen;               /* length of name, bytes */
-  unsigned short valuelen;             /* length of value, bytes */
-  unsigned char name[0];
+  u8 indirect: 1;                      /* 1 -> value gives sector number
+                                          where real value starts */
+#endif
+  u8 namelen;                          /* length of name, bytes */
+  u8 valuelen_lo;                      /* length of value, bytes */
+  u8 valuelen_hi;                      /* length of value, bytes */
+  u8 name[0];
   /*
-    unsigned char name[namelen];       ascii attrib name
-    unsigned char nul;                 terminating '\0', not counted
-    unsigned char value[valuelen];     value, arbitrary
+    u8 name[namelen];                  ascii attrib name
+    u8 nul;                            terminating '\0', not counted
+    u8 value[valuelen];                        value, arbitrary
       if this.indirect, valuelen is 8 and the value is
-        unsigned length;               real length of value, bytes
+        u32 length;                    real length of value, bytes
         secno secno;                   sector address where it starts
       if this.anode, the above sector number is the root of an anode tree
         which points to the value.
index c15adbca07ff1a433fbf8ec9d2ac03fb34d057c5..dd552f862c8f1c562a34768f970b6ddcb68b2336 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 
 #include "hpfs.h"
 
@@ -51,18 +52,16 @@ struct hpfs_inode_info {
        unsigned i_disk_sec;    /* (files) minimalist cache of alloc info */
        unsigned i_n_secs;      /* (files) minimalist cache of alloc info */
        unsigned i_ea_size;     /* size of extended attributes */
-       unsigned i_conv : 2;    /* (files) crlf->newline hackery */
        unsigned i_ea_mode : 1; /* file's permission is stored in ea */
        unsigned i_ea_uid : 1;  /* file's uid is stored in ea */
        unsigned i_ea_gid : 1;  /* file's gid is stored in ea */
        unsigned i_dirty : 1;
-       struct mutex i_mutex;
-       struct mutex i_parent_mutex;
        loff_t **i_rddir_off;
        struct inode vfs_inode;
 };
 
 struct hpfs_sb_info {
+       struct mutex hpfs_mutex;        /* global hpfs lock */
        ino_t sb_root;                  /* inode number of root dir */
        unsigned sb_fs_size;            /* file system size, sectors */
        unsigned sb_bitmaps;            /* sector number of bitmap list */
@@ -74,7 +73,6 @@ struct hpfs_sb_info {
        uid_t sb_uid;                   /* uid from mount options */
        gid_t sb_gid;                   /* gid from mount options */
        umode_t sb_mode;                /* mode from mount options */
-       unsigned sb_conv : 2;           /* crlf->newline hackery */
        unsigned sb_eas : 2;            /* eas: 0-ignore, 1-ro, 2-rw */
        unsigned sb_err : 2;            /* on errs: 0-cont, 1-ro, 2-panic */
        unsigned sb_chk : 2;            /* checks: 0-no, 1-normal, 2-strict */
@@ -87,20 +85,9 @@ struct hpfs_sb_info {
        unsigned *sb_bmp_dir;           /* main bitmap directory */
        unsigned sb_c_bitmap;           /* current bitmap */
        unsigned sb_max_fwd_alloc;      /* max forwad allocation */
-       struct mutex hpfs_creation_de;  /* when creating dirents, nobody else
-                                          can alloc blocks */
-       /*unsigned sb_mounting : 1;*/
        int sb_timeshift;
 };
 
-/*
- * conv= options
- */
-
-#define CONV_BINARY 0                  /* no conversion */
-#define CONV_TEXT 1                    /* crlf->newline */
-#define CONV_AUTO 2                    /* decide based on file contents */
-
 /* Four 512-byte buffers and the 2k block obtained by concatenating them */
 
 struct quad_buffer_head {
@@ -113,7 +100,7 @@ struct quad_buffer_head {
 static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
 {
   CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
-  return *(dnode_secno *) ((void *) de + de->length - 4);
+  return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4));
 }
 
 /* The first dir entry in a dnode */
@@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
 
 static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
 {
-  CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free));
-  return (void *) dnode + dnode->first_free;
+  CHKCOND(le32_to_cpu(dnode->first_free)>=0x14 && le32_to_cpu(dnode->first_free)<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %x\n",(unsigned)le32_to_cpu(dnode->first_free)));
+  return (void *) dnode + le32_to_cpu(dnode->first_free);
 }
 
 /* The dir entry after dir entry de */
 
 static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
 {
-  CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length));
-  return (void *) de + de->length;
+  CHKCOND(le16_to_cpu(de->length)>=0x20 && le16_to_cpu(de->length)<0x800,("HPFS: de_next_de: de->length = %x\n",(unsigned)le16_to_cpu(de->length)));
+  return (void *) de + le16_to_cpu(de->length);
 }
 
 static inline struct extended_attribute *fnode_ea(struct fnode *fnode)
 {
-       return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s);
+       return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s));
 }
 
 static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
 {
-       return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s);
+       return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s));
+}
+
+static unsigned ea_valuelen(struct extended_attribute *ea)
+{
+       return ea->valuelen_lo + 256 * ea->valuelen_hi;
 }
 
 static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
 {
-       return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen);
+       return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea));
 }
 
 static inline secno ea_sec(struct extended_attribute *ea)
 {
-       return *(secno *)((char *)ea + 9 + ea->namelen);
+       return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen)));
 }
 
 static inline secno ea_len(struct extended_attribute *ea)
 {
-       return *(secno *)((char *)ea + 5 + ea->namelen);
+       return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen)));
 }
 
 static inline char *ea_data(struct extended_attribute *ea)
@@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
        dst->not_8x3 = n;
 }
 
-static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
+static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n)
 {
        int i;
        if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
-       if (!((bmp[(b & 0x3fff) >> 5] >> (b & 0x1f)) & 1)) return 1;
+       if (!((le32_to_cpu(bmp[(b & 0x3fff) >> 5]) >> (b & 0x1f)) & 1)) return 1;
        for (i = 1; i < n; i++)
-               if (/*b+i < 0x4000 &&*/ !((bmp[((b+i) & 0x3fff) >> 5] >> ((b+i) & 0x1f)) & 1))
+               if (!((le32_to_cpu(bmp[((b+i) & 0x3fff) >> 5]) >> ((b+i) & 0x1f)) & 1))
                        return i + 1;
        return 0;
 }
@@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
 /* alloc.c */
 
 int hpfs_chk_sectors(struct super_block *, secno, int, char *);
-secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int);
+secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int);
 int hpfs_alloc_if_possible(struct super_block *, secno);
 void hpfs_free_sectors(struct super_block *, secno, unsigned);
 int hpfs_check_free_dnodes(struct super_block *, int);
 void hpfs_free_dnode(struct super_block *, secno);
-struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *, int);
+struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *);
 struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **);
 struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **);
 
@@ -222,8 +214,6 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
 
 /* buffer.c */
 
-void hpfs_lock_creation(struct super_block *);
-void hpfs_unlock_creation(struct super_block *);
 void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
 void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
 void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
@@ -247,7 +237,7 @@ void hpfs_del_pos(struct inode *, loff_t *);
 struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
                                const unsigned char *, unsigned, secno);
 int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned,
-                   struct hpfs_dirent *, int);
+                   struct hpfs_dirent *);
 int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
 void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
 dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
@@ -303,7 +293,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,
                       const unsigned char *, unsigned, int);
 int hpfs_is_name_long(const unsigned char *, unsigned);
 void hpfs_adjust_length(const unsigned char *, unsigned *);
-void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);
 
 /* namei.c */
 
@@ -346,21 +335,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t)
 /*
  * Locking:
  *
- * hpfs_lock() is a leftover from the big kernel lock.
- * Right now, these functions are empty and only left
- * for documentation purposes. The file system no longer
- * works on SMP systems, so the lock is not needed
- * any more.
+ * hpfs_lock() locks the whole filesystem. It must be taken
+ * on any method called by the VFS.
  *
- * If someone is interested in making it work again, this
- * would be the place to start by adding a per-superblock
- * mutex and fixing all the bugs and performance issues
- * caused by that.
+ * We don't do any per-file locking anymore, it is hard to
+ * review and HPFS is not performance-sensitive anyway.
  */
 static inline void hpfs_lock(struct super_block *s)
 {
+       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       mutex_lock(&sbi->hpfs_mutex);
 }
 
 static inline void hpfs_unlock(struct super_block *s)
 {
+       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       mutex_unlock(&sbi->hpfs_mutex);
+}
+
+static inline void hpfs_lock_assert(struct super_block *s)
+{
+       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex));
 }
index 87f1f787e7677efdd7a17a4e9a8ed2f71c397606..338cd8368451cd081a800aa77440ce237f24b592 100644 (file)
@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
        i->i_uid = hpfs_sb(sb)->sb_uid;
        i->i_gid = hpfs_sb(sb)->sb_gid;
        i->i_mode = hpfs_sb(sb)->sb_mode;
-       hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
        i->i_size = -1;
        i->i_blocks = -1;
        
@@ -116,8 +115,8 @@ void hpfs_read_inode(struct inode *i)
                i->i_mode |= S_IFDIR;
                i->i_op = &hpfs_dir_iops;
                i->i_fop = &hpfs_dir_ops;
-               hpfs_inode->i_parent_dir = fnode->up;
-               hpfs_inode->i_dno = fnode->u.external[0].disk_secno;
+               hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up);
+               hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno);
                if (hpfs_sb(sb)->sb_chk >= 2) {
                        struct buffer_head *bh0;
                        if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0);
@@ -133,7 +132,7 @@ void hpfs_read_inode(struct inode *i)
                i->i_op = &hpfs_file_iops;
                i->i_fop = &hpfs_file_ops;
                i->i_nlink = 1;
-               i->i_size = fnode->file_size;
+               i->i_size = le32_to_cpu(fnode->file_size);
                i->i_blocks = ((i->i_size + 511) >> 9) + 1;
                i->i_data.a_ops = &hpfs_aops;
                hpfs_i(i)->mmu_private = i->i_size;
@@ -144,7 +143,7 @@ void hpfs_read_inode(struct inode *i)
 static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
 {
        struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-       /*if (fnode->acl_size_l || fnode->acl_size_s) {
+       /*if (le32_to_cpu(fnode->acl_size_l) || le16_to_cpu(fnode->acl_size_s)) {
                   Some unknown structures like ACL may be in fnode,
                   we'd better not overwrite them
                hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino);
@@ -187,9 +186,7 @@ void hpfs_write_inode(struct inode *i)
                kfree(hpfs_inode->i_rddir_off);
                hpfs_inode->i_rddir_off = NULL;
        }
-       mutex_lock(&hpfs_inode->i_parent_mutex);
        if (!i->i_nlink) {
-               mutex_unlock(&hpfs_inode->i_parent_mutex);
                return;
        }
        parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir);
@@ -200,14 +197,9 @@ void hpfs_write_inode(struct inode *i)
                        hpfs_read_inode(parent);
                        unlock_new_inode(parent);
                }
-               mutex_lock(&hpfs_inode->i_mutex);
                hpfs_write_inode_nolock(i);
-               mutex_unlock(&hpfs_inode->i_mutex);
                iput(parent);
-       } else {
-               mark_inode_dirty(i);
        }
-       mutex_unlock(&hpfs_inode->i_parent_mutex);
 }
 
 void hpfs_write_inode_nolock(struct inode *i)
@@ -226,30 +218,30 @@ void hpfs_write_inode_nolock(struct inode *i)
                }
        } else de = NULL;
        if (S_ISREG(i->i_mode)) {
-               fnode->file_size = i->i_size;
-               if (de) de->file_size = i->i_size;
+               fnode->file_size = cpu_to_le32(i->i_size);
+               if (de) de->file_size = cpu_to_le32(i->i_size);
        } else if (S_ISDIR(i->i_mode)) {
-               fnode->file_size = 0;
-               if (de) de->file_size = 0;
+               fnode->file_size = cpu_to_le32(0);
+               if (de) de->file_size = cpu_to_le32(0);
        }
        hpfs_write_inode_ea(i, fnode);
        if (de) {
-               de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
-               de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
-               de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
+               de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
+               de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
+               de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
                de->read_only = !(i->i_mode & 0222);
-               de->ea_size = hpfs_inode->i_ea_size;
+               de->ea_size = cpu_to_le32(hpfs_inode->i_ea_size);
                hpfs_mark_4buffers_dirty(&qbh);
                hpfs_brelse4(&qbh);
        }
        if (S_ISDIR(i->i_mode)) {
                if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) {
-                       de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
-                       de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
-                       de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
+                       de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
+                       de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
+                       de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
                        de->read_only = !(i->i_mode & 0222);
-                       de->ea_size = /*hpfs_inode->i_ea_size*/0;
-                       de->file_size = 0;
+                       de->ea_size = cpu_to_le32(/*hpfs_inode->i_ea_size*/0);
+                       de->file_size = cpu_to_le32(0);
                        hpfs_mark_4buffers_dirty(&qbh);
                        hpfs_brelse4(&qbh);
                } else
@@ -269,6 +261,10 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
        hpfs_lock(inode->i_sb);
        if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root)
                goto out_unlock;
+       if ((attr->ia_valid & ATTR_UID) && attr->ia_uid >= 0x10000)
+               goto out_unlock;
+       if ((attr->ia_valid & ATTR_GID) && attr->ia_gid >= 0x10000)
+               goto out_unlock;
        if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
                goto out_unlock;
 
@@ -284,7 +280,6 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        setattr_copy(inode, attr);
-       mark_inode_dirty(inode);
 
        hpfs_write_inode(inode);
 
index 840d033ecee832561f7f9ed91cec78527a62e38f..a790821366a7f045d068fe47df517dc479b0ecce 100644 (file)
@@ -21,7 +21,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
                hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
                return NULL;
        }
-       sec = hpfs_sb(s)->sb_bmp_dir[bmp_block];
+       sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
        if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) {
                hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
                return NULL;
@@ -46,18 +46,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
        struct code_page_data *cpd;
        struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);
        if (!cp) return NULL;
-       if (cp->magic != CP_DIR_MAGIC) {
-               printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic);
+       if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) {
+               printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", le32_to_cpu(cp->magic));
                brelse(bh);
                return NULL;
        }
-       if (!cp->n_code_pages) {
+       if (!le32_to_cpu(cp->n_code_pages)) {
                printk("HPFS: n_code_pages == 0\n");
                brelse(bh);
                return NULL;
        }
-       cpds = cp->array[0].code_page_data;
-       cpi = cp->array[0].index;
+       cpds = le32_to_cpu(cp->array[0].code_page_data);
+       cpi = le16_to_cpu(cp->array[0].index);
        brelse(bh);
 
        if (cpi >= 3) {
@@ -66,12 +66,12 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
        }
        
        if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
-       if ((unsigned)cpd->offs[cpi] > 0x178) {
+       if (le16_to_cpu(cpd->offs[cpi]) > 0x178) {
                printk("HPFS: Code page index out of sector\n");
                brelse(bh);
                return NULL;
        }
-       ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6;
+       ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6;
        if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
                printk("HPFS: out of memory for code page table\n");
                brelse(bh);
@@ -125,7 +125,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
                if (hpfs_sb(s)->sb_chk) {
                        struct extended_attribute *ea;
                        struct extended_attribute *ea_end;
-                       if (fnode->magic != FNODE_MAGIC) {
+                       if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) {
                                hpfs_error(s, "bad magic on fnode %08lx",
                                        (unsigned long)ino);
                                goto bail;
@@ -138,7 +138,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
                                            (unsigned long)ino);
                                        goto bail;
                                }
-                               if (fnode->btree.first_free !=
+                               if (le16_to_cpu(fnode->btree.first_free) !=
                                    8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
                                        hpfs_error(s,
                                            "bad first_free pointer in fnode %08lx",
@@ -146,12 +146,12 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
                                        goto bail;
                                }
                        }
-                       if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 ||
-                          (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) {
+                       if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 ||
+                          le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) {
                                hpfs_error(s,
                                        "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",
                                        (unsigned long)ino,
-                                       fnode->ea_offs, fnode->ea_size_s);
+                                       le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
                                goto bail;
                        }
                        ea = fnode_ea(fnode);
@@ -178,16 +178,20 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
        if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL;
        if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))
                if (hpfs_sb(s)->sb_chk) {
-                       if (anode->magic != ANODE_MAGIC || anode->self != ano) {
+                       if (le32_to_cpu(anode->magic) != ANODE_MAGIC) {
                                hpfs_error(s, "bad magic on anode %08x", ano);
                                goto bail;
                        }
+                       if (le32_to_cpu(anode->self) != ano) {
+                               hpfs_error(s, "self pointer invalid on anode %08x", ano);
+                               goto bail;
+                       }
                        if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
                            (anode->btree.internal ? 60 : 40)) {
                                hpfs_error(s, "bad number of nodes in anode %08x", ano);
                                goto bail;
                        }
-                       if (anode->btree.first_free !=
+                       if (le16_to_cpu(anode->btree.first_free) !=
                            8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) {
                                hpfs_error(s, "bad first_free pointer in anode %08x", ano);
                                goto bail;
@@ -219,26 +223,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
                        unsigned p, pp = 0;
                        unsigned char *d = (unsigned char *)dnode;
                        int b = 0;
-                       if (dnode->magic != DNODE_MAGIC) {
+                       if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) {
                                hpfs_error(s, "bad magic on dnode %08x", secno);
                                goto bail;
                        }
-                       if (dnode->self != secno)
-                               hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self);
+                       if (le32_to_cpu(dnode->self) != secno)
+                               hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self));
                        /* Check dirents - bad dirents would cause infinite
                           loops or shooting to memory */
-                       if (dnode->first_free > 2048/* || dnode->first_free < 84*/) {
-                               hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free);
+                       if (le32_to_cpu(dnode->first_free) > 2048) {
+                               hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free));
                                goto bail;
                        }
-                       for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) {
+                       for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) {
                                struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
-                               if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) {
+                               if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) {
                                        hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
                                        goto bail;
                                }
-                               if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) {
-                                       if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok;
+                               if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) {
+                                       if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & MS_RDONLY) goto ok;
                                        hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
                                        goto bail;
                                }
@@ -251,7 +255,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
                                pp = p;
                                
                        }
-                       if (p != dnode->first_free) {
+                       if (p != le32_to_cpu(dnode->first_free)) {
                                hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);
                                goto bail;
                        }
@@ -277,7 +281,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)
        if (!fnode)
                return 0;
 
-       dno = fnode->u.external[0].disk_secno;
+       dno = le32_to_cpu(fnode->u.external[0].disk_secno);
        brelse(bh);
        return dno;
 }
index f24736d7a439218aa238f75df3338c3e3e64744f..9acdf338def0b4d3dc26c59171b9dc337217ec30 100644 (file)
@@ -8,39 +8,6 @@
 
 #include "hpfs_fn.h"
 
-static const char *text_postfix[]={
-".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
-".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
-".RC", ".TEX", ".TXT", ".Y", ""};
-
-static const char *text_prefix[]={
-"AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
-"MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
-
-void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len)
-{
-       struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
-       int i;
-       if (hpfs_inode->i_conv != CONV_AUTO) return;
-       for (i = 0; *text_postfix[i]; i++) {
-               int l = strlen(text_postfix[i]);
-               if (l <= len)
-                       if (!hpfs_compare_names(inode->i_sb, text_postfix[i], l, name + len - l, l, 0))
-                               goto text;
-       }
-       for (i = 0; *text_prefix[i]; i++) {
-               int l = strlen(text_prefix[i]);
-               if (l <= len)
-                       if (!hpfs_compare_names(inode->i_sb, text_prefix[i], l, name, l, 0))
-                               goto text;
-       }
-       hpfs_inode->i_conv = CONV_BINARY;
-       return;
-       text:
-       hpfs_inode->i_conv = CONV_TEXT;
-       return;
-}
-
 static inline int not_allowed_char(unsigned char c)
 {
        return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' ||
index d5f8c8a190233dc8cd066b065868aca822989128..1f05839c27a7fca1f24c99dda71adf07bb2930c5 100644 (file)
@@ -29,7 +29,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
        if (!fnode)
                goto bail;
-       dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1);
+       dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
        if (!dnode)
                goto bail1;
        memset(&dee, 0, sizeof dee);
@@ -37,8 +37,8 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (!(mode & 0222)) dee.read_only = 1;
        /*dee.archive = 0;*/
        dee.hidden = name[0] == '.';
-       dee.fnode = fno;
-       dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
+       dee.fnode = cpu_to_le32(fno);
+       dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
        result = new_inode(dir->i_sb);
        if (!result)
                goto bail2;
@@ -46,7 +46,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        result->i_ino = fno;
        hpfs_i(result)->i_parent_dir = dir->i_ino;
        hpfs_i(result)->i_dno = dno;
-       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0; 
        result->i_mtime.tv_nsec = 0; 
        result->i_atime.tv_nsec = 0; 
@@ -60,8 +60,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (dee.read_only)
                result->i_mode &= ~0222;
 
-       mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail3;
        if (r == -1) {
@@ -70,21 +69,21 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
-       fnode->up = dir->i_ino;
+       fnode->up = cpu_to_le32(dir->i_ino);
        fnode->dirflag = 1;
        fnode->btree.n_free_nodes = 7;
        fnode->btree.n_used_nodes = 1;
-       fnode->btree.first_free = 0x14;
-       fnode->u.external[0].disk_secno = dno;
-       fnode->u.external[0].file_secno = -1;
+       fnode->btree.first_free = cpu_to_le16(0x14);
+       fnode->u.external[0].disk_secno = cpu_to_le32(dno);
+       fnode->u.external[0].file_secno = cpu_to_le32(-1);
        dnode->root_dnode = 1;
-       dnode->up = fno;
+       dnode->up = cpu_to_le32(fno);
        de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
-       de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, get_seconds());
+       de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
        if (!(mode & 0222)) de->read_only = 1;
        de->first = de->directory = 1;
        /*de->hidden = de->system = 0;*/
-       de->fnode = fno;
+       de->fnode = cpu_to_le32(fno);
        mark_buffer_dirty(bh);
        brelse(bh);
        hpfs_mark_4buffers_dirty(&qbh0);
@@ -101,11 +100,9 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                hpfs_write_inode_nolock(result);
        }
        d_instantiate(dentry, result);
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        hpfs_unlock(dir->i_sb);
        return 0;
 bail3:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        iput(result);
 bail2:
        hpfs_brelse4(&qbh0);
@@ -140,8 +137,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        if (!(mode & 0222)) dee.read_only = 1;
        dee.archive = 1;
        dee.hidden = name[0] == '.';
-       dee.fnode = fno;
-       dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
+       dee.fnode = cpu_to_le32(fno);
+       dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
 
        result = new_inode(dir->i_sb);
        if (!result)
@@ -154,9 +151,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        result->i_op = &hpfs_file_iops;
        result->i_fop = &hpfs_file_ops;
        result->i_nlink = 1;
-       hpfs_decide_conv(result, name, len);
        hpfs_i(result)->i_parent_dir = dir->i_ino;
-       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
@@ -168,8 +164,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        result->i_data.a_ops = &hpfs_aops;
        hpfs_i(result)->mmu_private = 0;
 
-       mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -178,7 +173,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
-       fnode->up = dir->i_ino;
+       fnode->up = cpu_to_le32(dir->i_ino);
        mark_buffer_dirty(bh);
        brelse(bh);
 
@@ -193,12 +188,10 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
                hpfs_write_inode_nolock(result);
        }
        d_instantiate(dentry, result);
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        hpfs_unlock(dir->i_sb);
        return 0;
 
 bail2:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        iput(result);
 bail1:
        brelse(bh);
@@ -232,8 +225,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        if (!(mode & 0222)) dee.read_only = 1;
        dee.archive = 1;
        dee.hidden = name[0] == '.';
-       dee.fnode = fno;
-       dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
+       dee.fnode = cpu_to_le32(fno);
+       dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
 
        result = new_inode(dir->i_sb);
        if (!result)
@@ -242,7 +235,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        hpfs_init_inode(result);
        result->i_ino = fno;
        hpfs_i(result)->i_parent_dir = dir->i_ino;
-       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
@@ -254,8 +247,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        result->i_blocks = 1;
        init_special_inode(result, mode, rdev);
 
-       mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -264,19 +256,17 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
-       fnode->up = dir->i_ino;
+       fnode->up = cpu_to_le32(dir->i_ino);
        mark_buffer_dirty(bh);
 
        insert_inode_hash(result);
 
        hpfs_write_inode_nolock(result);
        d_instantiate(dentry, result);
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        brelse(bh);
        hpfs_unlock(dir->i_sb);
        return 0;
 bail2:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        iput(result);
 bail1:
        brelse(bh);
@@ -310,8 +300,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        memset(&dee, 0, sizeof dee);
        dee.archive = 1;
        dee.hidden = name[0] == '.';
-       dee.fnode = fno;
-       dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
+       dee.fnode = cpu_to_le32(fno);
+       dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
 
        result = new_inode(dir->i_sb);
        if (!result)
@@ -319,7 +309,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        result->i_ino = fno;
        hpfs_init_inode(result);
        hpfs_i(result)->i_parent_dir = dir->i_ino;
-       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+       result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
@@ -333,8 +323,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        result->i_op = &page_symlink_inode_operations;
        result->i_data.a_ops = &hpfs_symlink_aops;
 
-       mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -343,7 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
-       fnode->up = dir->i_ino;
+       fnode->up = cpu_to_le32(dir->i_ino);
        hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
        mark_buffer_dirty(bh);
        brelse(bh);
@@ -352,11 +341,9 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 
        hpfs_write_inode_nolock(result);
        d_instantiate(dentry, result);
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        hpfs_unlock(dir->i_sb);
        return 0;
 bail2:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
        iput(result);
 bail1:
        brelse(bh);
@@ -374,7 +361,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        struct hpfs_dirent *de;
        struct inode *inode = dentry->d_inode;
        dnode_secno dno;
-       fnode_secno fno;
        int r;
        int rep = 0;
        int err;
@@ -382,8 +368,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        hpfs_lock(dir->i_sb);
        hpfs_adjust_length(name, &len);
 again:
-       mutex_lock(&hpfs_i(inode)->i_parent_mutex);
-       mutex_lock(&hpfs_i(dir)->i_mutex);
        err = -ENOENT;
        de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
@@ -397,7 +381,6 @@ again:
        if (de->directory)
                goto out1;
 
-       fno = de->fnode;
        r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
        switch (r) {
        case 1:
@@ -410,8 +393,6 @@ again:
                if (rep++)
                        break;
 
-               mutex_unlock(&hpfs_i(dir)->i_mutex);
-               mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
                dentry_unhash(dentry);
                if (!d_unhashed(dentry)) {
                        dput(dentry);
@@ -445,8 +426,6 @@ again:
 out1:
        hpfs_brelse4(&qbh);
 out:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
-       mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
        hpfs_unlock(dir->i_sb);
        return err;
 }
@@ -459,15 +438,12 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct hpfs_dirent *de;
        struct inode *inode = dentry->d_inode;
        dnode_secno dno;
-       fnode_secno fno;
        int n_items = 0;
        int err;
        int r;
 
        hpfs_adjust_length(name, &len);
        hpfs_lock(dir->i_sb);
-       mutex_lock(&hpfs_i(inode)->i_parent_mutex);
-       mutex_lock(&hpfs_i(dir)->i_mutex);
        err = -ENOENT;
        de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
@@ -486,7 +462,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (n_items)
                goto out1;
 
-       fno = de->fnode;
        r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
        switch (r) {
        case 1:
@@ -505,8 +480,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 out1:
        hpfs_brelse4(&qbh);
 out:
-       mutex_unlock(&hpfs_i(dir)->i_mutex);
-       mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
        hpfs_unlock(dir->i_sb);
        return err;
 }
@@ -568,12 +541,6 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        hpfs_lock(i->i_sb);
        /* order doesn't matter, due to VFS exclusion */
-       mutex_lock(&hpfs_i(i)->i_parent_mutex);
-       if (new_inode)
-               mutex_lock(&hpfs_i(new_inode)->i_parent_mutex);
-       mutex_lock(&hpfs_i(old_dir)->i_mutex);
-       if (new_dir != old_dir)
-               mutex_lock(&hpfs_i(new_dir)->i_mutex);
        
        /* Erm? Moving over the empty non-busy directory is perfectly legal */
        if (new_inode && S_ISDIR(new_inode->i_mode)) {
@@ -610,9 +577,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        if (new_dir == old_dir) hpfs_brelse4(&qbh);
 
-       hpfs_lock_creation(i->i_sb);
-       if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {
-               hpfs_unlock_creation(i->i_sb);
+       if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {
                if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
                err = r == 1 ? -ENOSPC : -EFSERROR;
                if (new_dir != old_dir) hpfs_brelse4(&qbh);
@@ -621,20 +586,17 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        
        if (new_dir == old_dir)
                if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
-                       hpfs_unlock_creation(i->i_sb);
                        hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
                        err = -ENOENT;
                        goto end1;
                }
 
        if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
-               hpfs_unlock_creation(i->i_sb);
                hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
                err = r == 2 ? -ENOSPC : -EFSERROR;
                goto end1;
        }
-       hpfs_unlock_creation(i->i_sb);
-       
+
        end:
        hpfs_i(i)->i_parent_dir = new_dir->i_ino;
        if (S_ISDIR(i->i_mode)) {
@@ -642,22 +604,14 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                drop_nlink(old_dir);
        }
        if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
-               fnode->up = new_dir->i_ino;
+               fnode->up = cpu_to_le32(new_dir->i_ino);
                fnode->len = new_len;
                memcpy(fnode->name, new_name, new_len>15?15:new_len);
                if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
                mark_buffer_dirty(bh);
                brelse(bh);
        }
-       hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
-       hpfs_decide_conv(i, new_name, new_len);
 end1:
-       if (old_dir != new_dir)
-               mutex_unlock(&hpfs_i(new_dir)->i_mutex);
-       mutex_unlock(&hpfs_i(old_dir)->i_mutex);
-       mutex_unlock(&hpfs_i(i)->i_parent_mutex);
-       if (new_inode)
-               mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex);
        hpfs_unlock(i->i_sb);
        return err;
 }
index c89b40808587925c616c4c20cc5e6ee5b6932aa0..98580a3b5005feea514e961476d9a0686c912979 100644 (file)
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
-static void mark_dirty(struct super_block *s)
+static void mark_dirty(struct super_block *s, int remount)
 {
-       if (hpfs_sb(s)->sb_chkdsk && !(s->s_flags & MS_RDONLY)) {
+       if (hpfs_sb(s)->sb_chkdsk && (remount || !(s->s_flags & MS_RDONLY))) {
                struct buffer_head *bh;
                struct hpfs_spare_block *sb;
                if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
                        sb->dirty = 1;
                        sb->old_wrote = 0;
                        mark_buffer_dirty(bh);
+                       sync_dirty_buffer(bh);
                        brelse(bh);
                }
        }
@@ -40,10 +41,12 @@ static void unmark_dirty(struct super_block *s)
        struct buffer_head *bh;
        struct hpfs_spare_block *sb;
        if (s->s_flags & MS_RDONLY) return;
+       sync_blockdev(s->s_bdev);
        if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
                sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error;
                sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error;
                mark_buffer_dirty(bh);
+               sync_dirty_buffer(bh);
                brelse(bh);
        }
 }
@@ -63,13 +66,13 @@ void hpfs_error(struct super_block *s, const char *fmt, ...)
        if (!hpfs_sb(s)->sb_was_error) {
                if (hpfs_sb(s)->sb_err == 2) {
                        printk("; crashing the system because you wanted it\n");
-                       mark_dirty(s);
+                       mark_dirty(s, 0);
                        panic("HPFS panic");
                } else if (hpfs_sb(s)->sb_err == 1) {
                        if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n");
                        else {
                                printk("; remounting read-only\n");
-                               mark_dirty(s);
+                               mark_dirty(s, 0);
                                s->s_flags |= MS_RDONLY;
                        }
                } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
@@ -102,9 +105,12 @@ static void hpfs_put_super(struct super_block *s)
 {
        struct hpfs_sb_info *sbi = hpfs_sb(s);
 
+       hpfs_lock(s);
+       unmark_dirty(s);
+       hpfs_unlock(s);
+
        kfree(sbi->sb_cp_table);
        kfree(sbi->sb_bmp_dir);
-       unmark_dirty(s);
        s->s_fs_info = NULL;
        kfree(sbi);
 }
@@ -129,7 +135,7 @@ static unsigned count_bitmaps(struct super_block *s)
        n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
        count = 0;
        for (n = 0; n < n_bands; n++)
-               count += hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_bmp_dir[n]);
+               count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
        return count;
 }
 
@@ -188,8 +194,6 @@ static void init_once(void *foo)
 {
        struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
 
-       mutex_init(&ei->i_mutex);
-       mutex_init(&ei->i_parent_mutex);
        inode_init_once(&ei->vfs_inode);
 }
 
@@ -218,7 +222,6 @@ static void destroy_inodecache(void)
 
 enum {
        Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis,
-       Opt_conv_binary, Opt_conv_text, Opt_conv_auto,
        Opt_check_none, Opt_check_normal, Opt_check_strict,
        Opt_err_cont, Opt_err_ro, Opt_err_panic,
        Opt_eas_no, Opt_eas_ro, Opt_eas_rw,
@@ -233,9 +236,6 @@ static const match_table_t tokens = {
        {Opt_umask, "umask=%o"},
        {Opt_case_lower, "case=lower"},
        {Opt_case_asis, "case=asis"},
-       {Opt_conv_binary, "conv=binary"},
-       {Opt_conv_text, "conv=text"},
-       {Opt_conv_auto, "conv=auto"},
        {Opt_check_none, "check=none"},
        {Opt_check_normal, "check=normal"},
        {Opt_check_strict, "check=strict"},
@@ -253,7 +253,7 @@ static const match_table_t tokens = {
 };
 
 static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
-                     int *lowercase, int *conv, int *eas, int *chk, int *errs,
+                     int *lowercase, int *eas, int *chk, int *errs,
                      int *chkdsk, int *timeshift)
 {
        char *p;
@@ -295,15 +295,6 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
                case Opt_case_asis:
                        *lowercase = 0;
                        break;
-               case Opt_conv_binary:
-                       *conv = CONV_BINARY;
-                       break;
-               case Opt_conv_text:
-                       *conv = CONV_TEXT;
-                       break;
-               case Opt_conv_auto:
-                       *conv = CONV_AUTO;
-                       break;
                case Opt_check_none:
                        *chk = 0;
                        break;
@@ -370,9 +361,6 @@ HPFS filesystem options:\n\
       umask=xxx         set mode of files that don't have mode specified in eas\n\
       case=lower        lowercase all files\n\
       case=asis         do not lowercase files (default)\n\
-      conv=binary       do not convert CR/LF -> LF (default)\n\
-      conv=auto         convert only files with known text extensions\n\
-      conv=text         convert all files\n\
       check=none        no fs checks - kernel may crash on corrupted filesystem\n\
       check=normal      do some checks - it should not crash (default)\n\
       check=strict      do extra time-consuming checks, used for debugging\n\
@@ -394,7 +382,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
        uid_t uid;
        gid_t gid;
        umode_t umask;
-       int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
+       int lowercase, eas, chk, errs, chkdsk, timeshift;
        int o;
        struct hpfs_sb_info *sbi = hpfs_sb(s);
        char *new_opts = kstrdup(data, GFP_KERNEL);
@@ -405,11 +393,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
        lock_super(s);
        uid = sbi->sb_uid; gid = sbi->sb_gid;
        umask = 0777 & ~sbi->sb_mode;
-       lowercase = sbi->sb_lowercase; conv = sbi->sb_conv;
+       lowercase = sbi->sb_lowercase;
        eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk;
        errs = sbi->sb_err; timeshift = sbi->sb_timeshift;
 
-       if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, &conv,
+       if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase,
            &eas, &chk, &errs, &chkdsk, &timeshift))) {
                printk("HPFS: bad mount options.\n");
                goto out_err;
@@ -427,11 +415,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 
        sbi->sb_uid = uid; sbi->sb_gid = gid;
        sbi->sb_mode = 0777 & ~umask;
-       sbi->sb_lowercase = lowercase; sbi->sb_conv = conv;
+       sbi->sb_lowercase = lowercase;
        sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk;
        sbi->sb_err = errs; sbi->sb_timeshift = timeshift;
 
-       if (!(*flags & MS_RDONLY)) mark_dirty(s);
+       if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
 
        replace_mount_options(s, new_opts);
 
@@ -471,7 +459,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        uid_t uid;
        gid_t gid;
        umode_t umask;
-       int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
+       int lowercase, eas, chk, errs, chkdsk, timeshift;
 
        dnode_secno root_dno;
        struct hpfs_dirent *de = NULL;
@@ -479,11 +467,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        int o;
 
-       if (num_possible_cpus() > 1) {
-               printk(KERN_ERR "HPFS is not SMP safe\n");
-               return -EINVAL;
-       }
-
        save_mount_options(s, options);
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
@@ -495,20 +478,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        sbi->sb_bmp_dir = NULL;
        sbi->sb_cp_table = NULL;
 
-       mutex_init(&sbi->hpfs_creation_de);
+       mutex_init(&sbi->hpfs_mutex);
+       hpfs_lock(s);
 
        uid = current_uid();
        gid = current_gid();
        umask = current_umask();
        lowercase = 0;
-       conv = CONV_BINARY;
        eas = 2;
        chk = 1;
        errs = 1;
        chkdsk = 1;
        timeshift = 0;
 
-       if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &conv,
+       if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,
            &eas, &chk, &errs, &chkdsk, &timeshift))) {
                printk("HPFS: bad mount options.\n");
                goto bail0;
@@ -526,9 +509,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3;
 
        /* Check magics */
-       if (/*bootblock->magic != BB_MAGIC
-           ||*/ superblock->magic != SB_MAGIC
-           || spareblock->magic != SP_MAGIC) {
+       if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC
+           ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC
+           || le32_to_cpu(spareblock->magic) != SP_MAGIC) {
                if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n");
                goto bail4;
        }
@@ -549,19 +532,18 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        s->s_op = &hpfs_sops;
        s->s_d_op = &hpfs_dentry_operations;
 
-       sbi->sb_root = superblock->root;
-       sbi->sb_fs_size = superblock->n_sectors;
-       sbi->sb_bitmaps = superblock->bitmaps;
-       sbi->sb_dirband_start = superblock->dir_band_start;
-       sbi->sb_dirband_size = superblock->n_dir_band;
-       sbi->sb_dmap = superblock->dir_band_bitmap;
+       sbi->sb_root = le32_to_cpu(superblock->root);
+       sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors);
+       sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps);
+       sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start);
+       sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band);
+       sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap);
        sbi->sb_uid = uid;
        sbi->sb_gid = gid;
        sbi->sb_mode = 0777 & ~umask;
        sbi->sb_n_free = -1;
        sbi->sb_n_free_dnodes = -1;
        sbi->sb_lowercase = lowercase;
-       sbi->sb_conv = conv;
        sbi->sb_eas = eas;
        sbi->sb_chk = chk;
        sbi->sb_chkdsk = chkdsk;
@@ -573,7 +555,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        sbi->sb_max_fwd_alloc = 0xffffff;
        
        /* Load bitmap directory */
-       if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps)))
+       if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
                goto bail4;
        
        /* Check for general fs errors*/
@@ -591,20 +573,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
                mark_buffer_dirty(bh2);
        }
 
-       if (spareblock->hotfixes_used || spareblock->n_spares_used) {
+       if (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) {
                if (errs >= 2) {
                        printk("HPFS: Hotfixes not supported here, try chkdsk\n");
-                       mark_dirty(s);
+                       mark_dirty(s, 0);
                        goto bail4;
                }
                hpfs_error(s, "hotfixes not supported here, try chkdsk");
                if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
                else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
        }
-       if (spareblock->n_dnode_spares != spareblock->n_dnode_spares_free) {
+       if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
                if (errs >= 2) {
                        printk("HPFS: Spare dnodes used, try chkdsk\n");
-                       mark_dirty(s);
+                       mark_dirty(s, 0);
                        goto bail4;
                }
                hpfs_error(s, "warning: spare dnodes used, try chkdsk");
@@ -612,26 +594,26 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        }
        if (chk) {
                unsigned a;
-               if (superblock->dir_band_end - superblock->dir_band_start + 1 != superblock->n_dir_band ||
-                   superblock->dir_band_end < superblock->dir_band_start || superblock->n_dir_band > 0x4000) {
+               if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) ||
+                   le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) {
                        hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
-                               superblock->dir_band_start, superblock->dir_band_end, superblock->n_dir_band);
+                               le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band));
                        goto bail4;
                }
                a = sbi->sb_dirband_size;
                sbi->sb_dirband_size = 0;
-               if (hpfs_chk_sectors(s, superblock->dir_band_start, superblock->n_dir_band, "dir_band") ||
-                   hpfs_chk_sectors(s, superblock->dir_band_bitmap, 4, "dir_band_bitmap") ||
-                   hpfs_chk_sectors(s, superblock->bitmaps, 4, "bitmaps")) {
-                       mark_dirty(s);
+               if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") ||
+                   hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") ||
+                   hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) {
+                       mark_dirty(s, 0);
                        goto bail4;
                }
                sbi->sb_dirband_size = a;
        } else printk("HPFS: You really don't want any checks? You are crazy...\n");
 
        /* Load code page table */
-       if (spareblock->n_code_pages)
-               if (!(sbi->sb_cp_table = hpfs_load_code_page(s, spareblock->code_page_dir)))
+       if (le32_to_cpu(spareblock->n_code_pages))
+               if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir))))
                        printk("HPFS: Warning: code page support is disabled\n");
 
        brelse(bh2);
@@ -660,13 +642,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        if (!de)
                hpfs_error(s, "unable to find root dir");
        else {
-               root->i_atime.tv_sec = local_to_gmt(s, de->read_date);
+               root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date));
                root->i_atime.tv_nsec = 0;
-               root->i_mtime.tv_sec = local_to_gmt(s, de->write_date);
+               root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date));
                root->i_mtime.tv_nsec = 0;
-               root->i_ctime.tv_sec = local_to_gmt(s, de->creation_date);
+               root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
                root->i_ctime.tv_nsec = 0;
-               hpfs_i(root)->i_ea_size = de->ea_size;
+               hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size);
                hpfs_i(root)->i_parent_dir = root->i_ino;
                if (root->i_size == -1)
                        root->i_size = 2048;
@@ -674,6 +656,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
                        root->i_blocks = 5;
                hpfs_brelse4(&qbh);
        }
+       hpfs_unlock(s);
        return 0;
 
 bail4: brelse(bh2);
@@ -681,6 +664,7 @@ bail3:      brelse(bh1);
 bail2: brelse(bh0);
 bail1:
 bail0:
+       hpfs_unlock(s);
        kfree(sbi->sb_bmp_dir);
        kfree(sbi->sb_cp_table);
        s->s_fs_info = NULL;
index 33435e4b14d24aaad89bfab57da526870bbfa797..ce03a182c771c42e39e90c0f7b3737b897d02215 100644 (file)
@@ -480,10 +480,6 @@ static int logfs_read_sb(struct super_block *sb, int read_only)
                        !read_only)
                return -EIO;
 
-       mutex_init(&super->s_dirop_mutex);
-       mutex_init(&super->s_object_alias_mutex);
-       INIT_LIST_HEAD(&super->s_freeing_list);
-
        ret = logfs_init_rw(sb);
        if (ret)
                return ret;
@@ -601,6 +597,10 @@ static struct dentry *logfs_mount(struct file_system_type *type, int flags,
        if (!super)
                return ERR_PTR(-ENOMEM);
 
+       mutex_init(&super->s_dirop_mutex);
+       mutex_init(&super->s_object_alias_mutex);
+       INIT_LIST_HEAD(&super->s_freeing_list);
+
        if (!devname)
                err = logfs_get_sb_bdev(super, type, devname);
        else if (strncmp(devname, "mtd", 3))
index 54fc993e3027d4dff98dcf4f14ebbb4d817cdb0f..e3c4f112ebf754525de7d5634c298e9d4ba4fba8 100644 (file)
@@ -179,7 +179,7 @@ EXPORT_SYMBOL(putname);
 static int acl_permission_check(struct inode *inode, int mask, unsigned int flags,
                int (*check_acl)(struct inode *inode, int mask, unsigned int flags))
 {
-       umode_t                 mode = inode->i_mode;
+       unsigned int mode = inode->i_mode;
 
        mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
 
index 89fc160fd5b071af390ee4aea4590e929c43acee..1f063bacd2857caa119f4dce1bf429402b0be909 100644 (file)
@@ -119,7 +119,7 @@ Elong:
 }
 
 #ifdef CONFIG_NFS_V4
-static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode)
+static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
 {
        struct gss_api_mech *mech;
        struct xdr_netobj oid;
@@ -166,7 +166,7 @@ static int nfs_negotiate_security(const struct dentry *parent,
                }
                flavors = page_address(page);
                ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
-               *flavor = nfs_find_best_sec(flavors, dentry->d_inode);
+               *flavor = nfs_find_best_sec(flavors);
                put_page(page);
        }
 
index e1c261ddd65dc591408633469e5e90ec176f476c..c4a69833dd0d5b1abf3223e6e63f2153606ef9c5 100644 (file)
@@ -47,6 +47,7 @@ enum nfs4_client_state {
        NFS4CLNT_LAYOUTRECALL,
        NFS4CLNT_SESSION_RESET,
        NFS4CLNT_RECALL_SLOT,
+       NFS4CLNT_LEASE_CONFIRM,
 };
 
 enum nfs4_session_state {
index 6f8192f4cfc759b653c186c5122565bacdd96631..be79dc9f386da265328c1975127e8f577c85ed25 100644 (file)
@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
        case -EKEYEXPIRED:
                rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
                break;
+       case -NFS4ERR_RETRY_UNCACHED_REP:
+               break;
        default:
                dprintk("%s DS error. Retry through MDS %d\n", __func__,
                        task->tk_status);
@@ -416,7 +418,8 @@ static int
 filelayout_check_layout(struct pnfs_layout_hdr *lo,
                        struct nfs4_filelayout_segment *fl,
                        struct nfs4_layoutget_res *lgr,
-                       struct nfs4_deviceid *id)
+                       struct nfs4_deviceid *id,
+                       gfp_t gfp_flags)
 {
        struct nfs4_file_layout_dsaddr *dsaddr;
        int status = -EINVAL;
@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
        /* find and reference the deviceid */
        dsaddr = nfs4_fl_find_get_deviceid(id);
        if (dsaddr == NULL) {
-               dsaddr = get_device_info(lo->plh_inode, id);
+               dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
                if (dsaddr == NULL)
                        goto out;
        }
@@ -500,7 +503,8 @@ static int
 filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                         struct nfs4_filelayout_segment *fl,
                         struct nfs4_layoutget_res *lgr,
-                        struct nfs4_deviceid *id)
+                        struct nfs4_deviceid *id,
+                        gfp_t gfp_flags)
 {
        struct xdr_stream stream;
        struct xdr_buf buf = {
@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
 
        dprintk("%s: set_layout_map Begin\n", __func__);
 
-       scratch = alloc_page(GFP_KERNEL);
+       scratch = alloc_page(gfp_flags);
        if (!scratch)
                return -ENOMEM;
 
@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                goto out_err;
 
        fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
-                              GFP_KERNEL);
+                              gfp_flags);
        if (!fl->fh_array)
                goto out_err;
 
        for (i = 0; i < fl->num_fh; i++) {
                /* Do we want to use a mempool here? */
-               fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
+               fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags);
                if (!fl->fh_array[i])
                        goto out_err_free;
 
@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
 
 static struct pnfs_layout_segment *
 filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
-                     struct nfs4_layoutget_res *lgr)
+                     struct nfs4_layoutget_res *lgr,
+                     gfp_t gfp_flags)
 {
        struct nfs4_filelayout_segment *fl;
        int rc;
        struct nfs4_deviceid id;
 
        dprintk("--> %s\n", __func__);
-       fl = kzalloc(sizeof(*fl), GFP_KERNEL);
+       fl = kzalloc(sizeof(*fl), gfp_flags);
        if (!fl)
                return NULL;
 
-       rc = filelayout_decode_layout(layoutid, fl, lgr, &id);
-       if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) {
+       rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags);
+       if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) {
                _filelayout_free_lseg(fl);
                return NULL;
        }
@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
                int size = (fl->stripe_type == STRIPE_SPARSE) ?
                        fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
 
-               fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL);
+               fl->commit_buckets = kcalloc(size, sizeof(struct list_head), gfp_flags);
                if (!fl->commit_buckets) {
                        filelayout_free_lseg(&fl->generic_hdr);
                        return NULL;
index 7c44579f583250a34c97d622023ec335a70a0cca..2b461d77b43a9efa1c8235a955c18941ee8f56b5 100644 (file)
@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr *
 nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id);
 extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
-get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id);
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index de5350f2b2492139bf9b9d913a5bdf9e99a50ec3..db07c7af139519a3b938e44e0042a8d91102434c 100644 (file)
@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
 }
 
 static struct nfs4_pnfs_ds *
-nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
+nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port, gfp_t gfp_flags)
 {
        struct nfs4_pnfs_ds *tmp_ds, *ds;
 
-       ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL);
+       ds = kzalloc(sizeof(*tmp_ds), gfp_flags);
        if (!ds)
                goto out;
 
@@ -261,7 +261,7 @@ out:
  * Currently only support ipv4, and one multi-path address.
  */
 static struct nfs4_pnfs_ds *
-decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
+decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_flags)
 {
        struct nfs4_pnfs_ds *ds = NULL;
        char *buf;
@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
                        rlen);
                goto out_err;
        }
-       buf = kmalloc(rlen + 1, GFP_KERNEL);
+       buf = kmalloc(rlen + 1, gfp_flags);
        if (!buf) {
                dprintk("%s: Not enough memory\n", __func__);
                goto out_err;
@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
        sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]);
        port = htons((tmp[0] << 8) | (tmp[1]));
 
-       ds = nfs4_pnfs_ds_add(inode, ip_addr, port);
+       ds = nfs4_pnfs_ds_add(inode, ip_addr, port, gfp_flags);
        dprintk("%s: Decoded address and port %s\n", __func__, buf);
 out_free:
        kfree(buf);
@@ -343,7 +343,7 @@ out_err:
 
 /* Decode opaque device data and return the result */
 static struct nfs4_file_layout_dsaddr*
-decode_device(struct inode *ino, struct pnfs_device *pdev)
+decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
 {
        int i;
        u32 cnt, num;
@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
        struct page *scratch;
 
        /* set up xdr stream */
-       scratch = alloc_page(GFP_KERNEL);
+       scratch = alloc_page(gfp_flags);
        if (!scratch)
                goto out_err;
 
@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
        }
 
        /* read stripe indices */
-       stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL);
+       stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags);
        if (!stripe_indices)
                goto out_err_free_scratch;
 
@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
 
        dsaddr = kzalloc(sizeof(*dsaddr) +
                        (sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
-                       GFP_KERNEL);
+                       gfp_flags);
        if (!dsaddr)
                goto out_err_free_stripe_indices;
 
@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
                for (j = 0; j < mp_count; j++) {
                        if (j == 0) {
                                dsaddr->ds_list[i] = decode_and_add_ds(&stream,
-                                       ino);
+                                       ino, gfp_flags);
                                if (dsaddr->ds_list[i] == NULL)
                                        goto out_err_free_deviceid;
                        } else {
@@ -503,12 +503,12 @@ out_err:
  * available devices.
  */
 static struct nfs4_file_layout_dsaddr *
-decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
+decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags)
 {
        struct nfs4_file_layout_dsaddr *d, *new;
        long hash;
 
-       new = decode_device(inode, dev);
+       new = decode_device(inode, dev, gfp_flags);
        if (!new) {
                printk(KERN_WARNING "%s: Could not decode or add device\n",
                        __func__);
@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
  * of available devices, and return it.
  */
 struct nfs4_file_layout_dsaddr *
-get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags)
 {
        struct pnfs_device *pdev = NULL;
        u32 max_resp_sz;
@@ -556,17 +556,17 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
        dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
                __func__, inode, max_resp_sz, max_pages);
 
-       pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL);
+       pdev = kzalloc(sizeof(struct pnfs_device), gfp_flags);
        if (pdev == NULL)
                return NULL;
 
-       pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL);
+       pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
        if (pages == NULL) {
                kfree(pdev);
                return NULL;
        }
        for (i = 0; i < max_pages; i++) {
-               pages[i] = alloc_page(GFP_KERNEL);
+               pages[i] = alloc_page(gfp_flags);
                if (!pages[i])
                        goto out_free;
        }
@@ -587,7 +587,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
         * Found new device, need to decode it and then add it to the
         * list of known devices for this mountpoint.
         */
-       dsaddr = decode_and_add_device(inode, pdev);
+       dsaddr = decode_and_add_device(inode, pdev, gfp_flags);
 out_free:
        for (i = 0; i < max_pages; i++)
                __free_page(pages[i]);
index 9bf41eab3e4646eb1256c1192c4482fc89c4c61d..cf1b339c3937f7d959c6e5cbcf4a056ac16fbb2e 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/nfs_mount.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
@@ -299,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                        ret = nfs4_delay(server->client, &exception->timeout);
                        if (ret != 0)
                                break;
+               case -NFS4ERR_RETRY_UNCACHED_REP:
                case -NFS4ERR_OLD_STATEID:
                        exception->retry = 1;
                        break;
@@ -443,8 +445,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
        if (res->sr_status == 1)
                res->sr_status = NFS_OK;
 
-       /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-       if (!res->sr_slot)
+       /* don't increment the sequence number if the task wasn't sent */
+       if (!RPC_WAS_SENT(task))
                goto out;
 
        /* Check the SEQUENCE operation status */
@@ -2185,9 +2187,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_lookup_root(server, fhandle, info),
-                               &exception);
+               err = _nfs4_lookup_root(server, fhandle, info);
+               switch (err) {
+               case 0:
+               case -NFS4ERR_WRONGSEC:
+                       break;
+               default:
+                       err = nfs4_handle_exception(server, err, &exception);
+               }
        } while (exception.retry);
        return err;
 }
@@ -2208,25 +2215,47 @@ out:
        return ret;
 }
 
-/*
- * get the file handle for the "/" directory on the server
- */
-static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
                              struct nfs_fsinfo *info)
 {
        int i, len, status = 0;
-       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
+       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
 
-       flav_array[0] = RPC_AUTH_UNIX;
-       len = gss_mech_list_pseudoflavors(&flav_array[1]);
-       flav_array[1+len] = RPC_AUTH_NULL;
-       len += 2;
+       len = gss_mech_list_pseudoflavors(&flav_array[0]);
+       flav_array[len] = RPC_AUTH_NULL;
+       len += 1;
 
        for (i = 0; i < len; i++) {
                status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
-               if (status != -EPERM)
-                       break;
+               if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
+                       continue;
+               break;
        }
+       /*
+        * -EACCESS could mean that the user doesn't have correct permissions
+        * to access the mount.  It could also mean that we tried to mount
+        * with a gss auth flavor, but rpc.gssd isn't running.  Either way,
+        * existing mount programs don't handle -EACCES very well so it should
+        * be mapped to -EPERM instead.
+        */
+       if (status == -EACCES)
+               status = -EPERM;
+       return status;
+}
+
+/*
+ * get the file handle for the "/" directory on the server
+ */
+static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+                             struct nfs_fsinfo *info)
+{
+       int status = nfs4_lookup_root(server, fhandle, info);
+       if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
+               /*
+                * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
+                * by nfs4_map_errors() as this function exits.
+                */
+               status = nfs4_find_root_sec(server, fhandle, info);
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
        if (status == 0)
@@ -3667,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        rpc_delay(task, NFS4_POLL_RETRY_MAX);
                        task->tk_status = 0;
                        return -EAGAIN;
+               case -NFS4ERR_RETRY_UNCACHED_REP:
                case -NFS4ERR_OLD_STATEID:
                        task->tk_status = 0;
                        return -EAGAIN;
@@ -3723,21 +3753,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                                sizeof(setclientid.sc_uaddr), "%s.%u.%u",
                                clp->cl_ipaddr, port >> 8, port & 255);
 
-               status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+               status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
                if (status != -NFS4ERR_CLID_INUSE)
                        break;
-               if (signalled())
+               if (loop != 0) {
+                       ++clp->cl_id_uniquifier;
                        break;
-               if (loop++ & 1)
-                       ssleep(clp->cl_lease_time / HZ + 1);
-               else
-                       if (++clp->cl_id_uniquifier == 0)
-                               break;
+               }
+               ++loop;
+               ssleep(clp->cl_lease_time / HZ + 1);
        }
        return status;
 }
 
-static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
+int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                struct nfs4_setclientid_res *arg,
                struct rpc_cred *cred)
 {
@@ -3752,7 +3781,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        int status;
 
        now = jiffies;
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (status == 0) {
                spin_lock(&clp->cl_lock);
                clp->cl_lease_time = fsinfo.lease_time * HZ;
@@ -3762,26 +3791,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        return status;
 }
 
-int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
-               struct nfs4_setclientid_res *arg,
-               struct rpc_cred *cred)
-{
-       long timeout = 0;
-       int err;
-       do {
-               err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
-               switch (err) {
-                       case 0:
-                               return err;
-                       case -NFS4ERR_RESOURCE:
-                               /* The IBM lawyers misread another document! */
-                       case -NFS4ERR_DELAY:
-                               err = nfs4_delay(clp->cl_rpcclient, &timeout);
-               }
-       } while (err == 0);
-       return err;
-}
-
 struct nfs4_delegreturndata {
        struct nfs4_delegreturnargs args;
        struct nfs4_delegreturnres res;
@@ -4786,7 +4795,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                                init_utsname()->domainname,
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (!status)
                status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
        dprintk("<-- %s status= %d\n", __func__, status);
@@ -4837,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
                dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
                rpc_delay(task, NFS4_POLL_RETRY_MIN);
                task->tk_status = 0;
+               /* fall through */
+       case -NFS4ERR_RETRY_UNCACHED_REP:
                nfs_restart_rpc(task, data->clp);
                return;
        }
@@ -4869,7 +4880,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
                .rpc_client = clp->cl_rpcclient,
                .rpc_message = &msg,
                .callback_ops = &nfs4_get_lease_time_ops,
-               .callback_data = &data
+               .callback_data = &data,
+               .flags = RPC_TASK_TIMEOUT,
        };
        int status;
 
@@ -5171,7 +5183,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
        nfs4_init_channel_attrs(&args);
        args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
 
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (!status)
                /* Verify the session's negotiated channel_attrs values */
@@ -5194,20 +5206,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
        int status;
        unsigned *ptr;
        struct nfs4_session *session = clp->cl_session;
-       long timeout = 0;
-       int err;
 
        dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
 
-       do {
-               status = _nfs4_proc_create_session(clp);
-               if (status == -NFS4ERR_DELAY) {
-                       err = nfs4_delay(clp->cl_rpcclient, &timeout);
-                       if (err)
-                               status = err;
-               }
-       } while (status == -NFS4ERR_DELAY);
-
+       status = _nfs4_proc_create_session(clp);
        if (status)
                goto out;
 
@@ -5248,7 +5250,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
        msg.rpc_argp = session;
        msg.rpc_resp = NULL;
        msg.rpc_cred = NULL;
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (status)
                printk(KERN_WARNING
@@ -5481,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
                break;
        case -NFS4ERR_DELAY:
                rpc_delay(task, NFS4_POLL_RETRY_MAX);
+               /* fall through */
+       case -NFS4ERR_RETRY_UNCACHED_REP:
                return -EAGAIN;
        default:
                nfs4_schedule_lease_recovery(clp);
index a6804f704d9d8656868b6492c66232020132fe6d..036f5adc9e1fad417eb13c2b8687e6ea56abb613 100644 (file)
@@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list);
 
 int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
 {
-       struct nfs4_setclientid_res clid;
+       struct nfs4_setclientid_res clid = {
+               .clientid = clp->cl_clientid,
+               .confirm = clp->cl_confirm,
+       };
        unsigned short port;
        int status;
 
+       if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
+               goto do_confirm;
        port = nfs_callback_tcpport;
        if (clp->cl_addr.ss_family == AF_INET6)
                port = nfs_callback_tcpport6;
@@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
        status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
        if (status != 0)
                goto out;
+       clp->cl_clientid = clid.clientid;
+       clp->cl_confirm = clid.confirm;
+       set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+do_confirm:
        status = nfs4_proc_setclientid_confirm(clp, &clid, cred);
        if (status != 0)
                goto out;
-       clp->cl_clientid = clid.clientid;
+       clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
        nfs4_schedule_state_renewal(clp);
 out:
        return status;
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
 {
        int status;
 
+       if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
+               goto do_confirm;
        nfs4_begin_drain_session(clp);
        status = nfs4_proc_exchange_id(clp, cred);
        if (status != 0)
                goto out;
+       set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+do_confirm:
        status = nfs4_proc_create_session(clp);
        if (status != 0)
                goto out;
+       clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
        nfs41_setup_state_renewal(clp);
        nfs_mark_client_ready(clp, NFS_CS_READY);
 out:
@@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
  */
 static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
 {
-       if (nfs4_has_session(clp)) {
-               switch (status) {
-               case -NFS4ERR_DELAY:
-               case -NFS4ERR_CLID_INUSE:
-               case -EAGAIN:
-                       break;
+       switch (status) {
+       case -NFS4ERR_CLID_INUSE:
+       case -NFS4ERR_STALE_CLIENTID:
+               clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+               break;
+       case -NFS4ERR_DELAY:
+       case -ETIMEDOUT:
+       case -EAGAIN:
+               ssleep(1);
+               break;
 
-               case -EKEYEXPIRED:
-                       nfs4_warn_keyexpired(clp->cl_hostname);
-               case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
-                                        * in nfs4_exchange_id */
-               default:
-                       return;
-               }
+       case -EKEYEXPIRED:
+               nfs4_warn_keyexpired(clp->cl_hostname);
+       case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
+                                * in nfs4_exchange_id */
+       default:
+               return;
        }
        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
 }
@@ -1607,7 +1624,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
        int status = 0;
 
        /* Ensure exclusive access to NFSv4 state */
-       for(;;) {
+       do {
                if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
                        /* We're going to have to re-establish a clientid */
                        status = nfs4_reclaim_lease(clp);
@@ -1691,7 +1708,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                        break;
                if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
                        break;
-       }
+       } while (atomic_read(&clp->cl_count) > 1);
        return;
 out_error:
        printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
index dddfb5795d7b8c67999ebfc819b5cd8021e36cd8..c3ccd2c468344fab9076214fec8d99fc1eee9036 100644 (file)
@@ -1452,26 +1452,25 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
 
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
-       uint32_t attrs[2] = {0, 0};
+       uint32_t attrs[2] = {
+               FATTR4_WORD0_RDATTR_ERROR,
+               FATTR4_WORD1_MOUNTED_ON_FILEID,
+       };
        uint32_t dircount = readdir->count >> 1;
        __be32 *p;
 
        if (readdir->plus) {
                attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
-                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
+                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
                attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
                        FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
                        FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
                        FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
                dircount >>= 1;
        }
-       attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
-       attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
-       /* Switch to mounted_on_fileid if the server supports it */
-       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
-               attrs[0] &= ~FATTR4_WORD0_FILEID;
-       else
-               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+       /* Use mounted_on_fileid only if the server supports it */
+       if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
+               attrs[0] |= FATTR4_WORD0_FILEID;
 
        p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
        *p++ = cpu_to_be32(OP_READDIR);
@@ -3140,7 +3139,7 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma
                        goto out_overflow;
                xdr_decode_hyper(p, fileid);
                bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
-               ret = NFS_ATTR_FATTR_FILEID;
+               ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
        }
        dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
        return ret;
@@ -4002,7 +4001,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
 {
        int status;
        umode_t fmode = 0;
-       uint64_t fileid;
        uint32_t type;
 
        status = decode_attr_type(xdr, bitmap, &type);
@@ -4101,13 +4099,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
                goto xdr_error;
        fattr->valid |= status;
 
-       status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid);
+       status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid);
        if (status < 0)
                goto xdr_error;
-       if (status != 0 && !(fattr->valid & status)) {
-               fattr->fileid = fileid;
-               fattr->valid |= status;
-       }
+       fattr->valid |= status;
 
 xdr_error:
        dprintk("%s: xdr returned %d\n", __func__, -status);
@@ -4838,17 +4833,21 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
        struct nfs4_secinfo_flavor *sec_flavor;
        int status;
        __be32 *p;
-       int i;
+       int i, num_flavors;
 
        status = decode_op_hdr(xdr, OP_SECINFO);
+       if (status)
+               goto out;
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
-       res->flavors->num_flavors = be32_to_cpup(p);
 
-       for (i = 0; i < res->flavors->num_flavors; i++) {
+       res->flavors->num_flavors = 0;
+       num_flavors = be32_to_cpup(p);
+
+       for (i = 0; i < num_flavors; i++) {
                sec_flavor = &res->flavors->flavors[i];
-               if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE)
+               if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE)
                        break;
 
                p = xdr_inline_decode(xdr, 4);
@@ -4857,13 +4856,15 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
                sec_flavor->flavor = be32_to_cpup(p);
 
                if (sec_flavor->flavor == RPC_AUTH_GSS) {
-                       if (decode_secinfo_gss(xdr, sec_flavor))
-                               break;
+                       status = decode_secinfo_gss(xdr, sec_flavor);
+                       if (status)
+                               goto out;
                }
+               res->flavors->num_flavors++;
        }
 
-       return 0;
-
+out:
+       return status;
 out_overflow:
        print_overflow_msg(__func__, xdr);
        return -EIO;
@@ -6408,7 +6409,9 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
        if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
                                        entry->server, 1) < 0)
                goto out_overflow;
-       if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+       if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+               entry->ino = entry->fattr->mounted_on_fileid;
+       else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
                entry->ino = entry->fattr->fileid;
 
        entry->d_type = DT_UNKNOWN;
index d9ab97269ce6e83c2fbd652fddebb789f761a271..f57f5281a52090ac8445a3ebb362515708225661 100644 (file)
@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
                                plh_layouts);
                dprintk("%s freeing layout for inode %lu\n", __func__,
                        lo->plh_inode->i_ino);
+               list_del_init(&lo->plh_layouts);
                pnfs_destroy_layout(NFS_I(lo->plh_inode));
        }
 }
@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
 static struct pnfs_layout_segment *
 send_layoutget(struct pnfs_layout_hdr *lo,
           struct nfs_open_context *ctx,
-          u32 iomode)
+          u32 iomode,
+          gfp_t gfp_flags)
 {
        struct inode *ino = lo->plh_inode;
        struct nfs_server *server = NFS_SERVER(ino);
@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        dprintk("--> %s\n", __func__);
 
        BUG_ON(ctx == NULL);
-       lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
+       lgp = kzalloc(sizeof(*lgp), gfp_flags);
        if (lgp == NULL)
                return NULL;
 
@@ -487,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
        max_pages = max_resp_sz >> PAGE_SHIFT;
 
-       pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL);
+       pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
        if (!pages)
                goto out_err_free;
 
        for (i = 0; i < max_pages; i++) {
-               pages[i] = alloc_page(GFP_KERNEL);
+               pages[i] = alloc_page(gfp_flags);
                if (!pages[i])
                        goto out_err_free;
        }
@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        lgp->args.layout.pages = pages;
        lgp->args.layout.pglen = max_pages * PAGE_SIZE;
        lgp->lsegpp = &lseg;
+       lgp->gfp_flags = gfp_flags;
 
        /* Synchronously retrieve layout information from server and
         * store in lseg.
@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
 }
 
 static struct pnfs_layout_hdr *
-alloc_init_layout_hdr(struct inode *ino)
+alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags)
 {
        struct pnfs_layout_hdr *lo;
 
-       lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
+       lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags);
        if (!lo)
                return NULL;
        atomic_set(&lo->plh_refcount, 1);
@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino)
 }
 
 static struct pnfs_layout_hdr *
-pnfs_find_alloc_layout(struct inode *ino)
+pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
 {
        struct nfs_inode *nfsi = NFS_I(ino);
        struct pnfs_layout_hdr *new = NULL;
@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino)
                        return nfsi->layout;
        }
        spin_unlock(&ino->i_lock);
-       new = alloc_init_layout_hdr(ino);
+       new = alloc_init_layout_hdr(ino, gfp_flags);
        spin_lock(&ino->i_lock);
 
        if (likely(nfsi->layout == NULL))       /* Won the race? */
@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
 struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino,
                   struct nfs_open_context *ctx,
-                  enum pnfs_iomode iomode)
+                  enum pnfs_iomode iomode,
+                  gfp_t gfp_flags)
 {
        struct nfs_inode *nfsi = NFS_I(ino);
        struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino,
        if (!pnfs_enabled_sb(NFS_SERVER(ino)))
                return NULL;
        spin_lock(&ino->i_lock);
-       lo = pnfs_find_alloc_layout(ino);
+       lo = pnfs_find_alloc_layout(ino, gfp_flags);
        if (lo == NULL) {
                dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
                goto out_unlock;
@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino,
                spin_unlock(&clp->cl_lock);
        }
 
-       lseg = send_layoutget(lo, ctx, iomode);
+       lseg = send_layoutget(lo, ctx, iomode, gfp_flags);
        if (!lseg && first) {
                spin_lock(&clp->cl_lock);
                list_del_init(&lo->plh_layouts);
@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out;
        }
        /* Inject layout blob into I/O device driver */
-       lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res);
+       lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags);
        if (!lseg || IS_ERR(lseg)) {
                if (!lseg)
                        status = -ENOMEM;
@@ -899,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio,
                /* This is first coelesce call for a series of nfs_pages */
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   prev->wb_context,
-                                                  IOMODE_READ);
+                                                  IOMODE_READ,
+                                                  GFP_KERNEL);
        }
        return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
 }
@@ -921,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,
                /* This is first coelesce call for a series of nfs_pages */
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   prev->wb_context,
-                                                  IOMODE_RW);
+                                                  IOMODE_RW,
+                                                  GFP_NOFS);
        }
        return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
 }
@@ -1004,6 +1010,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
 {
        struct nfs_inode *nfsi = NFS_I(wdata->inode);
        loff_t end_pos = wdata->args.offset + wdata->res.count;
+       bool mark_as_dirty = false;
 
        spin_lock(&nfsi->vfs_inode.i_lock);
        if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
@@ -1011,13 +1018,18 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
                get_lseg(wdata->lseg);
                wdata->lseg->pls_lc_cred =
                        get_rpccred(wdata->args.context->state->owner->so_cred);
-               mark_inode_dirty_sync(wdata->inode);
+               mark_as_dirty = true;
                dprintk("%s: Set layoutcommit for inode %lu ",
                        __func__, wdata->inode->i_ino);
        }
        if (end_pos > wdata->lseg->pls_end_pos)
                wdata->lseg->pls_end_pos = end_pos;
        spin_unlock(&nfsi->vfs_inode.i_lock);
+
+       /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
+        * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
+       if (mark_as_dirty)
+               mark_inode_dirty_sync(wdata->inode);
 }
 EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
 
index bc4827202e7a2c862ae628c1e27b0bae48a9a93d..0c015bad9e7aa4c780297746a988581c8c69acda 100644 (file)
@@ -70,7 +70,7 @@ struct pnfs_layoutdriver_type {
        const u32 id;
        const char *name;
        struct module *owner;
-       struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
+       struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
        void (*free_lseg) (struct pnfs_layout_segment *lseg);
 
        /* test for nfs page cache coalescing */
@@ -126,7 +126,7 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo);
 void put_lseg(struct pnfs_layout_segment *lseg);
 struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
-                  enum pnfs_iomode access_type);
+                  enum pnfs_iomode access_type, gfp_t gfp_flags);
 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
 void unset_pnfs_layoutdriver(struct nfs_server *);
 enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
@@ -245,7 +245,7 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg)
 
 static inline struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
-                  enum pnfs_iomode access_type)
+                  enum pnfs_iomode access_type, gfp_t gfp_flags)
 {
        return NULL;
 }
index 7cded2b12a05eb0016421304afc87b68458fd03b..2bcf0dc306a1000e2211ef117670ac47f6ef4407 100644 (file)
@@ -288,7 +288,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
        atomic_set(&req->wb_complete, requests);
 
        BUG_ON(desc->pg_lseg != NULL);
-       lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ);
+       lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL);
        ClearPageError(page);
        offset = 0;
        nbytes = desc->pg_count;
@@ -351,7 +351,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
        }
        req = nfs_list_entry(data->pages.next);
        if ((!lseg) && list_is_singular(&data->pages))
-               lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ);
+               lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL);
 
        ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count,
                                0, lseg);
index 2b8e9a5e366a67a7eb6ce228d14df6ed69f51fb9..e288f06d3fa7de5f6d06e134b1854230aa9b7611 100644 (file)
@@ -1004,6 +1004,7 @@ static int nfs_parse_security_flavors(char *value,
                return 0;
        }
 
+       mnt->flags |= NFS_MOUNT_SECFLAVOUR;
        mnt->auth_flavor_len = 1;
        return 1;
 }
@@ -1976,6 +1977,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        if (error < 0)
                goto out;
 
+       /*
+        * noac is a special case. It implies -o sync, but that's not
+        * necessarily reflected in the mtab options. do_remount_sb
+        * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the
+        * remount options, so we have to explicitly reset it.
+        */
+       if (data->flags & NFS_MOUNT_NOAC)
+               *flags |= MS_SYNCHRONOUS;
+
        /* compare new mount options with old ones */
        error = nfs_compare_remount_data(nfss, data);
 out:
@@ -2235,8 +2245,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
        if (!s->s_root) {
                /* initial superblock/root creation */
                nfs_fill_super(s, data);
-               nfs_fscache_get_super_cookie(
-                       s, data ? data->fscache_uniq : NULL, NULL);
+               nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL);
        }
 
        mntroot = nfs_get_root(s, mntfh, dev_name);
index e4cbc11a74ab56238687c5445989177a7714dd5a..49c715b4ac927b9bbd283e0f991118d34bf9af10 100644 (file)
@@ -680,7 +680,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
        req = nfs_setup_write_request(ctx, page, offset, count);
        if (IS_ERR(req))
                return PTR_ERR(req);
-       nfs_mark_request_dirty(req);
        /* Update file length */
        nfs_grow_file(page, offset, count);
        nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
@@ -940,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
        atomic_set(&req->wb_complete, requests);
 
        BUG_ON(desc->pg_lseg);
-       lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW);
+       lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS);
        ClearPageError(page);
        offset = 0;
        nbytes = desc->pg_count;
@@ -1014,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
        }
        req = nfs_list_entry(data->pages.next);
        if ((!lseg) && list_is_singular(&data->pages))
-               lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW);
+               lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS);
 
        if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
            (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit))
@@ -1418,8 +1417,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                                 task->tk_pid, task->tk_status);
 
        /* Call the NFS version-specific code */
-       if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
-               return;
+       NFS_PROTO(data->inode)->commit_done(task, data);
 }
 
 void nfs_commit_release_pages(struct nfs_write_data *data)
index aa309aa93fe81be66e5e33c4d404ebec4b815f86..4cf04e11c66ca39c80dc6b54b6854842de246826 100644 (file)
@@ -258,6 +258,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp)
        if (atomic_dec_and_test(&fp->fi_delegees)) {
                vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
                fp->fi_lease = NULL;
+               fput(fp->fi_deleg_file);
                fp->fi_deleg_file = NULL;
        }
 }
@@ -402,8 +403,8 @@ static void free_generic_stateid(struct nfs4_stateid *stp)
        if (stp->st_access_bmap) {
                oflag = nfs4_access_bmap_to_omode(stp);
                nfs4_file_put_access(stp->st_file, oflag);
-               put_nfs4_file(stp->st_file);
        }
+       put_nfs4_file(stp->st_file);
        kmem_cache_free(stateid_slab, stp);
 }
 
index 2e1cebde90df4c69baa21635e959f9d81c9809f1..129f3c9f62d589f44b947fccd04c8f745cdfb485 100644 (file)
@@ -1363,7 +1363,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
        if (!(iap->ia_valid & ATTR_MODE))
                iap->ia_mode = 0;
-       err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+       err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
        if (err)
                goto out;
 
@@ -1385,6 +1385,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (IS_ERR(dchild))
                goto out_nfserr;
 
+       /* If file doesn't exist, check for permissions to create one */
+       if (!dchild->d_inode) {
+               err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+               if (err)
+                       goto out;
+       }
+
        err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
        if (err)
                goto out;
index 0a0a66d98cce85f327b32080c8a97045e8babdf7..f7684483785e848c1e59657ab141801100796012 100644 (file)
@@ -646,7 +646,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
        unsigned long group, group_offset;
        int i, j, n, ret;
 
-       for (i = 0; i < nitems; i += n) {
+       for (i = 0; i < nitems; i = j) {
                group = nilfs_palloc_group(inode, entry_nrs[i], &group_offset);
                ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh);
                if (ret < 0)
index 643720209a9899506b9a1c477b458b91b5070d4c..9a3e6bbff27bd4839b487c2c14282fd9ef1a4675 100644 (file)
@@ -539,25 +539,41 @@ static int o2hb_verify_crc(struct o2hb_region *reg,
 
 /* We want to make sure that nobody is heartbeating on top of us --
  * this will help detect an invalid configuration. */
-static int o2hb_check_last_timestamp(struct o2hb_region *reg)
+static void o2hb_check_last_timestamp(struct o2hb_region *reg)
 {
-       int node_num, ret;
        struct o2hb_disk_slot *slot;
        struct o2hb_disk_heartbeat_block *hb_block;
+       char *errstr;
 
-       node_num = o2nm_this_node();
-
-       ret = 1;
-       slot = &reg->hr_slots[node_num];
+       slot = &reg->hr_slots[o2nm_this_node()];
        /* Don't check on our 1st timestamp */
-       if (slot->ds_last_time) {
-               hb_block = slot->ds_raw_block;
+       if (!slot->ds_last_time)
+               return;
 
-               if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time)
-                       ret = 0;
-       }
+       hb_block = slot->ds_raw_block;
+       if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time &&
+           le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation &&
+           hb_block->hb_node == slot->ds_node_num)
+               return;
 
-       return ret;
+#define ERRSTR1                "Another node is heartbeating on device"
+#define ERRSTR2                "Heartbeat generation mismatch on device"
+#define ERRSTR3                "Heartbeat sequence mismatch on device"
+
+       if (hb_block->hb_node != slot->ds_node_num)
+               errstr = ERRSTR1;
+       else if (le64_to_cpu(hb_block->hb_generation) !=
+                slot->ds_last_generation)
+               errstr = ERRSTR2;
+       else
+               errstr = ERRSTR3;
+
+       mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), "
+            "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name,
+            slot->ds_node_num, (unsigned long long)slot->ds_last_generation,
+            (unsigned long long)slot->ds_last_time, hb_block->hb_node,
+            (unsigned long long)le64_to_cpu(hb_block->hb_generation),
+            (unsigned long long)le64_to_cpu(hb_block->hb_seq));
 }
 
 static inline void o2hb_prepare_block(struct o2hb_region *reg,
@@ -983,9 +999,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
        /* With an up to date view of the slots, we can check that no
         * other node has been improperly configured to heartbeat in
         * our slot. */
-       if (!o2hb_check_last_timestamp(reg))
-               mlog(ML_ERROR, "Device \"%s\": another node is heartbeating "
-                    "in our slot!\n", reg->hr_dev_name);
+       o2hb_check_last_timestamp(reg);
 
        /* fill in the proper info for our next heartbeat */
        o2hb_prepare_block(reg, reg->hr_generation);
@@ -999,8 +1013,8 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
        }
 
        i = -1;
-       while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
-
+       while((i = find_next_bit(configured_nodes,
+                                O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
                change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
        }
 
@@ -1690,6 +1704,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        struct file *filp = NULL;
        struct inode *inode = NULL;
        ssize_t ret = -EINVAL;
+       int live_threshold;
 
        if (reg->hr_bdev)
                goto out;
@@ -1766,8 +1781,18 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
         * A node is considered live after it has beat LIVE_THRESHOLD
         * times.  We're not steady until we've given them a chance
         * _after_ our first read.
+        * The default threshold is bare minimum so as to limit the delay
+        * during mounts. For global heartbeat, the threshold doubled for the
+        * first region.
         */
-       atomic_set(&reg->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1);
+       live_threshold = O2HB_LIVE_THRESHOLD;
+       if (o2hb_global_heartbeat_active()) {
+               spin_lock(&o2hb_live_lock);
+               if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+                       live_threshold <<= 1;
+               spin_unlock(&o2hb_live_lock);
+       }
+       atomic_set(&reg->hr_steady_iterations, live_threshold + 1);
 
        hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
                              reg->hr_item.ci_name);
index 9fe5b8fd658f0a3db09f1919512a0479a241ecca..8582e3f4f120647d05df81556639e627882b5811 100644 (file)
@@ -2868,7 +2868,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                bytes = blocks_wanted << sb->s_blocksize_bits;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        struct ocfs2_inode_info *oi = OCFS2_I(dir);
-       struct ocfs2_alloc_context *data_ac;
+       struct ocfs2_alloc_context *data_ac = NULL;
        struct ocfs2_alloc_context *meta_ac = NULL;
        struct buffer_head *dirdata_bh = NULL;
        struct buffer_head *dx_root_bh = NULL;
index 7540a492eaba0188d624a08f73688eee04838288..3b179d6cbde09be9017eb21fbefcc5df8b217a53 100644 (file)
@@ -1614,7 +1614,8 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
        spin_unlock(&dlm->spinlock);
 
        /* Support for global heartbeat and node info was added in 1.1 */
-       if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) {
+       if (dlm->dlm_locking_proto.pv_major > 1 ||
+           dlm->dlm_locking_proto.pv_minor > 0) {
                status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map);
                if (status) {
                        mlog_errno(status);
index fede57ed005ff417b80b5c3bc9c1d25fe3aaa526..84d166328cf7448f36cfcb0a54f08eefda50e18d 100644 (file)
@@ -2574,6 +2574,9 @@ fail:
                res->state &= ~DLM_LOCK_RES_MIGRATING;
                wake = 1;
                spin_unlock(&res->spinlock);
+               if (dlm_is_host_down(ret))
+                       dlm_wait_for_node_death(dlm, target,
+                                               DLM_NODE_DEATH_WAIT_MAX);
                goto leave;
        }
 
index 41565ae528566b3a5bfca14092aad21bba721812..89659d6dc2067276f2cebcea63a9bcc34a0a2486 100644 (file)
@@ -1607,6 +1607,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
        range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
 
        if (le32_to_cpu(rec->e_cpos) >= trunc_start) {
+               /*
+                * remove an entire extent record.
+                */
                *trunc_cpos = le32_to_cpu(rec->e_cpos);
                /*
                 * Skip holes if any.
@@ -1617,7 +1620,16 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
                *blkno = le64_to_cpu(rec->e_blkno);
                *trunc_end = le32_to_cpu(rec->e_cpos);
        } else if (range > trunc_start) {
+               /*
+                * remove a partial extent record, which means we're
+                * removing the last extent record.
+                */
                *trunc_cpos = trunc_start;
+               /*
+                * skip hole if any.
+                */
+               if (range < *trunc_end)
+                       *trunc_end = range;
                *trunc_len = *trunc_end - trunc_start;
                coff = trunc_start - le32_to_cpu(rec->e_cpos);
                *blkno = le64_to_cpu(rec->e_blkno) +
index b141a44605ca076132cd704e22226ac8ce263fa7..295d56454e8b23b6e9d97a6bd258e6170311c8f5 100644 (file)
@@ -1260,6 +1260,9 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb)
 {
        struct ocfs2_journal *journal = osb->journal;
 
+       if (ocfs2_is_hard_readonly(osb))
+               return;
+
        /* No need to queue up our truncate_log as regular cleanup will catch
         * that */
        ocfs2_queue_recovery_completion(journal, osb->slot_num,
index b68f87a8392462933d3ed32e47d52aa8fe0c77ce..938387a10d5d7c2caa65ee5faeb1649d5fbc578d 100644 (file)
@@ -1019,7 +1019,7 @@ struct ocfs2_xattr_entry {
        __le16  xe_name_offset;  /* byte offset from the 1st entry in the
                                    local xattr storage(inode, xattr block or
                                    xattr bucket). */
-       __u8    xe_name_len;     /* xattr name len, does't include prefix. */
+       __u8    xe_name_len;     /* xattr name len, doesn't include prefix. */
        __u8    xe_type;         /* the low 7 bits indicate the name prefix
                                  * type and the highest bit indicates whether
                                  * the EA is stored in the local storage. */
index ac0ccb5026a2d107eb5e5e38c84e4bdfe51682ed..19d6750d1d6ce3b5571e463ee2fb2d768985d644 100644 (file)
@@ -348,6 +348,12 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
                goto fail;
        }
 
+       /* Check that sizeof_partition_entry has the correct value */
+       if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
+               pr_debug("GUID Partitition Entry Size check failed.\n");
+               goto fail;
+       }
+
        if (!(*ptes = alloc_read_gpt_entries(state, *gpt)))
                goto fail;
 
index 2e7addfd9803559ca03a2527aaab161006e3b482..318d8654989bf70479321fb8599b0dcf9ac29365 100644 (file)
@@ -214,7 +214,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
        int flags = vma->vm_flags;
        unsigned long ino = 0;
        unsigned long long pgoff = 0;
-       unsigned long start;
+       unsigned long start, end;
        dev_t dev = 0;
        int len;
 
@@ -227,13 +227,15 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
 
        /* We don't show the stack guard page in /proc/maps */
        start = vma->vm_start;
-       if (vma->vm_flags & VM_GROWSDOWN)
-               if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
-                       start += PAGE_SIZE;
+       if (stack_guard_page_start(vma, start))
+               start += PAGE_SIZE;
+       end = vma->vm_end;
+       if (stack_guard_page_end(vma, end))
+               end -= PAGE_SIZE;
 
        seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
                        start,
-                       vma->vm_end,
+                       end,
                        flags & VM_READ ? 'r' : '-',
                        flags & VM_WRITE ? 'w' : '-',
                        flags & VM_EXEC ? 'x' : '-',
index 4d0cb1241460fbc2eacd709188293d5782b1dd3b..40fa780ebea7d6280cc83f30ca4db9b0a0052b98 100644 (file)
@@ -174,26 +174,6 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
        spin_unlock(&c->buds_lock);
 }
 
-/**
- * ubifs_create_buds_lists - create journal head buds lists for remount rw.
- * @c: UBIFS file-system description object
- */
-void ubifs_create_buds_lists(struct ubifs_info *c)
-{
-       struct rb_node *p;
-
-       spin_lock(&c->buds_lock);
-       p = rb_first(&c->buds);
-       while (p) {
-               struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
-               struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
-
-               list_add_tail(&bud->list, &jhead->buds_list);
-               p = rb_next(p);
-       }
-       spin_unlock(&c->buds_lock);
-}
-
 /**
  * ubifs_add_bud_to_log - add a new bud to the log.
  * @c: UBIFS file-system description object
index 936f2cbfe6b672437aec08219ad017f0fc6f3074..3dbad6fbd1eba528661e458ae56e97c03c43b609 100644 (file)
@@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c)
                        goto out_free;
                }
                memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
+
+               /*
+                * We had to recover the master node, which means there was an
+                * unclean reboot. However, it is possible that the master node
+                * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
+                * E.g., consider the following chain of events:
+                *
+                * 1. UBIFS was cleanly unmounted, so the master node is clean
+                * 2. UBIFS is being mounted R/W and starts changing the master
+                *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
+                *    so this LEB ends up with some amount of garbage at the
+                *    end.
+                * 3. UBIFS is being mounted R/O. We reach this place and
+                *    recover the master node from the second LEB
+                *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
+                *    because we are being mounted R/O. We have to defer the
+                *    operation.
+                * 4. However, this master node (@c->mst_node) is marked as
+                *    clean (since the step 1). And if we just return, the
+                *    mount code will be confused and won't recover the master
+                *    node when it is re-mounter R/W later.
+                *
+                *    Thus, to force the recovery by marking the master node as
+                *    dirty.
+                */
+               c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
        } else {
                /* Write the recovered master node */
                c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
index eed0fcff8d731710dc7723d25b1adb10ecbe6805..d3d6d365bfc11345d49e3a6bbdc33dd97c476ea9 100644 (file)
@@ -59,6 +59,7 @@ enum {
  * @new_size: truncation new size
  * @free: amount of free space in a bud
  * @dirty: amount of dirty space in a bud from padding and deletion nodes
+ * @jhead: journal head number of the bud
  *
  * UBIFS journal replay must compare node sequence numbers, which means it must
  * build a tree of node information to insert into the TNC.
@@ -80,6 +81,7 @@ struct replay_entry {
                struct {
                        int free;
                        int dirty;
+                       int jhead;
                };
        };
 };
@@ -159,6 +161,11 @@ static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r)
                err = PTR_ERR(lp);
                goto out;
        }
+
+       /* Make sure the journal head points to the latest bud */
+       err = ubifs_wbuf_seek_nolock(&c->jheads[r->jhead].wbuf, r->lnum,
+                                    c->leb_size - r->free, UBI_SHORTTERM);
+
 out:
        ubifs_release_lprops(c);
        return err;
@@ -627,10 +634,6 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
        ubifs_assert(sleb->endpt - offs >= used);
        ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-       if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
-               err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
-                                            sleb->endpt, UBI_SHORTTERM);
-
        *dirty = sleb->endpt - offs - used;
        *free = c->leb_size - sleb->endpt;
 
@@ -653,12 +656,14 @@ out_dump:
  * @sqnum: sequence number
  * @free: amount of free space in bud
  * @dirty: amount of dirty space from padding and deletion nodes
+ * @jhead: journal head number for the bud
  *
  * This function inserts a reference node to the replay tree and returns zero
  * in case of success or a negative error code in case of failure.
  */
 static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
-                          unsigned long long sqnum, int free, int dirty)
+                          unsigned long long sqnum, int free, int dirty,
+                          int jhead)
 {
        struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
        struct replay_entry *r;
@@ -688,6 +693,7 @@ static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
        r->flags = REPLAY_REF;
        r->free = free;
        r->dirty = dirty;
+       r->jhead = jhead;
 
        rb_link_node(&r->rb, parent, p);
        rb_insert_color(&r->rb, &c->replay_tree);
@@ -712,7 +718,7 @@ static int replay_buds(struct ubifs_info *c)
                if (err)
                        return err;
                err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum,
-                                     free, dirty);
+                                     free, dirty, b->bud->jhead);
                if (err)
                        return err;
        }
index c75f6133206cf5edfbf88d1162a81d5001953cb1..04ad07f4fcc3da11b05e868442ed6f3bc7ad7729 100644 (file)
@@ -1257,12 +1257,12 @@ static int mount_ubifs(struct ubifs_info *c)
                goto out_free;
        }
 
+       err = alloc_wbufs(c);
+       if (err)
+               goto out_cbuf;
+
        sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
        if (!c->ro_mount) {
-               err = alloc_wbufs(c);
-               if (err)
-                       goto out_cbuf;
-
                /* Create background thread */
                c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
                if (IS_ERR(c->bgt)) {
@@ -1631,12 +1631,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (err)
                goto out;
 
-       err = alloc_wbufs(c);
-       if (err)
-               goto out;
-
-       ubifs_create_buds_lists(c);
-
        /* Create background thread */
        c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
        if (IS_ERR(c->bgt)) {
@@ -1671,14 +1665,25 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (err)
                goto out;
 
+       dbg_gen("re-mounted read-write");
+       c->remounting_rw = 0;
+
        if (c->need_recovery) {
                c->need_recovery = 0;
                ubifs_msg("deferred recovery completed");
+       } else {
+               /*
+                * Do not run the debugging space check if the were doing
+                * recovery, because when we saved the information we had the
+                * file-system in a state where the TNC and lprops has been
+                * modified in memory, but all the I/O operations (including a
+                * commit) were deferred. So the file-system was in
+                * "non-committed" state. Now the file-system is in committed
+                * state, and of course the amount of free space will change
+                * because, for example, the old index size was imprecise.
+                */
+               err = dbg_check_space_info(c);
        }
-
-       dbg_gen("re-mounted read-write");
-       c->remounting_rw = 0;
-       err = dbg_check_space_info(c);
        mutex_unlock(&c->umount_mutex);
        return err;
 
@@ -1733,7 +1738,6 @@ static void ubifs_remount_ro(struct ubifs_info *c)
        if (err)
                ubifs_ro_mode(c, err);
 
-       free_wbufs(c);
        vfree(c->orph_buf);
        c->orph_buf = NULL;
        kfree(c->write_reserve_buf);
@@ -1761,10 +1765,12 @@ static void ubifs_put_super(struct super_block *sb)
         * of the media. For example, there will be dirty inodes if we failed
         * to write them back because of I/O errors.
         */
-       ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
-       ubifs_assert(c->budg_idx_growth == 0);
-       ubifs_assert(c->budg_dd_growth == 0);
-       ubifs_assert(c->budg_data_growth == 0);
+       if (!c->ro_error) {
+               ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
+               ubifs_assert(c->budg_idx_growth == 0);
+               ubifs_assert(c->budg_dd_growth == 0);
+               ubifs_assert(c->budg_data_growth == 0);
+       }
 
        /*
         * The 'c->umount_lock' prevents races between UBIFS memory shrinker
index a19acdb81cd1270c174711c851b17013edb9ca80..f1ef94974dea12f10beceff4a12899851ba7aeab 100644 (file)
@@ -666,7 +666,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(dentry, name, value, size, 0, handler->flags);
+       return handler->set(dentry, name, value, size, flags, handler->flags);
 }
 
 /*
index 3ca795609113c259483099d0bbdaae9815b2cc0e..9f76cceb678d8aec6db86a53863c7c6fc0f36c19 100644 (file)
@@ -34,8 +34,10 @@ __xfs_printk(
        const struct xfs_mount  *mp,
        struct va_format        *vaf)
 {
-       if (mp && mp->m_fsname)
+       if (mp && mp->m_fsname) {
                printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf);
+               return;
+       }
        printk("%sXFS: %pV\n", level, vaf);
 }
 
index e4f9c1b0836c9ef8ef9feb3515d2f29a97565004..3e898a48122d3921f56683c313b071968cc4a9df 100644 (file)
@@ -926,6 +926,7 @@ restart:
                                        XFS_LOOKUP_BATCH,
                                        XFS_ICI_RECLAIM_TAG);
                        if (!nr_found) {
+                               done = 1;
                                rcu_read_unlock();
                                break;
                        }
index acdb92f14d518fe43ac9c0be62d67ae49831ca1d..5fc2380092c8b88eae987cdfcf2bbd280ee92cdb 100644 (file)
@@ -346,20 +346,23 @@ xfs_ail_delete(
  */
 STATIC void
 xfs_ail_worker(
-       struct work_struct *work)
+       struct work_struct      *work)
 {
-       struct xfs_ail  *ailp = container_of(to_delayed_work(work),
+       struct xfs_ail          *ailp = container_of(to_delayed_work(work),
                                        struct xfs_ail, xa_work);
-       long            tout;
-       xfs_lsn_t       target =  ailp->xa_target;
-       xfs_lsn_t       lsn;
-       xfs_log_item_t  *lip;
-       int             flush_log, count, stuck;
-       xfs_mount_t     *mp = ailp->xa_mount;
+       xfs_mount_t             *mp = ailp->xa_mount;
        struct xfs_ail_cursor   *cur = &ailp->xa_cursors;
-       int             push_xfsbufd = 0;
+       xfs_log_item_t          *lip;
+       xfs_lsn_t               lsn;
+       xfs_lsn_t               target;
+       long                    tout = 10;
+       int                     flush_log = 0;
+       int                     stuck = 0;
+       int                     count = 0;
+       int                     push_xfsbufd = 0;
 
        spin_lock(&ailp->xa_lock);
+       target = ailp->xa_target;
        xfs_trans_ail_cursor_init(ailp, cur);
        lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
        if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
@@ -368,8 +371,7 @@ xfs_ail_worker(
                 */
                xfs_trans_ail_cursor_done(ailp, cur);
                spin_unlock(&ailp->xa_lock);
-               ailp->xa_last_pushed_lsn = 0;
-               return;
+               goto out_done;
        }
 
        XFS_STATS_INC(xs_push_ail);
@@ -386,8 +388,7 @@ xfs_ail_worker(
         * lots of contention on the AIL lists.
         */
        lsn = lip->li_lsn;
-       flush_log = stuck = count = 0;
-       while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) {
+       while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) {
                int     lock_result;
                /*
                 * If we can lock the item without sleeping, unlock the AIL
@@ -480,21 +481,25 @@ xfs_ail_worker(
        }
 
        /* assume we have more work to do in a short while */
-       tout = 10;
+out_done:
        if (!count) {
                /* We're past our target or empty, so idle */
                ailp->xa_last_pushed_lsn = 0;
 
                /*
-                * Check for an updated push target before clearing the
-                * XFS_AIL_PUSHING_BIT. If the target changed, we've got more
-                * work to do. Wait a bit longer before starting that work.
+                * We clear the XFS_AIL_PUSHING_BIT first before checking
+                * whether the target has changed. If the target has changed,
+                * this pushes the requeue race directly onto the result of the
+                * atomic test/set bit, so we are guaranteed that either the
+                * the pusher that changed the target or ourselves will requeue
+                * the work (but not both).
                 */
+               clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
                smp_rmb();
-               if (ailp->xa_target == target) {
-                       clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
+               if (XFS_LSN_CMP(ailp->xa_target, target) == 0 ||
+                   test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
                        return;
-               }
+
                tout = 50;
        } else if (XFS_LSN_CMP(lsn, target) >= 0) {
                /*
@@ -553,7 +558,7 @@ xfs_ail_push(
         * the XFS_AIL_PUSHING_BIT.
         */
        smp_wmb();
-       ailp->xa_target = threshold_lsn;
+       xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
        if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
                queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);
 }
index bd297a20ab98786b4d2a1d08e3cbb53d87103351..077c00d94f6e47f63092d6731085e61e12c012db 100644 (file)
        STRUCT_ALIGN();                                                 \
        *(__tracepoints)                                                \
        /* implement dynamic printk debug */                            \
+       . = ALIGN(8);                                                   \
+       VMLINUX_SYMBOL(__start___jump_table) = .;                       \
+       *(__jump_table)                                                 \
+       VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
        . = ALIGN(8);                                                   \
        VMLINUX_SYMBOL(__start___verbose) = .;                          \
        *(__verbose)                                                    \
                                                                        \
        BUG_TABLE                                                       \
                                                                        \
-       JUMP_TABLE                                                      \
-                                                                       \
        /* PCI quirks */                                                \
        .pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {        \
                VMLINUX_SYMBOL(__start_pci_fixups_early) = .;           \
        /* Kernel symbol table: Normal symbols */                       \
        __ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {         \
                VMLINUX_SYMBOL(__start___ksymtab) = .;                  \
-               *(__ksymtab)                                            \
+               *(SORT(___ksymtab+*))                                   \
                VMLINUX_SYMBOL(__stop___ksymtab) = .;                   \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-only symbols */                     \
        __ksymtab_gpl     : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) {     \
                VMLINUX_SYMBOL(__start___ksymtab_gpl) = .;              \
-               *(__ksymtab_gpl)                                        \
+               *(SORT(___ksymtab_gpl+*))                               \
                VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;               \
        }                                                               \
                                                                        \
        /* Kernel symbol table: Normal unused symbols */                \
        __ksymtab_unused  : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) {  \
                VMLINUX_SYMBOL(__start___ksymtab_unused) = .;           \
-               *(__ksymtab_unused)                                     \
+               *(SORT(___ksymtab_unused+*))                            \
                VMLINUX_SYMBOL(__stop___ksymtab_unused) = .;            \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-only unused symbols */              \
        __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
                VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .;       \
-               *(__ksymtab_unused_gpl)                                 \
+               *(SORT(___ksymtab_unused_gpl+*))                        \
                VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .;        \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-future-only symbols */              \
        __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
                VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .;       \
-               *(__ksymtab_gpl_future)                                 \
+               *(SORT(___ksymtab_gpl_future+*))                        \
                VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .;        \
        }                                                               \
                                                                        \
        /* Kernel symbol table: Normal symbols */                       \
        __kcrctab         : AT(ADDR(__kcrctab) - LOAD_OFFSET) {         \
                VMLINUX_SYMBOL(__start___kcrctab) = .;                  \
-               *(__kcrctab)                                            \
+               *(SORT(___kcrctab+*))                                   \
                VMLINUX_SYMBOL(__stop___kcrctab) = .;                   \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-only symbols */                     \
        __kcrctab_gpl     : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) {     \
                VMLINUX_SYMBOL(__start___kcrctab_gpl) = .;              \
-               *(__kcrctab_gpl)                                        \
+               *(SORT(___kcrctab_gpl+*))                               \
                VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .;               \
        }                                                               \
                                                                        \
        /* Kernel symbol table: Normal unused symbols */                \
        __kcrctab_unused  : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) {  \
                VMLINUX_SYMBOL(__start___kcrctab_unused) = .;           \
-               *(__kcrctab_unused)                                     \
+               *(SORT(___kcrctab_unused+*))                            \
                VMLINUX_SYMBOL(__stop___kcrctab_unused) = .;            \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-only unused symbols */              \
        __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
                VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .;       \
-               *(__kcrctab_unused_gpl)                                 \
+               *(SORT(___kcrctab_unused_gpl+*))                        \
                VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .;        \
        }                                                               \
                                                                        \
        /* Kernel symbol table: GPL-future-only symbols */              \
        __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
                VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .;       \
-               *(__kcrctab_gpl_future)                                 \
+               *(SORT(___kcrctab_gpl_future+*))                        \
                VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .;        \
        }                                                               \
                                                                        \
 #define BUG_TABLE
 #endif
 
-#define JUMP_TABLE                                                     \
-       . = ALIGN(8);                                                   \
-       __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) {           \
-               VMLINUX_SYMBOL(__start___jump_table) = .;               \
-               *(__jump_table)                                         \
-               VMLINUX_SYMBOL(__stop___jump_table) = .;                \
-       }
-
 #ifdef CONFIG_PM_TRACE
 #define TRACEDATA                                                      \
        . = ALIGN(4);                                                   \
index f22e7fe4b6dbf25815580ad3625fd09f5aed3946..c99c3d3e78113d8a8596d0696464034c5e20fe8b 100644 (file)
@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno,
                            unsigned transp,
                            struct fb_info *info);
 
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_restore(void);
 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
                            uint32_t fb_width, uint32_t fb_height);
@@ -126,7 +127,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
+int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
 bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
 int drm_fb_helper_debug_enter(struct fb_info *info);
index c2f93a8ae2e14b414bc6976c811f92406f7c4557..564b14aa7e165e70e45d741f1f2b88dd26992a65 100644 (file)
@@ -86,7 +86,7 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
 }
 #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
                                                &(mm)->head_node.node_list, \
-                                               node_list);
+                                               node_list)
 #define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
        for (entry = (mm)->prev_scanned_node, \
                next = entry ? list_entry(entry->node_list.next, \
index 816e30cbd9689ac59fbea5d92ca06c16d1558384..f04b2a3b0f49b7117cb74163af0997a7a6fd4742 100644 (file)
        {0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x671f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6729, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6739, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x673e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6741, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x689b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x68ba, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x68bf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
index 3bce1a4fc305b48f35667183f21b32f9a325fead..787f7b6fd62237683eb5dad3ecbd77958128f3f1 100644 (file)
@@ -909,6 +909,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_WANT_CMASK         0x08 /* get access to CMASK on r300 */
 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */
 #define RADEON_INFO_NUM_BACKENDS       0x0a /* DB/backends for r600+ - need for OQ */
+#define RADEON_INFO_NUM_TILE_PIPES     0x0b /* tile pipes for r600+ */
+#define RADEON_INFO_FUSION_GART_WORKING        0x0c /* fusion writes to GTT were broken before this */
 
 struct drm_radeon_info {
        uint32_t                request;
diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h
new file mode 100644 (file)
index 0000000..c5d6095
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _LINUX_ALARMTIMER_H
+#define _LINUX_ALARMTIMER_H
+
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/timerqueue.h>
+#include <linux/rtc.h>
+
+enum alarmtimer_type {
+       ALARM_REALTIME,
+       ALARM_BOOTTIME,
+
+       ALARM_NUMTYPE,
+};
+
+/**
+ * struct alarm - Alarm timer structure
+ * @node:      timerqueue node for adding to the event list this value
+ *             also includes the expiration time.
+ * @period:    Period for recuring alarms
+ * @function:  Function pointer to be executed when the timer fires.
+ * @type:      Alarm type (BOOTTIME/REALTIME)
+ * @enabled:   Flag that represents if the alarm is set to fire or not
+ * @data:      Internal data value.
+ */
+struct alarm {
+       struct timerqueue_node  node;
+       ktime_t                 period;
+       void                    (*function)(struct alarm *);
+       enum alarmtimer_type    type;
+       bool                    enabled;
+       void                    *data;
+};
+
+void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
+               void (*function)(struct alarm *));
+void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
+void alarm_cancel(struct alarm *alarm);
+
+#endif
index e612575a259683c2429cd2d1b46a1cc9671d8141..b4326bfa684f24c3ad147de3cb7d63a9f066da80 100644 (file)
@@ -23,11 +23,11 @@ static inline void bit_spin_lock(int bitnum, unsigned long *addr)
        preempt_disable();
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
        while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
-               while (test_bit(bitnum, addr)) {
-                       preempt_enable();
+               preempt_enable();
+               do {
                        cpu_relax();
-                       preempt_disable();
-               }
+               } while (test_bit(bitnum, addr));
+               preempt_disable();
        }
 #endif
        __acquire(bitlock);
index cbbfd98ad4a3f73f9f088a996236f0ae015eef7a..2ad95fa1d130f8c8f5cfd68e5fe7a0108aec31d9 100644 (file)
@@ -388,20 +388,19 @@ struct request_queue
 #define        QUEUE_FLAG_SYNCFULL     3       /* read queue has been filled */
 #define QUEUE_FLAG_ASYNCFULL   4       /* write queue has been filled */
 #define QUEUE_FLAG_DEAD                5       /* queue being torn down */
-#define QUEUE_FLAG_REENTER     6       /* Re-entrancy avoidance */
-#define QUEUE_FLAG_ELVSWITCH   7       /* don't use elevator, just do FIFO */
-#define QUEUE_FLAG_BIDI                8       /* queue supports bidi requests */
-#define QUEUE_FLAG_NOMERGES     9      /* disable merge attempts */
-#define QUEUE_FLAG_SAME_COMP   10      /* force complete on same CPU */
-#define QUEUE_FLAG_FAIL_IO     11      /* fake timeout */
-#define QUEUE_FLAG_STACKABLE   12      /* supports request stacking */
-#define QUEUE_FLAG_NONROT      13      /* non-rotational device (SSD) */
+#define QUEUE_FLAG_ELVSWITCH   6       /* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_BIDI                7       /* queue supports bidi requests */
+#define QUEUE_FLAG_NOMERGES     8      /* disable merge attempts */
+#define QUEUE_FLAG_SAME_COMP   9       /* force complete on same CPU */
+#define QUEUE_FLAG_FAIL_IO     10      /* fake timeout */
+#define QUEUE_FLAG_STACKABLE   11      /* supports request stacking */
+#define QUEUE_FLAG_NONROT      12      /* non-rotational device (SSD) */
 #define QUEUE_FLAG_VIRT        QUEUE_FLAG_NONROT /* paravirt device */
-#define QUEUE_FLAG_IO_STAT     15      /* do IO stats */
-#define QUEUE_FLAG_DISCARD     16      /* supports DISCARD */
-#define QUEUE_FLAG_NOXMERGES   17      /* No extended merges */
-#define QUEUE_FLAG_ADD_RANDOM  18      /* Contributes to random pool */
-#define QUEUE_FLAG_SECDISCARD  19      /* supports SECDISCARD */
+#define QUEUE_FLAG_IO_STAT     13      /* do IO stats */
+#define QUEUE_FLAG_DISCARD     14      /* supports DISCARD */
+#define QUEUE_FLAG_NOXMERGES   15      /* No extended merges */
+#define QUEUE_FLAG_ADD_RANDOM  16      /* Contributes to random pool */
+#define QUEUE_FLAG_SECDISCARD  17      /* supports SECDISCARD */
 
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
@@ -699,6 +698,7 @@ extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(struct request_queue *q);
 extern void __blk_run_queue(struct request_queue *q);
 extern void blk_run_queue(struct request_queue *);
+extern void blk_run_queue_async(struct request_queue *q);
 extern int blk_rq_map_user(struct request_queue *, struct request *,
                           struct rq_map_data *, void __user *, unsigned long,
                           gfp_t);
index b8613e806aa9c0b410b119519bc7044e44889570..01eca1794e148efb906d3aa9fe0327abb49cbd8a 100644 (file)
@@ -111,6 +111,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
        __alloc_bootmem_nopanic(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_node(pgdat, x) \
        __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_node_nopanic(pgdat, x) \
+       __alloc_bootmem_node_nopanic(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node(pgdat, x) \
        __alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node_nopanic(pgdat, x) \
diff --git a/include/linux/bsearch.h b/include/linux/bsearch.h
new file mode 100644 (file)
index 0000000..90b1aa8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _LINUX_BSEARCH_H
+#define _LINUX_BSEARCH_H
+
+#include <linux/types.h>
+
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+             int (*cmp)(const void *key, const void *elt));
+
+#endif /* _LINUX_BSEARCH_H */
index 16ee8b49a20030cc190c36d4689e43e0c01348a8..4554db0cde863dab0c454b42e6c032651545bf8f 100644 (file)
@@ -355,7 +355,12 @@ struct cpu_vfs_cap_data {
 
 #define CAP_SYSLOG           34
 
-#define CAP_LAST_CAP         CAP_SYSLOG
+/* Allow triggering something that will wake the system */
+
+#define CAP_WAKE_ALARM            35
+
+
+#define CAP_LAST_CAP         CAP_WAKE_ALARM
 
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 
@@ -546,18 +551,7 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap);
 extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool task_ns_capable(struct task_struct *t, int cap);
-
-/**
- * nsown_capable - Check superior capability to one's own user_ns
- * @cap: The capability in question
- *
- * Return true if the current task has the given superior capability
- * targeted at its own user namespace.
- */
-static inline bool nsown_capable(int cap)
-{
-       return ns_capable(current_user_ns(), cap);
-}
+extern bool nsown_capable(int cap);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
index fc53492b6ad7fb67e904e88d2f02d184771a326e..d6733e27af349349bdcf97f1a7674a530bc99e2f 100644 (file)
@@ -56,46 +56,52 @@ enum clock_event_nofitiers {
 
 /**
  * struct clock_event_device - clock event device descriptor
- * @name:              ptr to clock event name
- * @features:          features
+ * @event_handler:     Assigned by the framework to be called by the low
+ *                     level handler of the event source
+ * @set_next_event:    set next event function
+ * @next_event:                local storage for the next event in oneshot mode
  * @max_delta_ns:      maximum delta value in ns
  * @min_delta_ns:      minimum delta value in ns
  * @mult:              nanosecond to cycles multiplier
  * @shift:             nanoseconds to cycles divisor (power of two)
+ * @mode:              operating mode assigned by the management code
+ * @features:          features
+ * @retries:           number of forced programming retries
+ * @set_mode:          set mode function
+ * @broadcast:         function to broadcast events
+ * @min_delta_ticks:   minimum delta value in ticks stored for reconfiguration
+ * @max_delta_ticks:   maximum delta value in ticks stored for reconfiguration
+ * @name:              ptr to clock event name
  * @rating:            variable to rate clock event devices
  * @irq:               IRQ number (only for non CPU local devices)
  * @cpumask:           cpumask to indicate for which CPUs this device works
- * @set_next_event:    set next event function
- * @set_mode:          set mode function
- * @event_handler:     Assigned by the framework to be called by the low
- *                     level handler of the event source
- * @broadcast:         function to broadcast events
  * @list:              list head for the management code
- * @mode:              operating mode assigned by the management code
- * @next_event:                local storage for the next event in oneshot mode
- * @retries:           number of forced programming retries
  */
 struct clock_event_device {
-       const char              *name;
-       unsigned int            features;
+       void                    (*event_handler)(struct clock_event_device *);
+       int                     (*set_next_event)(unsigned long evt,
+                                                 struct clock_event_device *);
+       ktime_t                 next_event;
        u64                     max_delta_ns;
        u64                     min_delta_ns;
        u32                     mult;
        u32                     shift;
+       enum clock_event_mode   mode;
+       unsigned int            features;
+       unsigned long           retries;
+
+       void                    (*broadcast)(const struct cpumask *mask);
+       void                    (*set_mode)(enum clock_event_mode mode,
+                                           struct clock_event_device *);
+       unsigned long           min_delta_ticks;
+       unsigned long           max_delta_ticks;
+
+       const char              *name;
        int                     rating;
        int                     irq;
        const struct cpumask    *cpumask;
-       int                     (*set_next_event)(unsigned long evt,
-                                                 struct clock_event_device *);
-       void                    (*set_mode)(enum clock_event_mode mode,
-                                           struct clock_event_device *);
-       void                    (*event_handler)(struct clock_event_device *);
-       void                    (*broadcast)(const struct cpumask *mask);
        struct list_head        list;
-       enum clock_event_mode   mode;
-       ktime_t                 next_event;
-       unsigned long           retries;
-};
+} ____cacheline_aligned;
 
 /*
  * Calculate a multiplication factor for scaled math, which is used to convert
@@ -122,6 +128,12 @@ extern u64 clockevent_delta2ns(unsigned long latch,
                               struct clock_event_device *evt);
 extern void clockevents_register_device(struct clock_event_device *dev);
 
+extern void clockevents_config_and_register(struct clock_event_device *dev,
+                                           u32 freq, unsigned long min_delta,
+                                           unsigned long max_delta);
+
+extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
+
 extern void clockevents_exchange_device(struct clock_event_device *old,
                                        struct clock_event_device *new);
 extern void clockevents_set_mode(struct clock_event_device *dev,
index c37b21ad5a3b5c16dcc6c838ce0cb652682362f2..c918fbd33ee58e33f9560adbcc61c9901048ca78 100644 (file)
@@ -159,42 +159,38 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
  */
 struct clocksource {
        /*
-        * First part of structure is read mostly
+        * Hotpath data, fits in a single cache line when the
+        * clocksource itself is cacheline aligned.
         */
-       char *name;
-       struct list_head list;
-       int rating;
        cycle_t (*read)(struct clocksource *cs);
-       int (*enable)(struct clocksource *cs);
-       void (*disable)(struct clocksource *cs);
+       cycle_t cycle_last;
        cycle_t mask;
        u32 mult;
        u32 shift;
        u64 max_idle_ns;
-       unsigned long flags;
-       cycle_t (*vread)(void);
-       void (*suspend)(struct clocksource *cs);
-       void (*resume)(struct clocksource *cs);
+
 #ifdef CONFIG_IA64
        void *fsys_mmio;        /* used by fsyscall asm code */
 #define CLKSRC_FSYS_MMIO_SET(mmio, addr)      ((mmio) = (addr))
 #else
 #define CLKSRC_FSYS_MMIO_SET(mmio, addr)      do { } while (0)
 #endif
-
-       /*
-        * Second part is written at each timer interrupt
-        * Keep it in a different cache line to dirty no
-        * more than one cache line.
-        */
-       cycle_t cycle_last ____cacheline_aligned_in_smp;
+       const char *name;
+       struct list_head list;
+       int rating;
+       cycle_t (*vread)(void);
+       int (*enable)(struct clocksource *cs);
+       void (*disable)(struct clocksource *cs);
+       unsigned long flags;
+       void (*suspend)(struct clocksource *cs);
+       void (*resume)(struct clocksource *cs);
 
 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
        /* Watchdog related data, used by the framework */
        struct list_head wd_list;
        cycle_t wd_last;
 #endif
-};
+} ____cacheline_aligned;
 
 /*
  * Clock source flags bits::
@@ -341,4 +337,6 @@ static inline void update_vsyscall_tz(void)
 
 extern void timekeeping_notify(struct clocksource *clock);
 
+extern int clocksource_i8253_init(void);
+
 #endif /* _LINUX_CLOCKSOURCE_H */
index 9343dd3de858419de3b3a9569b3dde1d01e4d327..11be48e0d168b8e91ab1b2aefed6eb419ab801c8 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001 Russell King
  *            (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
- *            
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -56,9 +56,9 @@ static inline int cpufreq_unregister_notifier(struct notifier_block *nb,
 #define CPUFREQ_POLICY_POWERSAVE       (1)
 #define CPUFREQ_POLICY_PERFORMANCE     (2)
 
-/* Frequency values here are CPU kHz so that hardware which doesn't run 
- * with some frequencies can complain without having to guess what per 
- * cent / per mille means. 
+/* Frequency values here are CPU kHz so that hardware which doesn't run
+ * with some frequencies can complain without having to guess what per
+ * cent / per mille means.
  * Maximum transition latency is in nanoseconds - if it's unknown,
  * CPUFREQ_ETERNAL shall be used.
  */
@@ -72,13 +72,15 @@ extern struct kobject *cpufreq_global_kobject;
 struct cpufreq_cpuinfo {
        unsigned int            max_freq;
        unsigned int            min_freq;
-       unsigned int            transition_latency; /* in 10^(-9) s = nanoseconds */
+
+       /* in 10^(-9) s = nanoseconds */
+       unsigned int            transition_latency;
 };
 
 struct cpufreq_real_policy {
        unsigned int            min;    /* in kHz */
        unsigned int            max;    /* in kHz */
-        unsigned int           policy; /* see above */
+       unsigned int            policy; /* see above */
        struct cpufreq_governor *governor; /* see below */
 };
 
@@ -94,7 +96,7 @@ struct cpufreq_policy {
        unsigned int            max;    /* in kHz */
        unsigned int            cur;    /* in kHz, only needed if cpufreq
                                         * governors are used */
-        unsigned int           policy; /* see above */
+       unsigned int            policy; /* see above */
        struct cpufreq_governor *governor; /* see below */
 
        struct work_struct      update; /* if update_policy() needs to be
@@ -167,11 +169,11 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
 
 struct cpufreq_governor {
        char    name[CPUFREQ_NAME_LEN];
-       int     (*governor)     (struct cpufreq_policy *policy,
+       int     (*governor)     (struct cpufreq_policy *policy,
                                 unsigned int event);
        ssize_t (*show_setspeed)        (struct cpufreq_policy *policy,
                                         char *buf);
-       int     (*store_setspeed)       (struct cpufreq_policy *policy,
+       int     (*store_setspeed)       (struct cpufreq_policy *policy,
                                         unsigned int freq);
        unsigned int max_transition_latency; /* HW must be able to switch to
                        next freq faster than this value in nano secs or we
@@ -180,7 +182,8 @@ struct cpufreq_governor {
        struct module           *owner;
 };
 
-/* pass a target to the cpufreq driver 
+/*
+ * Pass a target to the cpufreq driver.
  */
 extern int cpufreq_driver_target(struct cpufreq_policy *policy,
                                 unsigned int target_freq,
@@ -237,9 +240,9 @@ struct cpufreq_driver {
 
 /* flags */
 
-#define CPUFREQ_STICKY         0x01    /* the driver isn't removed even if 
+#define CPUFREQ_STICKY         0x01    /* the driver isn't removed even if
                                         * all ->init() calls failed */
-#define CPUFREQ_CONST_LOOPS    0x02    /* loops_per_jiffy or other kernel
+#define CPUFREQ_CONST_LOOPS    0x02    /* loops_per_jiffy or other kernel
                                         * "constants" aren't affected by
                                         * frequency transitions */
 #define CPUFREQ_PM_NO_WARN     0x04    /* don't warn on suspend/resume speed
@@ -252,7 +255,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
 
 
-static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max) 
+static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max)
 {
        if (policy->min < min)
                policy->min = min;
@@ -386,34 +389,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 /* the following 3 funtions are for cpufreq core use only */
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
-void   cpufreq_cpu_put (struct cpufreq_policy *data);
+void   cpufreq_cpu_put(struct cpufreq_policy *data);
 
 /* the following are really really optional */
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
 
-void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
 
 
-/*********************************************************************
- *                     UNIFIED DEBUG HELPERS                         *
- *********************************************************************/
-
-#define CPUFREQ_DEBUG_CORE     1
-#define CPUFREQ_DEBUG_DRIVER   2
-#define CPUFREQ_DEBUG_GOVERNOR 4
-
-#ifdef CONFIG_CPU_FREQ_DEBUG
-
-extern void cpufreq_debug_printk(unsigned int type, const char *prefix, 
-                                const char *fmt, ...);
-
-#else
-
-#define cpufreq_debug_printk(msg...) do { } while(0)
-
-#endif /* CONFIG_CPU_FREQ_DEBUG */
-
 #endif /* _LINUX_CPUFREQ_H */
index 9aeeb0ba200363909bfd52a5a59f11cee7c54f5c..be16b61283ccb9855eabe82a97e4fd2345409f90 100644 (file)
@@ -146,6 +146,7 @@ struct cred {
        void            *security;      /* subjective LSM security */
 #endif
        struct user_struct *user;       /* real user ID subscription */
+       struct user_namespace *user_ns; /* cached user->user_ns */
        struct group_info *group_info;  /* supplementary groups for euid/fsgid */
        struct rcu_head rcu;            /* RCU deletion hook */
 };
@@ -354,10 +355,15 @@ static inline void put_cred(const struct cred *_cred)
 #define current_fsgid()        (current_cred_xxx(fsgid))
 #define current_cap()          (current_cred_xxx(cap_effective))
 #define current_user()         (current_cred_xxx(user))
-#define _current_user_ns()     (current_cred_xxx(user)->user_ns)
 #define current_security()     (current_cred_xxx(security))
 
-extern struct user_namespace *current_user_ns(void);
+#ifdef CONFIG_USER_NS
+#define current_user_ns() (current_cred_xxx(user_ns))
+#else
+extern struct user_namespace init_user_ns;
+#define current_user_ns() (&init_user_ns)
+#endif
+
 
 #define current_uid_gid(_uid, _gid)            \
 do {                                           \
index f2afed4fa9454776c79611d52755121dff749342..19d90a55541d99c37ea6d6c78040b9979dc38116 100644 (file)
@@ -197,7 +197,7 @@ struct dentry_operations {
       * typically using d_splice_alias. */
 
 #define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
-#define DCACHE_UNHASHED                0x0010  
+#define DCACHE_RCUACCESS       0x0010  /* Entry has ever been RCU-visible */
 #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
      /* Parent inode is watched by inotify */
 
@@ -384,7 +384,7 @@ extern struct dentry *dget_parent(struct dentry *dentry);
  
 static inline int d_unhashed(struct dentry *dentry)
 {
-       return (dentry->d_flags & DCACHE_UNHASHED);
+       return hlist_bl_unhashed(&dentry->d_hash);
 }
 
 static inline int d_unlinked(struct dentry *dentry)
index 42365067a83685d3e21b4390021ab816dc32950e..c66111affca9a6e93f246b66f39ff5e4b998da58 100644 (file)
@@ -590,7 +590,6 @@ struct device {
        struct dev_archdata     archdata;
 
        struct device_node      *of_node; /* associated device tree node */
-       const struct of_device_id *of_match; /* matching of_device_id from driver */
 
        dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
 
@@ -781,13 +780,6 @@ static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
 /* drivers/base/power/shutdown.c */
 extern void device_shutdown(void);
 
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-/* drivers/base/sys.c */
-extern void sysdev_shutdown(void);
-#else
-static inline void sysdev_shutdown(void) { }
-#endif
-
 /* debugging and troubleshooting/diagnostic helpers. */
 extern const char *dev_driver_string(const struct device *dev);
 
index 0c9653f11c181cb50885d5185786a8d2d3d6c335..e747ecd48e1c043a87549cb2cdab62e04e1edbf5 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _DYNAMIC_DEBUG_H
 #define _DYNAMIC_DEBUG_H
 
-#include <linux/jump_label.h>
-
 /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
  * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
  * use independent hash functions, to reduce the chance of false positives.
index df728c1c29ed39c0b25a8ead2fcc0f89696c911f..6a8274877171aa7959cb95e5370ccc49a626d665 100644 (file)
@@ -832,6 +832,7 @@ struct fb_tile_ops {
 #define FBINFO_CAN_FORCE_OUTPUT     0x200000
 
 struct fb_info {
+       atomic_t count;
        int node;
        int flags;
        struct mutex lock;              /* Lock for open/release/ioctl funcs */
index 70e4efabe0fb6983ed9524f4ade4e5d91e2ce2d0..ebeb2f3ad068db1ec6d8cee92a1bcfb6cd097630 100644 (file)
@@ -61,7 +61,7 @@ struct flex_array {
 struct flex_array *flex_array_alloc(int element_size, unsigned int total,
                gfp_t flags);
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-               unsigned int end, gfp_t flags);
+               unsigned int nr_elements, gfp_t flags);
 void flex_array_free(struct flex_array *fa);
 void flex_array_free_parts(struct flex_array *fa);
 int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
index dbd860af08041bbaa5e333104aaa3ab0849cb676..cdf9495df204aa917605613b220c852349528b54 100644 (file)
@@ -358,7 +358,6 @@ struct inodes_stat_t {
 #define FS_EXTENT_FL                   0x00080000 /* Extents */
 #define FS_DIRECTIO_FL                 0x00100000 /* Use direct i/o */
 #define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
-#define FS_COW_FL                      0x02000000 /* Cow file */
 #define FS_RESERVED_FL                 0x80000000 /* reserved for ext2 lib */
 
 #define FS_FL_USER_VISIBLE             0x0003DFFF /* User visible flags */
index ca29e03c1fac0c1d461814405b5c0724dc61bc99..9d88e1cb5dbbc557e14502005806002b7cdd8bc5 100644 (file)
@@ -29,9 +29,22 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 
 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);
 
+struct ftrace_hash;
+
+enum {
+       FTRACE_OPS_FL_ENABLED           = 1 << 0,
+       FTRACE_OPS_FL_GLOBAL            = 1 << 1,
+       FTRACE_OPS_FL_DYNAMIC           = 1 << 2,
+};
+
 struct ftrace_ops {
-       ftrace_func_t     func;
-       struct ftrace_ops *next;
+       ftrace_func_t                   func;
+       struct ftrace_ops               *next;
+       unsigned long                   flags;
+#ifdef CONFIG_DYNAMIC_FTRACE
+       struct ftrace_hash              *notrace_hash;
+       struct ftrace_hash              *filter_hash;
+#endif
 };
 
 extern int function_trace_stop;
@@ -146,14 +159,13 @@ extern void unregister_ftrace_function_probe_all(char *glob);
 extern int ftrace_text_reserved(void *start, void *end);
 
 enum {
-       FTRACE_FL_FREE          = (1 << 0),
-       FTRACE_FL_FAILED        = (1 << 1),
-       FTRACE_FL_FILTER        = (1 << 2),
-       FTRACE_FL_ENABLED       = (1 << 3),
-       FTRACE_FL_NOTRACE       = (1 << 4),
-       FTRACE_FL_CONVERTED     = (1 << 5),
+       FTRACE_FL_ENABLED       = (1 << 30),
+       FTRACE_FL_FREE          = (1 << 31),
 };
 
+#define FTRACE_FL_MASK         (0x3UL << 30)
+#define FTRACE_REF_MAX         ((1 << 30) - 1)
+
 struct dyn_ftrace {
        union {
                unsigned long           ip; /* address of mcount call-site */
@@ -167,7 +179,12 @@ struct dyn_ftrace {
 };
 
 int ftrace_force_update(void);
-void ftrace_set_filter(unsigned char *buf, int len, int reset);
+void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
+                      int len, int reset);
+void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
+                       int len, int reset);
+void ftrace_set_global_filter(unsigned char *buf, int len, int reset);
+void ftrace_set_global_notrace(unsigned char *buf, int len, int reset);
 
 int register_ftrace_command(struct ftrace_func_command *cmd);
 int unregister_ftrace_command(struct ftrace_func_command *cmd);
index 22b32af1b5ec3d1aa81ddebbc2de1ace29c17cc6..b5a550a39a70ddd0a119479ce4a528892c6a7aa9 100644 (file)
@@ -37,6 +37,7 @@ struct trace_entry {
        unsigned char           flags;
        unsigned char           preempt_count;
        int                     pid;
+       int                     padding;
 };
 
 #define FTRACE_MAX_EVENT                                               \
index bfb8f934521e02b313cc1a497ec08850ac3493c1..56d8fc87fbbc70e8f1d5de07aa0bd7aaccd6887c 100644 (file)
@@ -353,6 +353,8 @@ extern unsigned long get_zeroed_page(gfp_t gfp_mask);
 
 void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
 void free_pages_exact(void *virt, size_t size);
+/* This is different from alloc_pages_exact_node !!! */
+void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask);
 
 #define __get_free_page(gfp_mask) \
                __get_free_pages((gfp_mask), 0)
index df29c8fde36be8b7b9e0e13771d8ad4bb1fd6444..8847c8c29791c8c078dedaf0db9ff6dce85faa23 100644 (file)
@@ -117,7 +117,7 @@ static inline void vma_adjust_trans_huge(struct vm_area_struct *vma,
                                         unsigned long end,
                                         long adjust_next)
 {
-       if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+       if (!vma->anon_vma || vma->vm_ops)
                return;
        __vma_adjust_trans_huge(vma, start, end, adjust_next);
 }
index 577671c55153d4474f00b7f862ae2e97dff0b6ae..9146f39cdddfe97bd61473d54a72a33bfad3a04f 100644 (file)
 #define __exitused  __used
 #endif
 
-#define __exit          __section(.exit.text) __exitused __cold
+#define __exit          __section(.exit.text) __exitused __cold notrace
 
 /* Used for HOTPLUG */
-#define __devinit        __section(.devinit.text) __cold
+#define __devinit        __section(.devinit.text) __cold notrace
 #define __devinitdata    __section(.devinit.data)
 #define __devinitconst   __section(.devinit.rodata)
-#define __devexit        __section(.devexit.text) __exitused __cold
+#define __devexit        __section(.devexit.text) __exitused __cold notrace
 #define __devexitdata    __section(.devexit.data)
 #define __devexitconst   __section(.devexit.rodata)
 
 /* Used for HOTPLUG_CPU */
-#define __cpuinit        __section(.cpuinit.text) __cold
+#define __cpuinit        __section(.cpuinit.text) __cold notrace
 #define __cpuinitdata    __section(.cpuinit.data)
 #define __cpuinitconst   __section(.cpuinit.rodata)
-#define __cpuexit        __section(.cpuexit.text) __exitused __cold
+#define __cpuexit        __section(.cpuexit.text) __exitused __cold notrace
 #define __cpuexitdata    __section(.cpuexit.data)
 #define __cpuexitconst   __section(.cpuexit.rodata)
 
 /* Used for MEMORY_HOTPLUG */
-#define __meminit        __section(.meminit.text) __cold
+#define __meminit        __section(.meminit.text) __cold notrace
 #define __meminitdata    __section(.meminit.data)
 #define __meminitconst   __section(.meminit.rodata)
-#define __memexit        __section(.memexit.text) __exitused __cold
+#define __memexit        __section(.memexit.text) __exitused __cold notrace
 #define __memexitdata    __section(.memexit.data)
 #define __memexitconst   __section(.memexit.rodata)
 
index caa151fbebb74c661289a69ffb52762435178d53..689496bb6654b60ba37bbc000d982356140f9565 100644 (file)
@@ -134,7 +134,6 @@ extern struct cred init_cred;
        .stack          = &init_thread_info,                            \
        .usage          = ATOMIC_INIT(2),                               \
        .flags          = PF_KTHREAD,                                   \
-       .lock_depth     = -1,                                           \
        .prio           = MAX_PRIO-20,                                  \
        .static_prio    = MAX_PRIO-20,                                  \
        .normal_prio    = MAX_PRIO-20,                                  \
index bea0ac750712855bcfdd94289f4514ca57d4efb6..6c12989839d9093f970b9f90d8dffe44dec6f7a2 100644 (file)
@@ -414,7 +414,6 @@ enum
        TASKLET_SOFTIRQ,
        SCHED_SOFTIRQ,
        HRTIMER_SOFTIRQ,
-       RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
 
        NR_SOFTIRQS
 };
index 09a308072f5635c9a40b26aa04b193451ce20cd2..8b4538446636da5fca09de70d5e6ea33c5fac28c 100644 (file)
@@ -53,12 +53,13 @@ typedef     void (*irq_preflow_handler_t)(struct irq_data *data);
  * Bits which can be modified via irq_set/clear/modify_status_flags()
  * IRQ_LEVEL                   - Interrupt is level type. Will be also
  *                               updated in the code when the above trigger
- *                               bits are modified via set_irq_type()
+ *                               bits are modified via irq_set_irq_type()
  * IRQ_PER_CPU                 - Mark an interrupt PER_CPU. Will protect
  *                               it from affinity setting
  * IRQ_NOPROBE                 - Interrupt cannot be probed by autoprobing
  * IRQ_NOREQUEST               - Interrupt cannot be requested via
  *                               request_irq()
+ * IRQ_NOTHREAD                        - Interrupt cannot be threaded
  * IRQ_NOAUTOEN                        - Interrupt is not automatically enabled in
  *                               request/setup_irq()
  * IRQ_NO_BALANCING            - Interrupt cannot be balanced (affinity set)
@@ -85,6 +86,7 @@ enum {
        IRQ_NO_BALANCING        = (1 << 13),
        IRQ_MOVE_PCNTXT         = (1 << 14),
        IRQ_NESTED_THREAD       = (1 << 15),
+       IRQ_NOTHREAD            = (1 << 16),
 };
 
 #define IRQF_MODIFY_MASK       \
@@ -261,23 +263,6 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
  * struct irq_chip - hardware interrupt chip descriptor
  *
  * @name:              name for /proc/interrupts
- * @startup:           deprecated, replaced by irq_startup
- * @shutdown:          deprecated, replaced by irq_shutdown
- * @enable:            deprecated, replaced by irq_enable
- * @disable:           deprecated, replaced by irq_disable
- * @ack:               deprecated, replaced by irq_ack
- * @mask:              deprecated, replaced by irq_mask
- * @mask_ack:          deprecated, replaced by irq_mask_ack
- * @unmask:            deprecated, replaced by irq_unmask
- * @eoi:               deprecated, replaced by irq_eoi
- * @end:               deprecated, will go away with __do_IRQ()
- * @set_affinity:      deprecated, replaced by irq_set_affinity
- * @retrigger:         deprecated, replaced by irq_retrigger
- * @set_type:          deprecated, replaced by irq_set_type
- * @set_wake:          deprecated, replaced by irq_wake
- * @bus_lock:          deprecated, replaced by irq_bus_lock
- * @bus_sync_unlock:   deprecated, replaced by irq_bus_sync_unlock
- *
  * @irq_startup:       start up the interrupt (defaults to ->enable if NULL)
  * @irq_shutdown:      shut down the interrupt (defaults to ->disable if NULL)
  * @irq_enable:                enable the interrupt (defaults to chip->unmask if NULL)
@@ -295,6 +280,9 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
  * @irq_cpu_online:    configure an interrupt source for a secondary CPU
  * @irq_cpu_offline:   un-configure an interrupt source for a secondary CPU
+ * @irq_suspend:       function called from core code on suspend once per chip
+ * @irq_resume:                function called from core code on resume once per chip
+ * @irq_pm_shutdown:   function called from core code on shutdown once per chip
  * @irq_print_chip:    optional to print special chip info in show_interrupts
  * @flags:             chip specific flags
  *
@@ -324,6 +312,10 @@ struct irq_chip {
        void            (*irq_cpu_online)(struct irq_data *data);
        void            (*irq_cpu_offline)(struct irq_data *data);
 
+       void            (*irq_suspend)(struct irq_data *data);
+       void            (*irq_resume)(struct irq_data *data);
+       void            (*irq_pm_shutdown)(struct irq_data *data);
+
        void            (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
 
        unsigned long   flags;
@@ -439,7 +431,7 @@ irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
 /*
  * Set a highlevel chained flow handler for a given IRQ.
  * (a chained handler is automatically enabled and set to
- *  IRQ_NOREQUEST and IRQ_NOPROBE)
+ *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
  */
 static inline void
 irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
@@ -469,6 +461,16 @@ static inline void irq_set_probe(unsigned int irq)
        irq_modify_status(irq, IRQ_NOPROBE, 0);
 }
 
+static inline void irq_set_nothread(unsigned int irq)
+{
+       irq_modify_status(irq, 0, IRQ_NOTHREAD);
+}
+
+static inline void irq_set_thread(unsigned int irq)
+{
+       irq_modify_status(irq, IRQ_NOTHREAD, 0);
+}
+
 static inline void irq_set_nested_thread(unsigned int irq, bool nest)
 {
        if (nest)
@@ -573,6 +575,145 @@ static inline int irq_reserve_irq(unsigned int irq)
        return irq_reserve_irqs(irq, 1);
 }
 
+#ifndef irq_reg_writel
+# define irq_reg_writel(val, addr)     writel(val, addr)
+#endif
+#ifndef irq_reg_readl
+# define irq_reg_readl(addr)           readl(addr)
+#endif
+
+/**
+ * struct irq_chip_regs - register offsets for struct irq_gci
+ * @enable:    Enable register offset to reg_base
+ * @disable:   Disable register offset to reg_base
+ * @mask:      Mask register offset to reg_base
+ * @ack:       Ack register offset to reg_base
+ * @eoi:       Eoi register offset to reg_base
+ * @type:      Type configuration register offset to reg_base
+ * @polarity:  Polarity configuration register offset to reg_base
+ */
+struct irq_chip_regs {
+       unsigned long           enable;
+       unsigned long           disable;
+       unsigned long           mask;
+       unsigned long           ack;
+       unsigned long           eoi;
+       unsigned long           type;
+       unsigned long           polarity;
+};
+
+/**
+ * struct irq_chip_type - Generic interrupt chip instance for a flow type
+ * @chip:              The real interrupt chip which provides the callbacks
+ * @regs:              Register offsets for this chip
+ * @handler:           Flow handler associated with this chip
+ * @type:              Chip can handle these flow types
+ *
+ * A irq_generic_chip can have several instances of irq_chip_type when
+ * it requires different functions and register offsets for different
+ * flow types.
+ */
+struct irq_chip_type {
+       struct irq_chip         chip;
+       struct irq_chip_regs    regs;
+       irq_flow_handler_t      handler;
+       u32                     type;
+};
+
+/**
+ * struct irq_chip_generic - Generic irq chip data structure
+ * @lock:              Lock to protect register and cache data access
+ * @reg_base:          Register base address (virtual)
+ * @irq_base:          Interrupt base nr for this chip
+ * @irq_cnt:           Number of interrupts handled by this chip
+ * @mask_cache:                Cached mask register
+ * @type_cache:                Cached type register
+ * @polarity_cache:    Cached polarity register
+ * @wake_enabled:      Interrupt can wakeup from suspend
+ * @wake_active:       Interrupt is marked as an wakeup from suspend source
+ * @num_ct:            Number of available irq_chip_type instances (usually 1)
+ * @private:           Private data for non generic chip callbacks
+ * @list:              List head for keeping track of instances
+ * @chip_types:                Array of interrupt irq_chip_types
+ *
+ * Note, that irq_chip_generic can have multiple irq_chip_type
+ * implementations which can be associated to a particular irq line of
+ * an irq_chip_generic instance. That allows to share and protect
+ * state in an irq_chip_generic instance when we need to implement
+ * different flow mechanisms (level/edge) for it.
+ */
+struct irq_chip_generic {
+       raw_spinlock_t          lock;
+       void __iomem            *reg_base;
+       unsigned int            irq_base;
+       unsigned int            irq_cnt;
+       u32                     mask_cache;
+       u32                     type_cache;
+       u32                     polarity_cache;
+       u32                     wake_enabled;
+       u32                     wake_active;
+       unsigned int            num_ct;
+       void                    *private;
+       struct list_head        list;
+       struct irq_chip_type    chip_types[0];
+};
+
+/**
+ * enum irq_gc_flags - Initialization flags for generic irq chips
+ * @IRQ_GC_INIT_MASK_CACHE:    Initialize the mask_cache by reading mask reg
+ * @IRQ_GC_INIT_NESTED_LOCK:   Set the lock class of the irqs to nested for
+ *                             irq chips which need to call irq_set_wake() on
+ *                             the parent irq. Usually GPIO implementations
+ */
+enum irq_gc_flags {
+       IRQ_GC_INIT_MASK_CACHE          = 1 << 0,
+       IRQ_GC_INIT_NESTED_LOCK         = 1 << 1,
+};
+
+/* Generic chip callback functions */
+void irq_gc_noop(struct irq_data *d);
+void irq_gc_mask_disable_reg(struct irq_data *d);
+void irq_gc_mask_set_bit(struct irq_data *d);
+void irq_gc_mask_clr_bit(struct irq_data *d);
+void irq_gc_unmask_enable_reg(struct irq_data *d);
+void irq_gc_ack(struct irq_data *d);
+void irq_gc_mask_disable_reg_and_ack(struct irq_data *d);
+void irq_gc_eoi(struct irq_data *d);
+int irq_gc_set_wake(struct irq_data *d, unsigned int on);
+
+/* Setup functions for irq_chip_generic */
+struct irq_chip_generic *
+irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
+                      void __iomem *reg_base, irq_flow_handler_t handler);
+void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
+                           enum irq_gc_flags flags, unsigned int clr,
+                           unsigned int set);
+int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
+void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
+                            unsigned int clr, unsigned int set);
+
+static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
+{
+       return container_of(d->chip, struct irq_chip_type, chip);
+}
+
+#define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX)
+
+#ifdef CONFIG_SMP
+static inline void irq_gc_lock(struct irq_chip_generic *gc)
+{
+       raw_spin_lock(&gc->lock);
+}
+
+static inline void irq_gc_unlock(struct irq_chip_generic *gc)
+{
+       raw_spin_unlock(&gc->lock);
+}
+#else
+static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
+static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
+#endif
+
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
 #endif /* !CONFIG_S390 */
index a082905b5ebe494676591012768f050fe5d4c140..2d921b35212c42bbac394430b50fd90914439e24 100644 (file)
@@ -16,16 +16,18 @@ struct timer_rand_state;
  * @irq_data:          per irq and chip data passed down to chip functions
  * @timer_rand_state:  pointer to timer rand state struct
  * @kstat_irqs:                irq stats per cpu
- * @handle_irq:                highlevel irq-events handler [if NULL, __do_IRQ()]
+ * @handle_irq:                highlevel irq-events handler
+ * @preflow_handler:   handler called before the flow handler (currently used by sparc)
  * @action:            the irq action chain
  * @status:            status information
  * @core_internal_state__do_not_mess_with_it: core internal status information
  * @depth:             disable-depth, for nested irq_disable() calls
- * @wake_depth:                enable depth, for multiple set_irq_wake() callers
+ * @wake_depth:                enable depth, for multiple irq_set_irq_wake() callers
  * @irq_count:         stats field to detect stalled irqs
  * @last_unhandled:    aging timer for unhandled count
  * @irqs_unhandled:    stats field for spurious unhandled interrupts
  * @lock:              locking for SMP
+ * @affinity_hint:     hint to user space for preferred irq affinity
  * @affinity_notify:   context for notification of affinity changes
  * @pending_mask:      pending rebalanced interrupts
  * @threads_oneshot:   bitfield to handle shared oneshot threads
@@ -109,10 +111,7 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de
        desc->handle_irq(irq, desc);
 }
 
-static inline void generic_handle_irq(unsigned int irq)
-{
-       generic_handle_irq_desc(irq, irq_to_desc(irq));
-}
+int generic_handle_irq(unsigned int irq);
 
 /* Test to see if a driver has successfully requested an irq */
 static inline int irq_has_action(unsigned int irq)
index 7880f18e4b863b7d0ad6a84a0b55a06452ad0990..83e745f3ead76b225d52a92608819c47d8a8c209 100644 (file)
@@ -1,20 +1,43 @@
 #ifndef _LINUX_JUMP_LABEL_H
 #define _LINUX_JUMP_LABEL_H
 
+#include <linux/types.h>
+#include <linux/compiler.h>
+
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+
+struct jump_label_key {
+       atomic_t enabled;
+       struct jump_entry *entries;
+#ifdef CONFIG_MODULES
+       struct jump_label_mod *next;
+#endif
+};
+
 # include <asm/jump_label.h>
 # define HAVE_JUMP_LABEL
 #endif
 
 enum jump_label_type {
+       JUMP_LABEL_DISABLE = 0,
        JUMP_LABEL_ENABLE,
-       JUMP_LABEL_DISABLE
 };
 
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
 
+#ifdef CONFIG_MODULES
+#define JUMP_LABEL_INIT {{ 0 }, NULL, NULL}
+#else
+#define JUMP_LABEL_INIT {{ 0 }, NULL}
+#endif
+
+static __always_inline bool static_branch(struct jump_label_key *key)
+{
+       return arch_static_branch(key);
+}
+
 extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
@@ -23,37 +46,37 @@ extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
                                 enum jump_label_type type);
 extern void arch_jump_label_text_poke_early(jump_label_t addr);
-extern void jump_label_update(unsigned long key, enum jump_label_type type);
-extern void jump_label_apply_nops(struct module *mod);
 extern int jump_label_text_reserved(void *start, void *end);
+extern void jump_label_inc(struct jump_label_key *key);
+extern void jump_label_dec(struct jump_label_key *key);
+extern bool jump_label_enabled(struct jump_label_key *key);
+extern void jump_label_apply_nops(struct module *mod);
 
-#define jump_label_enable(key) \
-       jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE);
+#else
 
-#define jump_label_disable(key) \
-       jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE);
+#include <asm/atomic.h>
 
-#else
+#define JUMP_LABEL_INIT {ATOMIC_INIT(0)}
 
-#define JUMP_LABEL(key, label)                 \
-do {                                           \
-       if (unlikely(*key))                     \
-               goto label;                     \
-} while (0)
+struct jump_label_key {
+       atomic_t enabled;
+};
 
-#define jump_label_enable(cond_var)    \
-do {                                   \
-       *(cond_var) = 1;                        \
-} while (0)
+static __always_inline bool static_branch(struct jump_label_key *key)
+{
+       if (unlikely(atomic_read(&key->enabled)))
+               return true;
+       return false;
+}
 
-#define jump_label_disable(cond_var)   \
-do {                                   \
-       *(cond_var) = 0;                        \
-} while (0)
+static inline void jump_label_inc(struct jump_label_key *key)
+{
+       atomic_inc(&key->enabled);
+}
 
-static inline int jump_label_apply_nops(struct module *mod)
+static inline void jump_label_dec(struct jump_label_key *key)
 {
-       return 0;
+       atomic_dec(&key->enabled);
 }
 
 static inline int jump_label_text_reserved(void *start, void *end)
@@ -64,16 +87,16 @@ static inline int jump_label_text_reserved(void *start, void *end)
 static inline void jump_label_lock(void) {}
 static inline void jump_label_unlock(void) {}
 
-#endif
+static inline bool jump_label_enabled(struct jump_label_key *key)
+{
+       return !!atomic_read(&key->enabled);
+}
 
-#define COND_STMT(key, stmt)                                   \
-do {                                                           \
-       __label__ jl_enabled;                                   \
-       JUMP_LABEL(key, jl_enabled);                            \
-       if (0) {                                                \
-jl_enabled:                                                    \
-               stmt;                                           \
-       }                                                       \
-} while (0)
+static inline int jump_label_apply_nops(struct module *mod)
+{
+       return 0;
+}
+
+#endif
 
 #endif
diff --git a/include/linux/jump_label_ref.h b/include/linux/jump_label_ref.h
deleted file mode 100644 (file)
index e5d012a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _LINUX_JUMP_LABEL_REF_H
-#define _LINUX_JUMP_LABEL_REF_H
-
-#include <linux/jump_label.h>
-#include <asm/atomic.h>
-
-#ifdef HAVE_JUMP_LABEL
-
-static inline void jump_label_inc(atomic_t *key)
-{
-       if (atomic_add_return(1, key) == 1)
-               jump_label_enable(key);
-}
-
-static inline void jump_label_dec(atomic_t *key)
-{
-       if (atomic_dec_and_test(key))
-               jump_label_disable(key);
-}
-
-#else /* !HAVE_JUMP_LABEL */
-
-static inline void jump_label_inc(atomic_t *key)
-{
-       atomic_inc(key);
-}
-
-static inline void jump_label_dec(atomic_t *key)
-{
-       atomic_dec(key);
-}
-
-#undef JUMP_LABEL
-#define JUMP_LABEL(key, label)                                         \
-do {                                                                   \
-       if (unlikely(__builtin_choose_expr(                             \
-             __builtin_types_compatible_p(typeof(key), atomic_t *),    \
-             atomic_read((atomic_t *)(key)), *(key))))                 \
-               goto label;                                             \
-} while (0)
-
-#endif /* HAVE_JUMP_LABEL */
-
-#endif /* _LINUX_JUMP_LABEL_REF_H */
index 00cec4dc0ae25a3cf6ac57bebcc239d145b8d641..f37ba716ef8b7fe81f73a586289286a879404609 100644 (file)
@@ -283,6 +283,7 @@ extern char *get_options(const char *str, int nints, int *ints);
 extern unsigned long long memparse(const char *ptr, char **retptr);
 
 extern int core_kernel_text(unsigned long addr);
+extern int core_kernel_data(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
 extern int func_ptr_is_kernel_text(void *ptr);
index 6efd7a78de6aaaa6d74c526ba44f5fafa81e1fad..310231823852026b69bf25cc88868ab86de69975 100644 (file)
@@ -113,5 +113,6 @@ extern void usermodehelper_init(void);
 
 extern int usermodehelper_disable(void);
 extern void usermodehelper_enable(void);
+extern bool usermodehelper_is_disabled(void);
 
 #endif /* __LINUX_KMOD_H__ */
index 7f675aa81d877795b12e48c78a13f6ae144af606..04f32a3eb26b85dd9ea0b0e786f282c0c799f30d 100644 (file)
@@ -137,8 +137,6 @@ enum {
        ATA_DFLAG_ACPI_PENDING  = (1 << 5), /* ACPI resume action pending */
        ATA_DFLAG_ACPI_FAILED   = (1 << 6), /* ACPI on devcfg has failed */
        ATA_DFLAG_AN            = (1 << 7), /* AN configured */
-       ATA_DFLAG_HIPM          = (1 << 8), /* device supports HIPM */
-       ATA_DFLAG_DIPM          = (1 << 9), /* device supports DIPM */
        ATA_DFLAG_DMADIR        = (1 << 10), /* device requires DMADIR */
        ATA_DFLAG_CFG_MASK      = (1 << 12) - 1,
 
@@ -198,6 +196,7 @@ enum {
                                              * management */
        ATA_FLAG_SW_ACTIVITY    = (1 << 22), /* driver supports sw activity
                                              * led */
+       ATA_FLAG_NO_DIPM        = (1 << 23), /* host not happy with DIPM */
 
        /* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
index 3a54266a1e85c3fc60e603c8cff6368961296608..cc6d2aa6b415fef7627fc90ceb6ddfb8a6bf2256 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/poison.h>
-#include <linux/prefetch.h>
+#include <linux/const.h>
 
 /*
  * Simple doubly linked list implementation.
@@ -367,18 +367,15 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @head:      the head for your list.
  */
 #define list_for_each(pos, head) \
-       for (pos = (head)->next; prefetch(pos->next), pos != (head); \
-               pos = pos->next)
+       for (pos = (head)->next; pos != (head); pos = pos->next)
 
 /**
  * __list_for_each     -       iterate over a list
  * @pos:       the &struct list_head to use as a loop cursor.
  * @head:      the head for your list.
  *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
+ * This variant doesn't differ from list_for_each() any more.
+ * We don't do prefetching in either case.
  */
 #define __list_for_each(pos, head) \
        for (pos = (head)->next; pos != (head); pos = pos->next)
@@ -389,8 +386,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @head:      the head for your list.
  */
 #define list_for_each_prev(pos, head) \
-       for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
-               pos = pos->prev)
+       for (pos = (head)->prev; pos != (head); pos = pos->prev)
 
 /**
  * list_for_each_safe - iterate over a list safe against removal of list entry
@@ -410,7 +406,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_prev_safe(pos, n, head) \
        for (pos = (head)->prev, n = pos->prev; \
-            prefetch(pos->prev), pos != (head); \
+            pos != (head); \
             pos = n, n = pos->prev)
 
 /**
@@ -421,7 +417,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_entry(pos, head, member)                         \
        for (pos = list_entry((head)->next, typeof(*pos), member);      \
-            prefetch(pos->member.next), &pos->member != (head);        \
+            &pos->member != (head);    \
             pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
@@ -432,7 +428,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_entry_reverse(pos, head, member)                 \
        for (pos = list_entry((head)->prev, typeof(*pos), member);      \
-            prefetch(pos->member.prev), &pos->member != (head);        \
+            &pos->member != (head);    \
             pos = list_entry(pos->member.prev, typeof(*pos), member))
 
 /**
@@ -457,7 +453,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_entry_continue(pos, head, member)                \
        for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
-            prefetch(pos->member.next), &pos->member != (head);        \
+            &pos->member != (head);    \
             pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
@@ -471,7 +467,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_entry_continue_reverse(pos, head, member)                \
        for (pos = list_entry(pos->member.prev, typeof(*pos), member);  \
-            prefetch(pos->member.prev), &pos->member != (head);        \
+            &pos->member != (head);    \
             pos = list_entry(pos->member.prev, typeof(*pos), member))
 
 /**
@@ -483,7 +479,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * Iterate over list of given type, continuing from current position.
  */
 #define list_for_each_entry_from(pos, head, member)                    \
-       for (; prefetch(pos->member.next), &pos->member != (head);      \
+       for (; &pos->member != (head);  \
             pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
@@ -664,8 +660,7 @@ static inline void hlist_move_list(struct hlist_head *old,
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
 
 #define hlist_for_each(pos, head) \
-       for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
-            pos = pos->next)
+       for (pos = (head)->first; pos ; pos = pos->next)
 
 #define hlist_for_each_safe(pos, n, head) \
        for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
@@ -680,7 +675,7 @@ static inline void hlist_move_list(struct hlist_head *old,
  */
 #define hlist_for_each_entry(tpos, pos, head, member)                   \
        for (pos = (head)->first;                                        \
-            pos && ({ prefetch(pos->next); 1;}) &&                      \
+            pos &&                                                      \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)
 
@@ -692,7 +687,7 @@ static inline void hlist_move_list(struct hlist_head *old,
  */
 #define hlist_for_each_entry_continue(tpos, pos, member)                \
        for (pos = (pos)->next;                                          \
-            pos && ({ prefetch(pos->next); 1;}) &&                      \
+            pos &&                                                      \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)
 
@@ -703,7 +698,7 @@ static inline void hlist_move_list(struct hlist_head *old,
  * @member:    the name of the hlist_node within the struct.
  */
 #define hlist_for_each_entry_from(tpos, pos, member)                    \
-       for (; pos && ({ prefetch(pos->next); 1;}) &&                    \
+       for (; pos &&                                                    \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)
 
index 5bad17d1acdec6d386f6bf3d236c6900abb15ce8..31f9d75adc5bfaf4489d94473500cc01f74b2973 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_LIST_BL_H
 
 #include <linux/list.h>
+#include <linux/bit_spinlock.h>
 
 /*
  * Special version of lists, where head of the list has a lock in the lowest
@@ -114,6 +115,16 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n)
        }
 }
 
+static inline void hlist_bl_lock(struct hlist_bl_head *b)
+{
+       bit_spin_lock(0, (unsigned long *)b);
+}
+
+static inline void hlist_bl_unlock(struct hlist_bl_head *b)
+{
+       __bit_spin_unlock(0, (unsigned long *)b);
+}
+
 /**
  * hlist_bl_for_each_entry     - iterate over list of given type
  * @tpos:      the type * to use as a loop cursor.
index afe4db49402d142036761855cd9c9b6714bfec8d..632d1567a1b676f4c74dfeec798951081fed108c 100644 (file)
@@ -81,7 +81,9 @@ struct wm831x_touch_pdata {
        int rpu;               /** Pen down sensitivity resistor divider */
        int pressure;          /** Report pressure (boolean) */
        unsigned int data_irq; /** Touch data ready IRQ */
+       int data_irqf;         /** IRQ flags for data ready IRQ */
        unsigned int pd_irq;   /** Touch pendown detect IRQ */
+       int pd_irqf;           /** IRQ flags for pen down IRQ */
 };
 
 enum wm831x_watchdog_action {
index 692dbae6ffa76997058792ad3441f551bf303473..6507dde38b16602a1b819492088f6ce5ea8fba40 100644 (file)
@@ -137,7 +137,8 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_RandomReadHint(v)           ((v)->vm_flags & VM_RAND_READ)
 
 /*
- * special vmas that are non-mergable, non-mlock()able
+ * Special vmas that are non-mergable, non-mlock()able.
+ * Note: mm/huge_memory.c VM_NO_THP depends on this definition.
  */
 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
 
@@ -1010,11 +1011,33 @@ int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
 /* Is the vma a continuation of the stack vma above it? */
-static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
+static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
 {
        return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
 }
 
+static inline int stack_guard_page_start(struct vm_area_struct *vma,
+                                            unsigned long addr)
+{
+       return (vma->vm_flags & VM_GROWSDOWN) &&
+               (vma->vm_start == addr) &&
+               !vma_growsdown(vma->vm_prev, addr);
+}
+
+/* Is the vma a continuation of the stack vma below it? */
+static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
+{
+       return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
+}
+
+static inline int stack_guard_page_end(struct vm_area_struct *vma,
+                                          unsigned long addr)
+{
+       return (vma->vm_flags & VM_GROWSUP) &&
+               (vma->vm_end == addr) &&
+               !vma_growsup(vma->vm_next, addr);
+}
+
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
                unsigned long old_addr, struct vm_area_struct *new_vma,
                unsigned long new_addr, unsigned long len);
index 5de42043dff0c16a9f571e450bf96ed9d388c97e..d9ca2d5dc6d0d974c5d57eb89479365d0a9f8796 100644 (file)
@@ -64,6 +64,9 @@ struct module_version_attribute {
        const char *version;
 } __attribute__ ((__aligned__(sizeof(void *))));
 
+extern ssize_t __modver_version_show(struct module_attribute *,
+                                    struct module *, char *);
+
 struct module_kobject
 {
        struct kobject kobj;
@@ -172,12 +175,7 @@ extern struct module __this_module;
 #define MODULE_VERSION(_version) MODULE_INFO(version, _version)
 #else
 #define MODULE_VERSION(_version)                                       \
-       extern ssize_t __modver_version_show(struct module_attribute *, \
-                                            struct module *, char *);  \
-       static struct module_version_attribute __modver_version_attr    \
-       __used                                                          \
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-       = {                                                             \
+       static struct module_version_attribute ___modver_attr = {       \
                .mattr  = {                                             \
                        .attr   = {                                     \
                                .name   = "version",                    \
@@ -187,7 +185,10 @@ extern struct module __this_module;
                },                                                      \
                .module_name    = KBUILD_MODNAME,                       \
                .version        = _version,                             \
-       }
+       };                                                              \
+       static const struct module_version_attribute                    \
+       __used __attribute__ ((__section__ ("__modver")))               \
+       * __moduleparam_const __modver_attr = &___modver_attr
 #endif
 
 /* Optional firmware file (or files) needed by the module
@@ -223,7 +224,7 @@ struct module_use {
        extern void *__crc_##sym __attribute__((weak));         \
        static const unsigned long __kcrctab_##sym              \
        __used                                                  \
-       __attribute__((section("__kcrctab" sec), unused))       \
+       __attribute__((section("___kcrctab" sec "+" #sym), unused))     \
        = (unsigned long) &__crc_##sym;
 #else
 #define __CRC_SYMBOL(sym, sec)
@@ -238,7 +239,7 @@ struct module_use {
        = MODULE_SYMBOL_PREFIX #sym;                            \
        static const struct kernel_symbol __ksymtab_##sym       \
        __used                                                  \
-       __attribute__((section("__ksymtab" sec), unused))       \
+       __attribute__((section("___ksymtab" sec "+" #sym), unused))     \
        = { (unsigned long)&sym, __kstrtab_##sym }
 
 #define EXPORT_SYMBOL(sym)                                     \
@@ -367,34 +368,35 @@ struct module
        struct module_notes_attrs *notes_attrs;
 #endif
 
+       /* The command line arguments (may be mangled).  People like
+          keeping pointers to this stuff */
+       char *args;
+
 #ifdef CONFIG_SMP
        /* Per-cpu data. */
        void __percpu *percpu;
        unsigned int percpu_size;
 #endif
 
-       /* The command line arguments (may be mangled).  People like
-          keeping pointers to this stuff */
-       char *args;
 #ifdef CONFIG_TRACEPOINTS
-       struct tracepoint * const *tracepoints_ptrs;
        unsigned int num_tracepoints;
+       struct tracepoint * const *tracepoints_ptrs;
 #endif
 #ifdef HAVE_JUMP_LABEL
        struct jump_entry *jump_entries;
        unsigned int num_jump_entries;
 #endif
 #ifdef CONFIG_TRACING
-       const char **trace_bprintk_fmt_start;
        unsigned int num_trace_bprintk_fmt;
+       const char **trace_bprintk_fmt_start;
 #endif
 #ifdef CONFIG_EVENT_TRACING
        struct ftrace_event_call **trace_events;
        unsigned int num_trace_events;
 #endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
-       unsigned long *ftrace_callsites;
        unsigned int num_ftrace_callsites;
+       unsigned long *ftrace_callsites;
 #endif
 
 #ifdef CONFIG_MODULE_UNLOAD
@@ -475,8 +477,9 @@ const struct kernel_symbol *find_symbol(const char *name,
                                        bool warn);
 
 /* Walk the exported symbol table */
-bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
-                           unsigned int symnum, void *data), void *data);
+bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
+                                   struct module *owner,
+                                   void *data), void *data);
 
 /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
    symnum out of range. */
index 07b41951e3fa9eb7894032a4921cdd65a05c05bd..ddaae98c53f9191ec2314efa46c904912b1781ff 100644 (file)
@@ -67,9 +67,9 @@ struct kparam_string {
 struct kparam_array
 {
        unsigned int max;
+       unsigned int elemsize;
        unsigned int *num;
        const struct kernel_param_ops *ops;
-       unsigned int elemsize;
        void *elem;
 };
 
@@ -371,8 +371,9 @@ extern int param_get_invbool(char *buffer, const struct kernel_param *kp);
  */
 #define module_param_array_named(name, array, type, nump, perm)                \
        static const struct kparam_array __param_arr_##name             \
-       = { ARRAY_SIZE(array), nump, &param_ops_##type,                 \
-           sizeof(array[0]), array };                                  \
+       = { .max = ARRAY_SIZE(array), .num = nump,                      \
+           .ops = &param_ops_##type,                                   \
+           .elemsize = sizeof(array[0]), .elem = array };              \
        __module_param_call(MODULE_PARAM_PREFIX, name,                  \
                            &param_array_ops,                           \
                            .arr = &__param_arr_##name,                 \
index 94b48bd40dd735f77963fcd31797d32bb68b3379..c75471db576ef0d500eb5a363b607819f38b869b 100644 (file)
@@ -51,7 +51,7 @@ struct mutex {
        spinlock_t              wait_lock;
        struct list_head        wait_list;
 #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
-       struct thread_info      *owner;
+       struct task_struct      *owner;
 #endif
 #ifdef CONFIG_DEBUG_MUTEXES
        const char              *name;
index 216cea5db0aafbba934a9d55541c09788e10dbef..87694ca86914e379a098096fdd6989df71732a8f 100644 (file)
@@ -47,6 +47,7 @@ struct nfs_client {
 
 #ifdef CONFIG_NFS_V4
        u64                     cl_clientid;    /* constant */
+       nfs4_verifier           cl_confirm;     /* Clientid verifier */
        unsigned long           cl_state;
 
        spinlock_t              cl_lock;
index 78b101e487eac78113ea001974d7e50ebf6b6e8b..7e371f7df9c463270a15b23a1b3fce52b26fc02d 100644 (file)
@@ -50,6 +50,7 @@ struct nfs_fattr {
        } du;
        struct nfs_fsid         fsid;
        __u64                   fileid;
+       __u64                   mounted_on_fileid;
        struct timespec         atime;
        struct timespec         mtime;
        struct timespec         ctime;
@@ -83,6 +84,7 @@ struct nfs_fattr {
 #define NFS_ATTR_FATTR_PRECHANGE       (1U << 18)
 #define NFS_ATTR_FATTR_V4_REFERRAL     (1U << 19)      /* NFSv4 referral */
 #define NFS_ATTR_FATTR_MOUNTPOINT      (1U << 20)      /* Treat as mountpoint */
+#define NFS_ATTR_FATTR_MOUNTED_ON_FILEID               (1U << 21)
 
 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
                | NFS_ATTR_FATTR_MODE \
@@ -231,6 +233,7 @@ struct nfs4_layoutget {
        struct nfs4_layoutget_args args;
        struct nfs4_layoutget_res res;
        struct pnfs_layout_segment **lsegpp;
+       gfp_t gfp_flags;
 };
 
 struct nfs4_getdeviceinfo_args {
index 8bfe6c1d43654069b8fa2e1bbc61ab4d34dd4d22..ae5638480ef22141f0699854d4b59fbba57aeffe 100644 (file)
@@ -21,8 +21,7 @@ extern void of_device_make_bus_id(struct device *dev);
 static inline int of_driver_match_device(struct device *dev,
                                         const struct device_driver *drv)
 {
-       dev->of_match = of_match_device(drv->of_match_table, dev);
-       return dev->of_match != NULL;
+       return of_match_device(drv->of_match_table, dev) != NULL;
 }
 
 extern struct platform_device *of_dev_get(struct platform_device *dev);
@@ -58,6 +57,11 @@ static inline int of_device_uevent(struct device *dev,
 
 static inline void of_device_node_put(struct device *dev) { }
 
+static inline const struct of_device_id *of_match_device(
+               const struct of_device_id *matches, const struct device *dev)
+{
+       return NULL;
+}
 #endif /* CONFIG_OF_DEVICE */
 
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
new file mode 100644 (file)
index 0000000..655824f
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef LINUX_PCI_ATS_H
+#define LINUX_PCI_ATS_H
+
+/* Address Translation Service */
+struct pci_ats {
+       int pos;        /* capability position */
+       int stu;        /* Smallest Translation Unit */
+       int qdep;       /* Invalidate Queue Depth */
+       int ref_cnt;    /* Physical Function reference count */
+       unsigned int is_enabled:1;      /* Enable bit is set */
+};
+
+#ifdef CONFIG_PCI_IOV
+
+extern int pci_enable_ats(struct pci_dev *dev, int ps);
+extern void pci_disable_ats(struct pci_dev *dev);
+extern int pci_ats_queue_depth(struct pci_dev *dev);
+/**
+ * pci_ats_enabled - query the ATS status
+ * @dev: the PCI device
+ *
+ * Returns 1 if ATS capability is enabled, or 0 if not.
+ */
+static inline int pci_ats_enabled(struct pci_dev *dev)
+{
+       return dev->ats && dev->ats->is_enabled;
+}
+
+#else /* CONFIG_PCI_IOV */
+
+static inline int pci_enable_ats(struct pci_dev *dev, int ps)
+{
+       return -ENODEV;
+}
+
+static inline void pci_disable_ats(struct pci_dev *dev)
+{
+}
+
+static inline int pci_ats_queue_depth(struct pci_dev *dev)
+{
+       return -ENODEV;
+}
+
+static inline int pci_ats_enabled(struct pci_dev *dev)
+{
+       return 0;
+}
+
+#endif /* CONFIG_PCI_IOV */
+
+#endif /* LINUX_PCI_ATS_H*/
index 4e2c9150a78525859455ffb1e06551d4b3781b33..8abe8d78c4bfad95d409b8ef74e19d9e6fad11d0 100644 (file)
 #define PCI_DEVICE_ID_INTEL_82840_HB   0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
 #define PCI_DEVICE_ID_INTEL_IOAT       0x1a38
-#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS  0x1c22
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN        0x1c41
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX        0x1c5f
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS     0x1d22
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0     0x1d40
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1     0x1d41
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN   0x2310
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX   0x231f
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
 #define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN      0x3b00
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX      0x3b1f
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
 #define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
index 3a5c4449fd36050f667ee13553924bdf44d9a3f8..8b97308e65df3ccf094d79af23266e2da5fc73af 100644 (file)
@@ -948,7 +948,7 @@ do {                                                                        \
        irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
 # endif
 # define irqsafe_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)    \
-       __pcpu_double_call_return_int(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
+       __pcpu_double_call_return_bool(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
 #endif
 
 #endif /* __LINUX_PERCPU_H */
index ee9f1e7828001f26a5657962040277cb6e574795..3412684ce5d541176ba1e5b64f09244e8d3cdc45 100644 (file)
@@ -2,8 +2,8 @@
  * Performance events:
  *
  *    Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
- *    Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar
- *    Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra
+ *    Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar
+ *    Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra
  *
  * Data type definitions, declarations, prototypes.
  *
@@ -52,6 +52,8 @@ enum perf_hw_id {
        PERF_COUNT_HW_BRANCH_INSTRUCTIONS       = 4,
        PERF_COUNT_HW_BRANCH_MISSES             = 5,
        PERF_COUNT_HW_BUS_CYCLES                = 6,
+       PERF_COUNT_HW_STALLED_CYCLES_FRONTEND   = 7,
+       PERF_COUNT_HW_STALLED_CYCLES_BACKEND    = 8,
 
        PERF_COUNT_HW_MAX,                      /* non-ABI */
 };
@@ -468,9 +470,9 @@ enum perf_callchain_context {
        PERF_CONTEXT_MAX                = (__u64)-4095,
 };
 
-#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_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 */
 
 #ifdef __KERNEL__
 /*
@@ -484,9 +486,9 @@ enum perf_callchain_context {
 #endif
 
 struct perf_guest_info_callbacks {
-       int (*is_in_guest) (void);
-       int (*is_user_mode) (void);
-       unsigned long (*get_guest_ip) (void);
+       int                             (*is_in_guest)(void);
+       int                             (*is_user_mode)(void);
+       unsigned long                   (*get_guest_ip)(void);
 };
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
@@ -505,7 +507,7 @@ struct perf_guest_info_callbacks {
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
 #include <linux/irq_work.h>
-#include <linux/jump_label_ref.h>
+#include <linux/jump_label.h>
 #include <asm/atomic.h>
 #include <asm/local.h>
 
@@ -652,19 +654,19 @@ struct pmu {
         * Start the transaction, after this ->add() doesn't need to
         * do schedulability tests.
         */
-       void (*start_txn)       (struct pmu *pmu); /* optional */
+       void (*start_txn)               (struct pmu *pmu); /* optional */
        /*
         * If ->start_txn() disabled the ->add() schedulability test
         * then ->commit_txn() is required to perform one. On success
         * the transaction is closed. On error the transaction is kept
         * open until ->cancel_txn() is called.
         */
-       int  (*commit_txn)      (struct pmu *pmu); /* optional */
+       int  (*commit_txn)              (struct pmu *pmu); /* optional */
        /*
         * Will cancel the transaction, assumes ->del() is called
         * for each successful ->add() during the transaction.
         */
-       void (*cancel_txn)      (struct pmu *pmu); /* optional */
+       void (*cancel_txn)              (struct pmu *pmu); /* optional */
 };
 
 /**
@@ -712,15 +714,15 @@ typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
                                        struct pt_regs *regs);
 
 enum perf_group_flag {
-       PERF_GROUP_SOFTWARE = 0x1,
+       PERF_GROUP_SOFTWARE             = 0x1,
 };
 
-#define SWEVENT_HLIST_BITS     8
-#define SWEVENT_HLIST_SIZE     (1 << SWEVENT_HLIST_BITS)
+#define SWEVENT_HLIST_BITS             8
+#define SWEVENT_HLIST_SIZE             (1 << SWEVENT_HLIST_BITS)
 
 struct swevent_hlist {
-       struct hlist_head       heads[SWEVENT_HLIST_SIZE];
-       struct rcu_head         rcu_head;
+       struct hlist_head               heads[SWEVENT_HLIST_SIZE];
+       struct rcu_head                 rcu_head;
 };
 
 #define PERF_ATTACH_CONTEXT    0x01
@@ -733,13 +735,13 @@ struct swevent_hlist {
  * This is a per-cpu dynamically allocated data structure.
  */
 struct perf_cgroup_info {
-       u64 time;
-       u64 timestamp;
+       u64                             time;
+       u64                             timestamp;
 };
 
 struct perf_cgroup {
-       struct cgroup_subsys_state css;
-       struct perf_cgroup_info *info;  /* timing info, one per cpu */
+       struct                          cgroup_subsys_state css;
+       struct                          perf_cgroup_info *info; /* timing info, one per cpu */
 };
 #endif
 
@@ -923,7 +925,7 @@ struct perf_event_context {
 
 /*
  * Number of contexts where an event can trigger:
- *     task, softirq, hardirq, nmi.
+ *     task, softirq, hardirq, nmi.
  */
 #define PERF_NR_CONTEXTS       4
 
@@ -1001,8 +1003,7 @@ struct perf_sample_data {
        struct perf_raw_record          *raw;
 };
 
-static inline
-void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
+static inline void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
 {
        data->addr = addr;
        data->raw  = NULL;
@@ -1034,13 +1035,12 @@ static inline int is_software_event(struct perf_event *event)
        return event->pmu->task_ctx_nr == perf_sw_context;
 }
 
-extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
 
 extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);
 
 #ifndef perf_arch_fetch_caller_regs
-static inline void
-perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { }
+static inline void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { }
 #endif
 
 /*
@@ -1063,26 +1063,24 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
 {
        struct pt_regs hot_regs;
 
-       JUMP_LABEL(&perf_swevent_enabled[event_id], have_event);
-       return;
-
-have_event:
-       if (!regs) {
-               perf_fetch_caller_regs(&hot_regs);
-               regs = &hot_regs;
+       if (static_branch(&perf_swevent_enabled[event_id])) {
+               if (!regs) {
+                       perf_fetch_caller_regs(&hot_regs);
+                       regs = &hot_regs;
+               }
+               __perf_sw_event(event_id, nr, nmi, regs, addr);
        }
-       __perf_sw_event(event_id, nr, nmi, regs, addr);
 }
 
-extern atomic_t perf_sched_events;
+extern struct jump_label_key perf_sched_events;
 
 static inline void perf_event_task_sched_in(struct task_struct *task)
 {
-       COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task));
+       if (static_branch(&perf_sched_events))
+               __perf_event_task_sched_in(task);
 }
 
-static inline
-void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
+static inline void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
 {
        perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
 
@@ -1100,14 +1098,10 @@ extern void perf_event_fork(struct task_struct *tsk);
 /* Callchains */
 DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry);
 
-extern void perf_callchain_user(struct perf_callchain_entry *entry,
-                               struct pt_regs *regs);
-extern void perf_callchain_kernel(struct perf_callchain_entry *entry,
-                                 struct pt_regs *regs);
-
+extern void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs);
+extern void perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs);
 
-static inline void
-perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)
+static inline void perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)
 {
        if (entry->nr < PERF_MAX_STACK_DEPTH)
                entry->ip[entry->nr++] = ip;
@@ -1143,9 +1137,9 @@ extern void perf_tp_event(u64 addr, u64 count, void *record,
 extern void perf_bp_event(struct perf_event *event, void *data);
 
 #ifndef perf_misc_flags
-#define perf_misc_flags(regs)  (user_mode(regs) ? PERF_RECORD_MISC_USER : \
-                                PERF_RECORD_MISC_KERNEL)
-#define perf_instruction_pointer(regs) instruction_pointer(regs)
+# define perf_misc_flags(regs) \
+               (user_mode(regs) ? PERF_RECORD_MISC_USER : PERF_RECORD_MISC_KERNEL)
+# define perf_instruction_pointer(regs)        instruction_pointer(regs)
 #endif
 
 extern int perf_output_begin(struct perf_output_handle *handle,
@@ -1180,9 +1174,9 @@ static inline void
 perf_bp_event(struct perf_event *event, void *data)                    { }
 
 static inline int perf_register_guest_info_callbacks
-(struct perf_guest_info_callbacks *callbacks) { return 0; }
+(struct perf_guest_info_callbacks *callbacks)                          { return 0; }
 static inline int perf_unregister_guest_info_callbacks
-(struct perf_guest_info_callbacks *callbacks) { return 0; }
+(struct perf_guest_info_callbacks *callbacks)                          { return 0; }
 
 static inline void perf_event_mmap(struct vm_area_struct *vma)         { }
 static inline void perf_event_comm(struct task_struct *tsk)            { }
@@ -1195,23 +1189,22 @@ static inline void perf_event_disable(struct perf_event *event)         { }
 static inline void perf_event_task_tick(void)                          { }
 #endif
 
-#define perf_output_put(handle, x) \
-       perf_output_copy((handle), &(x), sizeof(x))
+#define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x))
 
 /*
  * This has to have a higher priority than migration_notifier in sched.c.
  */
-#define perf_cpu_notifier(fn)                                  \
-do {                                                           \
-       static struct notifier_block fn##_nb __cpuinitdata =    \
-               { .notifier_call = fn, .priority = CPU_PRI_PERF }; \
-       fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,             \
-               (void *)(unsigned long)smp_processor_id());     \
-       fn(&fn##_nb, (unsigned long)CPU_STARTING,               \
-               (void *)(unsigned long)smp_processor_id());     \
-       fn(&fn##_nb, (unsigned long)CPU_ONLINE,                 \
-               (void *)(unsigned long)smp_processor_id());     \
-       register_cpu_notifier(&fn##_nb);                        \
+#define perf_cpu_notifier(fn)                                          \
+do {                                                                   \
+       static struct notifier_block fn##_nb __cpuinitdata =            \
+               { .notifier_call = fn, .priority = CPU_PRI_PERF };      \
+       fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,                     \
+               (void *)(unsigned long)smp_processor_id());             \
+       fn(&fn##_nb, (unsigned long)CPU_STARTING,                       \
+               (void *)(unsigned long)smp_processor_id());             \
+       fn(&fn##_nb, (unsigned long)CPU_ONLINE,                         \
+               (void *)(unsigned long)smp_processor_id());             \
+       register_cpu_notifier(&fn##_nb);                                \
 } while (0)
 
 #endif /* __KERNEL__ */
index 744942c95fec478ff9b0e687e9496b9ff76a84bd..ede1a80e3358aeb4c63fc2185b2e53cedc4f4fde 100644 (file)
@@ -150,9 +150,6 @@ extern struct platform_device *platform_create_bundle(struct platform_driver *dr
                                        struct resource *res, unsigned int n_res,
                                        const void *data, size_t size);
 
-extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
-extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
-
 /* early platform driver interface */
 struct early_platform_driver {
        const char *class_str;
@@ -205,4 +202,64 @@ static inline char *early_platform_driver_setup_func(void)         \
 }
 #endif /* MODULE */
 
+#ifdef CONFIG_PM_SLEEP
+extern int platform_pm_prepare(struct device *dev);
+extern void platform_pm_complete(struct device *dev);
+#else
+#define platform_pm_prepare    NULL
+#define platform_pm_complete   NULL
+#endif
+
+#ifdef CONFIG_SUSPEND
+extern int platform_pm_suspend(struct device *dev);
+extern int platform_pm_suspend_noirq(struct device *dev);
+extern int platform_pm_resume(struct device *dev);
+extern int platform_pm_resume_noirq(struct device *dev);
+#else
+#define platform_pm_suspend            NULL
+#define platform_pm_resume             NULL
+#define platform_pm_suspend_noirq      NULL
+#define platform_pm_resume_noirq       NULL
+#endif
+
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+extern int platform_pm_freeze(struct device *dev);
+extern int platform_pm_freeze_noirq(struct device *dev);
+extern int platform_pm_thaw(struct device *dev);
+extern int platform_pm_thaw_noirq(struct device *dev);
+extern int platform_pm_poweroff(struct device *dev);
+extern int platform_pm_poweroff_noirq(struct device *dev);
+extern int platform_pm_restore(struct device *dev);
+extern int platform_pm_restore_noirq(struct device *dev);
+#else
+#define platform_pm_freeze             NULL
+#define platform_pm_thaw               NULL
+#define platform_pm_poweroff           NULL
+#define platform_pm_restore            NULL
+#define platform_pm_freeze_noirq       NULL
+#define platform_pm_thaw_noirq         NULL
+#define platform_pm_poweroff_noirq     NULL
+#define platform_pm_restore_noirq      NULL
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+#define USE_PLATFORM_PM_SLEEP_OPS \
+       .prepare = platform_pm_prepare, \
+       .complete = platform_pm_complete, \
+       .suspend = platform_pm_suspend, \
+       .resume = platform_pm_resume, \
+       .freeze = platform_pm_freeze, \
+       .thaw = platform_pm_thaw, \
+       .poweroff = platform_pm_poweroff, \
+       .restore = platform_pm_restore, \
+       .suspend_noirq = platform_pm_suspend_noirq, \
+       .resume_noirq = platform_pm_resume_noirq, \
+       .freeze_noirq = platform_pm_freeze_noirq, \
+       .thaw_noirq = platform_pm_thaw_noirq, \
+       .poweroff_noirq = platform_pm_poweroff_noirq, \
+       .restore_noirq = platform_pm_restore_noirq,
+#else
+#define USE_PLATFORM_PM_SLEEP_OPS
+#endif
+
 #endif /* _PLATFORM_DEVICE_H_ */
index 512e09177e57a59cf10386ff4fa822735899f38a..3160648ccdda1ffe47312d3b2e90b368f36898f3 100644 (file)
@@ -460,6 +460,7 @@ struct dev_pm_info {
        unsigned long           active_jiffies;
        unsigned long           suspended_jiffies;
        unsigned long           accounting_timestamp;
+       void                    *subsys_data;  /* Owned by the subsystem. */
 #endif
 };
 
@@ -529,21 +530,17 @@ struct dev_power_domain {
  */
 
 #ifdef CONFIG_PM_SLEEP
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-extern int sysdev_suspend(pm_message_t state);
-extern int sysdev_resume(void);
-#else
-static inline int sysdev_suspend(pm_message_t state) { return 0; }
-static inline int sysdev_resume(void) { return 0; }
-#endif
-
 extern void device_pm_lock(void);
 extern void dpm_resume_noirq(pm_message_t state);
 extern void dpm_resume_end(pm_message_t state);
+extern void dpm_resume(pm_message_t state);
+extern void dpm_complete(pm_message_t state);
 
 extern void device_pm_unlock(void);
 extern int dpm_suspend_noirq(pm_message_t state);
 extern int dpm_suspend_start(pm_message_t state);
+extern int dpm_suspend(pm_message_t state);
+extern int dpm_prepare(pm_message_t state);
 
 extern void __suspend_report_result(const char *function, void *fn, int ret);
 
@@ -553,6 +550,16 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
        } while (0)
 
 extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
+
+extern int pm_generic_prepare(struct device *dev);
+extern int pm_generic_suspend(struct device *dev);
+extern int pm_generic_resume(struct device *dev);
+extern int pm_generic_freeze(struct device *dev);
+extern int pm_generic_thaw(struct device *dev);
+extern int pm_generic_restore(struct device *dev);
+extern int pm_generic_poweroff(struct device *dev);
+extern void pm_generic_complete(struct device *dev);
+
 #else /* !CONFIG_PM_SLEEP */
 
 #define device_pm_lock() do {} while (0)
@@ -569,6 +576,15 @@ static inline int device_pm_wait_for_dev(struct device *a, struct device *b)
 {
        return 0;
 }
+
+#define pm_generic_prepare     NULL
+#define pm_generic_suspend     NULL
+#define pm_generic_resume      NULL
+#define pm_generic_freeze      NULL
+#define pm_generic_thaw                NULL
+#define pm_generic_restore     NULL
+#define pm_generic_poweroff    NULL
+#define pm_generic_complete    NULL
 #endif /* !CONFIG_PM_SLEEP */
 
 /* How to reorder dpm_list after device_move() */
@@ -579,11 +595,4 @@ enum dpm_order {
        DPM_ORDER_DEV_LAST,
 };
 
-extern int pm_generic_suspend(struct device *dev);
-extern int pm_generic_resume(struct device *dev);
-extern int pm_generic_freeze(struct device *dev);
-extern int pm_generic_thaw(struct device *dev);
-extern int pm_generic_restore(struct device *dev);
-extern int pm_generic_poweroff(struct device *dev);
-
 #endif /* _LINUX_PM_H */
index 8de9aa6e7def9a4e2380b3f2d4e9a17727518890..878cf84baeb1c3f89087e5106e292d32536f68d4 100644 (file)
@@ -245,4 +245,46 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
        __pm_runtime_use_autosuspend(dev, false);
 }
 
+struct pm_clk_notifier_block {
+       struct notifier_block nb;
+       struct dev_power_domain *pwr_domain;
+       char *con_ids[];
+};
+
+#ifdef CONFIG_PM_RUNTIME_CLK
+extern int pm_runtime_clk_init(struct device *dev);
+extern void pm_runtime_clk_destroy(struct device *dev);
+extern int pm_runtime_clk_add(struct device *dev, const char *con_id);
+extern void pm_runtime_clk_remove(struct device *dev, const char *con_id);
+extern int pm_runtime_clk_suspend(struct device *dev);
+extern int pm_runtime_clk_resume(struct device *dev);
+#else
+static inline int pm_runtime_clk_init(struct device *dev)
+{
+       return -EINVAL;
+}
+static inline void pm_runtime_clk_destroy(struct device *dev)
+{
+}
+static inline int pm_runtime_clk_add(struct device *dev, const char *con_id)
+{
+       return -EINVAL;
+}
+static inline void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+{
+}
+#define pm_runtime_clock_suspend       NULL
+#define pm_runtime_clock_resume                NULL
+#endif
+
+#ifdef CONFIG_HAVE_CLK
+extern void pm_runtime_clk_add_notifier(struct bus_type *bus,
+                                       struct pm_clk_notifier_block *clknb);
+#else
+static inline void pm_runtime_clk_add_notifier(struct bus_type *bus,
+                                       struct pm_clk_notifier_block *clknb)
+{
+}
+#endif
+
 #endif
index 369e19d3750ba9ac4365cf8e778d61f6a9e239a5..7f1183dcd119e0e25dfd959827364e30f7ee291c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/posix-timers.h>
+#include <linux/rwsem.h>
 
 struct posix_clock;
 
@@ -104,7 +105,7 @@ struct posix_clock_operations {
  * @ops:     Functional interface to the clock
  * @cdev:    Character device instance for this clock
  * @kref:    Reference count.
- * @mutex:   Protects the 'zombie' field from concurrent access.
+ * @rwsem:   Protects the 'zombie' field from concurrent access.
  * @zombie:  If 'zombie' is true, then the hardware has disappeared.
  * @release: A function to free the structure when the reference count reaches
  *           zero. May be NULL if structure is statically allocated.
@@ -117,7 +118,7 @@ struct posix_clock {
        struct posix_clock_operations ops;
        struct cdev cdev;
        struct kref kref;
-       struct mutex mutex;
+       struct rw_semaphore rwsem;
        bool zombie;
        void (*release)(struct posix_clock *clk);
 };
index d51243ae0726b321d3696eef4f3ff9bdc09a0403..808227d40a645a7cabf83cb0d0c10cc04e2ac86d 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/timex.h>
+#include <linux/alarmtimer.h>
 
 union cpu_time_count {
        cputime_t cpu;
@@ -80,6 +81,7 @@ struct k_itimer {
                        unsigned long incr;
                        unsigned long expires;
                } mmtimer;
+               struct alarm alarmtimer;
        } it;
 };
 
index 838c1149251a1e8edff75dd2db6ef58092542386..eaf4350c0f905bfb5e2dfa6380118fe805b1b785 100644 (file)
@@ -208,6 +208,8 @@ static inline struct proc_dir_entry *proc_symlink(const char *name,
                struct proc_dir_entry *parent,const char *dest) {return NULL;}
 static inline struct proc_dir_entry *proc_mkdir(const char *name,
        struct proc_dir_entry *parent) {return NULL;}
+static inline struct proc_dir_entry *proc_mkdir_mode(const char *name,
+       mode_t mode, struct proc_dir_entry *parent) { return NULL; }
 
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
        mode_t mode, struct proc_dir_entry *base, 
index a1147e5dd245e8d7d262598b3c920ceb796efd00..9178d5cc0b0143a0e81336e6dea09e1cbedab86e 100644 (file)
@@ -189,6 +189,10 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
                child->ptrace = current->ptrace;
                __ptrace_link(child, current->parent);
        }
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+       atomic_set(&child->ptrace_bp_refcnt, 1);
+#endif
 }
 
 /**
@@ -350,6 +354,13 @@ extern int task_current_syscall(struct task_struct *target, long *callno,
                                unsigned long args[6], unsigned int maxargs,
                                unsigned long *sp, unsigned long *pc);
 
-#endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+extern int ptrace_get_breakpoints(struct task_struct *tsk);
+extern void ptrace_put_breakpoints(struct task_struct *tsk);
+#else
+static inline void ptrace_put_breakpoints(struct task_struct *tsk) { }
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+#endif /* __KERNEL */
 
 #endif
index 7066acb2c53072c4d6df35b7bc909723d1d646a9..033b507b33b17075e5ab5cf287b264d3b9b22f35 100644 (file)
@@ -136,6 +136,14 @@ static inline void rb_set_color(struct rb_node *rb, int color)
 #define RB_EMPTY_NODE(node)    (rb_parent(node) == node)
 #define RB_CLEAR_NODE(node)    (rb_set_parent(node, node))
 
+static inline void rb_init_node(struct rb_node *rb)
+{
+       rb->rb_parent_color = 0;
+       rb->rb_right = NULL;
+       rb->rb_left = NULL;
+       RB_CLEAR_NODE(rb);
+}
+
 extern void rb_insert_color(struct rb_node *, struct rb_root *);
 extern void rb_erase(struct rb_node *, struct rb_root *);
 
index 2dea94fc44026a1048f912913be298b8df179873..e3beb315517a7a06dea6db0b2d0c8c9aee7ce9e4 100644 (file)
@@ -253,7 +253,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
  */
 #define list_for_each_entry_rcu(pos, head, member) \
        for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
-               prefetch(pos->member.next), &pos->member != (head); \
+               &pos->member != (head); \
                pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
 
@@ -270,7 +270,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
  */
 #define list_for_each_continue_rcu(pos, head) \
        for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
-               prefetch((pos)->next), (pos) != (head); \
+               (pos) != (head); \
                (pos) = rcu_dereference_raw(list_next_rcu(pos)))
 
 /**
@@ -284,7 +284,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
  */
 #define list_for_each_entry_continue_rcu(pos, head, member)            \
        for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \
-            prefetch(pos->member.next), &pos->member != (head);        \
+            &pos->member != (head);    \
             pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
 /**
@@ -427,7 +427,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
 
 #define __hlist_for_each_rcu(pos, head)                                \
        for (pos = rcu_dereference(hlist_first_rcu(head));      \
-            pos && ({ prefetch(pos->next); 1; });              \
+            pos;                                               \
             pos = rcu_dereference(hlist_next_rcu(pos)))
 
 /**
@@ -443,7 +443,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
  */
 #define hlist_for_each_entry_rcu(tpos, pos, head, member)              \
        for (pos = rcu_dereference_raw(hlist_first_rcu(head));          \
-               pos && ({ prefetch(pos->next); 1; }) &&                  \
+               pos &&                                                   \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_raw(hlist_next_rcu(pos)))
 
@@ -460,7 +460,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
  */
 #define hlist_for_each_entry_rcu_bh(tpos, pos, head, member)            \
        for (pos = rcu_dereference_bh((head)->first);                    \
-               pos && ({ prefetch(pos->next); 1; }) &&                  \
+               pos &&                                                   \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_bh(pos->next))
 
@@ -472,7 +472,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
  */
 #define hlist_for_each_entry_continue_rcu(tpos, pos, member)           \
        for (pos = rcu_dereference((pos)->next);                        \
-            pos && ({ prefetch(pos->next); 1; }) &&                    \
+            pos &&                                                     \
             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; });  \
             pos = rcu_dereference(pos->next))
 
@@ -484,7 +484,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
  */
 #define hlist_for_each_entry_continue_rcu_bh(tpos, pos, member)                \
        for (pos = rcu_dereference_bh((pos)->next);                     \
-            pos && ({ prefetch(pos->next); 1; }) &&                    \
+            pos &&                                                     \
             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; });  \
             pos = rcu_dereference_bh(pos->next))
 
index ff422d2b7f9012661e36a89213159db7da309f4e..99f9aa7c2804e2775ff552a87aeb2f27de7bac97 100644 (file)
 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);
+#else
+static inline void rcutorture_record_test_transition(void)
+{
+}
+static inline void rcutorture_record_progress(unsigned long vernum)
+{
+}
+#endif
+
 #define UINT_CMP_GE(a, b)      (UINT_MAX / 2 >= (a) - (b))
 #define UINT_CMP_LT(a, b)      (UINT_MAX / 2 < (a) - (b))
 #define ULONG_CMP_GE(a, b)     (ULONG_MAX / 2 >= (a) - (b))
@@ -68,7 +80,6 @@ extern void call_rcu_sched(struct rcu_head *head,
 extern void synchronize_sched(void);
 extern void rcu_barrier_bh(void);
 extern void rcu_barrier_sched(void);
-extern int sched_expedited_torture_stats(char *page);
 
 static inline void __rcu_read_lock_bh(void)
 {
@@ -774,6 +785,7 @@ extern struct debug_obj_descr rcuhead_debug_descr;
 
 static inline void debug_rcu_head_queue(struct rcu_head *head)
 {
+       WARN_ON_ONCE((unsigned long)head & 0x3);
        debug_object_activate(head, &rcuhead_debug_descr);
        debug_object_active_state(head, &rcuhead_debug_descr,
                                  STATE_RCU_HEAD_READY,
@@ -797,4 +809,60 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
 }
 #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
+static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
+{
+       return offset < 4096;
+}
+
+static __always_inline
+void __kfree_rcu(struct rcu_head *head, unsigned long offset)
+{
+       typedef void (*rcu_callback)(struct rcu_head *);
+
+       BUILD_BUG_ON(!__builtin_constant_p(offset));
+
+       /* See the kfree_rcu() header comment. */
+       BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
+
+       call_rcu(head, (rcu_callback)offset);
+}
+
+extern void kfree(const void *);
+
+static inline void __rcu_reclaim(struct rcu_head *head)
+{
+       unsigned long offset = (unsigned long)head->func;
+
+       if (__is_kfree_rcu_offset(offset))
+               kfree((void *)head - offset);
+       else
+               head->func(head);
+}
+
+/**
+ * kfree_rcu() - kfree an object after a grace period.
+ * @ptr:       pointer to kfree
+ * @rcu_head:  the name of the struct rcu_head within the type of @ptr.
+ *
+ * Many rcu callbacks functions just call kfree() on the base structure.
+ * These functions are trivial, but their size adds up, and furthermore
+ * when they are used in a kernel module, that module must invoke the
+ * high-latency rcu_barrier() function at module-unload time.
+ *
+ * The kfree_rcu() function handles this issue.  Rather than encoding a
+ * function address in the embedded rcu_head structure, kfree_rcu() instead
+ * encodes the offset of the rcu_head structure within the base structure.
+ * Because the functions are not allowed in the low-order 4096 bytes of
+ * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
+ * If the offset is larger than 4095 bytes, a compile-time error will
+ * be generated in __kfree_rcu().  If this error is triggered, you can
+ * either fall back to use of call_rcu() or rearrange the structure to
+ * position the rcu_head structure into the first 4096 bytes.
+ *
+ * Note that the allowable offset might decrease in the future, for example,
+ * to allow something like kmem_cache_free_rcu().
+ */
+#define kfree_rcu(ptr, rcu_head)                                       \
+       __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
+
 #endif /* __LINUX_RCUPDATE_H */
index 30ebd7c8d874b4dfeb9c9c9e5c5e857fbb43ab62..52b3e0281fd0ab2e5699783ca6f206a653bd280a 100644 (file)
@@ -99,6 +99,14 @@ static inline void rcu_note_context_switch(int cpu)
        rcu_preempt_note_context_switch();
 }
 
+/*
+ * Take advantage of the fact that there is only one CPU, which
+ * allows us to ignore virtualization-based context switches.
+ */
+static inline void rcu_virt_note_context_switch(int cpu)
+{
+}
+
 /*
  * Return the number of grace periods.
  */
index 3a933482734aeccbafc7a0bb735be11ede47cbd2..e65d06634dd80c7afc94ea7032110bcd925ac258 100644 (file)
@@ -35,6 +35,16 @@ extern void rcu_note_context_switch(int cpu);
 extern int rcu_needs_cpu(int cpu);
 extern void rcu_cpu_stall_reset(void);
 
+/*
+ * Note a virtualization-based context switch.  This is simply a
+ * wrapper around rcu_note_context_switch(), which allows TINY_RCU
+ * to save a few bytes.
+ */
+static inline void rcu_virt_note_context_switch(int cpu)
+{
+       rcu_note_context_switch(cpu);
+}
+
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
 extern void exit_rcu(void);
@@ -58,9 +68,12 @@ static inline void synchronize_rcu_bh_expedited(void)
 
 extern void rcu_barrier(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);
+
 extern void rcu_force_quiescent_state(void);
 extern void rcu_bh_force_quiescent_state(void);
 extern void rcu_sched_force_quiescent_state(void);
index 18d63cea28481c478906f791e384b520ad1f483b..12211e1666e2510b6389c47db75110b6ec8232ac 100644 (file)
@@ -360,7 +360,7 @@ extern signed long schedule_timeout_interruptible(signed long timeout);
 extern signed long schedule_timeout_killable(signed long timeout);
 extern signed long schedule_timeout_uninterruptible(signed long timeout);
 asmlinkage void schedule(void);
-extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner);
+extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
 
 struct nsproxy;
 struct user_namespace;
@@ -731,10 +731,6 @@ struct sched_info {
        /* timestamps */
        unsigned long long last_arrival,/* when we last ran on a cpu */
                           last_queued; /* when we were last queued to run */
-#ifdef CONFIG_SCHEDSTATS
-       /* BKL stats */
-       unsigned int bkl_count;
-#endif
 };
 #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
 
@@ -868,6 +864,7 @@ static inline int sd_power_saving_flags(void)
 
 struct sched_group {
        struct sched_group *next;       /* Must be a circular list */
+       atomic_t ref;
 
        /*
         * CPU power of this group, SCHED_LOAD_SCALE being max power for a
@@ -882,9 +879,6 @@ struct sched_group {
         * NOTE: this field is variable length. (Allocated dynamically
         * by attaching extra space to the end of the structure,
         * depending on how many CPUs the kernel has booted up with)
-        *
-        * It is also be embedded into static data structures at build
-        * time. (See 'struct static_sched_group' in kernel/sched.c)
         */
        unsigned long cpumask[0];
 };
@@ -894,17 +888,6 @@ static inline struct cpumask *sched_group_cpus(struct sched_group *sg)
        return to_cpumask(sg->cpumask);
 }
 
-enum sched_domain_level {
-       SD_LV_NONE = 0,
-       SD_LV_SIBLING,
-       SD_LV_MC,
-       SD_LV_BOOK,
-       SD_LV_CPU,
-       SD_LV_NODE,
-       SD_LV_ALLNODES,
-       SD_LV_MAX
-};
-
 struct sched_domain_attr {
        int relax_domain_level;
 };
@@ -913,6 +896,8 @@ struct sched_domain_attr {
        .relax_domain_level = -1,                       \
 }
 
+extern int sched_domain_level_max;
+
 struct sched_domain {
        /* These fields must be setup */
        struct sched_domain *parent;    /* top domain must be null terminated */
@@ -930,7 +915,7 @@ struct sched_domain {
        unsigned int forkexec_idx;
        unsigned int smt_gain;
        int flags;                      /* See SD_* */
-       enum sched_domain_level level;
+       int level;
 
        /* Runtime fields. */
        unsigned long last_balance;     /* init to jiffies. units in jiffies */
@@ -973,6 +958,10 @@ struct sched_domain {
 #ifdef CONFIG_SCHED_DEBUG
        char *name;
 #endif
+       union {
+               void *private;          /* used during construction */
+               struct rcu_head rcu;    /* used during destruction */
+       };
 
        unsigned int span_weight;
        /*
@@ -981,9 +970,6 @@ struct sched_domain {
         * NOTE: this field is variable length. (Allocated dynamically
         * by attaching extra space to the end of the structure,
         * depending on how many CPUs the kernel has booted up with)
-        *
-        * It is also be embedded into static data structures at build
-        * time. (See 'struct static_sched_domain' in kernel/sched.c)
         */
        unsigned long span[0];
 };
@@ -1048,8 +1034,12 @@ struct sched_domain;
 #define WF_FORK                0x02            /* child wakeup after fork */
 
 #define ENQUEUE_WAKEUP         1
-#define ENQUEUE_WAKING         2
-#define ENQUEUE_HEAD           4
+#define ENQUEUE_HEAD           2
+#ifdef CONFIG_SMP
+#define ENQUEUE_WAKING         4       /* sched_class::task_waking was called */
+#else
+#define ENQUEUE_WAKING         0
+#endif
 
 #define DEQUEUE_SLEEP          1
 
@@ -1067,12 +1057,11 @@ struct sched_class {
        void (*put_prev_task) (struct rq *rq, struct task_struct *p);
 
 #ifdef CONFIG_SMP
-       int  (*select_task_rq)(struct rq *rq, struct task_struct *p,
-                              int sd_flag, int flags);
+       int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
 
        void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
        void (*post_schedule) (struct rq *this_rq);
-       void (*task_waking) (struct rq *this_rq, struct task_struct *task);
+       void (*task_waking) (struct task_struct *task);
        void (*task_woken) (struct rq *this_rq, struct task_struct *task);
 
        void (*set_cpus_allowed)(struct task_struct *p,
@@ -1197,13 +1186,11 @@ struct task_struct {
        unsigned int flags;     /* per process flags, defined below */
        unsigned int ptrace;
 
-       int lock_depth;         /* BKL lock depth */
-
 #ifdef CONFIG_SMP
-#ifdef __ARCH_WANT_UNLOCKED_CTXSW
-       int oncpu;
-#endif
+       struct task_struct *wake_entry;
+       int on_cpu;
 #endif
+       int on_rq;
 
        int prio, static_prio, normal_prio;
        unsigned int rt_priority;
@@ -1274,6 +1261,7 @@ struct task_struct {
 
        /* Revert to default priority/policy when forking */
        unsigned sched_reset_on_fork:1;
+       unsigned sched_contributes_to_load:1;
 
        pid_t pid;
        pid_t tgid;
@@ -1537,6 +1525,9 @@ struct task_struct {
                unsigned long memsw_nr_pages; /* uncharged mem+swap usage */
        } memcg_batch;
 #endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+       atomic_t ptrace_bp_refcnt;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -2060,14 +2051,13 @@ extern void xtime_update(unsigned long ticks);
 
 extern int wake_up_state(struct task_struct *tsk, unsigned int state);
 extern int wake_up_process(struct task_struct *tsk);
-extern void wake_up_new_task(struct task_struct *tsk,
-                               unsigned long clone_flags);
+extern void wake_up_new_task(struct task_struct *tsk);
 #ifdef CONFIG_SMP
  extern void kick_process(struct task_struct *tsk);
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void sched_fork(struct task_struct *p, int clone_flags);
+extern void sched_fork(struct task_struct *p);
 extern void sched_dead(struct task_struct *p);
 
 extern void proc_caches_init(void);
@@ -2192,8 +2182,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
 extern char *get_task_comm(char *to, struct task_struct *tsk);
 
 #ifdef CONFIG_SMP
+void scheduler_ipi(void);
 extern unsigned long wait_task_inactive(struct task_struct *, long match_state);
 #else
+static inline void scheduler_ipi(void) { }
 static inline unsigned long wait_task_inactive(struct task_struct *p,
                                               long match_state)
 {
index ca02f1716736906c0bc98227a6b11be7975af2ff..8ce59ef3e5afbec48b903e5f8d3cd4318096f709 100644 (file)
@@ -1456,7 +1456,7 @@ struct security_operations {
                             struct inode *new_dir, struct dentry *new_dentry);
        int (*inode_readlink) (struct dentry *dentry);
        int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
-       int (*inode_permission) (struct inode *inode, int mask);
+       int (*inode_permission) (struct inode *inode, int mask, unsigned flags);
        int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
        int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
        int (*inode_setxattr) (struct dentry *dentry, const char *name,
index e98cd2e5719446fa69b03aeee3d349d14e138daa..06d69648fc86c3a731c528cde7fba3b72a2688be 100644 (file)
@@ -88,12 +88,12 @@ static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
        unsigned ret;
 
 repeat:
-       ret = sl->sequence;
-       smp_rmb();
+       ret = ACCESS_ONCE(sl->sequence);
        if (unlikely(ret & 1)) {
                cpu_relax();
                goto repeat;
        }
+       smp_rmb();
 
        return ret;
 }
index fcd2b14b19327a9765ff6e9e9a7e45e6cafa0f71..29a68ac7af834a80a71212f1e7ea0a050df30c0d 100644 (file)
@@ -7,6 +7,8 @@
 #ifdef __KERNEL__
 #include <linux/list.h>
 
+struct task_struct;
+
 /* for sysctl */
 extern int print_fatal_signals;
 /*
index 9659eff52ca2d146fa18cf85e97eb3bc4e9b150e..045f72ab5dfd7e1d6bb1d571f4d28434ea426d83 100644 (file)
@@ -404,7 +404,9 @@ extern bool ssb_is_sprom_available(struct ssb_bus *bus);
 
 /* Set a fallback SPROM.
  * See kdoc at the function definition for complete documentation. */
-extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
+extern int ssb_arch_register_fallback_sprom(
+               int (*sprom_callback)(struct ssb_bus *bus,
+               struct ssb_sprom *out));
 
 /* Suspend a SSB bus.
  * Call this from the parent bus suspend routine. */
index d81db8012c63b658158228469f89643426d9e435..f73c482ec9c6080cc5201c047546928c53c8b723 100644 (file)
@@ -127,13 +127,16 @@ struct rpc_task_setup {
 #define RPC_TASK_KILLED                0x0100          /* task was killed */
 #define RPC_TASK_SOFT          0x0200          /* Use soft timeouts */
 #define RPC_TASK_SOFTCONN      0x0400          /* Fail if can't connect */
+#define RPC_TASK_SENT          0x0800          /* message was sent */
+#define RPC_TASK_TIMEOUT       0x1000          /* fail with ETIMEDOUT on timeout */
 
 #define RPC_IS_ASYNC(t)                ((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)      ((t)->tk_flags & RPC_TASK_SWAPPER)
 #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
 #define RPC_ASSASSINATED(t)    ((t)->tk_flags & RPC_TASK_KILLED)
-#define RPC_IS_SOFT(t)         ((t)->tk_flags & RPC_TASK_SOFT)
+#define RPC_IS_SOFT(t)         ((t)->tk_flags & (RPC_TASK_SOFT|RPC_TASK_TIMEOUT))
 #define RPC_IS_SOFTCONN(t)     ((t)->tk_flags & RPC_TASK_SOFTCONN)
+#define RPC_WAS_SENT(t)                ((t)->tk_flags & RPC_TASK_SENT)
 
 #define RPC_TASK_RUNNING       0
 #define RPC_TASK_QUEUED                1
index dfb078db8ebbaacc6528b900e5bed06ced263082..d35e783a598c39065f66aae6d7497c7107a0a75e 100644 (file)
@@ -34,12 +34,6 @@ struct sysdev_class {
        struct list_head        drivers;
        struct sysdev_class_attribute **attrs;
        struct kset             kset;
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-       /* Default operations for these types of devices */
-       int     (*shutdown)(struct sys_device *);
-       int     (*suspend)(struct sys_device *, pm_message_t state);
-       int     (*resume)(struct sys_device *);
-#endif
 };
 
 struct sysdev_class_attribute {
@@ -77,11 +71,6 @@ struct sysdev_driver {
        struct list_head        entry;
        int     (*add)(struct sys_device *);
        int     (*remove)(struct sys_device *);
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-       int     (*shutdown)(struct sys_device *);
-       int     (*suspend)(struct sys_device *, pm_message_t state);
-       int     (*resume)(struct sys_device *);
-#endif
 };
 
 
index 454a262057878235c98e25db1de03bd94ab4c45a..b3061782dec3851765f3c398f67179744f4a39c2 100644 (file)
@@ -126,6 +126,7 @@ struct timespec __current_kernel_time(void); /* does not take xtime_lock */
 struct timespec get_monotonic_coarse(void);
 void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
                                struct timespec *wtom, struct timespec *sleep);
+void timekeeping_inject_sleeptime(struct timespec *delta);
 
 #define CURRENT_TIME           (current_kernel_time())
 #define CURRENT_TIME_SEC       ((struct timespec) { get_seconds(), 0 })
@@ -294,6 +295,8 @@ struct itimerval {
 #define CLOCK_REALTIME_COARSE          5
 #define CLOCK_MONOTONIC_COARSE         6
 #define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
 
 /*
  * The IDs of various hardware clocks:
index a520fd70a59f371f40a34f79e883dcf7b32c23f7..5088727478fd8ad91bc7e17f9b85252b8ef8e4a2 100644 (file)
@@ -39,7 +39,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
 
 static inline void timerqueue_init(struct timerqueue_node *node)
 {
-       RB_CLEAR_NODE(&node->node);
+       rb_init_node(&node->node);
 }
 
 static inline void timerqueue_init_head(struct timerqueue_head *head)
index 97c84a58efb8d806b1ad983a5dc7ac542768a314..d530a4460a0b96d4a73ebfb1a65e7fe32547f210 100644 (file)
@@ -29,7 +29,7 @@ struct tracepoint_func {
 
 struct tracepoint {
        const char *name;               /* Tracepoint name */
-       int state;                      /* State. */
+       struct jump_label_key key;
        void (*regfunc)(void);
        void (*unregfunc)(void);
        struct tracepoint_func __rcu *funcs;
@@ -146,9 +146,7 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin,
        extern struct tracepoint __tracepoint_##name;                   \
        static inline void trace_##name(proto)                          \
        {                                                               \
-               JUMP_LABEL(&__tracepoint_##name.state, do_trace);       \
-               return;                                                 \
-do_trace:                                                              \
+               if (static_branch(&__tracepoint_##name.key))            \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TP_PROTO(data_proto),                   \
                                TP_ARGS(data_args),                     \
@@ -176,14 +174,14 @@ do_trace:                                                         \
  * structures, so we create an array of pointers that will be used for iteration
  * on the tracepoints.
  */
-#define DEFINE_TRACE_FN(name, reg, unreg)                              \
-       static const char __tpstrtab_##name[]                           \
-       __attribute__((section("__tracepoints_strings"))) = #name;      \
-       struct tracepoint __tracepoint_##name                           \
-       __attribute__((section("__tracepoints"))) =                     \
-               { __tpstrtab_##name, 0, reg, unreg, NULL };             \
-       static struct tracepoint * const __tracepoint_ptr_##name __used \
-       __attribute__((section("__tracepoints_ptrs"))) =                \
+#define DEFINE_TRACE_FN(name, reg, unreg)                               \
+       static const char __tpstrtab_##name[]                            \
+       __attribute__((section("__tracepoints_strings"))) = #name;       \
+       struct tracepoint __tracepoint_##name                            \
+       __attribute__((section("__tracepoints"))) =                      \
+               { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\
+       static struct tracepoint * const __tracepoint_ptr_##name __used  \
+       __attribute__((section("__tracepoints_ptrs"))) =                 \
                &__tracepoint_##name;
 
 #define DEFINE_TRACE(name)                                             \
index 3c7329b8ea0e466a11fef6a176570138de116424..605b0aa8d852f63d4d0c7a3cf18add1f518e2acd 100644 (file)
@@ -68,6 +68,7 @@ struct usbnet {
 #              define EVENT_RX_PAUSED  5
 #              define EVENT_DEV_WAKING 6
 #              define EVENT_DEV_ASLEEP 7
+#              define EVENT_DEV_OPEN   8
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -103,8 +104,8 @@ struct driver_info {
  * Indicates to usbnet, that USB driver accumulates multiple IP packets.
  * Affects statistic (counters) and short packet handling.
  */
-#define FLAG_MULTI_PACKET      0x1000
-#define FLAG_RX_ASSEMBLE       0x2000  /* rx packets may span >1 frames */
+#define FLAG_MULTI_PACKET      0x2000
+#define FLAG_RX_ASSEMBLE       0x4000  /* rx packets may span >1 frames */
 
        /* init device ... can sleep, or cause probe() failure */
        int     (*bind)(struct usbnet *, struct usb_interface *);
index 7054a7a8065ec20689853e85f784efda5b857e27..de5c159210251ffae3deed5ad984be239221aca9 100644 (file)
@@ -47,7 +47,7 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
        V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
 
-       /* YUV (including grey) - next is 0x2013 */
+       /* YUV (including grey) - next is 0x2014 */
        V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
        V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
        V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
@@ -60,6 +60,7 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
        V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
        V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
+       V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
        V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
        V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
        V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
@@ -67,9 +68,11 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
        V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
 
-       /* Bayer - next is 0x3013 */
+       /* Bayer - next is 0x3015 */
        V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
+       V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
        V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
+       V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
        V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
        V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
        V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
index aa6c393b7ae991cd2f02242627fca08d0f0b713b..be82c8ead1af011ac7389e0ac2cbe94467df8583 100644 (file)
@@ -308,6 +308,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y4      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
 #define V4L2_PIX_FMT_Y6      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
 #define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
+#define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
 #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
 /* Palette formats */
index bd102cf509ac28ee9a0c5e70fcc9c4916ea50910..d61febfb1668549caa6b5610af09e3144aa3226e 100644 (file)
@@ -163,7 +163,7 @@ v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
 ({                                                                     \
        struct v4l2_subdev *__sd;                                       \
        __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, cond, o, \
-                                               f, args...);            \
+                                               f , ##args);            \
 })
 
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
index 88bdd010d65d3791eb634cae72709e01fc2c2090..2fa8d1341a0afa291e1fd5aa74bf0f7c4c91806f 100644 (file)
@@ -38,9 +38,19 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
        return outer;
 }
 
-#define        INET_ECN_xmit(sk) do { inet_sk(sk)->tos |= INET_ECN_ECT_0; } while (0)
-#define        INET_ECN_dontxmit(sk) \
-       do { inet_sk(sk)->tos &= ~INET_ECN_MASK; } while (0)
+static inline void INET_ECN_xmit(struct sock *sk)
+{
+       inet_sk(sk)->tos |= INET_ECN_ECT_0;
+       if (inet6_sk(sk) != NULL)
+               inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
+}
+
+static inline void INET_ECN_dontxmit(struct sock *sk)
+{
+       inet_sk(sk)->tos &= ~INET_ECN_MASK;
+       if (inet6_sk(sk) != NULL)
+               inet6_sk(sk)->tclass &= ~INET_ECN_MASK;
+}
 
 #define IP6_ECN_flow_init(label) do {          \
       (label) &= ~htonl(INET_ECN_MASK << 20);  \
index d516f00c8e0fc39c9aa0dc8a75aa2728df635388..86aefed6140b347b1f51e80096df1f209f48afce 100644 (file)
@@ -791,6 +791,7 @@ struct ip_vs_app {
 /* IPVS in network namespace */
 struct netns_ipvs {
        int                     gen;            /* Generation */
+       int                     enable;         /* enable like nf_hooks do */
        /*
         *      Hash table: for real service lookups
         */
@@ -1089,6 +1090,22 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
        atomic_inc(&ctl_cp->n_control);
 }
 
+/*
+ * IPVS netns init & cleanup functions
+ */
+extern int __ip_vs_estimator_init(struct net *net);
+extern int __ip_vs_control_init(struct net *net);
+extern int __ip_vs_protocol_init(struct net *net);
+extern int __ip_vs_app_init(struct net *net);
+extern int __ip_vs_conn_init(struct net *net);
+extern int __ip_vs_sync_init(struct net *net);
+extern void __ip_vs_conn_cleanup(struct net *net);
+extern void __ip_vs_app_cleanup(struct net *net);
+extern void __ip_vs_protocol_cleanup(struct net *net);
+extern void __ip_vs_control_cleanup(struct net *net);
+extern void __ip_vs_estimator_cleanup(struct net *net);
+extern void __ip_vs_sync_cleanup(struct net *net);
+extern void __ip_vs_service_cleanup(struct net *net);
 
 /*
  *      IPVS application functions
index 75b8e2968c9b1ef5e5cafadae67ab07934964043..f57e7d46a453db3fc52bc53cbb9dfc6cbdf26119 100644 (file)
@@ -199,7 +199,7 @@ struct llc_pdu_sn {
        u8 ssap;
        u8 ctrl_1;
        u8 ctrl_2;
-};
+} __packed;
 
 static inline struct llc_pdu_sn *llc_pdu_sn_hdr(struct sk_buff *skb)
 {
@@ -211,7 +211,7 @@ struct llc_pdu_un {
        u8 dsap;
        u8 ssap;
        u8 ctrl_1;
-};
+} __packed;
 
 static inline struct llc_pdu_un *llc_pdu_un_hdr(struct sk_buff *skb)
 {
@@ -359,7 +359,7 @@ struct llc_xid_info {
        u8 fmt_id;      /* always 0x81 for LLC */
        u8 type;        /* different if NULL/non-NULL LSAP */
        u8 rw;          /* sender receive window */
-};
+} __packed;
 
 /**
  *     llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID
@@ -415,7 +415,7 @@ struct llc_frmr_info {
        u8  curr_ssv;           /* current send state variable val */
        u8  curr_rsv;           /* current receive state variable */
        u8  ind_bits;           /* indicator bits set with macro */
-};
+} __packed;
 
 extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
 extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
index 505845ddb0bec9445478f1810623f13df27e5a82..01e094c6d0aecd2607e17dfbe572f4fa94a44655 100644 (file)
  * sctp/protocol.c
  */
 extern struct sock *sctp_get_ctl_sock(void);
-extern void sctp_local_addr_free(struct rcu_head *head);
 extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
                                     sctp_scope_t, gfp_t gfp,
                                     int flags);
index 6ae4bc5ce8a712796774e32637f875f4e98b173e..20afeaa39395ecbbed9dacf934c1df72184f68bb 100644 (file)
@@ -324,6 +324,7 @@ struct xfrm_state_afinfo {
        int                     (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
        int                     (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
        int                     (*output)(struct sk_buff *skb);
+       int                     (*output_finish)(struct sk_buff *skb);
        int                     (*extract_input)(struct xfrm_state *x,
                                                 struct sk_buff *skb);
        int                     (*extract_output)(struct xfrm_state *x,
@@ -1454,6 +1455,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
+extern int xfrm4_output_finish(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 extern int xfrm6_extract_header(struct sk_buff *skb);
@@ -1470,6 +1472,7 @@ extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr);
 extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm6_output(struct sk_buff *skb);
+extern int xfrm6_output_finish(struct sk_buff *skb);
 extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
                                 u8 **prevhdr);
 
index cbb822e8d7913d8cd30fbdc7217b9be373709f0c..2d0191c90f9eeda08da64fbbd0d9d6ba946442b7 100644 (file)
@@ -46,18 +46,9 @@ enum iw_cm_event_type {
        IW_CM_EVENT_CLOSE                /* close complete */
 };
 
-enum iw_cm_event_status {
-       IW_CM_EVENT_STATUS_OK = 0,       /* request successful */
-       IW_CM_EVENT_STATUS_ACCEPTED = 0, /* connect request accepted */
-       IW_CM_EVENT_STATUS_REJECTED,     /* connect request rejected */
-       IW_CM_EVENT_STATUS_TIMEOUT,      /* the operation timed out */
-       IW_CM_EVENT_STATUS_RESET,        /* reset from remote peer */
-       IW_CM_EVENT_STATUS_EINVAL,       /* asynchronous failure for bad parm */
-};
-
 struct iw_cm_event {
        enum iw_cm_event_type event;
-       enum iw_cm_event_status status;
+       int                      status;
        struct sockaddr_in local_addr;
        struct sockaddr_in remote_addr;
        void *private_data;
index 4fae903046483f7882cebfeea6777ee43dd37038..169f7a53fb0c696cf7cbb9f441a4e5fe021641bd 100644 (file)
@@ -329,4 +329,14 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
  */
 void rdma_set_service_type(struct rdma_cm_id *id, int tos);
 
+/**
+ * rdma_set_reuseaddr - Allow the reuse of local addresses when binding
+ *    the rdma_cm_id.
+ * @id: Communication identifier to configure.
+ * @reuse: Value indicating if the bound address is reusable.
+ *
+ * Reuse must be set before an address is bound to the id.
+ */
+int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse);
+
 #endif /* RDMA_CM_H */
index 1d165022c02d55880b16b42111ba590983141bab..fc82c1896f751a0e9f1c94c6761433f7ac7a8ad6 100644 (file)
@@ -221,8 +221,9 @@ enum {
 
 /* Option details */
 enum {
-       RDMA_OPTION_ID_TOS      = 0,
-       RDMA_OPTION_IB_PATH     = 1
+       RDMA_OPTION_ID_TOS       = 0,
+       RDMA_OPTION_ID_REUSEADDR = 1,
+       RDMA_OPTION_IB_PATH      = 1
 };
 
 struct rdma_ucm_set_option {
index 2d3ec509468557521a65ac7fb016eff3728dcd59..dd82e02ddde3d353d657b6fd8e7e08feff7fa0ad 100644 (file)
@@ -169,6 +169,7 @@ struct scsi_device {
                                sdev_dev;
 
        struct execute_work     ew; /* used to get process context on put */
+       struct work_struct      requeue_work;
 
        struct scsi_dh_data     *scsi_dh_data;
        enum scsi_device_state sdev_state;
index e3615c09374170669afa041d8eb9027a55037b8e..9fe3a36646e9ce47886bd7049684ce68d05808e4 100644 (file)
@@ -10,6 +10,7 @@
  */
 #define show_gfp_flags(flags)                                          \
        (flags) ? __print_flags(flags, "|",                             \
+       {(unsigned long)GFP_TRANSHUGE,          "GFP_TRANSHUGE"},       \
        {(unsigned long)GFP_HIGHUSER_MOVABLE,   "GFP_HIGHUSER_MOVABLE"}, \
        {(unsigned long)GFP_HIGHUSER,           "GFP_HIGHUSER"},        \
        {(unsigned long)GFP_USER,               "GFP_USER"},            \
@@ -32,6 +33,9 @@
        {(unsigned long)__GFP_HARDWALL,         "GFP_HARDWALL"},        \
        {(unsigned long)__GFP_THISNODE,         "GFP_THISNODE"},        \
        {(unsigned long)__GFP_RECLAIMABLE,      "GFP_RECLAIMABLE"},     \
-       {(unsigned long)__GFP_MOVABLE,          "GFP_MOVABLE"}          \
+       {(unsigned long)__GFP_MOVABLE,          "GFP_MOVABLE"},         \
+       {(unsigned long)__GFP_NOTRACK,          "GFP_NOTRACK"},         \
+       {(unsigned long)__GFP_NO_KSWAPD,        "GFP_NO_KSWAPD"},       \
+       {(unsigned long)__GFP_OTHER_NODE,       "GFP_OTHER_NODE"}       \
        ) : "GFP_NOWAIT"
 
index 1c09820df58564f8d0430d996998edc6f8d893c0..ae045ca7d356033d49c8a9650a618c206503f68c 100644 (file)
@@ -20,8 +20,7 @@ struct softirq_action;
                         softirq_name(BLOCK_IOPOLL),    \
                         softirq_name(TASKLET),         \
                         softirq_name(SCHED),           \
-                        softirq_name(HRTIMER),         \
-                        softirq_name(RCU))
+                        softirq_name(HRTIMER))
 
 /**
  * irq_handler_entry - called immediately before the irq action handler
index f1b87ad48ac7823dc6a39115cc0238c37b917e00..9af21e19545ae24d4350d3889259bf1868390206 100644 (file)
@@ -85,7 +85,8 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
 int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
 /* Bind an PSI pirq to an irq. */
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-                            int pirq, int vector, const char *name);
+                            int pirq, int vector, const char *name,
+                            domid_t domid);
 #endif
 
 /* De-allocates the above mentioned physical interrupt. */
@@ -94,4 +95,10 @@ int xen_destroy_irq(int irq);
 /* Return irq from pirq */
 int xen_irq_from_pirq(unsigned pirq);
 
+/* Return the pirq allocated to the irq. */
+int xen_pirq_from_irq(unsigned irq);
+
+/* Determine whether to ignore this IRQ if it is passed to a guest. */
+int xen_test_irq_shared(int irq);
+
 #endif /* _XEN_EVENTS_H */
index 56240e724d9a31dc4ef43647afcf354b8a70f108..4986ecc49e6566c4a7ac4900de1b540a3a0c1685 100644 (file)
@@ -485,7 +485,7 @@ config TREE_RCU_TRACE
 
 config RCU_BOOST
        bool "Enable RCU priority boosting"
-       depends on RT_MUTEXES && TINY_PREEMPT_RCU
+       depends on RT_MUTEXES && PREEMPT_RCU
        default n
        help
          This option boosts the priority of preempted RCU readers that
@@ -827,6 +827,11 @@ config SCHED_AUTOGROUP
          desktop applications.  Task group autogeneration is currently based
          upon task session.
 
+config SCHED_TTWU_QUEUE
+       bool
+       depends on !SPARC32
+       default y
+
 config MM_OWNER
        bool
 
@@ -924,14 +929,6 @@ menuconfig EXPERT
           environments which can tolerate a "non-standard" kernel.
           Only use this if you really know what you are doing.
 
-config EMBEDDED
-       bool "Embedded system"
-       select EXPERT
-       help
-         This option should be enabled if compiling the kernel for
-         an embedded system so certain expert options are available
-         for configuration.
-
 config UID16
        bool "Enable 16-bit UID system calls" if EXPERT
        depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
@@ -1104,6 +1101,14 @@ config AIO
           by some high performance threaded applications. Disabling
           this option saves about 7k.
 
+config EMBEDDED
+       bool "Embedded system"
+       select EXPERT
+       help
+         This option should be enabled if compiling the kernel for
+         an embedded system so certain expert options are available
+         for configuration.
+
 config HAVE_PERF_EVENTS
        bool
        help
index 4a9479ef4540df99586d5e0b3854c2b3c46d91c4..48df882d51d2e709eaf5e79be55e806d75b6d6c5 100644 (file)
@@ -580,8 +580,8 @@ asmlinkage void __init start_kernel(void)
 #endif
        page_cgroup_init();
        enable_debug_pagealloc();
-       kmemleak_init();
        debug_objects_mem_init();
+       kmemleak_init();
        setup_per_cpu_pageset();
        numa_policy_init();
        if (late_time_init)
index 85cbfb31e73e97b2e2548cba6837a98c39cbaf2b..e9cf19155b4620a061af103c9732fc5e7d7a8290 100644 (file)
@@ -21,7 +21,6 @@ CFLAGS_REMOVE_mutex-debug.o = -pg
 CFLAGS_REMOVE_rtmutex-debug.o = -pg
 CFLAGS_REMOVE_cgroup-debug.o = -pg
 CFLAGS_REMOVE_sched_clock.o = -pg
-CFLAGS_REMOVE_perf_event.o = -pg
 CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
@@ -103,8 +102,9 @@ obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_TRACEPOINTS) += trace/
 obj-$(CONFIG_SMP) += sched_cpupri.o
 obj-$(CONFIG_IRQ_WORK) += irq_work.o
-obj-$(CONFIG_PERF_EVENTS) += perf_event.o
-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
+
+obj-$(CONFIG_PERF_EVENTS) += events/
+
 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
index bf0c734d0c123f6b5733629f2f1bff4614197a3f..32a80e08ff4b8ebf725ebc8d3a526c2dee3f00f4 100644 (file)
@@ -399,3 +399,15 @@ bool task_ns_capable(struct task_struct *t, int cap)
        return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
 }
 EXPORT_SYMBOL(task_ns_capable);
+
+/**
+ * nsown_capable - Check superior capability to one's own user_ns
+ * @cap: The capability in question
+ *
+ * Return true if the current task has the given superior capability
+ * targeted at its own user namespace.
+ */
+bool nsown_capable(int cap)
+{
+       return ns_capable(current_user_ns(), cap);
+}
index 25c7eb52de1a1f62dfd0354e8e98060717a9df3f..909a35510af53656c684021b113977c10bfbbac8 100644 (file)
@@ -326,12 +326,6 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
        return &css_set_table[index];
 }
 
-static void free_css_set_rcu(struct rcu_head *obj)
-{
-       struct css_set *cg = container_of(obj, struct css_set, rcu_head);
-       kfree(cg);
-}
-
 /* We don't maintain the lists running through each css_set to its
  * task until after the first call to cgroup_iter_start(). This
  * reduces the fork()/exit() overhead for people who have cgroups
@@ -375,7 +369,7 @@ static void __put_css_set(struct css_set *cg, int taskexit)
        }
 
        write_unlock(&css_set_lock);
-       call_rcu(&cg->rcu_head, free_css_set_rcu);
+       kfree_rcu(cg, rcu_head);
 }
 
 /*
@@ -812,13 +806,6 @@ static int cgroup_call_pre_destroy(struct cgroup *cgrp)
        return ret;
 }
 
-static void free_cgroup_rcu(struct rcu_head *obj)
-{
-       struct cgroup *cgrp = container_of(obj, struct cgroup, rcu_head);
-
-       kfree(cgrp);
-}
-
 static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 {
        /* is dentry a directory ? if so, kfree() associated cgroup */
@@ -856,7 +843,7 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                 */
                BUG_ON(!list_empty(&cgrp->pidlists));
 
-               call_rcu(&cgrp->rcu_head, free_cgroup_rcu);
+               kfree_rcu(cgrp, rcu_head);
        }
        iput(inode);
 }
@@ -4623,14 +4610,6 @@ bool css_is_ancestor(struct cgroup_subsys_state *child,
        return ret;
 }
 
-static void __free_css_id_cb(struct rcu_head *head)
-{
-       struct css_id *id;
-
-       id = container_of(head, struct css_id, rcu_head);
-       kfree(id);
-}
-
 void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
 {
        struct css_id *id = css->id;
@@ -4645,7 +4624,7 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
        spin_lock(&ss->id_lock);
        idr_remove(&ss->idr, id->id);
        spin_unlock(&ss->id_lock);
-       call_rcu(&id->rcu_head, __free_css_id_cb);
+       kfree_rcu(id, rcu_head);
 }
 EXPORT_SYMBOL_GPL(free_css_id);
 
index 33eee16addb83bb6aaf411b03a09e3872671c42f..2bb8c2e98fff4074bce131a145966bfb1c788866 100644 (file)
@@ -1159,7 +1159,7 @@ int current_cpuset_is_being_rebound(void)
 static int update_relax_domain_level(struct cpuset *cs, s64 val)
 {
 #ifdef CONFIG_SMP
-       if (val < -1 || val >= SD_LV_MAX)
+       if (val < -1 || val >= sched_domain_level_max)
                return -EINVAL;
 #endif
 
index 5557b55048df1a35fff09933a274c9a5e32b7084..8093c16b84b13d2e9e0714af279b29b0549a0652 100644 (file)
@@ -54,6 +54,7 @@ struct cred init_cred = {
        .cap_effective          = CAP_INIT_EFF_SET,
        .cap_bset               = CAP_INIT_BSET,
        .user                   = INIT_USER,
+       .user_ns                = &init_user_ns,
        .group_info             = &init_groups,
 #ifdef CONFIG_KEYS
        .tgcred                 = &init_tgcred,
@@ -410,6 +411,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
                        goto error_put;
        }
 
+       /* cache user_ns in cred.  Doesn't need a refcount because it will
+        * stay pinned by cred->user
+        */
+       new->user_ns = new->user->user_ns;
+
 #ifdef CONFIG_KEYS
        /* new threads get their own thread keyrings if their parent already
         * had one */
@@ -741,12 +747,6 @@ int set_create_files_as(struct cred *new, struct inode *inode)
 }
 EXPORT_SYMBOL(set_create_files_as);
 
-struct user_namespace *current_user_ns(void)
-{
-       return _current_user_ns();
-}
-EXPORT_SYMBOL(current_user_ns);
-
 #ifdef CONFIG_DEBUG_CREDENTIALS
 
 bool creds_are_invalid(const struct cred *cred)
diff --git a/kernel/events/Makefile b/kernel/events/Makefile
new file mode 100644 (file)
index 0000000..1ce23d3
--- /dev/null
@@ -0,0 +1,6 @@
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_core.o = -pg
+endif
+
+obj-y := core.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
similarity index 99%
rename from kernel/perf_event.c
rename to kernel/events/core.c
index 8e81a9860a0d543c436716345b2ce0871229915b..c09767f7db3e20e4a510c7a51fba7d662e967659 100644 (file)
@@ -2,8 +2,8 @@
  * Performance events core code:
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
- *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
  *  Copyright  Â©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
 #include <asm/irq_regs.h>
 
 struct remote_function_call {
-       struct task_struct *p;
-       int (*func)(void *info);
-       void *info;
-       int ret;
+       struct task_struct      *p;
+       int                     (*func)(void *info);
+       void                    *info;
+       int                     ret;
 };
 
 static void remote_function(void *data)
@@ -76,10 +76,10 @@ static int
 task_function_call(struct task_struct *p, int (*func) (void *info), void *info)
 {
        struct remote_function_call data = {
-               .p = p,
-               .func = func,
-               .info = info,
-               .ret = -ESRCH, /* No such (running) process */
+               .p      = p,
+               .func   = func,
+               .info   = info,
+               .ret    = -ESRCH, /* No such (running) process */
        };
 
        if (task_curr(p))
@@ -100,10 +100,10 @@ task_function_call(struct task_struct *p, int (*func) (void *info), void *info)
 static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
 {
        struct remote_function_call data = {
-               .p = NULL,
-               .func = func,
-               .info = info,
-               .ret = -ENXIO, /* No such CPU */
+               .p      = NULL,
+               .func   = func,
+               .info   = info,
+               .ret    = -ENXIO, /* No such CPU */
        };
 
        smp_call_function_single(cpu, remote_function, &data, 1);
@@ -125,7 +125,7 @@ enum event_type_t {
  * perf_sched_events : >0 events exist
  * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
  */
-atomic_t perf_sched_events __read_mostly;
+struct jump_label_key perf_sched_events __read_mostly;
 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
 
 static atomic_t nr_mmap_events __read_mostly;
@@ -586,14 +586,6 @@ static void get_ctx(struct perf_event_context *ctx)
        WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
 }
 
-static void free_ctx(struct rcu_head *head)
-{
-       struct perf_event_context *ctx;
-
-       ctx = container_of(head, struct perf_event_context, rcu_head);
-       kfree(ctx);
-}
-
 static void put_ctx(struct perf_event_context *ctx)
 {
        if (atomic_dec_and_test(&ctx->refcount)) {
@@ -601,7 +593,7 @@ static void put_ctx(struct perf_event_context *ctx)
                        put_ctx(ctx->parent_ctx);
                if (ctx->task)
                        put_task_struct(ctx->task);
-               call_rcu(&ctx->rcu_head, free_ctx);
+               kfree_rcu(ctx, rcu_head);
        }
 }
 
@@ -5331,14 +5323,6 @@ swevent_hlist_deref(struct swevent_htable *swhash)
                                         lockdep_is_held(&swhash->hlist_mutex));
 }
 
-static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
-{
-       struct swevent_hlist *hlist;
-
-       hlist = container_of(rcu_head, struct swevent_hlist, rcu_head);
-       kfree(hlist);
-}
-
 static void swevent_hlist_release(struct swevent_htable *swhash)
 {
        struct swevent_hlist *hlist = swevent_hlist_deref(swhash);
@@ -5347,7 +5331,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)
                return;
 
        rcu_assign_pointer(swhash->swevent_hlist, NULL);
-       call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu);
+       kfree_rcu(hlist, rcu_head);
 }
 
 static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
@@ -5429,7 +5413,7 @@ fail:
        return err;
 }
 
-atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
 
 static void sw_perf_event_destroy(struct perf_event *event)
 {
@@ -7445,11 +7429,11 @@ static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
 }
 
 struct cgroup_subsys perf_subsys = {
-       .name = "perf_event",
-       .subsys_id = perf_subsys_id,
-       .create = perf_cgroup_create,
-       .destroy = perf_cgroup_destroy,
-       .exit = perf_cgroup_exit,
-       .attach = perf_cgroup_attach,
+       .name           = "perf_event",
+       .subsys_id      = perf_subsys_id,
+       .create         = perf_cgroup_create,
+       .destroy        = perf_cgroup_destroy,
+       .exit           = perf_cgroup_exit,
+       .attach         = perf_cgroup_attach,
 };
 #endif /* CONFIG_CGROUP_PERF */
index f5d2f63bae0b70b2818edd92e06040906f115216..8dd87418154205940341f98641191fe1c1d6ea70 100644 (file)
@@ -1016,7 +1016,7 @@ NORET_TYPE void do_exit(long code)
        /*
         * FIXME: do that only when needed, using sched_exit tracepoint
         */
-       flush_ptrace_hw_breakpoint(tsk);
+       ptrace_put_breakpoints(tsk);
 
        exit_notify(tsk, group_dead);
 #ifdef CONFIG_NUMA
index 7f8f263f85249a15ca8492fa5056c868262aa0f1..c2d625fcda77000d00a397529762bc1426a1d648 100644 (file)
@@ -72,6 +72,14 @@ int core_kernel_text(unsigned long addr)
        return 0;
 }
 
+int core_kernel_data(unsigned long addr)
+{
+       if (addr >= (unsigned long)_sdata &&
+           addr < (unsigned long)_edata)
+               return 1;
+       return 0;
+}
+
 int __kernel_text_address(unsigned long addr)
 {
        if (core_kernel_text(addr))
index e7548dee636b1f29f344d4c2a9749a963135f477..2b44d82b8237f6fb8e98cef8cff1c5cb84620efb 100644 (file)
@@ -1103,7 +1103,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        posix_cpu_timers_init(p);
 
-       p->lock_depth = -1;             /* -1 = no lock */
        do_posix_clock_monotonic_gettime(&p->start_time);
        p->real_start_time = p->start_time;
        monotonic_to_bootbased(&p->real_start_time);
@@ -1153,7 +1152,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 #endif
 
        /* Perform scheduler related setup. Assign this task to a CPU. */
-       sched_fork(p, clone_flags);
+       sched_fork(p);
 
        retval = perf_event_init_task(p);
        if (retval)
@@ -1464,7 +1463,7 @@ long do_fork(unsigned long clone_flags,
                 */
                p->flags &= ~PF_STARTING;
 
-               wake_up_new_task(p, clone_flags);
+               wake_up_new_task(p);
 
                tracehook_report_clone_complete(trace, regs,
                                                clone_flags, nr, p);
index 66ecd2ead215a9cb88ca8ae9f674e1c82766a066..7b01de98bb6a97aea6e1d5b99f38b113c099b780 100644 (file)
@@ -17,7 +17,7 @@ static inline void frozen_process(void)
 {
        if (!unlikely(current->flags & PF_NOFREEZE)) {
                current->flags |= PF_FROZEN;
-               wmb();
+               smp_wmb();
        }
        clear_freeze_flag(current);
 }
@@ -93,7 +93,7 @@ bool freeze_task(struct task_struct *p, bool sig_only)
         * the task as frozen and next clears its TIF_FREEZE.
         */
        if (!freezing(p)) {
-               rmb();
+               smp_rmb();
                if (frozen(p))
                        return false;
 
index 9017478c5d4c3f224cde995518976ed8d88d79d5..dbbbf7d430801923b8c6d544eab4f79943659547 100644 (file)
@@ -81,7 +81,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
        }
 };
 
-static int hrtimer_clock_to_base_table[MAX_CLOCKS];
+static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
+       [CLOCK_REALTIME]        = HRTIMER_BASE_REALTIME,
+       [CLOCK_MONOTONIC]       = HRTIMER_BASE_MONOTONIC,
+       [CLOCK_BOOTTIME]        = HRTIMER_BASE_BOOTTIME,
+};
 
 static inline int hrtimer_clockid_to_base(clockid_t clock_id)
 {
@@ -1722,10 +1726,6 @@ static struct notifier_block __cpuinitdata hrtimers_nb = {
 
 void __init hrtimers_init(void)
 {
-       hrtimer_clock_to_base_table[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME;
-       hrtimer_clock_to_base_table[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC;
-       hrtimer_clock_to_base_table[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME;
-
        hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
                          (void *)(long)smp_processor_id());
        register_cpu_notifier(&hrtimers_nb);
index 53ead174da2f0a7c7849df4ef81b60a96fe7c4f6..ea640120ab8606195e8fcddabe5c81180598b4cb 100644 (file)
@@ -33,7 +33,7 @@ unsigned long __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
 /*
  * Zero means infinite timeout - no checking done:
  */
-unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120;
+unsigned long __read_mostly sysctl_hung_task_timeout_secs = CONFIG_DEFAULT_HUNG_TASK_TIMEOUT;
 
 unsigned long __read_mostly sysctl_hung_task_warnings = 10;
 
index c574f9a12c48c8951b8616e4152e3ac40e84a388..d1d051b38e0b5fc1c84eb3bb94b85373d7d6bf47 100644 (file)
@@ -48,6 +48,10 @@ config IRQ_PREFLOW_FASTEOI
 config IRQ_EDGE_EOI_HANDLER
        bool
 
+# Generic configurable interrupt chip implementation
+config GENERIC_IRQ_CHIP
+       bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
index 54329cd7b3ee3cb5ed2084e2072933b183e8a446..73290056cfb6d11a77799684b49f1a888bebbade 100644 (file)
@@ -1,5 +1,6 @@
 
 obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
+obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
index 4af1e2b244cb258f24ed7644b18965ac9e65bc82..d5a3009da71aed6dd5f3a82895f2f21cecd656b6 100644 (file)
@@ -310,6 +310,7 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 out_unlock:
        raw_spin_unlock(&desc->lock);
 }
+EXPORT_SYMBOL_GPL(handle_simple_irq);
 
 /**
  *     handle_level_irq - Level type irq handler
@@ -573,6 +574,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
        if (handle != handle_bad_irq && is_chained) {
                irq_settings_set_noprobe(desc);
                irq_settings_set_norequest(desc);
+               irq_settings_set_nothread(desc);
                irq_startup(desc);
        }
 out:
@@ -612,6 +614,7 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 
        irq_put_desc_unlock(desc, flags);
 }
+EXPORT_SYMBOL_GPL(irq_modify_status);
 
 /**
  *     irq_cpu_online - Invoke all irq_cpu_online functions.
index 306cba37e9a57280b869b3317852efe48b34e78f..97a8bfadc88a0cec4192bd457e18a54aca159cf0 100644 (file)
@@ -27,6 +27,7 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
        P(IRQ_PER_CPU);
        P(IRQ_NOPROBE);
        P(IRQ_NOREQUEST);
+       P(IRQ_NOTHREAD);
        P(IRQ_NOAUTOEN);
 
        PS(IRQS_AUTODETECT);
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
new file mode 100644 (file)
index 0000000..31a9db7
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Library implementing the most common irq chip callback functions
+ *
+ * Copyright (C) 2011, Thomas Gleixner
+ */
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/syscore_ops.h>
+
+#include "internals.h"
+
+static LIST_HEAD(gc_list);
+static DEFINE_RAW_SPINLOCK(gc_lock);
+
+static inline struct irq_chip_regs *cur_regs(struct irq_data *d)
+{
+       return &container_of(d->chip, struct irq_chip_type, chip)->regs;
+}
+
+/**
+ * irq_gc_noop - NOOP function
+ * @d: irq_data
+ */
+void irq_gc_noop(struct irq_data *d)
+{
+}
+
+/**
+ * irq_gc_mask_disable_reg - Mask chip via disable register
+ * @d: irq_data
+ *
+ * Chip has separate enable/disable registers instead of a single mask
+ * register.
+ */
+void irq_gc_mask_disable_reg(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable);
+       gc->mask_cache &= ~mask;
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_mask_set_mask_bit - Mask chip via setting bit in mask register
+ * @d: irq_data
+ *
+ * Chip has a single mask register. Values of this register are cached
+ * and protected by gc->lock
+ */
+void irq_gc_mask_set_bit(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache |= mask;
+       irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_mask_set_mask_bit - Mask chip via clearing bit in mask register
+ * @d: irq_data
+ *
+ * Chip has a single mask register. Values of this register are cached
+ * and protected by gc->lock
+ */
+void irq_gc_mask_clr_bit(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache &= ~mask;
+       irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_unmask_enable_reg - Unmask chip via enable register
+ * @d: irq_data
+ *
+ * Chip has separate enable/disable registers instead of a single mask
+ * register.
+ */
+void irq_gc_unmask_enable_reg(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable);
+       gc->mask_cache |= mask;
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_ack - Ack pending interrupt
+ * @d: irq_data
+ */
+void irq_gc_ack(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_mask_disable_reg_and_ack- Mask and ack pending interrupt
+ * @d: irq_data
+ */
+void irq_gc_mask_disable_reg_and_ack(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_eoi - EOI interrupt
+ * @d: irq_data
+ */
+void irq_gc_eoi(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi);
+       irq_gc_unlock(gc);
+}
+
+/**
+ * irq_gc_set_wake - Set/clr wake bit for an interrupt
+ * @d: irq_data
+ *
+ * For chips where the wake from suspend functionality is not
+ * configured in a separate register and the wakeup active state is
+ * just stored in a bitmask.
+ */
+int irq_gc_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       if (!(mask & gc->wake_enabled))
+               return -EINVAL;
+
+       irq_gc_lock(gc);
+       if (on)
+               gc->wake_active |= mask;
+       else
+               gc->wake_active &= ~mask;
+       irq_gc_unlock(gc);
+       return 0;
+}
+
+/**
+ * irq_alloc_generic_chip - Allocate a generic chip and initialize it
+ * @name:      Name of the irq chip
+ * @num_ct:    Number of irq_chip_type instances associated with this
+ * @irq_base:  Interrupt base nr for this chip
+ * @reg_base:  Register base address (virtual)
+ * @handler:   Default flow handler associated with this chip
+ *
+ * Returns an initialized irq_chip_generic structure. The chip defaults
+ * to the primary (index 0) irq_chip_type and @handler
+ */
+struct irq_chip_generic *
+irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
+                      void __iomem *reg_base, irq_flow_handler_t handler)
+{
+       struct irq_chip_generic *gc;
+       unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
+
+       gc = kzalloc(sz, GFP_KERNEL);
+       if (gc) {
+               raw_spin_lock_init(&gc->lock);
+               gc->num_ct = num_ct;
+               gc->irq_base = irq_base;
+               gc->reg_base = reg_base;
+               gc->chip_types->chip.name = name;
+               gc->chip_types->handler = handler;
+       }
+       return gc;
+}
+
+/*
+ * Separate lockdep class for interrupt chip which can nest irq_desc
+ * lock.
+ */
+static struct lock_class_key irq_nested_lock_class;
+
+/**
+ * irq_setup_generic_chip - Setup a range of interrupts with a generic chip
+ * @gc:                Generic irq chip holding all data
+ * @msk:       Bitmask holding the irqs to initialize relative to gc->irq_base
+ * @flags:     Flags for initialization
+ * @clr:       IRQ_* bits to clear
+ * @set:       IRQ_* bits to set
+ *
+ * Set up max. 32 interrupts starting from gc->irq_base. Note, this
+ * initializes all interrupts to the primary irq_chip_type and its
+ * associated handler.
+ */
+void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
+                           enum irq_gc_flags flags, unsigned int clr,
+                           unsigned int set)
+{
+       struct irq_chip_type *ct = gc->chip_types;
+       unsigned int i;
+
+       raw_spin_lock(&gc_lock);
+       list_add_tail(&gc->list, &gc_list);
+       raw_spin_unlock(&gc_lock);
+
+       /* Init mask cache ? */
+       if (flags & IRQ_GC_INIT_MASK_CACHE)
+               gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
+
+       for (i = gc->irq_base; msk; msk >>= 1, i++) {
+               if (!msk & 0x01)
+                       continue;
+
+               if (flags & IRQ_GC_INIT_NESTED_LOCK)
+                       irq_set_lockdep_class(i, &irq_nested_lock_class);
+
+               irq_set_chip_and_handler(i, &ct->chip, ct->handler);
+               irq_set_chip_data(i, gc);
+               irq_modify_status(i, clr, set);
+       }
+       gc->irq_cnt = i - gc->irq_base;
+}
+
+/**
+ * irq_setup_alt_chip - Switch to alternative chip
+ * @d:         irq_data for this interrupt
+ * @type       Flow type to be initialized
+ *
+ * Only to be called from chip->irq_set_type() callbacks.
+ */
+int irq_setup_alt_chip(struct irq_data *d, unsigned int type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct irq_chip_type *ct = gc->chip_types;
+       unsigned int i;
+
+       for (i = 0; i < gc->num_ct; i++, ct++) {
+               if (ct->type & type) {
+                       d->chip = &ct->chip;
+                       irq_data_to_desc(d)->handle_irq = ct->handler;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+/**
+ * irq_remove_generic_chip - Remove a chip
+ * @gc:                Generic irq chip holding all data
+ * @msk:       Bitmask holding the irqs to initialize relative to gc->irq_base
+ * @clr:       IRQ_* bits to clear
+ * @set:       IRQ_* bits to set
+ *
+ * Remove up to 32 interrupts starting from gc->irq_base.
+ */
+void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
+                            unsigned int clr, unsigned int set)
+{
+       unsigned int i = gc->irq_base;
+
+       raw_spin_lock(&gc_lock);
+       list_del(&gc->list);
+       raw_spin_unlock(&gc_lock);
+
+       for (; msk; msk >>= 1, i++) {
+               if (!msk & 0x01)
+                       continue;
+
+               /* Remove handler first. That will mask the irq line */
+               irq_set_handler(i, NULL);
+               irq_set_chip(i, &no_irq_chip);
+               irq_set_chip_data(i, NULL);
+               irq_modify_status(i, clr, set);
+       }
+}
+
+#ifdef CONFIG_PM
+static int irq_gc_suspend(void)
+{
+       struct irq_chip_generic *gc;
+
+       list_for_each_entry(gc, &gc_list, list) {
+               struct irq_chip_type *ct = gc->chip_types;
+
+               if (ct->chip.irq_suspend)
+                       ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base));
+       }
+       return 0;
+}
+
+static void irq_gc_resume(void)
+{
+       struct irq_chip_generic *gc;
+
+       list_for_each_entry(gc, &gc_list, list) {
+               struct irq_chip_type *ct = gc->chip_types;
+
+               if (ct->chip.irq_resume)
+                       ct->chip.irq_resume(irq_get_irq_data(gc->irq_base));
+       }
+}
+#else
+#define irq_gc_suspend NULL
+#define irq_gc_resume NULL
+#endif
+
+static void irq_gc_shutdown(void)
+{
+       struct irq_chip_generic *gc;
+
+       list_for_each_entry(gc, &gc_list, list) {
+               struct irq_chip_type *ct = gc->chip_types;
+
+               if (ct->chip.irq_pm_shutdown)
+                       ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base));
+       }
+}
+
+static struct syscore_ops irq_gc_syscore_ops = {
+       .suspend = irq_gc_suspend,
+       .resume = irq_gc_resume,
+       .shutdown = irq_gc_shutdown,
+};
+
+static int __init irq_gc_init_ops(void)
+{
+       register_syscore_ops(&irq_gc_syscore_ops);
+       return 0;
+}
+device_initcall(irq_gc_init_ops);
index 2c039c9b9383a045b6d08b30b8c2a70a0e7ecf78..886e80347b322795b56630857fd98996545ea5a4 100644 (file)
@@ -22,7 +22,7 @@
  */
 static struct lock_class_key irq_desc_lock_class;
 
-#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
+#if defined(CONFIG_SMP)
 static void __init init_irq_default_affinity(void)
 {
        alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
@@ -290,6 +290,22 @@ static int irq_expand_nr_irqs(unsigned int nr)
 
 #endif /* !CONFIG_SPARSE_IRQ */
 
+/**
+ * generic_handle_irq - Invoke the handler for a particular irq
+ * @irq:       The irq number to handle
+ *
+ */
+int generic_handle_irq(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       if (!desc)
+               return -EINVAL;
+       generic_handle_irq_desc(irq, desc);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(generic_handle_irq);
+
 /* Dynamic interrupt handling */
 
 /**
@@ -311,6 +327,7 @@ void irq_free_descs(unsigned int from, unsigned int cnt)
        bitmap_clear(allocated_irqs, from, cnt);
        mutex_unlock(&sparse_irq_lock);
 }
+EXPORT_SYMBOL_GPL(irq_free_descs);
 
 /**
  * irq_alloc_descs - allocate and initialize a range of irq descriptors
@@ -351,6 +368,7 @@ err:
        mutex_unlock(&sparse_irq_lock);
        return ret;
 }
+EXPORT_SYMBOL_GPL(irq_alloc_descs);
 
 /**
  * irq_reserve_irqs - mark irqs allocated
@@ -430,7 +448,6 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
                        *per_cpu_ptr(desc->kstat_irqs, cpu) : 0;
 }
 
-#ifdef CONFIG_GENERIC_HARDIRQS
 unsigned int kstat_irqs(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
@@ -443,4 +460,3 @@ unsigned int kstat_irqs(unsigned int irq)
                sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
        return sum;
 }
-#endif /* CONFIG_GENERIC_HARDIRQS */
index 07c1611f38992ac98e5e8bb716d4d41f01290ea4..f7ce0021e1c48eb02e2eb6531265ac84bfc24d96 100644 (file)
@@ -900,7 +900,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                 */
                new->handler = irq_nested_primary_handler;
        } else {
-               irq_setup_forced_threading(new);
+               if (irq_settings_can_thread(desc))
+                       irq_setup_forced_threading(new);
        }
 
        /*
index dd201bd35103e221fc14debc1d09419529bf6f3d..834899f2500fc550d3da66306d31386eb80baf91 100644 (file)
@@ -419,7 +419,7 @@ int show_interrupts(struct seq_file *p, void *v)
        } else {
                seq_printf(p, " %8s", "None");
        }
-#ifdef CONFIG_GENIRC_IRQ_SHOW_LEVEL
+#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
        seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
 #endif
        if (desc->name)
index 0d91730b6330b9b59594fd2486d5a493627d7fb3..f1667833d444496d862a3bfdd87ead8d2d2fece2 100644 (file)
@@ -8,6 +8,7 @@ enum {
        _IRQ_LEVEL              = IRQ_LEVEL,
        _IRQ_NOPROBE            = IRQ_NOPROBE,
        _IRQ_NOREQUEST          = IRQ_NOREQUEST,
+       _IRQ_NOTHREAD           = IRQ_NOTHREAD,
        _IRQ_NOAUTOEN           = IRQ_NOAUTOEN,
        _IRQ_MOVE_PCNTXT        = IRQ_MOVE_PCNTXT,
        _IRQ_NO_BALANCING       = IRQ_NO_BALANCING,
@@ -20,6 +21,7 @@ enum {
 #define IRQ_LEVEL              GOT_YOU_MORON
 #define IRQ_NOPROBE            GOT_YOU_MORON
 #define IRQ_NOREQUEST          GOT_YOU_MORON
+#define IRQ_NOTHREAD           GOT_YOU_MORON
 #define IRQ_NOAUTOEN           GOT_YOU_MORON
 #define IRQ_NESTED_THREAD      GOT_YOU_MORON
 #undef IRQF_MODIFY_MASK
@@ -94,6 +96,21 @@ static inline void irq_settings_set_norequest(struct irq_desc *desc)
        desc->status_use_accessors |= _IRQ_NOREQUEST;
 }
 
+static inline bool irq_settings_can_thread(struct irq_desc *desc)
+{
+       return !(desc->status_use_accessors & _IRQ_NOTHREAD);
+}
+
+static inline void irq_settings_clr_nothread(struct irq_desc *desc)
+{
+       desc->status_use_accessors &= ~_IRQ_NOTHREAD;
+}
+
+static inline void irq_settings_set_nothread(struct irq_desc *desc)
+{
+       desc->status_use_accessors |= _IRQ_NOTHREAD;
+}
+
 static inline bool irq_settings_can_probe(struct irq_desc *desc)
 {
        return !(desc->status_use_accessors & _IRQ_NOPROBE);
index 3b79bd9383307a2b5a8325f53ed4ca472c77d9f8..74d1c099fbd1d8a8a3368865f919e978020e3521 100644 (file)
@@ -2,43 +2,23 @@
  * jump label support
  *
  * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ * Copyright (C) 2011 Peter Zijlstra <pzijlstr@redhat.com>
  *
  */
-#include <linux/jump_label.h>
 #include <linux/memory.h>
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/list.h>
-#include <linux/jhash.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
 #include <linux/err.h>
+#include <linux/jump_label.h>
 
 #ifdef HAVE_JUMP_LABEL
 
-#define JUMP_LABEL_HASH_BITS 6
-#define JUMP_LABEL_TABLE_SIZE (1 << JUMP_LABEL_HASH_BITS)
-static struct hlist_head jump_label_table[JUMP_LABEL_TABLE_SIZE];
-
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
-struct jump_label_entry {
-       struct hlist_node hlist;
-       struct jump_entry *table;
-       int nr_entries;
-       /* hang modules off here */
-       struct hlist_head modules;
-       unsigned long key;
-};
-
-struct jump_label_module_entry {
-       struct hlist_node hlist;
-       struct jump_entry *table;
-       int nr_entries;
-       struct module *mod;
-};
-
 void jump_label_lock(void)
 {
        mutex_lock(&jump_label_mutex);
@@ -49,6 +29,11 @@ void jump_label_unlock(void)
        mutex_unlock(&jump_label_mutex);
 }
 
+bool jump_label_enabled(struct jump_label_key *key)
+{
+       return !!atomic_read(&key->enabled);
+}
+
 static int jump_label_cmp(const void *a, const void *b)
 {
        const struct jump_entry *jea = a;
@@ -64,7 +49,7 @@ static int jump_label_cmp(const void *a, const void *b)
 }
 
 static void
-sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop)
+jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop)
 {
        unsigned long size;
 
@@ -73,118 +58,25 @@ sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop)
        sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
 }
 
-static struct jump_label_entry *get_jump_label_entry(jump_label_t key)
-{
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct jump_label_entry *e;
-       u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0);
-
-       head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
-       hlist_for_each_entry(e, node, head, hlist) {
-               if (key == e->key)
-                       return e;
-       }
-       return NULL;
-}
+static void jump_label_update(struct jump_label_key *key, int enable);
 
-static struct jump_label_entry *
-add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table)
+void jump_label_inc(struct jump_label_key *key)
 {
-       struct hlist_head *head;
-       struct jump_label_entry *e;
-       u32 hash;
-
-       e = get_jump_label_entry(key);
-       if (e)
-               return ERR_PTR(-EEXIST);
-
-       e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL);
-       if (!e)
-               return ERR_PTR(-ENOMEM);
-
-       hash = jhash((void *)&key, sizeof(jump_label_t), 0);
-       head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
-       e->key = key;
-       e->table = table;
-       e->nr_entries = nr_entries;
-       INIT_HLIST_HEAD(&(e->modules));
-       hlist_add_head(&e->hlist, head);
-       return e;
-}
+       if (atomic_inc_not_zero(&key->enabled))
+               return;
 
-static int
-build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop)
-{
-       struct jump_entry *iter, *iter_begin;
-       struct jump_label_entry *entry;
-       int count;
-
-       sort_jump_label_entries(start, stop);
-       iter = start;
-       while (iter < stop) {
-               entry = get_jump_label_entry(iter->key);
-               if (!entry) {
-                       iter_begin = iter;
-                       count = 0;
-                       while ((iter < stop) &&
-                               (iter->key == iter_begin->key)) {
-                               iter++;
-                               count++;
-                       }
-                       entry = add_jump_label_entry(iter_begin->key,
-                                                       count, iter_begin);
-                       if (IS_ERR(entry))
-                               return PTR_ERR(entry);
-                } else {
-                       WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n");
-                       return -1;
-               }
-       }
-       return 0;
+       jump_label_lock();
+       if (atomic_add_return(1, &key->enabled) == 1)
+               jump_label_update(key, JUMP_LABEL_ENABLE);
+       jump_label_unlock();
 }
 
-/***
- * jump_label_update - update jump label text
- * @key -  key value associated with a a jump label
- * @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE
- *
- * Will enable/disable the jump for jump label @key, depending on the
- * value of @type.
- *
- */
-
-void jump_label_update(unsigned long key, enum jump_label_type type)
+void jump_label_dec(struct jump_label_key *key)
 {
-       struct jump_entry *iter;
-       struct jump_label_entry *entry;
-       struct hlist_node *module_node;
-       struct jump_label_module_entry *e_module;
-       int count;
+       if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex))
+               return;
 
-       jump_label_lock();
-       entry = get_jump_label_entry((jump_label_t)key);
-       if (entry) {
-               count = entry->nr_entries;
-               iter = entry->table;
-               while (count--) {
-                       if (kernel_text_address(iter->code))
-                               arch_jump_label_transform(iter, type);
-                       iter++;
-               }
-               /* eanble/disable jump labels in modules */
-               hlist_for_each_entry(e_module, module_node, &(entry->modules),
-                                                       hlist) {
-                       count = e_module->nr_entries;
-                       iter = e_module->table;
-                       while (count--) {
-                               if (iter->key &&
-                                               kernel_text_address(iter->code))
-                                       arch_jump_label_transform(iter, type);
-                               iter++;
-                       }
-               }
-       }
+       jump_label_update(key, JUMP_LABEL_DISABLE);
        jump_label_unlock();
 }
 
@@ -197,77 +89,33 @@ static int addr_conflict(struct jump_entry *entry, void *start, void *end)
        return 0;
 }
 
-#ifdef CONFIG_MODULES
-
-static int module_conflict(void *start, void *end)
+static int __jump_label_text_reserved(struct jump_entry *iter_start,
+               struct jump_entry *iter_stop, void *start, void *end)
 {
-       struct hlist_head *head;
-       struct hlist_node *node, *node_next, *module_node, *module_node_next;
-       struct jump_label_entry *e;
-       struct jump_label_module_entry *e_module;
        struct jump_entry *iter;
-       int i, count;
-       int conflict = 0;
-
-       for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
-               head = &jump_label_table[i];
-               hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
-                       hlist_for_each_entry_safe(e_module, module_node,
-                                                       module_node_next,
-                                                       &(e->modules), hlist) {
-                               count = e_module->nr_entries;
-                               iter = e_module->table;
-                               while (count--) {
-                                       if (addr_conflict(iter, start, end)) {
-                                               conflict = 1;
-                                               goto out;
-                                       }
-                                       iter++;
-                               }
-                       }
-               }
-       }
-out:
-       return conflict;
-}
-
-#endif
-
-/***
- * jump_label_text_reserved - check if addr range is reserved
- * @start: start text addr
- * @end: end text addr
- *
- * checks if the text addr located between @start and @end
- * overlaps with any of the jump label patch addresses. Code
- * that wants to modify kernel text should first verify that
- * it does not overlap with any of the jump label addresses.
- * Caller must hold jump_label_mutex.
- *
- * returns 1 if there is an overlap, 0 otherwise
- */
-int jump_label_text_reserved(void *start, void *end)
-{
-       struct jump_entry *iter;
-       struct jump_entry *iter_start = __start___jump_table;
-       struct jump_entry *iter_stop = __start___jump_table;
-       int conflict = 0;
 
        iter = iter_start;
        while (iter < iter_stop) {
-               if (addr_conflict(iter, start, end)) {
-                       conflict = 1;
-                       goto out;
-               }
+               if (addr_conflict(iter, start, end))
+                       return 1;
                iter++;
        }
 
-       /* now check modules */
-#ifdef CONFIG_MODULES
-       conflict = module_conflict(start, end);
-#endif
-out:
-       return conflict;
+       return 0;
+}
+
+static void __jump_label_update(struct jump_label_key *key,
+               struct jump_entry *entry, int enable)
+{
+       for (; entry->key == (jump_label_t)(unsigned long)key; entry++) {
+               /*
+                * entry->code set to 0 invalidates module init text sections
+                * kernel_text_address() verifies we are not in core kernel
+                * init code, see jump_label_invalidate_module_init().
+                */
+               if (entry->code && kernel_text_address(entry->code))
+                       arch_jump_label_transform(entry, enable);
+       }
 }
 
 /*
@@ -277,142 +125,173 @@ void __weak arch_jump_label_text_poke_early(jump_label_t addr)
 {
 }
 
-static __init int init_jump_label(void)
+static __init int jump_label_init(void)
 {
-       int ret;
        struct jump_entry *iter_start = __start___jump_table;
        struct jump_entry *iter_stop = __stop___jump_table;
+       struct jump_label_key *key = NULL;
        struct jump_entry *iter;
 
        jump_label_lock();
-       ret = build_jump_label_hashtable(__start___jump_table,
-                                        __stop___jump_table);
-       iter = iter_start;
-       while (iter < iter_stop) {
+       jump_label_sort_entries(iter_start, iter_stop);
+
+       for (iter = iter_start; iter < iter_stop; iter++) {
                arch_jump_label_text_poke_early(iter->code);
-               iter++;
+               if (iter->key == (jump_label_t)(unsigned long)key)
+                       continue;
+
+               key = (struct jump_label_key *)(unsigned long)iter->key;
+               atomic_set(&key->enabled, 0);
+               key->entries = iter;
+#ifdef CONFIG_MODULES
+               key->next = NULL;
+#endif
        }
        jump_label_unlock();
-       return ret;
+
+       return 0;
 }
-early_initcall(init_jump_label);
+early_initcall(jump_label_init);
 
 #ifdef CONFIG_MODULES
 
-static struct jump_label_module_entry *
-add_jump_label_module_entry(struct jump_label_entry *entry,
-                           struct jump_entry *iter_begin,
-                           int count, struct module *mod)
+struct jump_label_mod {
+       struct jump_label_mod *next;
+       struct jump_entry *entries;
+       struct module *mod;
+};
+
+static int __jump_label_mod_text_reserved(void *start, void *end)
+{
+       struct module *mod;
+
+       mod = __module_text_address((unsigned long)start);
+       if (!mod)
+               return 0;
+
+       WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
+
+       return __jump_label_text_reserved(mod->jump_entries,
+                               mod->jump_entries + mod->num_jump_entries,
+                               start, end);
+}
+
+static void __jump_label_mod_update(struct jump_label_key *key, int enable)
+{
+       struct jump_label_mod *mod = key->next;
+
+       while (mod) {
+               __jump_label_update(key, mod->entries, enable);
+               mod = mod->next;
+       }
+}
+
+/***
+ * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
+ * @mod: module to patch
+ *
+ * Allow for run-time selection of the optimal nops. Before the module
+ * loads patch these with arch_get_jump_label_nop(), which is specified by
+ * the arch specific jump label code.
+ */
+void jump_label_apply_nops(struct module *mod)
 {
-       struct jump_label_module_entry *e;
-
-       e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL);
-       if (!e)
-               return ERR_PTR(-ENOMEM);
-       e->mod = mod;
-       e->nr_entries = count;
-       e->table = iter_begin;
-       hlist_add_head(&e->hlist, &entry->modules);
-       return e;
+       struct jump_entry *iter_start = mod->jump_entries;
+       struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
+       struct jump_entry *iter;
+
+       /* if the module doesn't have jump label entries, just return */
+       if (iter_start == iter_stop)
+               return;
+
+       for (iter = iter_start; iter < iter_stop; iter++)
+               arch_jump_label_text_poke_early(iter->code);
 }
 
-static int add_jump_label_module(struct module *mod)
+static int jump_label_add_module(struct module *mod)
 {
-       struct jump_entry *iter, *iter_begin;
-       struct jump_label_entry *entry;
-       struct jump_label_module_entry *module_entry;
-       int count;
+       struct jump_entry *iter_start = mod->jump_entries;
+       struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
+       struct jump_entry *iter;
+       struct jump_label_key *key = NULL;
+       struct jump_label_mod *jlm;
 
        /* if the module doesn't have jump label entries, just return */
-       if (!mod->num_jump_entries)
+       if (iter_start == iter_stop)
                return 0;
 
-       sort_jump_label_entries(mod->jump_entries,
-                               mod->jump_entries + mod->num_jump_entries);
-       iter = mod->jump_entries;
-       while (iter < mod->jump_entries + mod->num_jump_entries) {
-               entry = get_jump_label_entry(iter->key);
-               iter_begin = iter;
-               count = 0;
-               while ((iter < mod->jump_entries + mod->num_jump_entries) &&
-                       (iter->key == iter_begin->key)) {
-                               iter++;
-                               count++;
-               }
-               if (!entry) {
-                       entry = add_jump_label_entry(iter_begin->key, 0, NULL);
-                       if (IS_ERR(entry))
-                               return PTR_ERR(entry);
+       jump_label_sort_entries(iter_start, iter_stop);
+
+       for (iter = iter_start; iter < iter_stop; iter++) {
+               if (iter->key == (jump_label_t)(unsigned long)key)
+                       continue;
+
+               key = (struct jump_label_key *)(unsigned long)iter->key;
+
+               if (__module_address(iter->key) == mod) {
+                       atomic_set(&key->enabled, 0);
+                       key->entries = iter;
+                       key->next = NULL;
+                       continue;
                }
-               module_entry = add_jump_label_module_entry(entry, iter_begin,
-                                                          count, mod);
-               if (IS_ERR(module_entry))
-                       return PTR_ERR(module_entry);
+
+               jlm = kzalloc(sizeof(struct jump_label_mod), GFP_KERNEL);
+               if (!jlm)
+                       return -ENOMEM;
+
+               jlm->mod = mod;
+               jlm->entries = iter;
+               jlm->next = key->next;
+               key->next = jlm;
+
+               if (jump_label_enabled(key))
+                       __jump_label_update(key, iter, JUMP_LABEL_ENABLE);
        }
+
        return 0;
 }
 
-static void remove_jump_label_module(struct module *mod)
+static void jump_label_del_module(struct module *mod)
 {
-       struct hlist_head *head;
-       struct hlist_node *node, *node_next, *module_node, *module_node_next;
-       struct jump_label_entry *e;
-       struct jump_label_module_entry *e_module;
-       int i;
+       struct jump_entry *iter_start = mod->jump_entries;
+       struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
+       struct jump_entry *iter;
+       struct jump_label_key *key = NULL;
+       struct jump_label_mod *jlm, **prev;
 
-       /* if the module doesn't have jump label entries, just return */
-       if (!mod->num_jump_entries)
-               return;
+       for (iter = iter_start; iter < iter_stop; iter++) {
+               if (iter->key == (jump_label_t)(unsigned long)key)
+                       continue;
+
+               key = (struct jump_label_key *)(unsigned long)iter->key;
+
+               if (__module_address(iter->key) == mod)
+                       continue;
+
+               prev = &key->next;
+               jlm = key->next;
 
-       for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
-               head = &jump_label_table[i];
-               hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
-                       hlist_for_each_entry_safe(e_module, module_node,
-                                                 module_node_next,
-                                                 &(e->modules), hlist) {
-                               if (e_module->mod == mod) {
-                                       hlist_del(&e_module->hlist);
-                                       kfree(e_module);
-                               }
-                       }
-                       if (hlist_empty(&e->modules) && (e->nr_entries == 0)) {
-                               hlist_del(&e->hlist);
-                               kfree(e);
-                       }
+               while (jlm && jlm->mod != mod) {
+                       prev = &jlm->next;
+                       jlm = jlm->next;
+               }
+
+               if (jlm) {
+                       *prev = jlm->next;
+                       kfree(jlm);
                }
        }
 }
 
-static void remove_jump_label_module_init(struct module *mod)
+static void jump_label_invalidate_module_init(struct module *mod)
 {
-       struct hlist_head *head;
-       struct hlist_node *node, *node_next, *module_node, *module_node_next;
-       struct jump_label_entry *e;
-       struct jump_label_module_entry *e_module;
+       struct jump_entry *iter_start = mod->jump_entries;
+       struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
        struct jump_entry *iter;
-       int i, count;
-
-       /* if the module doesn't have jump label entries, just return */
-       if (!mod->num_jump_entries)
-               return;
 
-       for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
-               head = &jump_label_table[i];
-               hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
-                       hlist_for_each_entry_safe(e_module, module_node,
-                                                 module_node_next,
-                                                 &(e->modules), hlist) {
-                               if (e_module->mod != mod)
-                                       continue;
-                               count = e_module->nr_entries;
-                               iter = e_module->table;
-                               while (count--) {
-                                       if (within_module_init(iter->code, mod))
-                                               iter->key = 0;
-                                       iter++;
-                               }
-                       }
-               }
+       for (iter = iter_start; iter < iter_stop; iter++) {
+               if (within_module_init(iter->code, mod))
+                       iter->code = 0;
        }
 }
 
@@ -426,59 +305,77 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val,
        switch (val) {
        case MODULE_STATE_COMING:
                jump_label_lock();
-               ret = add_jump_label_module(mod);
+               ret = jump_label_add_module(mod);
                if (ret)
-                       remove_jump_label_module(mod);
+                       jump_label_del_module(mod);
                jump_label_unlock();
                break;
        case MODULE_STATE_GOING:
                jump_label_lock();
-               remove_jump_label_module(mod);
+               jump_label_del_module(mod);
                jump_label_unlock();
                break;
        case MODULE_STATE_LIVE:
                jump_label_lock();
-               remove_jump_label_module_init(mod);
+               jump_label_invalidate_module_init(mod);
                jump_label_unlock();
                break;
        }
-       return ret;
-}
 
-/***
- * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
- * @mod: module to patch
- *
- * Allow for run-time selection of the optimal nops. Before the module
- * loads patch these with arch_get_jump_label_nop(), which is specified by
- * the arch specific jump label code.
- */
-void jump_label_apply_nops(struct module *mod)
-{
-       struct jump_entry *iter;
-
-       /* if the module doesn't have jump label entries, just return */
-       if (!mod->num_jump_entries)
-               return;
-
-       iter = mod->jump_entries;
-       while (iter < mod->jump_entries + mod->num_jump_entries) {
-               arch_jump_label_text_poke_early(iter->code);
-               iter++;
-       }
+       return notifier_from_errno(ret);
 }
 
 struct notifier_block jump_label_module_nb = {
        .notifier_call = jump_label_module_notify,
-       .priority = 0,
+       .priority = 1, /* higher than tracepoints */
 };
 
-static __init int init_jump_label_module(void)
+static __init int jump_label_init_module(void)
 {
        return register_module_notifier(&jump_label_module_nb);
 }
-early_initcall(init_jump_label_module);
+early_initcall(jump_label_init_module);
 
 #endif /* CONFIG_MODULES */
 
+/***
+ * jump_label_text_reserved - check if addr range is reserved
+ * @start: start text addr
+ * @end: end text addr
+ *
+ * checks if the text addr located between @start and @end
+ * overlaps with any of the jump label patch addresses. Code
+ * that wants to modify kernel text should first verify that
+ * it does not overlap with any of the jump label addresses.
+ * Caller must hold jump_label_mutex.
+ *
+ * returns 1 if there is an overlap, 0 otherwise
+ */
+int jump_label_text_reserved(void *start, void *end)
+{
+       int ret = __jump_label_text_reserved(__start___jump_table,
+                       __stop___jump_table, start, end);
+
+       if (ret)
+               return ret;
+
+#ifdef CONFIG_MODULES
+       ret = __jump_label_mod_text_reserved(start, end);
+#endif
+       return ret;
+}
+
+static void jump_label_update(struct jump_label_key *key, int enable)
+{
+       struct jump_entry *entry = key->entries;
+
+       /* if there are no users, entry can be NULL */
+       if (entry)
+               __jump_label_update(key, entry, enable);
+
+#ifdef CONFIG_MODULES
+       __jump_label_mod_update(key, enable);
+#endif
+}
+
 #endif
index 55936f9cb251b9eb114d9b827ee478e18a3448b7..8d814cbc810950700113fc32b0bcaf8750265118 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swap.h>
 #include <linux/kmsg_dump.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -1530,8 +1531,7 @@ int kernel_kexec(void)
                if (error)
                        goto Enable_cpus;
                local_irq_disable();
-               /* Suspend system devices */
-               error = sysdev_suspend(PMSG_FREEZE);
+               error = syscore_suspend();
                if (error)
                        goto Enable_irqs;
        } else
@@ -1546,7 +1546,7 @@ int kernel_kexec(void)
 
 #ifdef CONFIG_KEXEC_JUMP
        if (kexec_image->preserve_context) {
-               sysdev_resume();
+               syscore_resume();
  Enable_irqs:
                local_irq_enable();
  Enable_cpus:
index 9cd0591c96a21acf825861c7672533c0273ae25e..5ae0ff38425f7ec6dfd0a794668df7a02d1ff923 100644 (file)
@@ -245,7 +245,6 @@ static void __call_usermodehelper(struct work_struct *work)
        }
 }
 
-#ifdef CONFIG_PM_SLEEP
 /*
  * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
  * (used for preventing user land processes from being created after the user
@@ -301,6 +300,15 @@ void usermodehelper_enable(void)
        usermodehelper_disabled = 0;
 }
 
+/**
+ * usermodehelper_is_disabled - check if new helpers are allowed to be started
+ */
+bool usermodehelper_is_disabled(void)
+{
+       return usermodehelper_disabled;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_is_disabled);
+
 static void helper_lock(void)
 {
        atomic_inc(&running_helpers);
@@ -312,12 +320,6 @@ static void helper_unlock(void)
        if (atomic_dec_and_test(&running_helpers))
                wake_up(&running_helpers_waitq);
 }
-#else /* CONFIG_PM_SLEEP */
-#define usermodehelper_disabled        0
-
-static inline void helper_lock(void) {}
-static inline void helper_unlock(void) {}
-#endif /* CONFIG_PM_SLEEP */
 
 /**
  * call_usermodehelper_setup - prepare to call a usermode helper
index 53a68956f1311497568930994cf69d4031763478..63437d065ac89d69bbc6e70fd3789e64ac7e1d6a 100644 (file)
@@ -490,6 +490,18 @@ void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS])
        usage[i] = '\0';
 }
 
+static int __print_lock_name(struct lock_class *class)
+{
+       char str[KSYM_NAME_LEN];
+       const char *name;
+
+       name = class->name;
+       if (!name)
+               name = __get_key_name(class->key, str);
+
+       return printk("%s", name);
+}
+
 static void print_lock_name(struct lock_class *class)
 {
        char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS];
@@ -1053,6 +1065,56 @@ print_circular_bug_entry(struct lock_list *target, int depth)
        return 0;
 }
 
+static void
+print_circular_lock_scenario(struct held_lock *src,
+                            struct held_lock *tgt,
+                            struct lock_list *prt)
+{
+       struct lock_class *source = hlock_class(src);
+       struct lock_class *target = hlock_class(tgt);
+       struct lock_class *parent = prt->class;
+
+       /*
+        * A direct locking problem where unsafe_class lock is taken
+        * directly by safe_class lock, then all we need to show
+        * is the deadlock scenario, as it is obvious that the
+        * unsafe lock is taken under the safe lock.
+        *
+        * But if there is a chain instead, where the safe lock takes
+        * an intermediate lock (middle_class) where this lock is
+        * not the same as the safe lock, then the lock chain is
+        * used to describe the problem. Otherwise we would need
+        * to show a different CPU case for each link in the chain
+        * from the safe_class lock to the unsafe_class lock.
+        */
+       if (parent != source) {
+               printk("Chain exists of:\n  ");
+               __print_lock_name(source);
+               printk(" --> ");
+               __print_lock_name(parent);
+               printk(" --> ");
+               __print_lock_name(target);
+               printk("\n\n");
+       }
+
+       printk(" Possible unsafe locking scenario:\n\n");
+       printk("       CPU0                    CPU1\n");
+       printk("       ----                    ----\n");
+       printk("  lock(");
+       __print_lock_name(target);
+       printk(");\n");
+       printk("                               lock(");
+       __print_lock_name(parent);
+       printk(");\n");
+       printk("                               lock(");
+       __print_lock_name(target);
+       printk(");\n");
+       printk("  lock(");
+       __print_lock_name(source);
+       printk(");\n");
+       printk("\n *** DEADLOCK ***\n\n");
+}
+
 /*
  * When a circular dependency is detected, print the
  * header first:
@@ -1096,6 +1158,7 @@ static noinline int print_circular_bug(struct lock_list *this,
 {
        struct task_struct *curr = current;
        struct lock_list *parent;
+       struct lock_list *first_parent;
        int depth;
 
        if (!debug_locks_off_graph_unlock() || debug_locks_silent)
@@ -1109,6 +1172,7 @@ static noinline int print_circular_bug(struct lock_list *this,
        print_circular_bug_header(target, depth, check_src, check_tgt);
 
        parent = get_lock_parent(target);
+       first_parent = parent;
 
        while (parent) {
                print_circular_bug_entry(parent, --depth);
@@ -1116,6 +1180,9 @@ static noinline int print_circular_bug(struct lock_list *this,
        }
 
        printk("\nother info that might help us debug this:\n\n");
+       print_circular_lock_scenario(check_src, check_tgt,
+                                    first_parent);
+
        lockdep_print_held_locks(curr);
 
        printk("\nstack backtrace:\n");
@@ -1314,7 +1381,7 @@ print_shortest_lock_dependencies(struct lock_list *leaf,
                printk("\n");
 
                if (depth == 0 && (entry != root)) {
-                       printk("lockdep:%s bad BFS generated tree\n", __func__);
+                       printk("lockdep:%s bad path found in chain graph\n", __func__);
                        break;
                }
 
@@ -1325,6 +1392,62 @@ print_shortest_lock_dependencies(struct lock_list *leaf,
        return;
 }
 
+static void
+print_irq_lock_scenario(struct lock_list *safe_entry,
+                       struct lock_list *unsafe_entry,
+                       struct lock_class *prev_class,
+                       struct lock_class *next_class)
+{
+       struct lock_class *safe_class = safe_entry->class;
+       struct lock_class *unsafe_class = unsafe_entry->class;
+       struct lock_class *middle_class = prev_class;
+
+       if (middle_class == safe_class)
+               middle_class = next_class;
+
+       /*
+        * A direct locking problem where unsafe_class lock is taken
+        * directly by safe_class lock, then all we need to show
+        * is the deadlock scenario, as it is obvious that the
+        * unsafe lock is taken under the safe lock.
+        *
+        * But if there is a chain instead, where the safe lock takes
+        * an intermediate lock (middle_class) where this lock is
+        * not the same as the safe lock, then the lock chain is
+        * used to describe the problem. Otherwise we would need
+        * to show a different CPU case for each link in the chain
+        * from the safe_class lock to the unsafe_class lock.
+        */
+       if (middle_class != unsafe_class) {
+               printk("Chain exists of:\n  ");
+               __print_lock_name(safe_class);
+               printk(" --> ");
+               __print_lock_name(middle_class);
+               printk(" --> ");
+               __print_lock_name(unsafe_class);
+               printk("\n\n");
+       }
+
+       printk(" Possible interrupt unsafe locking scenario:\n\n");
+       printk("       CPU0                    CPU1\n");
+       printk("       ----                    ----\n");
+       printk("  lock(");
+       __print_lock_name(unsafe_class);
+       printk(");\n");
+       printk("                               local_irq_disable();\n");
+       printk("                               lock(");
+       __print_lock_name(safe_class);
+       printk(");\n");
+       printk("                               lock(");
+       __print_lock_name(middle_class);
+       printk(");\n");
+       printk("  <Interrupt>\n");
+       printk("    lock(");
+       __print_lock_name(safe_class);
+       printk(");\n");
+       printk("\n *** DEADLOCK ***\n\n");
+}
+
 static int
 print_bad_irq_dependency(struct task_struct *curr,
                         struct lock_list *prev_root,
@@ -1376,6 +1499,9 @@ print_bad_irq_dependency(struct task_struct *curr,
        print_stack_trace(forwards_entry->class->usage_traces + bit2, 1);
 
        printk("\nother info that might help us debug this:\n\n");
+       print_irq_lock_scenario(backwards_entry, forwards_entry,
+                               hlock_class(prev), hlock_class(next));
+
        lockdep_print_held_locks(curr);
 
        printk("\nthe dependencies between %s-irq-safe lock", irqclass);
@@ -1539,6 +1665,26 @@ static inline void inc_chains(void)
 
 #endif
 
+static void
+print_deadlock_scenario(struct held_lock *nxt,
+                            struct held_lock *prv)
+{
+       struct lock_class *next = hlock_class(nxt);
+       struct lock_class *prev = hlock_class(prv);
+
+       printk(" Possible unsafe locking scenario:\n\n");
+       printk("       CPU0\n");
+       printk("       ----\n");
+       printk("  lock(");
+       __print_lock_name(prev);
+       printk(");\n");
+       printk("  lock(");
+       __print_lock_name(next);
+       printk(");\n");
+       printk("\n *** DEADLOCK ***\n\n");
+       printk(" May be due to missing lock nesting notation\n\n");
+}
+
 static int
 print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
                   struct held_lock *next)
@@ -1557,6 +1703,7 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
        print_lock(prev);
 
        printk("\nother info that might help us debug this:\n");
+       print_deadlock_scenario(next, prev);
        lockdep_print_held_locks(curr);
 
        printk("\nstack backtrace:\n");
@@ -1826,7 +1973,7 @@ static inline int lookup_chain_cache(struct task_struct *curr,
        struct list_head *hash_head = chainhashentry(chain_key);
        struct lock_chain *chain;
        struct held_lock *hlock_curr, *hlock_next;
-       int i, j, n, cn;
+       int i, j;
 
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return 0;
@@ -1886,15 +2033,9 @@ cache_hit:
        }
        i++;
        chain->depth = curr->lockdep_depth + 1 - i;
-       cn = nr_chain_hlocks;
-       while (cn + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS) {
-               n = cmpxchg(&nr_chain_hlocks, cn, cn + chain->depth);
-               if (n == cn)
-                       break;
-               cn = n;
-       }
-       if (likely(cn + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) {
-               chain->base = cn;
+       if (likely(nr_chain_hlocks + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) {
+               chain->base = nr_chain_hlocks;
+               nr_chain_hlocks += chain->depth;
                for (j = 0; j < chain->depth - 1; j++, i++) {
                        int lock_id = curr->held_locks[i].class_idx - 1;
                        chain_hlocks[chain->base + j] = lock_id;
@@ -2011,6 +2152,24 @@ static void check_chain_key(struct task_struct *curr)
 #endif
 }
 
+static void
+print_usage_bug_scenario(struct held_lock *lock)
+{
+       struct lock_class *class = hlock_class(lock);
+
+       printk(" Possible unsafe locking scenario:\n\n");
+       printk("       CPU0\n");
+       printk("       ----\n");
+       printk("  lock(");
+       __print_lock_name(class);
+       printk(");\n");
+       printk("  <Interrupt>\n");
+       printk("    lock(");
+       __print_lock_name(class);
+       printk(");\n");
+       printk("\n *** DEADLOCK ***\n\n");
+}
+
 static int
 print_usage_bug(struct task_struct *curr, struct held_lock *this,
                enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
@@ -2039,6 +2198,8 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this,
 
        print_irqtrace_events(curr);
        printk("\nother info that might help us debug this:\n");
+       print_usage_bug_scenario(this);
+
        lockdep_print_held_locks(curr);
 
        printk("\nstack backtrace:\n");
@@ -2073,6 +2234,10 @@ print_irq_inversion_bug(struct task_struct *curr,
                        struct held_lock *this, int forwards,
                        const char *irqclass)
 {
+       struct lock_list *entry = other;
+       struct lock_list *middle = NULL;
+       int depth;
+
        if (!debug_locks_off_graph_unlock() || debug_locks_silent)
                return 0;
 
@@ -2091,6 +2256,25 @@ print_irq_inversion_bug(struct task_struct *curr,
        printk("\n\nand interrupts could create inverse lock ordering between them.\n\n");
 
        printk("\nother info that might help us debug this:\n");
+
+       /* Find a middle lock (if one exists) */
+       depth = get_lock_depth(other);
+       do {
+               if (depth == 0 && (entry != root)) {
+                       printk("lockdep:%s bad path found in chain graph\n", __func__);
+                       break;
+               }
+               middle = entry;
+               entry = get_lock_parent(entry);
+               depth--;
+       } while (entry && entry != root && (depth >= 0));
+       if (forwards)
+               print_irq_lock_scenario(root, other,
+                       middle ? middle->class : root->class, other->class);
+       else
+               print_irq_lock_scenario(other, root,
+                       middle ? middle->class : other->class, root->class);
+
        lockdep_print_held_locks(curr);
 
        printk("\nthe shortest dependencies between 2nd lock and 1st lock:\n");
index d5938a5c19c47516499ef289b2087620783e23df..22879725678dfcd53324698504500dc97decdea6 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/kmemleak.h>
 #include <linux/jump_label.h>
 #include <linux/pfn.h>
+#include <linux/bsearch.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -240,23 +241,24 @@ static bool each_symbol_in_section(const struct symsearch *arr,
                                   struct module *owner,
                                   bool (*fn)(const struct symsearch *syms,
                                              struct module *owner,
-                                             unsigned int symnum, void *data),
+                                             void *data),
                                   void *data)
 {
-       unsigned int i, j;
+       unsigned int j;
 
        for (j = 0; j < arrsize; j++) {
-               for (i = 0; i < arr[j].stop - arr[j].start; i++)
-                       if (fn(&arr[j], owner, i, data))
-                               return true;
+               if (fn(&arr[j], owner, data))
+                       return true;
        }
 
        return false;
 }
 
 /* Returns true as soon as fn returns true, otherwise false. */
-bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
-                           unsigned int symnum, void *data), void *data)
+bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
+                                   struct module *owner,
+                                   void *data),
+                        void *data)
 {
        struct module *mod;
        static const struct symsearch arr[] = {
@@ -309,7 +311,7 @@ bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
        }
        return false;
 }
-EXPORT_SYMBOL_GPL(each_symbol);
+EXPORT_SYMBOL_GPL(each_symbol_section);
 
 struct find_symbol_arg {
        /* Input */
@@ -323,15 +325,12 @@ struct find_symbol_arg {
        const struct kernel_symbol *sym;
 };
 
-static bool find_symbol_in_section(const struct symsearch *syms,
-                                  struct module *owner,
-                                  unsigned int symnum, void *data)
+static bool check_symbol(const struct symsearch *syms,
+                                struct module *owner,
+                                unsigned int symnum, void *data)
 {
        struct find_symbol_arg *fsa = data;
 
-       if (strcmp(syms->start[symnum].name, fsa->name) != 0)
-               return false;
-
        if (!fsa->gplok) {
                if (syms->licence == GPL_ONLY)
                        return false;
@@ -365,6 +364,30 @@ static bool find_symbol_in_section(const struct symsearch *syms,
        return true;
 }
 
+static int cmp_name(const void *va, const void *vb)
+{
+       const char *a;
+       const struct kernel_symbol *b;
+       a = va; b = vb;
+       return strcmp(a, b->name);
+}
+
+static bool find_symbol_in_section(const struct symsearch *syms,
+                                  struct module *owner,
+                                  void *data)
+{
+       struct find_symbol_arg *fsa = data;
+       struct kernel_symbol *sym;
+
+       sym = bsearch(fsa->name, syms->start, syms->stop - syms->start,
+                       sizeof(struct kernel_symbol), cmp_name);
+
+       if (sym != NULL && check_symbol(syms, owner, sym - syms->start, data))
+               return true;
+
+       return false;
+}
+
 /* Find a symbol and return it, along with, (optional) crc and
  * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
 const struct kernel_symbol *find_symbol(const char *name,
@@ -379,7 +402,7 @@ const struct kernel_symbol *find_symbol(const char *name,
        fsa.gplok = gplok;
        fsa.warn = warn;
 
-       if (each_symbol(find_symbol_in_section, &fsa)) {
+       if (each_symbol_section(find_symbol_in_section, &fsa)) {
                if (owner)
                        *owner = fsa.owner;
                if (crc)
@@ -1607,27 +1630,28 @@ static void set_section_ro_nx(void *base,
        }
 }
 
-/* Setting memory back to RW+NX before releasing it */
-void unset_section_ro_nx(struct module *mod, void *module_region)
+static void unset_module_core_ro_nx(struct module *mod)
 {
-       unsigned long total_pages;
-
-       if (mod->module_core == module_region) {
-               /* Set core as NX+RW */
-               total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size);
-               set_memory_nx((unsigned long)mod->module_core, total_pages);
-               set_memory_rw((unsigned long)mod->module_core, total_pages);
+       set_page_attributes(mod->module_core + mod->core_text_size,
+               mod->module_core + mod->core_size,
+               set_memory_x);
+       set_page_attributes(mod->module_core,
+               mod->module_core + mod->core_ro_size,
+               set_memory_rw);
+}
 
-       } else if (mod->module_init == module_region) {
-               /* Set init as NX+RW */
-               total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size);
-               set_memory_nx((unsigned long)mod->module_init, total_pages);
-               set_memory_rw((unsigned long)mod->module_init, total_pages);
-       }
+static void unset_module_init_ro_nx(struct module *mod)
+{
+       set_page_attributes(mod->module_init + mod->init_text_size,
+               mod->module_init + mod->init_size,
+               set_memory_x);
+       set_page_attributes(mod->module_init,
+               mod->module_init + mod->init_ro_size,
+               set_memory_rw);
 }
 
 /* Iterate through all modules and set each module's text as RW */
-void set_all_modules_text_rw()
+void set_all_modules_text_rw(void)
 {
        struct module *mod;
 
@@ -1648,7 +1672,7 @@ void set_all_modules_text_rw()
 }
 
 /* Iterate through all modules and set each module's text as RO */
-void set_all_modules_text_ro()
+void set_all_modules_text_ro(void)
 {
        struct module *mod;
 
@@ -1669,7 +1693,8 @@ void set_all_modules_text_ro()
 }
 #else
 static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { }
-static inline void unset_section_ro_nx(struct module *mod, void *module_region) { }
+static void unset_module_core_ro_nx(struct module *mod) { }
+static void unset_module_init_ro_nx(struct module *mod) { }
 #endif
 
 /* Free a module, remove from lists, etc. */
@@ -1696,7 +1721,7 @@ static void free_module(struct module *mod)
        destroy_params(mod->kp, mod->num_kp);
 
        /* This may be NULL, but that's OK */
-       unset_section_ro_nx(mod, mod->module_init);
+       unset_module_init_ro_nx(mod);
        module_free(mod, mod->module_init);
        kfree(mod->args);
        percpu_modfree(mod);
@@ -1705,7 +1730,7 @@ static void free_module(struct module *mod)
        lockdep_free_key_range(mod->module_core, mod->core_size);
 
        /* Finally, free the core (containing the module structure) */
-       unset_section_ro_nx(mod, mod->module_core);
+       unset_module_core_ro_nx(mod);
        module_free(mod, mod->module_core);
 
 #ifdef CONFIG_MPU
@@ -2030,11 +2055,8 @@ static const struct kernel_symbol *lookup_symbol(const char *name,
        const struct kernel_symbol *start,
        const struct kernel_symbol *stop)
 {
-       const struct kernel_symbol *ks = start;
-       for (; ks < stop; ks++)
-               if (strcmp(ks->name, name) == 0)
-                       return ks;
-       return NULL;
+       return bsearch(name, start, stop - start,
+                       sizeof(struct kernel_symbol), cmp_name);
 }
 
 static int is_exported(const char *name, unsigned long value,
@@ -2931,10 +2953,11 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
        mod->symtab = mod->core_symtab;
        mod->strtab = mod->core_strtab;
 #endif
-       unset_section_ro_nx(mod, mod->module_init);
+       unset_module_init_ro_nx(mod);
        module_free(mod, mod->module_init);
        mod->module_init = NULL;
        mod->init_size = 0;
+       mod->init_ro_size = 0;
        mod->init_text_size = 0;
        mutex_unlock(&module_mutex);
 
index ec815a960b5d526a29992dfd59e30ae21e35d9f3..73da83aff418d30d0b488454bf95bb172467cb82 100644 (file)
@@ -75,7 +75,7 @@ void debug_mutex_unlock(struct mutex *lock)
                return;
 
        DEBUG_LOCKS_WARN_ON(lock->magic != lock);
-       DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
+       DEBUG_LOCKS_WARN_ON(lock->owner != current);
        DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
        mutex_clear_owner(lock);
 }
index 57d527a16f9d1058bb9aacf3fa7ebba64a7c032b..0799fd3e4cfacbfdac923c6dedba278dbc36e0f9 100644 (file)
@@ -29,7 +29,7 @@ extern void debug_mutex_init(struct mutex *lock, const char *name,
 
 static inline void mutex_set_owner(struct mutex *lock)
 {
-       lock->owner = current_thread_info();
+       lock->owner = current;
 }
 
 static inline void mutex_clear_owner(struct mutex *lock)
index c4195fa98900b65528bf5ee2229f7eeadfa5c4d7..2c938e2337cd36f3e627bb5758186aa7b4e0a327 100644 (file)
@@ -160,14 +160,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
         */
 
        for (;;) {
-               struct thread_info *owner;
-
-               /*
-                * If we own the BKL, then don't spin. The owner of
-                * the mutex might be waiting on us to release the BKL.
-                */
-               if (unlikely(current->lock_depth >= 0))
-                       break;
+               struct task_struct *owner;
 
                /*
                 * If there's an owner, wait for it to either
index 67578ca48f94e1dad6f7cf3760c28d20a86605e2..4115fbf83b12ed11e2b05bc7cccfb5933cb3311d 100644 (file)
@@ -19,7 +19,7 @@
 #ifdef CONFIG_SMP
 static inline void mutex_set_owner(struct mutex *lock)
 {
-       lock->owner = current_thread_info();
+       lock->owner = current;
 }
 
 static inline void mutex_clear_owner(struct mutex *lock)
index 6888761f1b4e13e15c181bd7e311210f380ce84f..ed72e1330862d265e4276669830ec3f6b26c7d0d 100644 (file)
@@ -815,15 +815,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
        return sprintf(buf, "%s\n", vattr->version);
 }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
 static void __init version_sysfs_builtin(void)
 {
-       const struct module_version_attribute *vattr;
+       const struct module_version_attribute **p;
        struct module_kobject *mk;
        int err;
 
-       for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+       for (p = __start___modver; p < __stop___modver; p++) {
+               const struct module_version_attribute *vattr = *p;
+
                mk = locate_module_kobject(vattr->module_name);
                if (mk) {
                        err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
index 6de9a8fc34179448c0768a1c4a12ad4849cb1ce6..87f4d24b55b02872388661fad0e4a51757a4fc76 100644 (file)
@@ -125,12 +125,6 @@ config PM_DEBUG
        code. This is helpful when debugging and reporting PM bugs, like
        suspend support.
 
-config PM_VERBOSE
-       bool "Verbose Power Management debugging"
-       depends on PM_DEBUG
-       ---help---
-       This option enables verbose messages from the Power Management code.
-
 config PM_ADVANCED_DEBUG
        bool "Extra PM attributes in sysfs for low-level debugging/testing"
        depends on PM_DEBUG
@@ -229,3 +223,7 @@ config PM_OPP
          representing individual voltage domains and provides SOC
          implementations a ready to use framework to manage OPPs.
          For more information, read <file:Documentation/power/opp.txt>
+
+config PM_RUNTIME_CLK
+       def_bool y
+       depends on PM_RUNTIME && HAVE_CLK
index aeabd26e3342788e4330cfb4e8e2a5ba40b348d0..f9bec56d88258992b61e8f9fb3306dd010e652e1 100644 (file)
@@ -272,9 +272,7 @@ static int create_image(int platform_mode)
 
        local_irq_disable();
 
-       error = sysdev_suspend(PMSG_FREEZE);
-       if (!error)
-               error = syscore_suspend();
+       error = syscore_suspend();
        if (error) {
                printk(KERN_ERR "PM: Some system devices failed to power down, "
                        "aborting hibernation\n");
@@ -299,7 +297,6 @@ static int create_image(int platform_mode)
 
  Power_up:
        syscore_resume();
-       sysdev_resume();
        /* NOTE:  dpm_resume_noirq() is just a resume() for devices
         * that suspended with irqs off ... no overall powerup.
         */
@@ -330,20 +327,25 @@ static int create_image(int platform_mode)
 
 int hibernation_snapshot(int platform_mode)
 {
+       pm_message_t msg = PMSG_RECOVER;
        int error;
 
        error = platform_begin(platform_mode);
        if (error)
                goto Close;
 
+       error = dpm_prepare(PMSG_FREEZE);
+       if (error)
+               goto Complete_devices;
+
        /* Preallocate image memory before shutting down devices. */
        error = hibernate_preallocate_memory();
        if (error)
-               goto Close;
+               goto Complete_devices;
 
        suspend_console();
        pm_restrict_gfp_mask();
-       error = dpm_suspend_start(PMSG_FREEZE);
+       error = dpm_suspend(PMSG_FREEZE);
        if (error)
                goto Recover_platform;
 
@@ -361,13 +363,17 @@ int hibernation_snapshot(int platform_mode)
        if (error || !in_suspend)
                swsusp_free();
 
-       dpm_resume_end(in_suspend ?
-               (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+       msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE;
+       dpm_resume(msg);
 
        if (error || !in_suspend)
                pm_restore_gfp_mask();
 
        resume_console();
+
+ Complete_devices:
+       dpm_complete(msg);
+
  Close:
        platform_end(platform_mode);
        return error;
@@ -406,9 +412,7 @@ static int resume_target_kernel(bool platform_mode)
 
        local_irq_disable();
 
-       error = sysdev_suspend(PMSG_QUIESCE);
-       if (!error)
-               error = syscore_suspend();
+       error = syscore_suspend();
        if (error)
                goto Enable_irqs;
 
@@ -436,7 +440,6 @@ static int resume_target_kernel(bool platform_mode)
        touch_softlockup_watchdog();
 
        syscore_resume();
-       sysdev_resume();
 
  Enable_irqs:
        local_irq_enable();
@@ -522,7 +525,6 @@ int hibernation_platform_enter(void)
                goto Platform_finish;
 
        local_irq_disable();
-       sysdev_suspend(PMSG_HIBERNATE);
        syscore_suspend();
        if (pm_wakeup_pending()) {
                error = -EAGAIN;
@@ -535,7 +537,6 @@ int hibernation_platform_enter(void)
 
  Power_up:
        syscore_resume();
-       sysdev_resume();
        local_irq_enable();
        enable_nonboot_cpus();
 
@@ -976,10 +977,33 @@ static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *att
 
 power_attr(image_size);
 
+static ssize_t reserved_size_show(struct kobject *kobj,
+                                 struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lu\n", reserved_size);
+}
+
+static ssize_t reserved_size_store(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  const char *buf, size_t n)
+{
+       unsigned long size;
+
+       if (sscanf(buf, "%lu", &size) == 1) {
+               reserved_size = size;
+               return n;
+       }
+
+       return -EINVAL;
+}
+
+power_attr(reserved_size);
+
 static struct attribute * g[] = {
        &disk_attr.attr,
        &resume_attr.attr,
        &image_size_attr.attr,
+       &reserved_size_attr.attr,
        NULL,
 };
 
index de9aef8742f400df8f8cd696e6c977565fe21917..2981af4ce7cbbce49314e2fb2fef9fa13496f41e 100644 (file)
@@ -337,6 +337,7 @@ static int __init pm_init(void)
        if (error)
                return error;
        hibernate_image_size_init();
+       hibernate_reserved_size_init();
        power_kobj = kobject_create_and_add("power", NULL);
        if (!power_kobj)
                return -ENOMEM;
index 03634be55f62aabb407b8797d6a5a74ca6feef96..9a00a0a262806b11905a84fb85c5a26c7e99592b 100644 (file)
@@ -15,6 +15,7 @@ struct swsusp_info {
 
 #ifdef CONFIG_HIBERNATION
 /* kernel/power/snapshot.c */
+extern void __init hibernate_reserved_size_init(void);
 extern void __init hibernate_image_size_init(void);
 
 #ifdef CONFIG_ARCH_HIBERNATION_HEADER
@@ -55,6 +56,7 @@ extern int hibernation_platform_enter(void);
 
 #else /* !CONFIG_HIBERNATION */
 
+static inline void hibernate_reserved_size_init(void) {}
 static inline void hibernate_image_size_init(void) {}
 #endif /* !CONFIG_HIBERNATION */
 
@@ -72,6 +74,8 @@ static struct kobj_attribute _name##_attr = { \
 
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
+/* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */
+extern unsigned long reserved_size;
 extern int in_suspend;
 extern dev_t swsusp_resume_device;
 extern sector_t swsusp_resume_block;
index ca0aacc2487426522df9b9cf71297a61d9faa0b1..ace55889f7027b051acbaabdbce71389315418e5 100644 (file)
@@ -40,17 +40,29 @@ static int swsusp_page_is_free(struct page *);
 static void swsusp_set_page_forbidden(struct page *);
 static void swsusp_unset_page_forbidden(struct page *);
 
+/*
+ * Number of bytes to reserve for memory allocations made by device drivers
+ * from their ->freeze() and ->freeze_noirq() callbacks so that they don't
+ * cause image creation to fail (tunable via /sys/power/reserved_size).
+ */
+unsigned long reserved_size;
+
+void __init hibernate_reserved_size_init(void)
+{
+       reserved_size = SPARE_PAGES * PAGE_SIZE;
+}
+
 /*
  * Preferred image size in bytes (tunable via /sys/power/image_size).
- * When it is set to N, the image creating code will do its best to
- * ensure the image size will not exceed N bytes, but if that is
- * impossible, it will try to create the smallest image possible.
+ * When it is set to N, swsusp will do its best to ensure the image
+ * size will not exceed N bytes, but if that is impossible, it will
+ * try to create the smallest image possible.
  */
 unsigned long image_size;
 
 void __init hibernate_image_size_init(void)
 {
-       image_size = (totalram_pages / 3) * PAGE_SIZE;
+       image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
 }
 
 /* List of PBEs needed for restoring the pages that were allocated before
@@ -1263,11 +1275,13 @@ static unsigned long minimum_image_size(unsigned long saveable)
  * frame in use.  We also need a number of page frames to be free during
  * hibernation for allocations made while saving the image and for device
  * drivers, in case they need to allocate memory from their hibernation
- * callbacks (these two numbers are given by PAGES_FOR_IO and SPARE_PAGES,
- * respectively, both of which are rough estimates).  To make this happen, we
- * compute the total number of available page frames and allocate at least
+ * callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough
+ * estimate) and reserverd_size divided by PAGE_SIZE (which is tunable through
+ * /sys/power/reserved_size, respectively).  To make this happen, we compute the
+ * total number of available page frames and allocate at least
  *
- * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 + 2 * SPARE_PAGES
+ * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2
+ *  + 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE)
  *
  * of them, which corresponds to the maximum size of a hibernation image.
  *
@@ -1322,7 +1336,8 @@ int hibernate_preallocate_memory(void)
        count -= totalreserve_pages;
 
        /* Compute the maximum number of saveable pages to leave in memory. */
-       max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES;
+       max_size = (count - (size + PAGES_FOR_IO)) / 2
+                       - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
        /* Compute the desired number of image pages specified by image_size. */
        size = DIV_ROUND_UP(image_size, PAGE_SIZE);
        if (size > max_size)
index 2814c32aed51c121a7ff9689aa38f6b98d025b15..1c41ba215419d4d086fc27113caa20bcc8a81d6d 100644 (file)
@@ -163,16 +163,13 @@ static int suspend_enter(suspend_state_t state)
        arch_suspend_disable_irqs();
        BUG_ON(!irqs_disabled());
 
-       error = sysdev_suspend(PMSG_SUSPEND);
-       if (!error)
-               error = syscore_suspend();
+       error = syscore_suspend();
        if (!error) {
                if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
                        error = suspend_ops->enter(state);
                        events_check_enabled = false;
                }
                syscore_resume();
-               sysdev_resume();
        }
 
        arch_suspend_enable_irqs();
@@ -213,7 +210,6 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
-       pm_restrict_gfp_mask();
        suspend_test_start();
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
@@ -224,13 +220,12 @@ int suspend_devices_and_enter(suspend_state_t state)
        if (suspend_test(TEST_DEVICES))
                goto Recover_platform;
 
-       suspend_enter(state);
+       error = suspend_enter(state);
 
  Resume_devices:
        suspend_test_start();
        dpm_resume_end(PMSG_RESUME);
        suspend_test_finish("resume devices");
-       pm_restore_gfp_mask();
        resume_console();
  Close:
        if (suspend_ops->end)
@@ -291,7 +286,9 @@ int enter_state(suspend_state_t state)
                goto Finish;
 
        pr_debug("PM: Entering %s sleep\n", pm_states[state]);
+       pm_restrict_gfp_mask();
        error = suspend_devices_and_enter(state);
+       pm_restore_gfp_mask();
 
  Finish:
        pr_debug("PM: Finishing wakeup.\n");
index c36c3b9e8a84f59ad5894a1e2d04c7252b656ebe..7d02d33be699f97d4956c76ea71b939bb0832d06 100644 (file)
@@ -135,8 +135,10 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_basic_memory_bitmaps();
        data = filp->private_data;
        free_all_swap_pages(data->swap);
-       if (data->frozen)
+       if (data->frozen) {
+               pm_restore_gfp_mask();
                thaw_processes();
+       }
        pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
@@ -379,6 +381,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                 * PM_HIBERNATION_PREPARE
                 */
                error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+               data->ready = 0;
                break;
 
        case SNAPSHOT_PLATFORM_SUPPORT:
index 0fc1eed28d2783e0b2779fe50d1ff86fbf4ca858..dc7ab65f3b36cb0b71c8365e13d0e73a9601f6ee 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <linux/regset.h>
+#include <linux/hw_breakpoint.h>
 
 
 /*
@@ -879,3 +880,19 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
        return ret;
 }
 #endif /* CONFIG_COMPAT */
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+int ptrace_get_breakpoints(struct task_struct *tsk)
+{
+       if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt))
+               return 0;
+
+       return -1;
+}
+
+void ptrace_put_breakpoints(struct task_struct *tsk)
+{
+       if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt))
+               flush_ptrace_hw_breakpoint(tsk);
+}
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
index f3240e987928ca9630b15d39784180339c8727dd..7784bd216b6a25277445cbcf6435298bdb11cdbc 100644 (file)
@@ -142,10 +142,17 @@ static int rcuhead_fixup_init(void *addr, enum debug_obj_state state)
                 * Ensure that queued callbacks are all executed.
                 * If we detect that we are nested in a RCU read-side critical
                 * section, we should simply fail, otherwise we would deadlock.
+                * In !PREEMPT configurations, there is no way to tell if we are
+                * in a RCU read-side critical section or not, so we never
+                * attempt any fixup and just print a warning.
                 */
+#ifndef CONFIG_PREEMPT
+               WARN_ON_ONCE(1);
+               return 0;
+#endif
                if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
                    irqs_disabled()) {
-                       WARN_ON(1);
+                       WARN_ON_ONCE(1);
                        return 0;
                }
                rcu_barrier();
@@ -184,10 +191,17 @@ static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state)
                 * Ensure that queued callbacks are all executed.
                 * If we detect that we are nested in a RCU read-side critical
                 * section, we should simply fail, otherwise we would deadlock.
+                * In !PREEMPT configurations, there is no way to tell if we are
+                * in a RCU read-side critical section or not, so we never
+                * attempt any fixup and just print a warning.
                 */
+#ifndef CONFIG_PREEMPT
+               WARN_ON_ONCE(1);
+               return 0;
+#endif
                if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
                    irqs_disabled()) {
-                       WARN_ON(1);
+                       WARN_ON_ONCE(1);
                        return 0;
                }
                rcu_barrier();
@@ -214,15 +228,17 @@ static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)
                 * Ensure that queued callbacks are all executed.
                 * If we detect that we are nested in a RCU read-side critical
                 * section, we should simply fail, otherwise we would deadlock.
-                * Note that the machinery to reliably determine whether
-                * or not we are in an RCU read-side critical section
-                * exists only in the preemptible RCU implementations
-                * (TINY_PREEMPT_RCU and TREE_PREEMPT_RCU), which is why
-                * DEBUG_OBJECTS_RCU_HEAD is disallowed if !PREEMPT.
+                * In !PREEMPT configurations, there is no way to tell if we are
+                * in a RCU read-side critical section or not, so we never
+                * attempt any fixup and just print a warning.
                 */
+#ifndef CONFIG_PREEMPT
+               WARN_ON_ONCE(1);
+               return 0;
+#endif
                if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
                    irqs_disabled()) {
-                       WARN_ON(1);
+                       WARN_ON_ONCE(1);
                        return 0;
                }
                rcu_barrier();
index 0c343b9a46d565cde538f153894010748f1c924d..421abfd3641d2f011fe7b33b85a36a6b7cf8faf1 100644 (file)
 static struct task_struct *rcu_kthread_task;
 static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq);
 static unsigned long have_rcu_kthread_work;
-static void invoke_rcu_kthread(void);
 
 /* Forward declarations for rcutiny_plugin.h. */
 struct rcu_ctrlblk;
+static void invoke_rcu_kthread(void);
 static void rcu_process_callbacks(struct rcu_ctrlblk *rcp);
 static int rcu_kthread(void *arg);
 static void __call_rcu(struct rcu_head *head,
@@ -79,26 +79,31 @@ void rcu_exit_nohz(void)
 #endif /* #ifdef CONFIG_NO_HZ */
 
 /*
- * Helper function for rcu_qsctr_inc() and rcu_bh_qsctr_inc().
- * Also disable irqs to avoid confusion due to interrupt handlers
+ * Helper function for rcu_sched_qs() and rcu_bh_qs().
+ * Also irqs are disabled to avoid confusion due to interrupt handlers
  * invoking call_rcu().
  */
 static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
 {
-       unsigned long flags;
-
-       local_irq_save(flags);
        if (rcp->rcucblist != NULL &&
            rcp->donetail != rcp->curtail) {
                rcp->donetail = rcp->curtail;
-               local_irq_restore(flags);
                return 1;
        }
-       local_irq_restore(flags);
 
        return 0;
 }
 
+/*
+ * Wake up rcu_kthread() to process callbacks now eligible for invocation
+ * or to boost readers.
+ */
+static void invoke_rcu_kthread(void)
+{
+       have_rcu_kthread_work = 1;
+       wake_up(&rcu_kthread_wq);
+}
+
 /*
  * Record an rcu quiescent state.  And an rcu_bh quiescent state while we
  * are at it, given that any rcu quiescent state is also an rcu_bh
@@ -106,9 +111,13 @@ static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
  */
 void rcu_sched_qs(int cpu)
 {
+       unsigned long flags;
+
+       local_irq_save(flags);
        if (rcu_qsctr_help(&rcu_sched_ctrlblk) +
            rcu_qsctr_help(&rcu_bh_ctrlblk))
                invoke_rcu_kthread();
+       local_irq_restore(flags);
 }
 
 /*
@@ -116,8 +125,12 @@ void rcu_sched_qs(int cpu)
  */
 void rcu_bh_qs(int cpu)
 {
+       unsigned long flags;
+
+       local_irq_save(flags);
        if (rcu_qsctr_help(&rcu_bh_ctrlblk))
                invoke_rcu_kthread();
+       local_irq_restore(flags);
 }
 
 /*
@@ -167,7 +180,7 @@ static void rcu_process_callbacks(struct rcu_ctrlblk *rcp)
                prefetch(next);
                debug_rcu_head_unqueue(list);
                local_bh_disable();
-               list->func(list);
+               __rcu_reclaim(list);
                local_bh_enable();
                list = next;
                RCU_TRACE(cb_count++);
@@ -207,20 +220,6 @@ static int rcu_kthread(void *arg)
        return 0;  /* Not reached, but needed to shut gcc up. */
 }
 
-/*
- * Wake up rcu_kthread() to process callbacks now eligible for invocation
- * or to boost readers.
- */
-static void invoke_rcu_kthread(void)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       have_rcu_kthread_work = 1;
-       wake_up(&rcu_kthread_wq);
-       local_irq_restore(flags);
-}
-
 /*
  * Wait for a grace period to elapse.  But it is illegal to invoke
  * synchronize_sched() from within an RCU read-side critical section.
index 3cb8e362e8838454c0467bc4f20b93b19fbda054..f259c676195fcab24fb36af68130519a931778e0 100644 (file)
@@ -100,23 +100,28 @@ struct rcu_preempt_ctrlblk {
        u8 completed;           /* Last grace period completed. */
                                /*  If all three are equal, RCU is idle. */
 #ifdef CONFIG_RCU_BOOST
-       s8 boosted_this_gp;     /* Has boosting already happened? */
        unsigned long boost_time; /* When to start boosting (jiffies) */
 #endif /* #ifdef CONFIG_RCU_BOOST */
 #ifdef CONFIG_RCU_TRACE
        unsigned long n_grace_periods;
 #ifdef CONFIG_RCU_BOOST
        unsigned long n_tasks_boosted;
+                               /* Total number of tasks boosted. */
        unsigned long n_exp_boosts;
+                               /* Number of tasks boosted for expedited GP. */
        unsigned long n_normal_boosts;
-       unsigned long n_normal_balk_blkd_tasks;
-       unsigned long n_normal_balk_gp_tasks;
-       unsigned long n_normal_balk_boost_tasks;
-       unsigned long n_normal_balk_boosted;
-       unsigned long n_normal_balk_notyet;
-       unsigned long n_normal_balk_nos;
-       unsigned long n_exp_balk_blkd_tasks;
-       unsigned long n_exp_balk_nos;
+                               /* Number of tasks boosted for normal GP. */
+       unsigned long n_balk_blkd_tasks;
+                               /* Refused to boost: no blocked tasks. */
+       unsigned long n_balk_exp_gp_tasks;
+                               /* Refused to boost: nothing blocking GP. */
+       unsigned long n_balk_boost_tasks;
+                               /* Refused to boost: already boosting. */
+       unsigned long n_balk_notyet;
+                               /* Refused to boost: not yet time. */
+       unsigned long n_balk_nos;
+                               /* Refused to boost: not sure why, though. */
+                               /*  This can happen due to race conditions. */
 #endif /* #ifdef CONFIG_RCU_BOOST */
 #endif /* #ifdef CONFIG_RCU_TRACE */
 };
@@ -201,7 +206,6 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t)
 
 #ifdef CONFIG_RCU_BOOST
 static void rcu_initiate_boost_trace(void);
-static void rcu_initiate_exp_boost_trace(void);
 #endif /* #ifdef CONFIG_RCU_BOOST */
 
 /*
@@ -219,41 +223,21 @@ static void show_tiny_preempt_stats(struct seq_file *m)
                   "N."[!rcu_preempt_ctrlblk.gp_tasks],
                   "E."[!rcu_preempt_ctrlblk.exp_tasks]);
 #ifdef CONFIG_RCU_BOOST
-       seq_printf(m, "             ttb=%c btg=",
-                  "B."[!rcu_preempt_ctrlblk.boost_tasks]);
-       switch (rcu_preempt_ctrlblk.boosted_this_gp) {
-       case -1:
-               seq_puts(m, "exp");
-               break;
-       case 0:
-               seq_puts(m, "no");
-               break;
-       case 1:
-               seq_puts(m, "begun");
-               break;
-       case 2:
-               seq_puts(m, "done");
-               break;
-       default:
-               seq_printf(m, "?%d?", rcu_preempt_ctrlblk.boosted_this_gp);
-       }
-       seq_printf(m, " ntb=%lu neb=%lu nnb=%lu j=%04x bt=%04x\n",
+       seq_printf(m, "%sttb=%c ntb=%lu neb=%lu nnb=%lu j=%04x bt=%04x\n",
+                  "             ",
+                  "B."[!rcu_preempt_ctrlblk.boost_tasks],
                   rcu_preempt_ctrlblk.n_tasks_boosted,
                   rcu_preempt_ctrlblk.n_exp_boosts,
                   rcu_preempt_ctrlblk.n_normal_boosts,
                   (int)(jiffies & 0xffff),
                   (int)(rcu_preempt_ctrlblk.boost_time & 0xffff));
-       seq_printf(m, "             %s: nt=%lu gt=%lu bt=%lu b=%lu ny=%lu nos=%lu\n",
-                  "normal balk",
-                  rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks,
-                  rcu_preempt_ctrlblk.n_normal_balk_gp_tasks,
-                  rcu_preempt_ctrlblk.n_normal_balk_boost_tasks,
-                  rcu_preempt_ctrlblk.n_normal_balk_boosted,
-                  rcu_preempt_ctrlblk.n_normal_balk_notyet,
-                  rcu_preempt_ctrlblk.n_normal_balk_nos);
-       seq_printf(m, "             exp balk: bt=%lu nos=%lu\n",
-                  rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks,
-                  rcu_preempt_ctrlblk.n_exp_balk_nos);
+       seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu ny=%lu nos=%lu\n",
+                  "             balk",
+                  rcu_preempt_ctrlblk.n_balk_blkd_tasks,
+                  rcu_preempt_ctrlblk.n_balk_exp_gp_tasks,
+                  rcu_preempt_ctrlblk.n_balk_boost_tasks,
+                  rcu_preempt_ctrlblk.n_balk_notyet,
+                  rcu_preempt_ctrlblk.n_balk_nos);
 #endif /* #ifdef CONFIG_RCU_BOOST */
 }
 
@@ -271,25 +255,59 @@ static int rcu_boost(void)
 {
        unsigned long flags;
        struct rt_mutex mtx;
-       struct list_head *np;
        struct task_struct *t;
+       struct list_head *tb;
 
-       if (rcu_preempt_ctrlblk.boost_tasks == NULL)
+       if (rcu_preempt_ctrlblk.boost_tasks == NULL &&
+           rcu_preempt_ctrlblk.exp_tasks == NULL)
                return 0;  /* Nothing to boost. */
+
        raw_local_irq_save(flags);
-       rcu_preempt_ctrlblk.boosted_this_gp++;
-       t = container_of(rcu_preempt_ctrlblk.boost_tasks, struct task_struct,
-                        rcu_node_entry);
-       np = rcu_next_node_entry(t);
+
+       /*
+        * Recheck with irqs disabled: all tasks in need of boosting
+        * might exit their RCU read-side critical sections on their own
+        * if we are preempted just before disabling irqs.
+        */
+       if (rcu_preempt_ctrlblk.boost_tasks == NULL &&
+           rcu_preempt_ctrlblk.exp_tasks == NULL) {
+               raw_local_irq_restore(flags);
+               return 0;
+       }
+
+       /*
+        * Preferentially boost tasks blocking expedited grace periods.
+        * This cannot starve the normal grace periods because a second
+        * expedited grace period must boost all blocked tasks, including
+        * those blocking the pre-existing normal grace period.
+        */
+       if (rcu_preempt_ctrlblk.exp_tasks != NULL) {
+               tb = rcu_preempt_ctrlblk.exp_tasks;
+               RCU_TRACE(rcu_preempt_ctrlblk.n_exp_boosts++);
+       } else {
+               tb = rcu_preempt_ctrlblk.boost_tasks;
+               RCU_TRACE(rcu_preempt_ctrlblk.n_normal_boosts++);
+       }
+       RCU_TRACE(rcu_preempt_ctrlblk.n_tasks_boosted++);
+
+       /*
+        * We boost task t by manufacturing an rt_mutex that appears to
+        * be held by task t.  We leave a pointer to that rt_mutex where
+        * task t can find it, and task t will release the mutex when it
+        * exits its outermost RCU read-side critical section.  Then
+        * simply acquiring this artificial rt_mutex will boost task
+        * t's priority.  (Thanks to tglx for suggesting this approach!)
+        */
+       t = container_of(tb, struct task_struct, rcu_node_entry);
        rt_mutex_init_proxy_locked(&mtx, t);
        t->rcu_boost_mutex = &mtx;
        t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BOOSTED;
        raw_local_irq_restore(flags);
        rt_mutex_lock(&mtx);
-       RCU_TRACE(rcu_preempt_ctrlblk.n_tasks_boosted++);
-       rcu_preempt_ctrlblk.boosted_this_gp++;
-       rt_mutex_unlock(&mtx);
-       return rcu_preempt_ctrlblk.boost_tasks != NULL;
+       rt_mutex_unlock(&mtx);  /* Keep lockdep happy. */
+
+       return rcu_preempt_ctrlblk.boost_tasks != NULL ||
+              rcu_preempt_ctrlblk.exp_tasks != NULL;
 }
 
 /*
@@ -304,42 +322,25 @@ static int rcu_boost(void)
  */
 static int rcu_initiate_boost(void)
 {
-       if (!rcu_preempt_blocked_readers_cgp()) {
-               RCU_TRACE(rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks++);
+       if (!rcu_preempt_blocked_readers_cgp() &&
+           rcu_preempt_ctrlblk.exp_tasks == NULL) {
+               RCU_TRACE(rcu_preempt_ctrlblk.n_balk_exp_gp_tasks++);
                return 0;
        }
-       if (rcu_preempt_ctrlblk.gp_tasks != NULL &&
-           rcu_preempt_ctrlblk.boost_tasks == NULL &&
-           rcu_preempt_ctrlblk.boosted_this_gp == 0 &&
-           ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time)) {
-               rcu_preempt_ctrlblk.boost_tasks = rcu_preempt_ctrlblk.gp_tasks;
+       if (rcu_preempt_ctrlblk.exp_tasks != NULL ||
+           (rcu_preempt_ctrlblk.gp_tasks != NULL &&
+            rcu_preempt_ctrlblk.boost_tasks == NULL &&
+            ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time))) {
+               if (rcu_preempt_ctrlblk.exp_tasks == NULL)
+                       rcu_preempt_ctrlblk.boost_tasks =
+                               rcu_preempt_ctrlblk.gp_tasks;
                invoke_rcu_kthread();
-               RCU_TRACE(rcu_preempt_ctrlblk.n_normal_boosts++);
        } else
                RCU_TRACE(rcu_initiate_boost_trace());
        return 1;
 }
 
-/*
- * Initiate boosting for an expedited grace period.
- */
-static void rcu_initiate_expedited_boost(void)
-{
-       unsigned long flags;
-
-       raw_local_irq_save(flags);
-       if (!list_empty(&rcu_preempt_ctrlblk.blkd_tasks)) {
-               rcu_preempt_ctrlblk.boost_tasks =
-                       rcu_preempt_ctrlblk.blkd_tasks.next;
-               rcu_preempt_ctrlblk.boosted_this_gp = -1;
-               invoke_rcu_kthread();
-               RCU_TRACE(rcu_preempt_ctrlblk.n_exp_boosts++);
-       } else
-               RCU_TRACE(rcu_initiate_exp_boost_trace());
-       raw_local_irq_restore(flags);
-}
-
-#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000);
+#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)
 
 /*
  * Do priority-boost accounting for the start of a new grace period.
@@ -347,8 +348,6 @@ static void rcu_initiate_expedited_boost(void)
 static void rcu_preempt_boost_start_gp(void)
 {
        rcu_preempt_ctrlblk.boost_time = jiffies + RCU_BOOST_DELAY_JIFFIES;
-       if (rcu_preempt_ctrlblk.boosted_this_gp > 0)
-               rcu_preempt_ctrlblk.boosted_this_gp = 0;
 }
 
 #else /* #ifdef CONFIG_RCU_BOOST */
@@ -371,13 +370,6 @@ static int rcu_initiate_boost(void)
        return rcu_preempt_blocked_readers_cgp();
 }
 
-/*
- * If there is no RCU priority boosting, we don't initiate expedited boosting.
- */
-static void rcu_initiate_expedited_boost(void)
-{
-}
-
 /*
  * If there is no RCU priority boosting, nothing to do at grace-period start.
  */
@@ -418,7 +410,7 @@ static void rcu_preempt_cpu_qs(void)
        if (!rcu_preempt_gp_in_progress())
                return;
        /*
-        * Check up on boosting.  If there are no readers blocking the
+        * Check up on boosting.  If there are readers blocking the
         * current grace period, leave.
         */
        if (rcu_initiate_boost())
@@ -578,7 +570,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
                empty = !rcu_preempt_blocked_readers_cgp();
                empty_exp = rcu_preempt_ctrlblk.exp_tasks == NULL;
                np = rcu_next_node_entry(t);
-               list_del(&t->rcu_node_entry);
+               list_del_init(&t->rcu_node_entry);
                if (&t->rcu_node_entry == rcu_preempt_ctrlblk.gp_tasks)
                        rcu_preempt_ctrlblk.gp_tasks = np;
                if (&t->rcu_node_entry == rcu_preempt_ctrlblk.exp_tasks)
@@ -587,7 +579,6 @@ static void rcu_read_unlock_special(struct task_struct *t)
                if (&t->rcu_node_entry == rcu_preempt_ctrlblk.boost_tasks)
                        rcu_preempt_ctrlblk.boost_tasks = np;
 #endif /* #ifdef CONFIG_RCU_BOOST */
-               INIT_LIST_HEAD(&t->rcu_node_entry);
 
                /*
                 * If this was the last task on the current list, and if
@@ -812,13 +803,16 @@ void synchronize_rcu_expedited(void)
        rpcp->exp_tasks = rpcp->blkd_tasks.next;
        if (rpcp->exp_tasks == &rpcp->blkd_tasks)
                rpcp->exp_tasks = NULL;
-       local_irq_restore(flags);
 
        /* Wait for tail of ->blkd_tasks list to drain. */
-       if (rcu_preempted_readers_exp())
-               rcu_initiate_expedited_boost();
+       if (!rcu_preempted_readers_exp())
+               local_irq_restore(flags);
+       else {
+               rcu_initiate_boost();
+               local_irq_restore(flags);
                wait_event(sync_rcu_preempt_exp_wq,
                           !rcu_preempted_readers_exp());
+       }
 
        /* Clean up and exit. */
        barrier(); /* ensure expedited GP seen before counter increment. */
@@ -931,24 +925,17 @@ void __init rcu_scheduler_starting(void)
 
 static void rcu_initiate_boost_trace(void)
 {
-       if (rcu_preempt_ctrlblk.gp_tasks == NULL)
-               rcu_preempt_ctrlblk.n_normal_balk_gp_tasks++;
+       if (list_empty(&rcu_preempt_ctrlblk.blkd_tasks))
+               rcu_preempt_ctrlblk.n_balk_blkd_tasks++;
+       else if (rcu_preempt_ctrlblk.gp_tasks == NULL &&
+                rcu_preempt_ctrlblk.exp_tasks == NULL)
+               rcu_preempt_ctrlblk.n_balk_exp_gp_tasks++;
        else if (rcu_preempt_ctrlblk.boost_tasks != NULL)
-               rcu_preempt_ctrlblk.n_normal_balk_boost_tasks++;
-       else if (rcu_preempt_ctrlblk.boosted_this_gp != 0)
-               rcu_preempt_ctrlblk.n_normal_balk_boosted++;
+               rcu_preempt_ctrlblk.n_balk_boost_tasks++;
        else if (!ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time))
-               rcu_preempt_ctrlblk.n_normal_balk_notyet++;
-       else
-               rcu_preempt_ctrlblk.n_normal_balk_nos++;
-}
-
-static void rcu_initiate_exp_boost_trace(void)
-{
-       if (list_empty(&rcu_preempt_ctrlblk.blkd_tasks))
-               rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks++;
+               rcu_preempt_ctrlblk.n_balk_notyet++;
        else
-               rcu_preempt_ctrlblk.n_exp_balk_nos++;
+               rcu_preempt_ctrlblk.n_balk_nos++;
 }
 
 #endif /* #ifdef CONFIG_RCU_BOOST */
index c224da41890cd3382b060ffb1567d3827f71e21c..2e138db03382adfb86da06b45d619fc1d8a6dd25 100644 (file)
@@ -131,7 +131,7 @@ struct rcu_torture {
 
 static LIST_HEAD(rcu_torture_freelist);
 static struct rcu_torture __rcu *rcu_torture_current;
-static long rcu_torture_current_version;
+static unsigned long rcu_torture_current_version;
 static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
 static DEFINE_SPINLOCK(rcu_torture_lock);
 static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
@@ -146,8 +146,6 @@ static atomic_t n_rcu_torture_mberror;
 static atomic_t n_rcu_torture_error;
 static long n_rcu_torture_boost_ktrerror;
 static long n_rcu_torture_boost_rterror;
-static long n_rcu_torture_boost_allocerror;
-static long n_rcu_torture_boost_afferror;
 static long n_rcu_torture_boost_failure;
 static long n_rcu_torture_boosts;
 static long n_rcu_torture_timers;
@@ -163,11 +161,11 @@ static int stutter_pause_test;
 #endif
 int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
 
-#ifdef CONFIG_RCU_BOOST
+#if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU)
 #define rcu_can_boost() 1
-#else /* #ifdef CONFIG_RCU_BOOST */
+#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
 #define rcu_can_boost() 0
-#endif /* #else #ifdef CONFIG_RCU_BOOST */
+#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
 
 static unsigned long boost_starttime;  /* jiffies of next boost test start. */
 DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
@@ -751,6 +749,7 @@ static int rcu_torture_boost(void *arg)
                n_rcu_torture_boost_rterror++;
        }
 
+       init_rcu_head_on_stack(&rbi.rcu);
        /* Each pass through the following loop does one boost-test cycle. */
        do {
                /* Wait for the next test interval. */
@@ -810,6 +809,7 @@ checkwait:  rcu_stutter_wait("rcu_torture_boost");
 
        /* Clean up and exit. */
        VERBOSE_PRINTK_STRING("rcu_torture_boost task stopping");
+       destroy_rcu_head_on_stack(&rbi.rcu);
        rcutorture_shutdown_absorb("rcu_torture_boost");
        while (!kthread_should_stop() || rbi.inflight)
                schedule_timeout_uninterruptible(1);
@@ -886,7 +886,7 @@ rcu_torture_writer(void *arg)
                        old_rp->rtort_pipe_count++;
                        cur_ops->deferred_free(old_rp);
                }
-               rcu_torture_current_version++;
+               rcutorture_record_progress(++rcu_torture_current_version);
                oldbatch = cur_ops->completed();
                rcu_stutter_wait("rcu_torture_writer");
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
@@ -1066,8 +1066,8 @@ rcu_torture_printk(char *page)
        }
        cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
        cnt += sprintf(&page[cnt],
-                      "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d "
-                      "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld "
+                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
+                      "rtmbe: %d rtbke: %ld rtbre: %ld "
                       "rtbf: %ld rtb: %ld nt: %ld",
                       rcu_torture_current,
                       rcu_torture_current_version,
@@ -1078,16 +1078,12 @@ rcu_torture_printk(char *page)
                       atomic_read(&n_rcu_torture_mberror),
                       n_rcu_torture_boost_ktrerror,
                       n_rcu_torture_boost_rterror,
-                      n_rcu_torture_boost_allocerror,
-                      n_rcu_torture_boost_afferror,
                       n_rcu_torture_boost_failure,
                       n_rcu_torture_boosts,
                       n_rcu_torture_timers);
        if (atomic_read(&n_rcu_torture_mberror) != 0 ||
            n_rcu_torture_boost_ktrerror != 0 ||
            n_rcu_torture_boost_rterror != 0 ||
-           n_rcu_torture_boost_allocerror != 0 ||
-           n_rcu_torture_boost_afferror != 0 ||
            n_rcu_torture_boost_failure != 0)
                cnt += sprintf(&page[cnt], " !!!");
        cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
@@ -1331,6 +1327,7 @@ rcu_torture_cleanup(void)
        int i;
 
        mutex_lock(&fullstop_mutex);
+       rcutorture_record_test_transition();
        if (fullstop == FULLSTOP_SHUTDOWN) {
                printk(KERN_WARNING /* but going down anyway, so... */
                       "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
@@ -1486,8 +1483,6 @@ rcu_torture_init(void)
        atomic_set(&n_rcu_torture_error, 0);
        n_rcu_torture_boost_ktrerror = 0;
        n_rcu_torture_boost_rterror = 0;
-       n_rcu_torture_boost_allocerror = 0;
-       n_rcu_torture_boost_afferror = 0;
        n_rcu_torture_boost_failure = 0;
        n_rcu_torture_boosts = 0;
        for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
@@ -1624,6 +1619,7 @@ rcu_torture_init(void)
                }
        }
        register_reboot_notifier(&rcutorture_shutdown_nb);
+       rcutorture_record_test_transition();
        mutex_unlock(&fullstop_mutex);
        return 0;
 
index dd4aea806f8ef63ba882af3a47d5981b366d4dc7..e486f7c3ffb8b239a31eddb37f9ed0251629bdeb 100644 (file)
@@ -47,6 +47,8 @@
 #include <linux/mutex.h>
 #include <linux/time.h>
 #include <linux/kernel_stat.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
 
 #include "rcutree.h"
 
@@ -79,9 +81,40 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
+static struct rcu_state *rcu_state;
+
 int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 
+/*
+ * Control variables for per-CPU and per-rcu_node kthreads.  These
+ * handle all flavors of RCU.
+ */
+static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
+DEFINE_PER_CPU(int, rcu_cpu_kthread_cpu);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
+static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq);
+DEFINE_PER_CPU(char, rcu_cpu_has_work);
+static char rcu_kthreads_spawnable;
+
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu);
+static void invoke_rcu_cpu_kthread(void);
+
+#define RCU_KTHREAD_PRIO 1     /* RT priority for per-CPU kthreads. */
+
+/*
+ * Track the rcutorture test sequence number and the update version
+ * number within a given test.  The rcutorture_testseq is incremented
+ * on every rcutorture module load and unload, so has an odd value
+ * when a test is running.  The rcutorture_vernum is set to zero
+ * when rcutorture starts and is incremented on each rcutorture update.
+ * These variables enable correlating rcutorture output with the
+ * RCU tracing information.
+ */
+unsigned long rcutorture_testseq;
+unsigned long rcutorture_vernum;
+
 /*
  * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
  * permit this function to be invoked without holding the root rcu_node
@@ -124,6 +157,7 @@ void rcu_note_context_switch(int cpu)
        rcu_sched_qs(cpu);
        rcu_preempt_note_context_switch(cpu);
 }
+EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 
 #ifdef CONFIG_NO_HZ
 DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
@@ -140,10 +174,8 @@ module_param(blimit, int, 0);
 module_param(qhimark, int, 0);
 module_param(qlowmark, int, 0);
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-int rcu_cpu_stall_suppress __read_mostly = RCU_CPU_STALL_SUPPRESS_INIT;
+int rcu_cpu_stall_suppress __read_mostly;
 module_param(rcu_cpu_stall_suppress, int, 0644);
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 static void force_quiescent_state(struct rcu_state *rsp, int relaxed);
 static int rcu_pending(int cpu);
@@ -175,6 +207,31 @@ void rcu_bh_force_quiescent_state(void)
 }
 EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
 
+/*
+ * Record the number of times rcutorture tests have been initiated and
+ * terminated.  This information allows the debugfs tracing stats to be
+ * correlated to the rcutorture messages, even when the rcutorture module
+ * is being repeatedly loaded and unloaded.  In other words, we cannot
+ * store this state in rcutorture itself.
+ */
+void rcutorture_record_test_transition(void)
+{
+       rcutorture_testseq++;
+       rcutorture_vernum = 0;
+}
+EXPORT_SYMBOL_GPL(rcutorture_record_test_transition);
+
+/*
+ * Record the number of writer passes through the current rcutorture test.
+ * This is also used to correlate debugfs tracing stats with the rcutorture
+ * messages.
+ */
+void rcutorture_record_progress(unsigned long vernum)
+{
+       rcutorture_vernum++;
+}
+EXPORT_SYMBOL_GPL(rcutorture_record_progress);
+
 /*
  * Force a quiescent state for RCU-sched.
  */
@@ -234,8 +291,8 @@ static int rcu_implicit_offline_qs(struct rcu_data *rdp)
                return 1;
        }
 
-       /* If preemptable RCU, no point in sending reschedule IPI. */
-       if (rdp->preemptable)
+       /* If preemptible RCU, no point in sending reschedule IPI. */
+       if (rdp->preemptible)
                return 0;
 
        /* The CPU is online, so send it a reschedule IPI. */
@@ -450,8 +507,6 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
 
 #endif /* #else #ifdef CONFIG_NO_HZ */
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-
 int rcu_cpu_stall_suppress __read_mostly;
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
@@ -537,21 +592,24 @@ static void print_cpu_stall(struct rcu_state *rsp)
 
 static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       long delta;
+       unsigned long j;
+       unsigned long js;
        struct rcu_node *rnp;
 
        if (rcu_cpu_stall_suppress)
                return;
-       delta = jiffies - ACCESS_ONCE(rsp->jiffies_stall);
+       j = ACCESS_ONCE(jiffies);
+       js = ACCESS_ONCE(rsp->jiffies_stall);
        rnp = rdp->mynode;
-       if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && delta >= 0) {
+       if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) {
 
                /* We haven't checked in, so go dump stack. */
                print_cpu_stall(rsp);
 
-       } else if (rcu_gp_in_progress(rsp) && delta >= RCU_STALL_RAT_DELAY) {
+       } else if (rcu_gp_in_progress(rsp) &&
+                  ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY)) {
 
-               /* They had two time units to dump stack, so complain. */
+               /* They had a few time units to dump stack, so complain. */
                print_other_cpu_stall(rsp);
        }
 }
@@ -587,26 +645,6 @@ static void __init check_cpu_stall_init(void)
        atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
 }
 
-#else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-
-static void record_gp_stall_check_time(struct rcu_state *rsp)
-{
-}
-
-static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
-{
-}
-
-void rcu_cpu_stall_reset(void)
-{
-}
-
-static void __init check_cpu_stall_init(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-
 /*
  * Update CPU-local rcu_data state to record the newly noticed grace period.
  * This is used both when we started the grace period and when we notice
@@ -809,6 +847,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
                rnp->completed = rsp->completed;
                rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */
                rcu_start_gp_per_cpu(rsp, rnp, rdp);
+               rcu_preempt_boost_start_gp(rnp);
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
@@ -844,6 +883,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
                rnp->completed = rsp->completed;
                if (rnp == rdp->mynode)
                        rcu_start_gp_per_cpu(rsp, rnp, rdp);
+               rcu_preempt_boost_start_gp(rnp);
                raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
        }
 
@@ -864,7 +904,12 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
 static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
        __releases(rcu_get_root(rsp)->lock)
 {
+       unsigned long gp_duration;
+
        WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
+       gp_duration = jiffies - rsp->gp_start;
+       if (gp_duration > rsp->gp_max)
+               rsp->gp_max = gp_duration;
        rsp->completed = rsp->gpnum;
        rsp->signaled = RCU_GP_IDLE;
        rcu_start_gp(rsp, flags);  /* releases root node's rnp->lock. */
@@ -894,7 +939,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                        return;
                }
                rnp->qsmask &= ~mask;
-               if (rnp->qsmask != 0 || rcu_preempted_readers(rnp)) {
+               if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
 
                        /* Other bits still set at this level, so done. */
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
@@ -1037,6 +1082,8 @@ static void rcu_send_cbs_to_online(struct rcu_state *rsp)
 /*
  * Remove the outgoing CPU from the bitmasks in the rcu_node hierarchy
  * and move all callbacks from the outgoing CPU to the current one.
+ * There can only be one CPU hotplug operation at a time, so no other
+ * CPU can be attempting to update rcu_cpu_kthread_task.
  */
 static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
 {
@@ -1045,6 +1092,14 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
        int need_report = 0;
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp;
+       struct task_struct *t;
+
+       /* Stop the CPU's kthread. */
+       t = per_cpu(rcu_cpu_kthread_task, cpu);
+       if (t != NULL) {
+               per_cpu(rcu_cpu_kthread_task, cpu) = NULL;
+               kthread_stop(t);
+       }
 
        /* Exclude any attempts to start a new grace period. */
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
@@ -1082,6 +1137,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        if (need_report & RCU_OFL_TASKS_EXP_GP)
                rcu_report_exp_rnp(rsp, rnp);
+       rcu_node_kthread_setaffinity(rnp, -1);
 }
 
 /*
@@ -1143,7 +1199,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
                next = list->next;
                prefetch(next);
                debug_rcu_head_unqueue(list);
-               list->func(list);
+               __rcu_reclaim(list);
                list = next;
                if (++count >= rdp->blimit)
                        break;
@@ -1179,7 +1235,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 
        /* Re-raise the RCU softirq if there are callbacks remaining. */
        if (cpu_has_callbacks_ready_to_invoke(rdp))
-               raise_softirq(RCU_SOFTIRQ);
+               invoke_rcu_cpu_kthread();
 }
 
 /*
@@ -1225,7 +1281,7 @@ void rcu_check_callbacks(int cpu, int user)
        }
        rcu_preempt_check_callbacks(cpu);
        if (rcu_pending(cpu))
-               raise_softirq(RCU_SOFTIRQ);
+               invoke_rcu_cpu_kthread();
 }
 
 #ifdef CONFIG_SMP
@@ -1233,6 +1289,8 @@ void rcu_check_callbacks(int cpu, int user)
 /*
  * Scan the leaf rcu_node structures, processing dyntick state for any that
  * have not yet encountered a quiescent state, using the function specified.
+ * Also initiate boosting for any threads blocked on the root rcu_node.
+ *
  * The caller must have suppressed start of new grace periods.
  */
 static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
@@ -1251,7 +1309,7 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
                        return;
                }
                if (rnp->qsmask == 0) {
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       rcu_initiate_boost(rnp, flags); /* releases rnp->lock */
                        continue;
                }
                cpu = rnp->grplo;
@@ -1269,6 +1327,11 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
                }
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        }
+       rnp = rcu_get_root(rsp);
+       if (rnp->qsmask == 0) {
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
+       }
 }
 
 /*
@@ -1389,7 +1452,7 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
 /*
  * Do softirq processing for the current CPU.
  */
-static void rcu_process_callbacks(struct softirq_action *unused)
+static void rcu_process_callbacks(void)
 {
        /*
         * Memory references from any prior RCU read-side critical sections
@@ -1414,6 +1477,347 @@ static void rcu_process_callbacks(struct softirq_action *unused)
        rcu_needs_cpu_flush();
 }
 
+/*
+ * Wake up the current CPU's kthread.  This replaces raise_softirq()
+ * in earlier versions of RCU.  Note that because we are running on
+ * the current CPU with interrupts disabled, the rcu_cpu_kthread_task
+ * cannot disappear out from under us.
+ */
+static void invoke_rcu_cpu_kthread(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __this_cpu_write(rcu_cpu_has_work, 1);
+       if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) {
+               local_irq_restore(flags);
+               return;
+       }
+       wake_up(&__get_cpu_var(rcu_cpu_wq));
+       local_irq_restore(flags);
+}
+
+/*
+ * Wake up the specified per-rcu_node-structure kthread.
+ * Because the per-rcu_node kthreads are immortal, we don't need
+ * to do anything to keep them alive.
+ */
+static void invoke_rcu_node_kthread(struct rcu_node *rnp)
+{
+       struct task_struct *t;
+
+       t = rnp->node_kthread_task;
+       if (t != NULL)
+               wake_up_process(t);
+}
+
+/*
+ * Set the specified CPU's kthread to run RT or not, as specified by
+ * the to_rt argument.  The CPU-hotplug locks are held, so the task
+ * is not going away.
+ */
+static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
+{
+       int policy;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       t = per_cpu(rcu_cpu_kthread_task, cpu);
+       if (t == NULL)
+               return;
+       if (to_rt) {
+               policy = SCHED_FIFO;
+               sp.sched_priority = RCU_KTHREAD_PRIO;
+       } else {
+               policy = SCHED_NORMAL;
+               sp.sched_priority = 0;
+       }
+       sched_setscheduler_nocheck(t, policy, &sp);
+}
+
+/*
+ * Timer handler to initiate the waking up of per-CPU kthreads that
+ * have yielded the CPU due to excess numbers of RCU callbacks.
+ * We wake up the per-rcu_node kthread, which in turn will wake up
+ * the booster kthread.
+ */
+static void rcu_cpu_kthread_timer(unsigned long arg)
+{
+       unsigned long flags;
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg);
+       struct rcu_node *rnp = rdp->mynode;
+
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       rnp->wakemask |= rdp->grpmask;
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       invoke_rcu_node_kthread(rnp);
+}
+
+/*
+ * Drop to non-real-time priority and yield, but only after posting a
+ * timer that will cause us to regain our real-time priority if we
+ * remain preempted.  Either way, we restore our real-time priority
+ * before returning.
+ */
+static void rcu_yield(void (*f)(unsigned long), unsigned long arg)
+{
+       struct sched_param sp;
+       struct timer_list yield_timer;
+
+       setup_timer_on_stack(&yield_timer, f, arg);
+       mod_timer(&yield_timer, jiffies + 2);
+       sp.sched_priority = 0;
+       sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp);
+       set_user_nice(current, 19);
+       schedule();
+       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+       del_timer(&yield_timer);
+}
+
+/*
+ * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU.
+ * This can happen while the corresponding CPU is either coming online
+ * or going offline.  We cannot wait until the CPU is fully online
+ * before starting the kthread, because the various notifier functions
+ * can wait for RCU grace periods.  So we park rcu_cpu_kthread() until
+ * the corresponding CPU is online.
+ *
+ * Return 1 if the kthread needs to stop, 0 otherwise.
+ *
+ * Caller must disable bh.  This function can momentarily enable it.
+ */
+static int rcu_cpu_kthread_should_stop(int cpu)
+{
+       while (cpu_is_offline(cpu) ||
+              !cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)) ||
+              smp_processor_id() != cpu) {
+               if (kthread_should_stop())
+                       return 1;
+               per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
+               per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id();
+               local_bh_enable();
+               schedule_timeout_uninterruptible(1);
+               if (!cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)))
+                       set_cpus_allowed_ptr(current, cpumask_of(cpu));
+               local_bh_disable();
+       }
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
+       return 0;
+}
+
+/*
+ * Per-CPU kernel thread that invokes RCU callbacks.  This replaces the
+ * earlier RCU softirq.
+ */
+static int rcu_cpu_kthread(void *arg)
+{
+       int cpu = (int)(long)arg;
+       unsigned long flags;
+       int spincnt = 0;
+       unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu);
+       wait_queue_head_t *wqp = &per_cpu(rcu_cpu_wq, cpu);
+       char work;
+       char *workp = &per_cpu(rcu_cpu_has_work, cpu);
+
+       for (;;) {
+               *statusp = RCU_KTHREAD_WAITING;
+               wait_event_interruptible(*wqp,
+                                        *workp != 0 || kthread_should_stop());
+               local_bh_disable();
+               if (rcu_cpu_kthread_should_stop(cpu)) {
+                       local_bh_enable();
+                       break;
+               }
+               *statusp = RCU_KTHREAD_RUNNING;
+               per_cpu(rcu_cpu_kthread_loops, cpu)++;
+               local_irq_save(flags);
+               work = *workp;
+               *workp = 0;
+               local_irq_restore(flags);
+               if (work)
+                       rcu_process_callbacks();
+               local_bh_enable();
+               if (*workp != 0)
+                       spincnt++;
+               else
+                       spincnt = 0;
+               if (spincnt > 10) {
+                       *statusp = RCU_KTHREAD_YIELDING;
+                       rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu);
+                       spincnt = 0;
+               }
+       }
+       *statusp = RCU_KTHREAD_STOPPED;
+       return 0;
+}
+
+/*
+ * Spawn a per-CPU kthread, setting up affinity and priority.
+ * Because the CPU hotplug lock is held, no other CPU will be attempting
+ * to manipulate rcu_cpu_kthread_task.  There might be another CPU
+ * attempting to access it during boot, but the locking in kthread_bind()
+ * will enforce sufficient ordering.
+ */
+static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
+{
+       struct sched_param sp;
+       struct task_struct *t;
+
+       if (!rcu_kthreads_spawnable ||
+           per_cpu(rcu_cpu_kthread_task, cpu) != NULL)
+               return 0;
+       t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu);
+       if (IS_ERR(t))
+               return PTR_ERR(t);
+       kthread_bind(t, cpu);
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
+       WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL);
+       per_cpu(rcu_cpu_kthread_task, cpu) = t;
+       wake_up_process(t);
+       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       return 0;
+}
+
+/*
+ * Per-rcu_node kthread, which is in charge of waking up the per-CPU
+ * kthreads when needed.  We ignore requests to wake up kthreads
+ * for offline CPUs, which is OK because force_quiescent_state()
+ * takes care of this case.
+ */
+static int rcu_node_kthread(void *arg)
+{
+       int cpu;
+       unsigned long flags;
+       unsigned long mask;
+       struct rcu_node *rnp = (struct rcu_node *)arg;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       for (;;) {
+               rnp->node_kthread_status = RCU_KTHREAD_WAITING;
+               wait_event_interruptible(rnp->node_wq, rnp->wakemask != 0);
+               rnp->node_kthread_status = RCU_KTHREAD_RUNNING;
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               mask = rnp->wakemask;
+               rnp->wakemask = 0;
+               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
+               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) {
+                       if ((mask & 0x1) == 0)
+                               continue;
+                       preempt_disable();
+                       t = per_cpu(rcu_cpu_kthread_task, cpu);
+                       if (!cpu_online(cpu) || t == NULL) {
+                               preempt_enable();
+                               continue;
+                       }
+                       per_cpu(rcu_cpu_has_work, cpu) = 1;
+                       sp.sched_priority = RCU_KTHREAD_PRIO;
+                       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+                       preempt_enable();
+               }
+       }
+       /* NOTREACHED */
+       rnp->node_kthread_status = RCU_KTHREAD_STOPPED;
+       return 0;
+}
+
+/*
+ * Set the per-rcu_node kthread's affinity to cover all CPUs that are
+ * served by the rcu_node in question.  The CPU hotplug lock is still
+ * held, so the value of rnp->qsmaskinit will be stable.
+ *
+ * We don't include outgoingcpu in the affinity set, use -1 if there is
+ * no outgoing CPU.  If there are no CPUs left in the affinity set,
+ * this function allows the kthread to execute on any CPU.
+ */
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
+{
+       cpumask_var_t cm;
+       int cpu;
+       unsigned long mask = rnp->qsmaskinit;
+
+       if (rnp->node_kthread_task == NULL)
+               return;
+       if (!alloc_cpumask_var(&cm, GFP_KERNEL))
+               return;
+       cpumask_clear(cm);
+       for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1)
+               if ((mask & 0x1) && cpu != outgoingcpu)
+                       cpumask_set_cpu(cpu, cm);
+       if (cpumask_weight(cm) == 0) {
+               cpumask_setall(cm);
+               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++)
+                       cpumask_clear_cpu(cpu, cm);
+               WARN_ON_ONCE(cpumask_weight(cm) == 0);
+       }
+       set_cpus_allowed_ptr(rnp->node_kthread_task, cm);
+       rcu_boost_kthread_setaffinity(rnp, cm);
+       free_cpumask_var(cm);
+}
+
+/*
+ * Spawn a per-rcu_node kthread, setting priority and affinity.
+ * Called during boot before online/offline can happen, or, if
+ * during runtime, with the main CPU-hotplug locks held.  So only
+ * one of these can be executing at a time.
+ */
+static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp,
+                                               struct rcu_node *rnp)
+{
+       unsigned long flags;
+       int rnp_index = rnp - &rsp->node[0];
+       struct sched_param sp;
+       struct task_struct *t;
+
+       if (!rcu_kthreads_spawnable ||
+           rnp->qsmaskinit == 0)
+               return 0;
+       if (rnp->node_kthread_task == NULL) {
+               t = kthread_create(rcu_node_kthread, (void *)rnp,
+                                  "rcun%d", rnp_index);
+               if (IS_ERR(t))
+                       return PTR_ERR(t);
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               rnp->node_kthread_task = t;
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               wake_up_process(t);
+               sp.sched_priority = 99;
+               sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       }
+       return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index);
+}
+
+/*
+ * Spawn all kthreads -- called as soon as the scheduler is running.
+ */
+static int __init rcu_spawn_kthreads(void)
+{
+       int cpu;
+       struct rcu_node *rnp;
+
+       rcu_kthreads_spawnable = 1;
+       for_each_possible_cpu(cpu) {
+               init_waitqueue_head(&per_cpu(rcu_cpu_wq, cpu));
+               per_cpu(rcu_cpu_has_work, cpu) = 0;
+               if (cpu_online(cpu))
+                       (void)rcu_spawn_one_cpu_kthread(cpu);
+       }
+       rnp = rcu_get_root(rcu_state);
+       init_waitqueue_head(&rnp->node_wq);
+       rcu_init_boost_waitqueue(rnp);
+       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       if (NUM_RCU_NODES > 1)
+               rcu_for_each_leaf_node(rcu_state, rnp) {
+                       init_waitqueue_head(&rnp->node_wq);
+                       rcu_init_boost_waitqueue(rnp);
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+               }
+       return 0;
+}
+early_initcall(rcu_spawn_kthreads);
+
 static void
 __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
           struct rcu_state *rsp)
@@ -1439,6 +1843,13 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        /* Add the callback to our list. */
        *rdp->nxttail[RCU_NEXT_TAIL] = head;
        rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
+       rdp->qlen++;
+
+       /* If interrupts were disabled, don't dive into RCU core. */
+       if (irqs_disabled_flags(flags)) {
+               local_irq_restore(flags);
+               return;
+       }
 
        /*
         * Force the grace period if too many callbacks or too long waiting.
@@ -1447,7 +1858,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
         * invoking force_quiescent_state() if the newly enqueued callback
         * is the only one waiting for a grace period to complete.
         */
-       if (unlikely(++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
+       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
 
                /* Are we ignoring a completed grace period? */
                rcu_process_gp_end(rsp, rdp);
@@ -1583,7 +1994,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
                 * or RCU-bh, force a local reschedule.
                 */
                rdp->n_rp_qs_pending++;
-               if (!rdp->preemptable &&
+               if (!rdp->preemptible &&
                    ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1,
                                 jiffies))
                        set_need_resched();
@@ -1760,7 +2171,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
  * that this CPU cannot possibly have any RCU callbacks in flight yet.
  */
 static void __cpuinit
-rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
+rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 {
        unsigned long flags;
        unsigned long mask;
@@ -1772,7 +2183,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
        rdp->passed_quiesc = 0;  /* We could be racing with new GP, */
        rdp->qs_pending = 1;     /*  so set up to respond to current GP. */
        rdp->beenonline = 1;     /* We have now been online. */
-       rdp->preemptable = preemptable;
+       rdp->preemptible = preemptible;
        rdp->qlen_last_fqs_check = 0;
        rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
@@ -1813,6 +2224,19 @@ static void __cpuinit rcu_online_cpu(int cpu)
        rcu_preempt_init_percpu_data(cpu);
 }
 
+static void __cpuinit rcu_online_kthreads(int cpu)
+{
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
+       struct rcu_node *rnp = rdp->mynode;
+
+       /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
+       if (rcu_kthreads_spawnable) {
+               (void)rcu_spawn_one_cpu_kthread(cpu);
+               if (rnp->node_kthread_task == NULL)
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       }
+}
+
 /*
  * Handle CPU online/offline notification events.
  */
@@ -1820,11 +2244,23 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                                    unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
+       struct rcu_node *rnp = rdp->mynode;
 
        switch (action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
                rcu_online_cpu(cpu);
+               rcu_online_kthreads(cpu);
+               break;
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+               rcu_node_kthread_setaffinity(rnp, -1);
+               rcu_cpu_kthread_setrt(cpu, 1);
+               break;
+       case CPU_DOWN_PREPARE:
+               rcu_node_kthread_setaffinity(rnp, cpu);
+               rcu_cpu_kthread_setrt(cpu, 0);
                break;
        case CPU_DYING:
        case CPU_DYING_FROZEN:
@@ -1943,10 +2379,7 @@ static void __init rcu_init_one(struct rcu_state *rsp,
                                              j / rsp->levelspread[i - 1];
                        }
                        rnp->level = i;
-                       INIT_LIST_HEAD(&rnp->blocked_tasks[0]);
-                       INIT_LIST_HEAD(&rnp->blocked_tasks[1]);
-                       INIT_LIST_HEAD(&rnp->blocked_tasks[2]);
-                       INIT_LIST_HEAD(&rnp->blocked_tasks[3]);
+                       INIT_LIST_HEAD(&rnp->blkd_tasks);
                }
        }
 
@@ -1968,7 +2401,6 @@ void __init rcu_init(void)
        rcu_init_one(&rcu_sched_state, &rcu_sched_data);
        rcu_init_one(&rcu_bh_state, &rcu_bh_data);
        __rcu_init_preempt();
-       open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
        /*
         * We don't need protection against CPU-hotplug here because
index e8f057e44e3ee00466e840593983ca5062302545..257664815d5d9cdfd645d08f6bd2e873e10a2cff 100644 (file)
@@ -91,6 +91,14 @@ struct rcu_dynticks {
                                /*  remains even for nmi from irq handler. */
 };
 
+/* RCU's kthread states for tracing. */
+#define RCU_KTHREAD_STOPPED  0
+#define RCU_KTHREAD_RUNNING  1
+#define RCU_KTHREAD_WAITING  2
+#define RCU_KTHREAD_OFFCPU   3
+#define RCU_KTHREAD_YIELDING 4
+#define RCU_KTHREAD_MAX      4
+
 /*
  * Definition for node within the RCU grace-period-detection hierarchy.
  */
@@ -109,10 +117,11 @@ struct rcu_node {
                                /*  an rcu_data structure, otherwise, each */
                                /*  bit corresponds to a child rcu_node */
                                /*  structure. */
-       unsigned long expmask;  /* Groups that have ->blocked_tasks[] */
+       unsigned long expmask;  /* Groups that have ->blkd_tasks */
                                /*  elements that need to drain to allow the */
                                /*  current expedited grace period to */
                                /*  complete (only for TREE_PREEMPT_RCU). */
+       unsigned long wakemask; /* CPUs whose kthread needs to be awakened. */
        unsigned long qsmaskinit;
                                /* Per-GP initial value for qsmask & expmask. */
        unsigned long grpmask;  /* Mask to apply to parent qsmask. */
@@ -122,11 +131,68 @@ struct rcu_node {
        u8      grpnum;         /* CPU/group number for next level up. */
        u8      level;          /* root is at level 0. */
        struct rcu_node *parent;
-       struct list_head blocked_tasks[4];
-                               /* Tasks blocked in RCU read-side critsect. */
-                               /*  Grace period number (->gpnum) x blocked */
-                               /*  by tasks on the (x & 0x1) element of the */
-                               /*  blocked_tasks[] array. */
+       struct list_head blkd_tasks;
+                               /* Tasks blocked in RCU read-side critical */
+                               /*  section.  Tasks are placed at the head */
+                               /*  of this list and age towards the tail. */
+       struct list_head *gp_tasks;
+                               /* Pointer to the first task blocking the */
+                               /*  current grace period, or NULL if there */
+                               /*  is no such task. */
+       struct list_head *exp_tasks;
+                               /* Pointer to the first task blocking the */
+                               /*  current expedited grace period, or NULL */
+                               /*  if there is no such task.  If there */
+                               /*  is no current expedited grace period, */
+                               /*  then there can cannot be any such task. */
+#ifdef CONFIG_RCU_BOOST
+       struct list_head *boost_tasks;
+                               /* Pointer to first task that needs to be */
+                               /*  priority boosted, or NULL if no priority */
+                               /*  boosting is needed for this rcu_node */
+                               /*  structure.  If there are no tasks */
+                               /*  queued on this rcu_node structure that */
+                               /*  are blocking the current grace period, */
+                               /*  there can be no such task. */
+       unsigned long boost_time;
+                               /* When to start boosting (jiffies). */
+       struct task_struct *boost_kthread_task;
+                               /* kthread that takes care of priority */
+                               /*  boosting for this rcu_node structure. */
+       wait_queue_head_t boost_wq;
+                               /* Wait queue on which to park the boost */
+                               /*  kthread. */
+       unsigned int boost_kthread_status;
+                               /* State of boost_kthread_task for tracing. */
+       unsigned long n_tasks_boosted;
+                               /* Total number of tasks boosted. */
+       unsigned long n_exp_boosts;
+                               /* Number of tasks boosted for expedited GP. */
+       unsigned long n_normal_boosts;
+                               /* Number of tasks boosted for normal GP. */
+       unsigned long n_balk_blkd_tasks;
+                               /* Refused to boost: no blocked tasks. */
+       unsigned long n_balk_exp_gp_tasks;
+                               /* Refused to boost: nothing blocking GP. */
+       unsigned long n_balk_boost_tasks;
+                               /* Refused to boost: already boosting. */
+       unsigned long n_balk_notblocked;
+                               /* Refused to boost: RCU RS CS still running. */
+       unsigned long n_balk_notyet;
+                               /* Refused to boost: not yet time. */
+       unsigned long n_balk_nos;
+                               /* Refused to boost: not sure why, though. */
+                               /*  This can happen due to race conditions. */
+#endif /* #ifdef CONFIG_RCU_BOOST */
+       struct task_struct *node_kthread_task;
+                               /* kthread that takes care of this rcu_node */
+                               /*  structure, for example, awakening the */
+                               /*  per-CPU kthreads as needed. */
+       wait_queue_head_t node_wq;
+                               /* Wait queue on which to park the per-node */
+                               /*  kthread. */
+       unsigned int node_kthread_status;
+                               /* State of node_kthread_task for tracing. */
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -175,7 +241,7 @@ struct rcu_data {
        bool            passed_quiesc;  /* User-mode/idle loop etc. */
        bool            qs_pending;     /* Core waits for quiesc state. */
        bool            beenonline;     /* CPU online at least once. */
-       bool            preemptable;    /* Preemptable RCU? */
+       bool            preemptible;    /* Preemptible RCU? */
        struct rcu_node *mynode;        /* This CPU's leaf of hierarchy */
        unsigned long grpmask;          /* Mask to apply to leaf qsmask. */
 
@@ -254,7 +320,6 @@ struct rcu_data {
 #endif /* #else #ifdef CONFIG_NO_HZ */
 
 #define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
 #ifdef CONFIG_PROVE_RCU
 #define RCU_STALL_DELAY_DELTA         (5 * HZ)
@@ -272,13 +337,6 @@ struct rcu_data {
                                                /*  scheduling clock irq */
                                                /*  before ratting on them. */
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE
-#define RCU_CPU_STALL_SUPPRESS_INIT 0
-#else
-#define RCU_CPU_STALL_SUPPRESS_INIT 1
-#endif
-
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
  * RCU global state, including node hierarchy.  This hierarchy is
@@ -325,12 +383,12 @@ struct rcu_state {
                                                /*  due to lock unavailable. */
        unsigned long n_force_qs_ngp;           /* Number of calls leaving */
                                                /*  due to no GP active. */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
        unsigned long gp_start;                 /* Time at which GP started, */
                                                /*  but in jiffies. */
        unsigned long jiffies_stall;            /* Time at which to check */
                                                /*  for CPU stalls. */
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+       unsigned long gp_max;                   /* Maximum GP duration in */
+                                               /*  jiffies. */
        char *name;                             /* Name of structure. */
 };
 
@@ -361,16 +419,14 @@ DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);
 static void rcu_bootup_announce(void);
 long rcu_batches_completed(void);
 static void rcu_preempt_note_context_switch(int cpu);
-static int rcu_preempted_readers(struct rcu_node *rnp);
+static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
                                      unsigned long flags);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static void rcu_print_task_stall(struct rcu_node *rnp);
 static void rcu_preempt_stall_reset(void);
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
@@ -390,5 +446,13 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
 static void rcu_preempt_send_cbs_to_online(void);
 static void __init __rcu_init_preempt(void);
 static void rcu_needs_cpu_flush(void);
+static void __init rcu_init_boost_waitqueue(struct rcu_node *rnp);
+static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
+static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
+                                         cpumask_var_t cm);
+static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
+static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
+                                                struct rcu_node *rnp,
+                                                int rnp_index);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
index a3638710dc67f4627f5cdb88e1cafb43b500d24a..3f6559a5f5cd7911fac44ac500b670e125e73157 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Read-Copy Update mechanism for mutual exclusion (tree-based version)
  * Internal non-public definitions that provide either classic
- * or preemptable semantics.
+ * or preemptible semantics.
  *
  * 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
@@ -54,10 +54,6 @@ static void __init rcu_bootup_announce_oddness(void)
 #ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE
        printk(KERN_INFO "\tRCU torture testing starts during boot.\n");
 #endif
-#ifndef CONFIG_RCU_CPU_STALL_DETECTOR
-       printk(KERN_INFO
-              "\tRCU-based detection of stalled CPUs is disabled.\n");
-#endif
 #if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
        printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n");
 #endif
@@ -70,6 +66,7 @@ static void __init rcu_bootup_announce_oddness(void)
 
 struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state);
 DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data);
+static struct rcu_state *rcu_state = &rcu_preempt_state;
 
 static int rcu_preempted_readers_exp(struct rcu_node *rnp);
 
@@ -78,7 +75,7 @@ static int rcu_preempted_readers_exp(struct rcu_node *rnp);
  */
 static void __init rcu_bootup_announce(void)
 {
-       printk(KERN_INFO "Preemptable hierarchical RCU implementation.\n");
+       printk(KERN_INFO "Preemptible hierarchical RCU implementation.\n");
        rcu_bootup_announce_oddness();
 }
 
@@ -111,7 +108,7 @@ void rcu_force_quiescent_state(void)
 EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
 
 /*
- * Record a preemptable-RCU quiescent state for the specified CPU.  Note
+ * Record a preemptible-RCU quiescent state for the specified CPU.  Note
  * that this just means that the task currently running on the CPU is
  * not in a quiescent state.  There might be any number of tasks blocked
  * while in an RCU read-side critical section.
@@ -134,12 +131,12 @@ static void rcu_preempt_qs(int cpu)
  * We have entered the scheduler, and the current task might soon be
  * context-switched away from.  If this task is in an RCU read-side
  * critical section, we will no longer be able to rely on the CPU to
- * record that fact, so we enqueue the task on the appropriate entry
- * of the blocked_tasks[] array.  The task will dequeue itself when
- * it exits the outermost enclosing RCU read-side critical section.
- * Therefore, the current grace period cannot be permitted to complete
- * until the blocked_tasks[] entry indexed by the low-order bit of
- * rnp->gpnum empties.
+ * record that fact, so we enqueue the task on the blkd_tasks list.
+ * The task will dequeue itself when it exits the outermost enclosing
+ * RCU read-side critical section.  Therefore, the current grace period
+ * cannot be permitted to complete until the blkd_tasks list entries
+ * predating the current grace period drain, in other words, until
+ * rnp->gp_tasks becomes NULL.
  *
  * Caller must disable preemption.
  */
@@ -147,7 +144,6 @@ static void rcu_preempt_note_context_switch(int cpu)
 {
        struct task_struct *t = current;
        unsigned long flags;
-       int phase;
        struct rcu_data *rdp;
        struct rcu_node *rnp;
 
@@ -169,15 +165,30 @@ static void rcu_preempt_note_context_switch(int cpu)
                 * (i.e., this CPU has not yet passed through a quiescent
                 * state for the current grace period), then as long
                 * as that task remains queued, the current grace period
-                * cannot end.
+                * cannot end.  Note that there is some uncertainty as
+                * to exactly when the current grace period started.
+                * We take a conservative approach, which can result
+                * in unnecessarily waiting on tasks that started very
+                * slightly after the current grace period began.  C'est
+                * la vie!!!
                 *
                 * But first, note that the current CPU must still be
                 * on line!
                 */
                WARN_ON_ONCE((rdp->grpmask & rnp->qsmaskinit) == 0);
                WARN_ON_ONCE(!list_empty(&t->rcu_node_entry));
-               phase = (rnp->gpnum + !(rnp->qsmask & rdp->grpmask)) & 0x1;
-               list_add(&t->rcu_node_entry, &rnp->blocked_tasks[phase]);
+               if ((rnp->qsmask & rdp->grpmask) && rnp->gp_tasks != NULL) {
+                       list_add(&t->rcu_node_entry, rnp->gp_tasks->prev);
+                       rnp->gp_tasks = &t->rcu_node_entry;
+#ifdef CONFIG_RCU_BOOST
+                       if (rnp->boost_tasks != NULL)
+                               rnp->boost_tasks = rnp->gp_tasks;
+#endif /* #ifdef CONFIG_RCU_BOOST */
+               } else {
+                       list_add(&t->rcu_node_entry, &rnp->blkd_tasks);
+                       if (rnp->qsmask & rdp->grpmask)
+                               rnp->gp_tasks = &t->rcu_node_entry;
+               }
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        }
 
@@ -196,7 +207,7 @@ static void rcu_preempt_note_context_switch(int cpu)
 }
 
 /*
- * Tree-preemptable RCU implementation for rcu_read_lock().
+ * Tree-preemptible RCU implementation for rcu_read_lock().
  * Just increment ->rcu_read_lock_nesting, shared state will be updated
  * if we block.
  */
@@ -212,12 +223,9 @@ EXPORT_SYMBOL_GPL(__rcu_read_lock);
  * for the specified rcu_node structure.  If the caller needs a reliable
  * answer, it must hold the rcu_node's ->lock.
  */
-static int rcu_preempted_readers(struct rcu_node *rnp)
+static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
 {
-       int phase = rnp->gpnum & 0x1;
-
-       return !list_empty(&rnp->blocked_tasks[phase]) ||
-              !list_empty(&rnp->blocked_tasks[phase + 2]);
+       return rnp->gp_tasks != NULL;
 }
 
 /*
@@ -233,7 +241,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
        unsigned long mask;
        struct rcu_node *rnp_p;
 
-       if (rnp->qsmask != 0 || rcu_preempted_readers(rnp)) {
+       if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;  /* Still need more quiescent states! */
        }
@@ -256,6 +264,21 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
        rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags);
 }
 
+/*
+ * Advance a ->blkd_tasks-list pointer to the next entry, instead
+ * returning NULL if at the end of the list.
+ */
+static struct list_head *rcu_next_node_entry(struct task_struct *t,
+                                            struct rcu_node *rnp)
+{
+       struct list_head *np;
+
+       np = t->rcu_node_entry.next;
+       if (np == &rnp->blkd_tasks)
+               np = NULL;
+       return np;
+}
+
 /*
  * Handle special cases during rcu_read_unlock(), such as needing to
  * notify RCU core processing or task having blocked during the RCU
@@ -266,6 +289,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
        int empty;
        int empty_exp;
        unsigned long flags;
+       struct list_head *np;
        struct rcu_node *rnp;
        int special;
 
@@ -306,10 +330,19 @@ static void rcu_read_unlock_special(struct task_struct *t)
                                break;
                        raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
                }
-               empty = !rcu_preempted_readers(rnp);
+               empty = !rcu_preempt_blocked_readers_cgp(rnp);
                empty_exp = !rcu_preempted_readers_exp(rnp);
                smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */
+               np = rcu_next_node_entry(t, rnp);
                list_del_init(&t->rcu_node_entry);
+               if (&t->rcu_node_entry == rnp->gp_tasks)
+                       rnp->gp_tasks = np;
+               if (&t->rcu_node_entry == rnp->exp_tasks)
+                       rnp->exp_tasks = np;
+#ifdef CONFIG_RCU_BOOST
+               if (&t->rcu_node_entry == rnp->boost_tasks)
+                       rnp->boost_tasks = np;
+#endif /* #ifdef CONFIG_RCU_BOOST */
                t->rcu_blocked_node = NULL;
 
                /*
@@ -322,6 +355,15 @@ static void rcu_read_unlock_special(struct task_struct *t)
                else
                        rcu_report_unblock_qs_rnp(rnp, flags);
 
+#ifdef CONFIG_RCU_BOOST
+               /* Unboost if we were boosted. */
+               if (special & RCU_READ_UNLOCK_BOOSTED) {
+                       t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_BOOSTED;
+                       rt_mutex_unlock(t->rcu_boost_mutex);
+                       t->rcu_boost_mutex = NULL;
+               }
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
                /*
                 * If this was the last task on the expedited lists,
                 * then we need to report up the rcu_node hierarchy.
@@ -334,7 +376,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
 }
 
 /*
- * Tree-preemptable RCU implementation for rcu_read_unlock().
+ * Tree-preemptible RCU implementation for rcu_read_unlock().
  * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
  * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
  * invoke rcu_read_unlock_special() to clean up after a context switch
@@ -356,8 +398,6 @@ void __rcu_read_unlock(void)
 }
 EXPORT_SYMBOL_GPL(__rcu_read_unlock);
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-
 #ifdef CONFIG_RCU_CPU_STALL_VERBOSE
 
 /*
@@ -367,18 +407,16 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);
 static void rcu_print_detail_task_stall_rnp(struct rcu_node *rnp)
 {
        unsigned long flags;
-       struct list_head *lp;
-       int phase;
        struct task_struct *t;
 
-       if (rcu_preempted_readers(rnp)) {
-               raw_spin_lock_irqsave(&rnp->lock, flags);
-               phase = rnp->gpnum & 0x1;
-               lp = &rnp->blocked_tasks[phase];
-               list_for_each_entry(t, lp, rcu_node_entry)
-                       sched_show_task(t);
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       }
+       if (!rcu_preempt_blocked_readers_cgp(rnp))
+               return;
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       t = list_entry(rnp->gp_tasks,
+                      struct task_struct, rcu_node_entry);
+       list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry)
+               sched_show_task(t);
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
 }
 
 /*
@@ -408,16 +446,14 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)
  */
 static void rcu_print_task_stall(struct rcu_node *rnp)
 {
-       struct list_head *lp;
-       int phase;
        struct task_struct *t;
 
-       if (rcu_preempted_readers(rnp)) {
-               phase = rnp->gpnum & 0x1;
-               lp = &rnp->blocked_tasks[phase];
-               list_for_each_entry(t, lp, rcu_node_entry)
-                       printk(" P%d", t->pid);
-       }
+       if (!rcu_preempt_blocked_readers_cgp(rnp))
+               return;
+       t = list_entry(rnp->gp_tasks,
+                      struct task_struct, rcu_node_entry);
+       list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry)
+               printk(" P%d", t->pid);
 }
 
 /*
@@ -430,18 +466,21 @@ static void rcu_preempt_stall_reset(void)
        rcu_preempt_state.jiffies_stall = jiffies + ULONG_MAX / 2;
 }
 
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-
 /*
  * Check that the list of blocked tasks for the newly completed grace
  * period is in fact empty.  It is a serious bug to complete a grace
  * period that still has RCU readers blocked!  This function must be
  * invoked -before- updating this rnp's ->gpnum, and the rnp's ->lock
  * must be held by the caller.
+ *
+ * Also, if there are blocked tasks on the list, they automatically
+ * block the newly created grace period, so set up ->gp_tasks accordingly.
  */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
 {
-       WARN_ON_ONCE(rcu_preempted_readers(rnp));
+       WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp));
+       if (!list_empty(&rnp->blkd_tasks))
+               rnp->gp_tasks = rnp->blkd_tasks.next;
        WARN_ON_ONCE(rnp->qsmask);
 }
 
@@ -465,50 +504,68 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
                                     struct rcu_node *rnp,
                                     struct rcu_data *rdp)
 {
-       int i;
        struct list_head *lp;
        struct list_head *lp_root;
        int retval = 0;
        struct rcu_node *rnp_root = rcu_get_root(rsp);
-       struct task_struct *tp;
+       struct task_struct *t;
 
        if (rnp == rnp_root) {
                WARN_ONCE(1, "Last CPU thought to be offlined?");
                return 0;  /* Shouldn't happen: at least one CPU online. */
        }
-       WARN_ON_ONCE(rnp != rdp->mynode &&
-                    (!list_empty(&rnp->blocked_tasks[0]) ||
-                     !list_empty(&rnp->blocked_tasks[1]) ||
-                     !list_empty(&rnp->blocked_tasks[2]) ||
-                     !list_empty(&rnp->blocked_tasks[3])));
+
+       /* If we are on an internal node, complain bitterly. */
+       WARN_ON_ONCE(rnp != rdp->mynode);
 
        /*
-        * Move tasks up to root rcu_node.  Rely on the fact that the
-        * root rcu_node can be at most one ahead of the rest of the
-        * rcu_nodes in terms of gp_num value.  This fact allows us to
-        * move the blocked_tasks[] array directly, element by element.
+        * Move tasks up to root rcu_node.  Don't try to get fancy for
+        * this corner-case operation -- just put this node's tasks
+        * at the head of the root node's list, and update the root node's
+        * ->gp_tasks and ->exp_tasks pointers to those of this node's,
+        * if non-NULL.  This might result in waiting for more tasks than
+        * absolutely necessary, but this is a good performance/complexity
+        * tradeoff.
         */
-       if (rcu_preempted_readers(rnp))
+       if (rcu_preempt_blocked_readers_cgp(rnp))
                retval |= RCU_OFL_TASKS_NORM_GP;
        if (rcu_preempted_readers_exp(rnp))
                retval |= RCU_OFL_TASKS_EXP_GP;
-       for (i = 0; i < 4; i++) {
-               lp = &rnp->blocked_tasks[i];
-               lp_root = &rnp_root->blocked_tasks[i];
-               while (!list_empty(lp)) {
-                       tp = list_entry(lp->next, typeof(*tp), rcu_node_entry);
-                       raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
-                       list_del(&tp->rcu_node_entry);
-                       tp->rcu_blocked_node = rnp_root;
-                       list_add(&tp->rcu_node_entry, lp_root);
-                       raw_spin_unlock(&rnp_root->lock); /* irqs remain disabled */
-               }
+       lp = &rnp->blkd_tasks;
+       lp_root = &rnp_root->blkd_tasks;
+       while (!list_empty(lp)) {
+               t = list_entry(lp->next, typeof(*t), rcu_node_entry);
+               raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
+               list_del(&t->rcu_node_entry);
+               t->rcu_blocked_node = rnp_root;
+               list_add(&t->rcu_node_entry, lp_root);
+               if (&t->rcu_node_entry == rnp->gp_tasks)
+                       rnp_root->gp_tasks = rnp->gp_tasks;
+               if (&t->rcu_node_entry == rnp->exp_tasks)
+                       rnp_root->exp_tasks = rnp->exp_tasks;
+#ifdef CONFIG_RCU_BOOST
+               if (&t->rcu_node_entry == rnp->boost_tasks)
+                       rnp_root->boost_tasks = rnp->boost_tasks;
+#endif /* #ifdef CONFIG_RCU_BOOST */
+               raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
        }
+
+#ifdef CONFIG_RCU_BOOST
+       /* In case root is being boosted and leaf is not. */
+       raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
+       if (rnp_root->boost_tasks != NULL &&
+           rnp_root->boost_tasks != rnp_root->gp_tasks)
+               rnp_root->boost_tasks = rnp_root->gp_tasks;
+       raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
+       rnp->gp_tasks = NULL;
+       rnp->exp_tasks = NULL;
        return retval;
 }
 
 /*
- * Do CPU-offline processing for preemptable RCU.
+ * Do CPU-offline processing for preemptible RCU.
  */
 static void rcu_preempt_offline_cpu(int cpu)
 {
@@ -537,7 +594,7 @@ static void rcu_preempt_check_callbacks(int cpu)
 }
 
 /*
- * Process callbacks for preemptable RCU.
+ * Process callbacks for preemptible RCU.
  */
 static void rcu_preempt_process_callbacks(void)
 {
@@ -546,7 +603,7 @@ static void rcu_preempt_process_callbacks(void)
 }
 
 /*
- * Queue a preemptable-RCU callback for invocation after a grace period.
+ * Queue a preemptible-RCU callback for invocation after a grace period.
  */
 void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
@@ -594,8 +651,7 @@ static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex);
  */
 static int rcu_preempted_readers_exp(struct rcu_node *rnp)
 {
-       return !list_empty(&rnp->blocked_tasks[2]) ||
-              !list_empty(&rnp->blocked_tasks[3]);
+       return rnp->exp_tasks != NULL;
 }
 
 /*
@@ -655,13 +711,17 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp)
 static void
 sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
 {
-       int must_wait;
+       unsigned long flags;
+       int must_wait = 0;
 
-       raw_spin_lock(&rnp->lock); /* irqs already disabled */
-       list_splice_init(&rnp->blocked_tasks[0], &rnp->blocked_tasks[2]);
-       list_splice_init(&rnp->blocked_tasks[1], &rnp->blocked_tasks[3]);
-       must_wait = rcu_preempted_readers_exp(rnp);
-       raw_spin_unlock(&rnp->lock); /* irqs remain disabled */
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       if (list_empty(&rnp->blkd_tasks))
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       else {
+               rnp->exp_tasks = rnp->blkd_tasks.next;
+               rcu_initiate_boost(rnp, flags);  /* releases rnp->lock */
+               must_wait = 1;
+       }
        if (!must_wait)
                rcu_report_exp_rnp(rsp, rnp);
 }
@@ -669,9 +729,7 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
 /*
  * Wait for an rcu-preempt grace period, but expedite it.  The basic idea
  * is to invoke synchronize_sched_expedited() to push all the tasks to
- * the ->blocked_tasks[] lists, move all entries from the first set of
- * ->blocked_tasks[] lists to the second set, and finally wait for this
- * second set to drain.
+ * the ->blkd_tasks lists and wait for this list to drain.
  */
 void synchronize_rcu_expedited(void)
 {
@@ -703,7 +761,7 @@ void synchronize_rcu_expedited(void)
        if ((ACCESS_ONCE(sync_rcu_preempt_exp_count) - snap) > 0)
                goto unlock_mb_ret; /* Others did our work for us. */
 
-       /* force all RCU readers onto blocked_tasks[]. */
+       /* force all RCU readers onto ->blkd_tasks lists. */
        synchronize_sched_expedited();
 
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
@@ -715,7 +773,7 @@ void synchronize_rcu_expedited(void)
                raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
        }
 
-       /* Snapshot current state of ->blocked_tasks[] lists. */
+       /* Snapshot current state of ->blkd_tasks lists. */
        rcu_for_each_leaf_node(rsp, rnp)
                sync_rcu_preempt_exp_init(rsp, rnp);
        if (NUM_RCU_NODES > 1)
@@ -723,7 +781,7 @@ void synchronize_rcu_expedited(void)
 
        raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
 
-       /* Wait for snapshotted ->blocked_tasks[] lists to drain. */
+       /* Wait for snapshotted ->blkd_tasks lists to drain. */
        rnp = rcu_get_root(rsp);
        wait_event(sync_rcu_preempt_exp_wq,
                   sync_rcu_preempt_exp_done(rnp));
@@ -739,7 +797,7 @@ mb_ret:
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
 /*
- * Check to see if there is any immediate preemptable-RCU-related work
+ * Check to see if there is any immediate preemptible-RCU-related work
  * to be done.
  */
 static int rcu_preempt_pending(int cpu)
@@ -749,7 +807,7 @@ static int rcu_preempt_pending(int cpu)
 }
 
 /*
- * Does preemptable RCU need the CPU to stay out of dynticks mode?
+ * Does preemptible RCU need the CPU to stay out of dynticks mode?
  */
 static int rcu_preempt_needs_cpu(int cpu)
 {
@@ -766,7 +824,7 @@ void rcu_barrier(void)
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
 /*
- * Initialize preemptable RCU's per-CPU data.
+ * Initialize preemptible RCU's per-CPU data.
  */
 static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
 {
@@ -774,7 +832,7 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
 }
 
 /*
- * Move preemptable RCU's callbacks from dying CPU to other online CPU.
+ * Move preemptible RCU's callbacks from dying CPU to other online CPU.
  */
 static void rcu_preempt_send_cbs_to_online(void)
 {
@@ -782,7 +840,7 @@ static void rcu_preempt_send_cbs_to_online(void)
 }
 
 /*
- * Initialize preemptable RCU's state structures.
+ * Initialize preemptible RCU's state structures.
  */
 static void __init __rcu_init_preempt(void)
 {
@@ -790,7 +848,7 @@ static void __init __rcu_init_preempt(void)
 }
 
 /*
- * Check for a task exiting while in a preemptable-RCU read-side
+ * Check for a task exiting while in a preemptible-RCU read-side
  * critical section, clean up if so.  No need to issue warnings,
  * as debug_check_no_locks_held() already does this if lockdep
  * is enabled.
@@ -802,11 +860,13 @@ void exit_rcu(void)
        if (t->rcu_read_lock_nesting == 0)
                return;
        t->rcu_read_lock_nesting = 1;
-       rcu_read_unlock();
+       __rcu_read_unlock();
 }
 
 #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
+static struct rcu_state *rcu_state = &rcu_sched_state;
+
 /*
  * Tell them what RCU they are running.
  */
@@ -836,7 +896,7 @@ void rcu_force_quiescent_state(void)
 EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
 
 /*
- * Because preemptable RCU does not exist, we never have to check for
+ * Because preemptible RCU does not exist, we never have to check for
  * CPUs being in quiescent states.
  */
 static void rcu_preempt_note_context_switch(int cpu)
@@ -844,10 +904,10 @@ static void rcu_preempt_note_context_switch(int cpu)
 }
 
 /*
- * Because preemptable RCU does not exist, there are never any preempted
+ * Because preemptible RCU does not exist, there are never any preempted
  * RCU readers.
  */
-static int rcu_preempted_readers(struct rcu_node *rnp)
+static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
 {
        return 0;
 }
@@ -862,10 +922,8 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-
 /*
- * Because preemptable RCU does not exist, we never have to check for
+ * Because preemptible RCU does not exist, we never have to check for
  * tasks blocked within RCU read-side critical sections.
  */
 static void rcu_print_detail_task_stall(struct rcu_state *rsp)
@@ -873,7 +931,7 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)
 }
 
 /*
- * Because preemptable RCU does not exist, we never have to check for
+ * Because preemptible RCU does not exist, we never have to check for
  * tasks blocked within RCU read-side critical sections.
  */
 static void rcu_print_task_stall(struct rcu_node *rnp)
@@ -888,10 +946,8 @@ static void rcu_preempt_stall_reset(void)
 {
 }
 
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-
 /*
- * Because there is no preemptable RCU, there can be no readers blocked,
+ * Because there is no preemptible RCU, there can be no readers blocked,
  * so there is no need to check for blocked tasks.  So check only for
  * bogus qsmask values.
  */
@@ -903,7 +959,7 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
- * Because preemptable RCU does not exist, it never needs to migrate
+ * Because preemptible RCU does not exist, it never needs to migrate
  * tasks that were blocked within RCU read-side critical sections, and
  * such non-existent tasks cannot possibly have been blocking the current
  * grace period.
@@ -916,7 +972,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 }
 
 /*
- * Because preemptable RCU does not exist, it never needs CPU-offline
+ * Because preemptible RCU does not exist, it never needs CPU-offline
  * processing.
  */
 static void rcu_preempt_offline_cpu(int cpu)
@@ -926,7 +982,7 @@ static void rcu_preempt_offline_cpu(int cpu)
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
 /*
- * Because preemptable RCU does not exist, it never has any callbacks
+ * Because preemptible RCU does not exist, it never has any callbacks
  * to check.
  */
 static void rcu_preempt_check_callbacks(int cpu)
@@ -934,7 +990,7 @@ static void rcu_preempt_check_callbacks(int cpu)
 }
 
 /*
- * Because preemptable RCU does not exist, it never has any callbacks
+ * Because preemptible RCU does not exist, it never has any callbacks
  * to process.
  */
 static void rcu_preempt_process_callbacks(void)
@@ -943,7 +999,7 @@ static void rcu_preempt_process_callbacks(void)
 
 /*
  * Wait for an rcu-preempt grace period, but make it happen quickly.
- * But because preemptable RCU does not exist, map to rcu-sched.
+ * But because preemptible RCU does not exist, map to rcu-sched.
  */
 void synchronize_rcu_expedited(void)
 {
@@ -954,7 +1010,7 @@ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
- * Because preemptable RCU does not exist, there is never any need to
+ * Because preemptible RCU does not exist, there is never any need to
  * report on tasks preempted in RCU read-side critical sections during
  * expedited RCU grace periods.
  */
@@ -966,7 +1022,7 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp)
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
 /*
- * Because preemptable RCU does not exist, it never has any work to do.
+ * Because preemptible RCU does not exist, it never has any work to do.
  */
 static int rcu_preempt_pending(int cpu)
 {
@@ -974,7 +1030,7 @@ static int rcu_preempt_pending(int cpu)
 }
 
 /*
- * Because preemptable RCU does not exist, it never needs any CPU.
+ * Because preemptible RCU does not exist, it never needs any CPU.
  */
 static int rcu_preempt_needs_cpu(int cpu)
 {
@@ -982,7 +1038,7 @@ static int rcu_preempt_needs_cpu(int cpu)
 }
 
 /*
- * Because preemptable RCU does not exist, rcu_barrier() is just
+ * Because preemptible RCU does not exist, rcu_barrier() is just
  * another name for rcu_barrier_sched().
  */
 void rcu_barrier(void)
@@ -992,7 +1048,7 @@ void rcu_barrier(void)
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
 /*
- * Because preemptable RCU does not exist, there is no per-CPU
+ * Because preemptible RCU does not exist, there is no per-CPU
  * data to initialize.
  */
 static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
@@ -1000,14 +1056,14 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
 }
 
 /*
- * Because there is no preemptable RCU, there are no callbacks to move.
+ * Because there is no preemptible RCU, there are no callbacks to move.
  */
 static void rcu_preempt_send_cbs_to_online(void)
 {
 }
 
 /*
- * Because preemptable RCU does not exist, it need not be initialized.
+ * Because preemptible RCU does not exist, it need not be initialized.
  */
 static void __init __rcu_init_preempt(void)
 {
@@ -1015,6 +1071,276 @@ static void __init __rcu_init_preempt(void)
 
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
+#ifdef CONFIG_RCU_BOOST
+
+#include "rtmutex_common.h"
+
+#ifdef CONFIG_RCU_TRACE
+
+static void rcu_initiate_boost_trace(struct rcu_node *rnp)
+{
+       if (list_empty(&rnp->blkd_tasks))
+               rnp->n_balk_blkd_tasks++;
+       else if (rnp->exp_tasks == NULL && rnp->gp_tasks == NULL)
+               rnp->n_balk_exp_gp_tasks++;
+       else if (rnp->gp_tasks != NULL && rnp->boost_tasks != NULL)
+               rnp->n_balk_boost_tasks++;
+       else if (rnp->gp_tasks != NULL && rnp->qsmask != 0)
+               rnp->n_balk_notblocked++;
+       else if (rnp->gp_tasks != NULL &&
+                ULONG_CMP_LT(jiffies, rnp->boost_time))
+               rnp->n_balk_notyet++;
+       else
+               rnp->n_balk_nos++;
+}
+
+#else /* #ifdef CONFIG_RCU_TRACE */
+
+static void rcu_initiate_boost_trace(struct rcu_node *rnp)
+{
+}
+
+#endif /* #else #ifdef CONFIG_RCU_TRACE */
+
+/*
+ * Carry out RCU priority boosting on the task indicated by ->exp_tasks
+ * or ->boost_tasks, advancing the pointer to the next task in the
+ * ->blkd_tasks list.
+ *
+ * Note that irqs must be enabled: boosting the task can block.
+ * Returns 1 if there are more tasks needing to be boosted.
+ */
+static int rcu_boost(struct rcu_node *rnp)
+{
+       unsigned long flags;
+       struct rt_mutex mtx;
+       struct task_struct *t;
+       struct list_head *tb;
+
+       if (rnp->exp_tasks == NULL && rnp->boost_tasks == NULL)
+               return 0;  /* Nothing left to boost. */
+
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+
+       /*
+        * Recheck under the lock: all tasks in need of boosting
+        * might exit their RCU read-side critical sections on their own.
+        */
+       if (rnp->exp_tasks == NULL && rnp->boost_tasks == NULL) {
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               return 0;
+       }
+
+       /*
+        * Preferentially boost tasks blocking expedited grace periods.
+        * This cannot starve the normal grace periods because a second
+        * expedited grace period must boost all blocked tasks, including
+        * those blocking the pre-existing normal grace period.
+        */
+       if (rnp->exp_tasks != NULL) {
+               tb = rnp->exp_tasks;
+               rnp->n_exp_boosts++;
+       } else {
+               tb = rnp->boost_tasks;
+               rnp->n_normal_boosts++;
+       }
+       rnp->n_tasks_boosted++;
+
+       /*
+        * We boost task t by manufacturing an rt_mutex that appears to
+        * be held by task t.  We leave a pointer to that rt_mutex where
+        * task t can find it, and task t will release the mutex when it
+        * exits its outermost RCU read-side critical section.  Then
+        * simply acquiring this artificial rt_mutex will boost task
+        * t's priority.  (Thanks to tglx for suggesting this approach!)
+        *
+        * Note that task t must acquire rnp->lock to remove itself from
+        * the ->blkd_tasks list, which it will do from exit() if from
+        * nowhere else.  We therefore are guaranteed that task t will
+        * stay around at least until we drop rnp->lock.  Note that
+        * rnp->lock also resolves races between our priority boosting
+        * and task t's exiting its outermost RCU read-side critical
+        * section.
+        */
+       t = container_of(tb, struct task_struct, rcu_node_entry);
+       rt_mutex_init_proxy_locked(&mtx, t);
+       t->rcu_boost_mutex = &mtx;
+       t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BOOSTED;
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       rt_mutex_lock(&mtx);  /* Side effect: boosts task t's priority. */
+       rt_mutex_unlock(&mtx);  /* Keep lockdep happy. */
+
+       return rnp->exp_tasks != NULL || rnp->boost_tasks != NULL;
+}
+
+/*
+ * Timer handler to initiate waking up of boost kthreads that
+ * have yielded the CPU due to excessive numbers of tasks to
+ * boost.  We wake up the per-rcu_node kthread, which in turn
+ * will wake up the booster kthread.
+ */
+static void rcu_boost_kthread_timer(unsigned long arg)
+{
+       invoke_rcu_node_kthread((struct rcu_node *)arg);
+}
+
+/*
+ * Priority-boosting kthread.  One per leaf rcu_node and one for the
+ * root rcu_node.
+ */
+static int rcu_boost_kthread(void *arg)
+{
+       struct rcu_node *rnp = (struct rcu_node *)arg;
+       int spincnt = 0;
+       int more2boost;
+
+       for (;;) {
+               rnp->boost_kthread_status = RCU_KTHREAD_WAITING;
+               wait_event_interruptible(rnp->boost_wq, rnp->boost_tasks ||
+                                                       rnp->exp_tasks);
+               rnp->boost_kthread_status = RCU_KTHREAD_RUNNING;
+               more2boost = rcu_boost(rnp);
+               if (more2boost)
+                       spincnt++;
+               else
+                       spincnt = 0;
+               if (spincnt > 10) {
+                       rcu_yield(rcu_boost_kthread_timer, (unsigned long)rnp);
+                       spincnt = 0;
+               }
+       }
+       /* NOTREACHED */
+       return 0;
+}
+
+/*
+ * Check to see if it is time to start boosting RCU readers that are
+ * blocking the current grace period, and, if so, tell the per-rcu_node
+ * kthread to start boosting them.  If there is an expedited grace
+ * period in progress, it is always time to boost.
+ *
+ * The caller must hold rnp->lock, which this function releases,
+ * but irqs remain disabled.  The ->boost_kthread_task is immortal,
+ * so we don't need to worry about it going away.
+ */
+static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
+{
+       struct task_struct *t;
+
+       if (!rcu_preempt_blocked_readers_cgp(rnp) && rnp->exp_tasks == NULL) {
+               rnp->n_balk_exp_gp_tasks++;
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               return;
+       }
+       if (rnp->exp_tasks != NULL ||
+           (rnp->gp_tasks != NULL &&
+            rnp->boost_tasks == NULL &&
+            rnp->qsmask == 0 &&
+            ULONG_CMP_GE(jiffies, rnp->boost_time))) {
+               if (rnp->exp_tasks == NULL)
+                       rnp->boost_tasks = rnp->gp_tasks;
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               t = rnp->boost_kthread_task;
+               if (t != NULL)
+                       wake_up_process(t);
+       } else {
+               rcu_initiate_boost_trace(rnp);
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       }
+}
+
+/*
+ * Set the affinity of the boost kthread.  The CPU-hotplug locks are
+ * held, so no one should be messing with the existence of the boost
+ * kthread.
+ */
+static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
+                                         cpumask_var_t cm)
+{
+       struct task_struct *t;
+
+       t = rnp->boost_kthread_task;
+       if (t != NULL)
+               set_cpus_allowed_ptr(rnp->boost_kthread_task, cm);
+}
+
+#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)
+
+/*
+ * Do priority-boost accounting for the start of a new grace period.
+ */
+static void rcu_preempt_boost_start_gp(struct rcu_node *rnp)
+{
+       rnp->boost_time = jiffies + RCU_BOOST_DELAY_JIFFIES;
+}
+
+/*
+ * Initialize the RCU-boost waitqueue.
+ */
+static void __init rcu_init_boost_waitqueue(struct rcu_node *rnp)
+{
+       init_waitqueue_head(&rnp->boost_wq);
+}
+
+/*
+ * Create an RCU-boost kthread for the specified node if one does not
+ * already exist.  We only create this kthread for preemptible RCU.
+ * Returns zero if all is well, a negated errno otherwise.
+ */
+static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
+                                                struct rcu_node *rnp,
+                                                int rnp_index)
+{
+       unsigned long flags;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       if (&rcu_preempt_state != rsp)
+               return 0;
+       if (rnp->boost_kthread_task != NULL)
+               return 0;
+       t = kthread_create(rcu_boost_kthread, (void *)rnp,
+                          "rcub%d", rnp_index);
+       if (IS_ERR(t))
+               return PTR_ERR(t);
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       rnp->boost_kthread_task = t;
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       wake_up_process(t);
+       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       return 0;
+}
+
+#else /* #ifdef CONFIG_RCU_BOOST */
+
+static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
+{
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+}
+
+static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
+                                         cpumask_var_t cm)
+{
+}
+
+static void rcu_preempt_boost_start_gp(struct rcu_node *rnp)
+{
+}
+
+static void __init rcu_init_boost_waitqueue(struct rcu_node *rnp)
+{
+}
+
+static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
+                                                struct rcu_node *rnp,
+                                                int rnp_index)
+{
+       return 0;
+}
+
+#endif /* #else #ifdef CONFIG_RCU_BOOST */
+
 #ifndef CONFIG_SMP
 
 void synchronize_sched_expedited(void)
@@ -1187,8 +1513,8 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff);
  *
  * Because it is not legal to invoke rcu_process_callbacks() with irqs
  * disabled, we do one pass of force_quiescent_state(), then do a
- * raise_softirq() to cause rcu_process_callbacks() to be invoked later.
- * The per-cpu rcu_dyntick_drain variable controls the sequencing.
+ * invoke_rcu_cpu_kthread() to cause rcu_process_callbacks() to be invoked
+ * later.  The per-cpu rcu_dyntick_drain variable controls the sequencing.
  */
 int rcu_needs_cpu(int cpu)
 {
@@ -1239,7 +1565,7 @@ int rcu_needs_cpu(int cpu)
 
        /* If RCU callbacks are still pending, RCU still needs this CPU. */
        if (c)
-               raise_softirq(RCU_SOFTIRQ);
+               invoke_rcu_cpu_kthread();
        return c;
 }
 
index c8e97853b970f71ad662732ef46da011cf46ac1d..aa0fd72b4bc714ae3b8f4c41f48f712513e8d6f3 100644 (file)
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
+DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
+DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu);
+DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
+DECLARE_PER_CPU(char, rcu_cpu_has_work);
+
+static char convert_kthread_status(unsigned int kthread_status)
+{
+       if (kthread_status > RCU_KTHREAD_MAX)
+               return '?';
+       return "SRWOY"[kthread_status];
+}
+
 static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
 {
        if (!rdp->beenonline)
@@ -64,7 +76,21 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, " ql=%ld b=%ld", rdp->qlen, rdp->blimit);
+       seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld",
+                  rdp->qlen,
+                  ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
+                       rdp->nxttail[RCU_NEXT_TAIL]],
+                  ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
+                       rdp->nxttail[RCU_NEXT_READY_TAIL]],
+                  ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
+                       rdp->nxttail[RCU_WAIT_TAIL]],
+                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]],
+                  per_cpu(rcu_cpu_has_work, rdp->cpu),
+                  convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
+                                         rdp->cpu)),
+                  per_cpu(rcu_cpu_kthread_cpu, rdp->cpu),
+                  per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff,
+                  rdp->blimit);
        seq_printf(m, " ci=%lu co=%lu ca=%lu\n",
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
@@ -121,7 +147,18 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, ",%ld,%ld", rdp->qlen, rdp->blimit);
+       seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen,
+                  ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
+                       rdp->nxttail[RCU_NEXT_TAIL]],
+                  ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
+                       rdp->nxttail[RCU_NEXT_READY_TAIL]],
+                  ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
+                       rdp->nxttail[RCU_WAIT_TAIL]],
+                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]],
+                  per_cpu(rcu_cpu_has_work, rdp->cpu),
+                  convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
+                                         rdp->cpu)),
+                  rdp->blimit);
        seq_printf(m, ",%lu,%lu,%lu\n",
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
@@ -157,11 +194,76 @@ static const struct file_operations rcudata_csv_fops = {
        .release = single_release,
 };
 
+#ifdef CONFIG_RCU_BOOST
+
+static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
+{
+       seq_printf(m,  "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu "
+                  "j=%04x bt=%04x\n",
+                  rnp->grplo, rnp->grphi,
+                  "T."[list_empty(&rnp->blkd_tasks)],
+                  "N."[!rnp->gp_tasks],
+                  "E."[!rnp->exp_tasks],
+                  "B."[!rnp->boost_tasks],
+                  convert_kthread_status(rnp->boost_kthread_status),
+                  rnp->n_tasks_boosted, rnp->n_exp_boosts,
+                  rnp->n_normal_boosts,
+                  (int)(jiffies & 0xffff),
+                  (int)(rnp->boost_time & 0xffff));
+       seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
+                  "     balk",
+                  rnp->n_balk_blkd_tasks,
+                  rnp->n_balk_exp_gp_tasks,
+                  rnp->n_balk_boost_tasks,
+                  rnp->n_balk_notblocked,
+                  rnp->n_balk_notyet,
+                  rnp->n_balk_nos);
+}
+
+static int show_rcu_node_boost(struct seq_file *m, void *unused)
+{
+       struct rcu_node *rnp;
+
+       rcu_for_each_leaf_node(&rcu_preempt_state, rnp)
+               print_one_rcu_node_boost(m, rnp);
+       return 0;
+}
+
+static int rcu_node_boost_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_rcu_node_boost, NULL);
+}
+
+static const struct file_operations rcu_node_boost_fops = {
+       .owner = THIS_MODULE,
+       .open = rcu_node_boost_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+/*
+ * Create the rcuboost debugfs entry.  Standard error return.
+ */
+static int rcu_boost_trace_create_file(struct dentry *rcudir)
+{
+       return !debugfs_create_file("rcuboost", 0444, rcudir, NULL,
+                                   &rcu_node_boost_fops);
+}
+
+#else /* #ifdef CONFIG_RCU_BOOST */
+
+static int rcu_boost_trace_create_file(struct dentry *rcudir)
+{
+       return 0;  /* There cannot be an error if we didn't create it! */
+}
+
+#endif /* #else #ifdef CONFIG_RCU_BOOST */
+
 static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 {
        unsigned long gpnum;
        int level = 0;
-       int phase;
        struct rcu_node *rnp;
 
        gpnum = rsp->gpnum;
@@ -178,13 +280,11 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
                        seq_puts(m, "\n");
                        level = rnp->level;
                }
-               phase = gpnum & 0x1;
-               seq_printf(m, "%lx/%lx %c%c>%c%c %d:%d ^%d    ",
+               seq_printf(m, "%lx/%lx %c%c>%c %d:%d ^%d    ",
                           rnp->qsmask, rnp->qsmaskinit,
-                          "T."[list_empty(&rnp->blocked_tasks[phase])],
-                          "E."[list_empty(&rnp->blocked_tasks[phase + 2])],
-                          "T."[list_empty(&rnp->blocked_tasks[!phase])],
-                          "E."[list_empty(&rnp->blocked_tasks[!phase + 2])],
+                          ".G"[rnp->gp_tasks != NULL],
+                          ".E"[rnp->exp_tasks != NULL],
+                          ".T"[!list_empty(&rnp->blkd_tasks)],
                           rnp->grplo, rnp->grphi, rnp->grpnum);
        }
        seq_puts(m, "\n");
@@ -216,16 +316,35 @@ static const struct file_operations rcuhier_fops = {
        .release = single_release,
 };
 
+static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
+{
+       unsigned long flags;
+       unsigned long completed;
+       unsigned long gpnum;
+       unsigned long gpage;
+       unsigned long gpmax;
+       struct rcu_node *rnp = &rsp->node[0];
+
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       completed = rsp->completed;
+       gpnum = rsp->gpnum;
+       if (rsp->completed == rsp->gpnum)
+               gpage = 0;
+       else
+               gpage = jiffies - rsp->gp_start;
+       gpmax = rsp->gp_max;
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       seq_printf(m, "%s: completed=%ld  gpnum=%lu  age=%ld  max=%ld\n",
+                  rsp->name, completed, gpnum, gpage, gpmax);
+}
+
 static int show_rcugp(struct seq_file *m, void *unused)
 {
 #ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_printf(m, "rcu_preempt: completed=%ld  gpnum=%lu\n",
-                  rcu_preempt_state.completed, rcu_preempt_state.gpnum);
+       show_one_rcugp(m, &rcu_preempt_state);
 #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_printf(m, "rcu_sched: completed=%ld  gpnum=%lu\n",
-                  rcu_sched_state.completed, rcu_sched_state.gpnum);
-       seq_printf(m, "rcu_bh: completed=%ld  gpnum=%lu\n",
-                  rcu_bh_state.completed, rcu_bh_state.gpnum);
+       show_one_rcugp(m, &rcu_sched_state);
+       show_one_rcugp(m, &rcu_bh_state);
        return 0;
 }
 
@@ -298,6 +417,29 @@ static const struct file_operations rcu_pending_fops = {
        .release = single_release,
 };
 
+static int show_rcutorture(struct seq_file *m, void *unused)
+{
+       seq_printf(m, "rcutorture test sequence: %lu %s\n",
+                  rcutorture_testseq >> 1,
+                  (rcutorture_testseq & 0x1) ? "(test in progress)" : "");
+       seq_printf(m, "rcutorture update version number: %lu\n",
+                  rcutorture_vernum);
+       return 0;
+}
+
+static int rcutorture_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_rcutorture, NULL);
+}
+
+static const struct file_operations rcutorture_fops = {
+       .owner = THIS_MODULE,
+       .open = rcutorture_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 static struct dentry *rcudir;
 
 static int __init rcutree_trace_init(void)
@@ -318,6 +460,9 @@ static int __init rcutree_trace_init(void)
        if (!retval)
                goto free_out;
 
+       if (rcu_boost_trace_create_file(rcudir))
+               goto free_out;
+
        retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
        if (!retval)
                goto free_out;
@@ -331,6 +476,11 @@ static int __init rcutree_trace_init(void)
                                                NULL, &rcu_pending_fops);
        if (!retval)
                goto free_out;
+
+       retval = debugfs_create_file("rcutorture", 0444, rcudir,
+                                               NULL, &rcutorture_fops);
+       if (!retval)
+               goto free_out;
        return 0;
 free_out:
        debugfs_remove_recursive(rcudir);
index 312f8b95c2d44fbbc7c7097de04b52d92abc0648..c62acf45d3b9c0c4954090454de59bd08e2eb180 100644 (file)
@@ -231,7 +231,7 @@ static void destroy_rt_bandwidth(struct rt_bandwidth *rt_b)
 #endif
 
 /*
- * sched_domains_mutex serializes calls to arch_init_sched_domains,
+ * sched_domains_mutex serializes calls to init_sched_domains,
  * detach_destroy_domains and partition_sched_domains.
  */
 static DEFINE_MUTEX(sched_domains_mutex);
@@ -312,6 +312,9 @@ struct cfs_rq {
 
        u64 exec_clock;
        u64 min_vruntime;
+#ifndef CONFIG_64BIT
+       u64 min_vruntime_copy;
+#endif
 
        struct rb_root tasks_timeline;
        struct rb_node *rb_leftmost;
@@ -325,7 +328,9 @@ struct cfs_rq {
         */
        struct sched_entity *curr, *next, *last, *skip;
 
+#ifdef CONFIG_SCHED_DEBUG
        unsigned int nr_spread_over;
+#endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
        struct rq *rq;  /* cpu runqueue to which this cfs_rq is attached */
@@ -417,6 +422,7 @@ struct rt_rq {
  */
 struct root_domain {
        atomic_t refcount;
+       struct rcu_head rcu;
        cpumask_var_t span;
        cpumask_var_t online;
 
@@ -460,7 +466,7 @@ struct rq {
        u64 nohz_stamp;
        unsigned char nohz_balance_kick;
 #endif
-       unsigned int skip_clock_update;
+       int skip_clock_update;
 
        /* capture load from *all* tasks on this cpu: */
        struct load_weight load;
@@ -553,6 +559,10 @@ struct rq {
        unsigned int ttwu_count;
        unsigned int ttwu_local;
 #endif
+
+#ifdef CONFIG_SMP
+       struct task_struct *wake_list;
+#endif
 };
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
@@ -571,7 +581,7 @@ static inline int cpu_of(struct rq *rq)
 
 #define rcu_dereference_check_sched_domain(p) \
        rcu_dereference_check((p), \
-                             rcu_read_lock_sched_held() || \
+                             rcu_read_lock_held() || \
                              lockdep_is_held(&sched_domains_mutex))
 
 /*
@@ -596,7 +606,7 @@ static inline int cpu_of(struct rq *rq)
  * Return the group to which this tasks belongs.
  *
  * We use task_subsys_state_check() and extend the RCU verification
- * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach()
+ * with lockdep_is_held(&p->pi_lock) because cpu_cgroup_attach()
  * holds that lock for each task it moves into the cgroup. Therefore
  * by holding that lock, we pin the task to the current cgroup.
  */
@@ -606,7 +616,7 @@ static inline struct task_group *task_group(struct task_struct *p)
        struct cgroup_subsys_state *css;
 
        css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
-                       lockdep_is_held(&task_rq(p)->lock));
+                       lockdep_is_held(&p->pi_lock));
        tg = container_of(css, struct task_group, css);
 
        return autogroup_task_group(p, tg);
@@ -642,7 +652,7 @@ static void update_rq_clock(struct rq *rq)
 {
        s64 delta;
 
-       if (rq->skip_clock_update)
+       if (rq->skip_clock_update > 0)
                return;
 
        delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
@@ -838,18 +848,39 @@ static inline int task_current(struct rq *rq, struct task_struct *p)
        return rq->curr == p;
 }
 
-#ifndef __ARCH_WANT_UNLOCKED_CTXSW
 static inline int task_running(struct rq *rq, struct task_struct *p)
 {
+#ifdef CONFIG_SMP
+       return p->on_cpu;
+#else
        return task_current(rq, p);
+#endif
 }
 
+#ifndef __ARCH_WANT_UNLOCKED_CTXSW
 static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next)
 {
+#ifdef CONFIG_SMP
+       /*
+        * We can optimise this out completely for !SMP, because the
+        * SMP rebalancing from interrupt is the only thing that cares
+        * here.
+        */
+       next->on_cpu = 1;
+#endif
 }
 
 static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 {
+#ifdef CONFIG_SMP
+       /*
+        * After ->on_cpu is cleared, the task can be moved to a different CPU.
+        * We must ensure this doesn't happen until the switch is completely
+        * finished.
+        */
+       smp_wmb();
+       prev->on_cpu = 0;
+#endif
 #ifdef CONFIG_DEBUG_SPINLOCK
        /* this is a valid case when another task releases the spinlock */
        rq->lock.owner = current;
@@ -865,15 +896,6 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 }
 
 #else /* __ARCH_WANT_UNLOCKED_CTXSW */
-static inline int task_running(struct rq *rq, struct task_struct *p)
-{
-#ifdef CONFIG_SMP
-       return p->oncpu;
-#else
-       return task_current(rq, p);
-#endif
-}
-
 static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next)
 {
 #ifdef CONFIG_SMP
@@ -882,7 +904,7 @@ static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next)
         * SMP rebalancing from interrupt is the only thing that cares
         * here.
         */
-       next->oncpu = 1;
+       next->on_cpu = 1;
 #endif
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
        raw_spin_unlock_irq(&rq->lock);
@@ -895,12 +917,12 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 {
 #ifdef CONFIG_SMP
        /*
-        * After ->oncpu is cleared, the task can be moved to a different CPU.
+        * After ->on_cpu is cleared, the task can be moved to a different CPU.
         * We must ensure this doesn't happen until the switch is completely
         * finished.
         */
        smp_wmb();
-       prev->oncpu = 0;
+       prev->on_cpu = 0;
 #endif
 #ifndef __ARCH_WANT_INTERRUPTS_ON_CTXSW
        local_irq_enable();
@@ -909,23 +931,15 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 #endif /* __ARCH_WANT_UNLOCKED_CTXSW */
 
 /*
- * Check whether the task is waking, we use this to synchronize ->cpus_allowed
- * against ttwu().
- */
-static inline int task_is_waking(struct task_struct *p)
-{
-       return unlikely(p->state == TASK_WAKING);
-}
-
-/*
- * __task_rq_lock - lock the runqueue a given task resides on.
- * Must be called interrupts disabled.
+ * __task_rq_lock - lock the rq @p resides on.
  */
 static inline struct rq *__task_rq_lock(struct task_struct *p)
        __acquires(rq->lock)
 {
        struct rq *rq;
 
+       lockdep_assert_held(&p->pi_lock);
+
        for (;;) {
                rq = task_rq(p);
                raw_spin_lock(&rq->lock);
@@ -936,22 +950,22 @@ static inline struct rq *__task_rq_lock(struct task_struct *p)
 }
 
 /*
- * task_rq_lock - lock the runqueue a given task resides on and disable
- * interrupts. Note the ordering: we can safely lookup the task_rq without
- * explicitly disabling preemption.
+ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on.
  */
 static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags)
+       __acquires(p->pi_lock)
        __acquires(rq->lock)
 {
        struct rq *rq;
 
        for (;;) {
-               local_irq_save(*flags);
+               raw_spin_lock_irqsave(&p->pi_lock, *flags);
                rq = task_rq(p);
                raw_spin_lock(&rq->lock);
                if (likely(rq == task_rq(p)))
                        return rq;
-               raw_spin_unlock_irqrestore(&rq->lock, *flags);
+               raw_spin_unlock(&rq->lock);
+               raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
        }
 }
 
@@ -961,10 +975,13 @@ static void __task_rq_unlock(struct rq *rq)
        raw_spin_unlock(&rq->lock);
 }
 
-static inline void task_rq_unlock(struct rq *rq, unsigned long *flags)
+static inline void
+task_rq_unlock(struct rq *rq, struct task_struct *p, unsigned long *flags)
        __releases(rq->lock)
+       __releases(p->pi_lock)
 {
-       raw_spin_unlock_irqrestore(&rq->lock, *flags);
+       raw_spin_unlock(&rq->lock);
+       raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
 }
 
 /*
@@ -1193,11 +1210,17 @@ int get_nohz_timer_target(void)
        int i;
        struct sched_domain *sd;
 
+       rcu_read_lock();
        for_each_domain(cpu, sd) {
-               for_each_cpu(i, sched_domain_span(sd))
-                       if (!idle_cpu(i))
-                               return i;
+               for_each_cpu(i, sched_domain_span(sd)) {
+                       if (!idle_cpu(i)) {
+                               cpu = i;
+                               goto unlock;
+                       }
+               }
        }
+unlock:
+       rcu_read_unlock();
        return cpu;
 }
 /*
@@ -1307,15 +1330,15 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight,
 {
        u64 tmp;
 
+       tmp = (u64)delta_exec * weight;
+
        if (!lw->inv_weight) {
                if (BITS_PER_LONG > 32 && unlikely(lw->weight >= WMULT_CONST))
                        lw->inv_weight = 1;
                else
-                       lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2)
-                               / (lw->weight+1);
+                       lw->inv_weight = WMULT_CONST / lw->weight;
        }
 
-       tmp = (u64)delta_exec * weight;
        /*
         * Check whether we'd overflow the 64-bit multiplication:
         */
@@ -1773,7 +1796,6 @@ static void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
        update_rq_clock(rq);
        sched_info_queued(p);
        p->sched_class->enqueue_task(rq, p, flags);
-       p->se.on_rq = 1;
 }
 
 static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
@@ -1781,7 +1803,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
        update_rq_clock(rq);
        sched_info_dequeued(p);
        p->sched_class->dequeue_task(rq, p, flags);
-       p->se.on_rq = 0;
 }
 
 /*
@@ -2116,7 +2137,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
         * A queue event has occurred, and we're going to schedule.  In
         * this case, we can save a useless back to back clock update.
         */
-       if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))
+       if (rq->curr->on_rq && test_tsk_need_resched(rq->curr))
                rq->skip_clock_update = 1;
 }
 
@@ -2162,6 +2183,11 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
         */
        WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
                        !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
+
+#ifdef CONFIG_LOCKDEP
+       WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
+                                     lockdep_is_held(&task_rq(p)->lock)));
+#endif
 #endif
 
        trace_sched_migrate_task(p, new_cpu);
@@ -2181,19 +2207,6 @@ struct migration_arg {
 
 static int migration_cpu_stop(void *data);
 
-/*
- * The task's runqueue lock must be held.
- * Returns true if you have to wait for migration thread.
- */
-static bool migrate_task(struct task_struct *p, struct rq *rq)
-{
-       /*
-        * If the task is not on a runqueue (and not running), then
-        * the next wake-up will properly place the task.
-        */
-       return p->se.on_rq || task_running(rq, p);
-}
-
 /*
  * wait_task_inactive - wait for a thread to unschedule.
  *
@@ -2251,11 +2264,11 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state)
                rq = task_rq_lock(p, &flags);
                trace_sched_wait_task(p);
                running = task_running(rq, p);
-               on_rq = p->se.on_rq;
+               on_rq = p->on_rq;
                ncsw = 0;
                if (!match_state || p->state == match_state)
                        ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
-               task_rq_unlock(rq, &flags);
+               task_rq_unlock(rq, p, &flags);
 
                /*
                 * If it changed from the expected state, bail out now.
@@ -2330,7 +2343,7 @@ EXPORT_SYMBOL_GPL(kick_process);
 
 #ifdef CONFIG_SMP
 /*
- * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held.
+ * ->cpus_allowed is protected by both rq->lock and p->pi_lock
  */
 static int select_fallback_rq(int cpu, struct task_struct *p)
 {
@@ -2363,12 +2376,12 @@ static int select_fallback_rq(int cpu, struct task_struct *p)
 }
 
 /*
- * The caller (fork, wakeup) owns TASK_WAKING, ->cpus_allowed is stable.
+ * The caller (fork, wakeup) owns p->pi_lock, ->cpus_allowed is stable.
  */
 static inline
-int select_task_rq(struct rq *rq, struct task_struct *p, int sd_flags, int wake_flags)
+int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags)
 {
-       int cpu = p->sched_class->select_task_rq(rq, p, sd_flags, wake_flags);
+       int cpu = p->sched_class->select_task_rq(p, sd_flags, wake_flags);
 
        /*
         * In order not to call set_task_cpu() on a blocking task we need
@@ -2394,27 +2407,62 @@ static void update_avg(u64 *avg, u64 sample)
 }
 #endif
 
-static inline void ttwu_activate(struct task_struct *p, struct rq *rq,
-                                bool is_sync, bool is_migrate, bool is_local,
-                                unsigned long en_flags)
+static void
+ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
 {
+#ifdef CONFIG_SCHEDSTATS
+       struct rq *rq = this_rq();
+
+#ifdef CONFIG_SMP
+       int this_cpu = smp_processor_id();
+
+       if (cpu == this_cpu) {
+               schedstat_inc(rq, ttwu_local);
+               schedstat_inc(p, se.statistics.nr_wakeups_local);
+       } else {
+               struct sched_domain *sd;
+
+               schedstat_inc(p, se.statistics.nr_wakeups_remote);
+               rcu_read_lock();
+               for_each_domain(this_cpu, sd) {
+                       if (cpumask_test_cpu(cpu, sched_domain_span(sd))) {
+                               schedstat_inc(sd, ttwu_wake_remote);
+                               break;
+                       }
+               }
+               rcu_read_unlock();
+       }
+#endif /* CONFIG_SMP */
+
+       schedstat_inc(rq, ttwu_count);
        schedstat_inc(p, se.statistics.nr_wakeups);
-       if (is_sync)
+
+       if (wake_flags & WF_SYNC)
                schedstat_inc(p, se.statistics.nr_wakeups_sync);
-       if (is_migrate)
+
+       if (cpu != task_cpu(p))
                schedstat_inc(p, se.statistics.nr_wakeups_migrate);
-       if (is_local)
-               schedstat_inc(p, se.statistics.nr_wakeups_local);
-       else
-               schedstat_inc(p, se.statistics.nr_wakeups_remote);
 
+#endif /* CONFIG_SCHEDSTATS */
+}
+
+static void ttwu_activate(struct rq *rq, struct task_struct *p, int en_flags)
+{
        activate_task(rq, p, en_flags);
+       p->on_rq = 1;
+
+       /* if a worker is waking up, notify workqueue */
+       if (p->flags & PF_WQ_WORKER)
+               wq_worker_waking_up(p, cpu_of(rq));
 }
 
-static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq,
-                                       int wake_flags, bool success)
+/*
+ * Mark the task runnable and perform wakeup-preemption.
+ */
+static void
+ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags)
 {
-       trace_sched_wakeup(p, success);
+       trace_sched_wakeup(p, true);
        check_preempt_curr(rq, p, wake_flags);
 
        p->state = TASK_RUNNING;
@@ -2433,9 +2481,99 @@ static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq,
                rq->idle_stamp = 0;
        }
 #endif
-       /* if a worker is waking up, notify workqueue */
-       if ((p->flags & PF_WQ_WORKER) && success)
-               wq_worker_waking_up(p, cpu_of(rq));
+}
+
+static void
+ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags)
+{
+#ifdef CONFIG_SMP
+       if (p->sched_contributes_to_load)
+               rq->nr_uninterruptible--;
+#endif
+
+       ttwu_activate(rq, p, ENQUEUE_WAKEUP | ENQUEUE_WAKING);
+       ttwu_do_wakeup(rq, p, wake_flags);
+}
+
+/*
+ * Called in case the task @p isn't fully descheduled from its runqueue,
+ * in this case we must do a remote wakeup. Its a 'light' wakeup though,
+ * since all we need to do is flip p->state to TASK_RUNNING, since
+ * the task is still ->on_rq.
+ */
+static int ttwu_remote(struct task_struct *p, int wake_flags)
+{
+       struct rq *rq;
+       int ret = 0;
+
+       rq = __task_rq_lock(p);
+       if (p->on_rq) {
+               ttwu_do_wakeup(rq, p, wake_flags);
+               ret = 1;
+       }
+       __task_rq_unlock(rq);
+
+       return ret;
+}
+
+#ifdef CONFIG_SMP
+static void sched_ttwu_pending(void)
+{
+       struct rq *rq = this_rq();
+       struct task_struct *list = xchg(&rq->wake_list, NULL);
+
+       if (!list)
+               return;
+
+       raw_spin_lock(&rq->lock);
+
+       while (list) {
+               struct task_struct *p = list;
+               list = list->wake_entry;
+               ttwu_do_activate(rq, p, 0);
+       }
+
+       raw_spin_unlock(&rq->lock);
+}
+
+void scheduler_ipi(void)
+{
+       sched_ttwu_pending();
+}
+
+static void ttwu_queue_remote(struct task_struct *p, int cpu)
+{
+       struct rq *rq = cpu_rq(cpu);
+       struct task_struct *next = rq->wake_list;
+
+       for (;;) {
+               struct task_struct *old = next;
+
+               p->wake_entry = next;
+               next = cmpxchg(&rq->wake_list, old, p);
+               if (next == old)
+                       break;
+       }
+
+       if (!next)
+               smp_send_reschedule(cpu);
+}
+#endif
+
+static void ttwu_queue(struct task_struct *p, int cpu)
+{
+       struct rq *rq = cpu_rq(cpu);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_SCHED_TTWU_QUEUE)
+       if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) {
+               ttwu_queue_remote(p, cpu);
+               return;
+       }
+#endif
+
+       raw_spin_lock(&rq->lock);
+       ttwu_do_activate(rq, p, 0);
+       raw_spin_unlock(&rq->lock);
 }
 
 /**
@@ -2453,92 +2591,64 @@ static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq,
  * Returns %true if @p was woken up, %false if it was already running
  * or @state didn't match @p's state.
  */
-static int try_to_wake_up(struct task_struct *p, unsigned int state,
-                         int wake_flags)
+static int
+try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 {
-       int cpu, orig_cpu, this_cpu, success = 0;
        unsigned long flags;
-       unsigned long en_flags = ENQUEUE_WAKEUP;
-       struct rq *rq;
-
-       this_cpu = get_cpu();
+       int cpu, success = 0;
 
        smp_wmb();
-       rq = task_rq_lock(p, &flags);
+       raw_spin_lock_irqsave(&p->pi_lock, flags);
        if (!(p->state & state))
                goto out;
 
-       if (p->se.on_rq)
-               goto out_running;
-
+       success = 1; /* we're going to change ->state */
        cpu = task_cpu(p);
-       orig_cpu = cpu;
 
-#ifdef CONFIG_SMP
-       if (unlikely(task_running(rq, p)))
-               goto out_activate;
+       if (p->on_rq && ttwu_remote(p, wake_flags))
+               goto stat;
 
+#ifdef CONFIG_SMP
        /*
-        * In order to handle concurrent wakeups and release the rq->lock
-        * we put the task in TASK_WAKING state.
-        *
-        * First fix up the nr_uninterruptible count:
+        * If the owning (remote) cpu is still in the middle of schedule() with
+        * this task as prev, wait until its done referencing the task.
         */
-       if (task_contributes_to_load(p)) {
-               if (likely(cpu_online(orig_cpu)))
-                       rq->nr_uninterruptible--;
-               else
-                       this_rq()->nr_uninterruptible--;
-       }
-       p->state = TASK_WAKING;
-
-       if (p->sched_class->task_waking) {
-               p->sched_class->task_waking(rq, p);
-               en_flags |= ENQUEUE_WAKING;
+       while (p->on_cpu) {
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+               /*
+                * If called from interrupt context we could have landed in the
+                * middle of schedule(), in this case we should take care not
+                * to spin on ->on_cpu if p is current, since that would
+                * deadlock.
+                */
+               if (p == current) {
+                       ttwu_queue(p, cpu);
+                       goto stat;
+               }
+#endif
+               cpu_relax();
        }
-
-       cpu = select_task_rq(rq, p, SD_BALANCE_WAKE, wake_flags);
-       if (cpu != orig_cpu)
-               set_task_cpu(p, cpu);
-       __task_rq_unlock(rq);
-
-       rq = cpu_rq(cpu);
-       raw_spin_lock(&rq->lock);
-
        /*
-        * We migrated the task without holding either rq->lock, however
-        * since the task is not on the task list itself, nobody else
-        * will try and migrate the task, hence the rq should match the
-        * cpu we just moved it to.
+        * Pairs with the smp_wmb() in finish_lock_switch().
         */
-       WARN_ON(task_cpu(p) != cpu);
-       WARN_ON(p->state != TASK_WAKING);
+       smp_rmb();
 
-#ifdef CONFIG_SCHEDSTATS
-       schedstat_inc(rq, ttwu_count);
-       if (cpu == this_cpu)
-               schedstat_inc(rq, ttwu_local);
-       else {
-               struct sched_domain *sd;
-               for_each_domain(this_cpu, sd) {
-                       if (cpumask_test_cpu(cpu, sched_domain_span(sd))) {
-                               schedstat_inc(sd, ttwu_wake_remote);
-                               break;
-                       }
-               }
-       }
-#endif /* CONFIG_SCHEDSTATS */
+       p->sched_contributes_to_load = !!task_contributes_to_load(p);
+       p->state = TASK_WAKING;
 
-out_activate:
+       if (p->sched_class->task_waking)
+               p->sched_class->task_waking(p);
+
+       cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
+       if (task_cpu(p) != cpu)
+               set_task_cpu(p, cpu);
 #endif /* CONFIG_SMP */
-       ttwu_activate(p, rq, wake_flags & WF_SYNC, orig_cpu != cpu,
-                     cpu == this_cpu, en_flags);
-       success = 1;
-out_running:
-       ttwu_post_activation(p, rq, wake_flags, success);
+
+       ttwu_queue(p, cpu);
+stat:
+       ttwu_stat(p, cpu, wake_flags);
 out:
-       task_rq_unlock(rq, &flags);
-       put_cpu();
+       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
        return success;
 }
@@ -2547,31 +2657,34 @@ out:
  * try_to_wake_up_local - try to wake up a local task with rq lock held
  * @p: the thread to be awakened
  *
- * Put @p on the run-queue if it's not already there.  The caller must
+ * Put @p on the run-queue if it's not already there. The caller must
  * ensure that this_rq() is locked, @p is bound to this_rq() and not
- * the current task.  this_rq() stays locked over invocation.
+ * the current task.
  */
 static void try_to_wake_up_local(struct task_struct *p)
 {
        struct rq *rq = task_rq(p);
-       bool success = false;
 
        BUG_ON(rq != this_rq());
        BUG_ON(p == current);
        lockdep_assert_held(&rq->lock);
 
+       if (!raw_spin_trylock(&p->pi_lock)) {
+               raw_spin_unlock(&rq->lock);
+               raw_spin_lock(&p->pi_lock);
+               raw_spin_lock(&rq->lock);
+       }
+
        if (!(p->state & TASK_NORMAL))
-               return;
+               goto out;
 
-       if (!p->se.on_rq) {
-               if (likely(!task_running(rq, p))) {
-                       schedstat_inc(rq, ttwu_count);
-                       schedstat_inc(rq, ttwu_local);
-               }
-               ttwu_activate(p, rq, false, false, true, ENQUEUE_WAKEUP);
-               success = true;
-       }
-       ttwu_post_activation(p, rq, 0, success);
+       if (!p->on_rq)
+               ttwu_activate(rq, p, ENQUEUE_WAKEUP);
+
+       ttwu_do_wakeup(rq, p, 0);
+       ttwu_stat(p, smp_processor_id(), 0);
+out:
+       raw_spin_unlock(&p->pi_lock);
 }
 
 /**
@@ -2604,19 +2717,21 @@ int wake_up_state(struct task_struct *p, unsigned int state)
  */
 static void __sched_fork(struct task_struct *p)
 {
+       p->on_rq                        = 0;
+
+       p->se.on_rq                     = 0;
        p->se.exec_start                = 0;
        p->se.sum_exec_runtime          = 0;
        p->se.prev_sum_exec_runtime     = 0;
        p->se.nr_migrations             = 0;
        p->se.vruntime                  = 0;
+       INIT_LIST_HEAD(&p->se.group_node);
 
 #ifdef CONFIG_SCHEDSTATS
        memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
 
        INIT_LIST_HEAD(&p->rt.run_list);
-       p->se.on_rq = 0;
-       INIT_LIST_HEAD(&p->se.group_node);
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
        INIT_HLIST_HEAD(&p->preempt_notifiers);
@@ -2626,8 +2741,9 @@ static void __sched_fork(struct task_struct *p)
 /*
  * fork()/clone()-time setup:
  */
-void sched_fork(struct task_struct *p, int clone_flags)
+void sched_fork(struct task_struct *p)
 {
+       unsigned long flags;
        int cpu = get_cpu();
 
        __sched_fork(p);
@@ -2678,16 +2794,16 @@ void sched_fork(struct task_struct *p, int clone_flags)
         *
         * Silence PROVE_RCU.
         */
-       rcu_read_lock();
+       raw_spin_lock_irqsave(&p->pi_lock, flags);
        set_task_cpu(p, cpu);
-       rcu_read_unlock();
+       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
        if (likely(sched_info_on()))
                memset(&p->sched_info, 0, sizeof(p->sched_info));
 #endif
-#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
-       p->oncpu = 0;
+#if defined(CONFIG_SMP)
+       p->on_cpu = 0;
 #endif
 #ifdef CONFIG_PREEMPT
        /* Want to start with kernel preemption disabled. */
@@ -2707,41 +2823,31 @@ void sched_fork(struct task_struct *p, int clone_flags)
  * that must be done for every newly created context, then puts the task
  * on the runqueue and wakes it.
  */
-void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
+void wake_up_new_task(struct task_struct *p)
 {
        unsigned long flags;
        struct rq *rq;
-       int cpu __maybe_unused = get_cpu();
 
+       raw_spin_lock_irqsave(&p->pi_lock, flags);
 #ifdef CONFIG_SMP
-       rq = task_rq_lock(p, &flags);
-       p->state = TASK_WAKING;
-
        /*
         * Fork balancing, do it here and not earlier because:
         *  - cpus_allowed can change in the fork path
         *  - any previously selected cpu might disappear through hotplug
-        *
-        * We set TASK_WAKING so that select_task_rq() can drop rq->lock
-        * without people poking at ->cpus_allowed.
         */
-       cpu = select_task_rq(rq, p, SD_BALANCE_FORK, 0);
-       set_task_cpu(p, cpu);
-
-       p->state = TASK_RUNNING;
-       task_rq_unlock(rq, &flags);
+       set_task_cpu(p, select_task_rq(p, SD_BALANCE_FORK, 0));
 #endif
 
-       rq = task_rq_lock(p, &flags);
+       rq = __task_rq_lock(p);
        activate_task(rq, p, 0);
-       trace_sched_wakeup_new(p, 1);
+       p->on_rq = 1;
+       trace_sched_wakeup_new(p, true);
        check_preempt_curr(rq, p, WF_FORK);
 #ifdef CONFIG_SMP
        if (p->sched_class->task_woken)
                p->sched_class->task_woken(rq, p);
 #endif
-       task_rq_unlock(rq, &flags);
-       put_cpu();
+       task_rq_unlock(rq, p, &flags);
 }
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
@@ -3450,27 +3556,22 @@ void sched_exec(void)
 {
        struct task_struct *p = current;
        unsigned long flags;
-       struct rq *rq;
        int dest_cpu;
 
-       rq = task_rq_lock(p, &flags);
-       dest_cpu = p->sched_class->select_task_rq(rq, p, SD_BALANCE_EXEC, 0);
+       raw_spin_lock_irqsave(&p->pi_lock, flags);
+       dest_cpu = p->sched_class->select_task_rq(p, SD_BALANCE_EXEC, 0);
        if (dest_cpu == smp_processor_id())
                goto unlock;
 
-       /*
-        * select_task_rq() can race against ->cpus_allowed
-        */
-       if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) &&
-           likely(cpu_active(dest_cpu)) && migrate_task(p, rq)) {
+       if (likely(cpu_active(dest_cpu))) {
                struct migration_arg arg = { p, dest_cpu };
 
-               task_rq_unlock(rq, &flags);
-               stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
+               raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+               stop_one_cpu(task_cpu(p), migration_cpu_stop, &arg);
                return;
        }
 unlock:
-       task_rq_unlock(rq, &flags);
+       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 }
 
 #endif
@@ -3507,7 +3608,7 @@ unsigned long long task_delta_exec(struct task_struct *p)
 
        rq = task_rq_lock(p, &flags);
        ns = do_task_delta_exec(p, rq);
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        return ns;
 }
@@ -3525,7 +3626,7 @@ unsigned long long task_sched_runtime(struct task_struct *p)
 
        rq = task_rq_lock(p, &flags);
        ns = p->se.sum_exec_runtime + do_task_delta_exec(p, rq);
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        return ns;
 }
@@ -3549,7 +3650,7 @@ unsigned long long thread_group_sched_runtime(struct task_struct *p)
        rq = task_rq_lock(p, &flags);
        thread_group_cputime(p, &totals);
        ns = totals.sum_exec_runtime + do_task_delta_exec(p, rq);
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        return ns;
 }
@@ -3903,9 +4004,6 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
- *
- * It also gets called by the fork code, when changing the parent's
- * timeslices.
  */
 void scheduler_tick(void)
 {
@@ -4025,17 +4123,11 @@ static inline void schedule_debug(struct task_struct *prev)
        profile_hit(SCHED_PROFILING, __builtin_return_address(0));
 
        schedstat_inc(this_rq(), sched_count);
-#ifdef CONFIG_SCHEDSTATS
-       if (unlikely(prev->lock_depth >= 0)) {
-               schedstat_inc(this_rq(), rq_sched_info.bkl_count);
-               schedstat_inc(prev, sched_info.bkl_count);
-       }
-#endif
 }
 
 static void put_prev_task(struct rq *rq, struct task_struct *prev)
 {
-       if (prev->se.on_rq)
+       if (prev->on_rq || rq->skip_clock_update < 0)
                update_rq_clock(rq);
        prev->sched_class->put_prev_task(rq, prev);
 }
@@ -4097,11 +4189,13 @@ need_resched:
                if (unlikely(signal_pending_state(prev->state, prev))) {
                        prev->state = TASK_RUNNING;
                } else {
+                       deactivate_task(rq, prev, DEQUEUE_SLEEP);
+                       prev->on_rq = 0;
+
                        /*
-                        * If a worker is going to sleep, notify and
-                        * ask workqueue whether it wants to wake up a
-                        * task to maintain concurrency.  If so, wake
-                        * up the task.
+                        * If a worker went to sleep, notify and ask workqueue
+                        * whether it wants to wake up a task to maintain
+                        * concurrency.
                         */
                        if (prev->flags & PF_WQ_WORKER) {
                                struct task_struct *to_wakeup;
@@ -4110,11 +4204,10 @@ need_resched:
                                if (to_wakeup)
                                        try_to_wake_up_local(to_wakeup);
                        }
-                       deactivate_task(rq, prev, DEQUEUE_SLEEP);
 
                        /*
-                        * If we are going to sleep and we have plugged IO queued, make
-                        * sure to submit it to avoid deadlocks.
+                        * If we are going to sleep and we have plugged IO
+                        * queued, make sure to submit it to avoid deadlocks.
                         */
                        if (blk_needs_flush_plug(prev)) {
                                raw_spin_unlock(&rq->lock);
@@ -4161,70 +4254,53 @@ need_resched:
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-/*
- * Look out! "owner" is an entirely speculative pointer
- * access and not reliable.
- */
-int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
-{
-       unsigned int cpu;
-       struct rq *rq;
 
-       if (!sched_feat(OWNER_SPIN))
-               return 0;
+static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
+{
+       bool ret = false;
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       /*
-        * Need to access the cpu field knowing that
-        * DEBUG_PAGEALLOC could have unmapped it if
-        * the mutex owner just released it and exited.
-        */
-       if (probe_kernel_address(&owner->cpu, cpu))
-               return 0;
-#else
-       cpu = owner->cpu;
-#endif
+       rcu_read_lock();
+       if (lock->owner != owner)
+               goto fail;
 
        /*
-        * Even if the access succeeded (likely case),
-        * the cpu field may no longer be valid.
+        * Ensure we emit the owner->on_cpu, dereference _after_ checking
+        * lock->owner still matches owner, if that fails, owner might
+        * point to free()d memory, if it still matches, the rcu_read_lock()
+        * ensures the memory stays valid.
         */
-       if (cpu >= nr_cpumask_bits)
-               return 0;
+       barrier();
 
-       /*
-        * We need to validate that we can do a
-        * get_cpu() and that we have the percpu area.
-        */
-       if (!cpu_online(cpu))
-               return 0;
+       ret = owner->on_cpu;
+fail:
+       rcu_read_unlock();
 
-       rq = cpu_rq(cpu);
+       return ret;
+}
 
-       for (;;) {
-               /*
-                * Owner changed, break to re-assess state.
-                */
-               if (lock->owner != owner) {
-                       /*
-                        * If the lock has switched to a different owner,
-                        * we likely have heavy contention. Return 0 to quit
-                        * optimistic spinning and not contend further:
-                        */
-                       if (lock->owner)
-                               return 0;
-                       break;
-               }
+/*
+ * Look out! "owner" is an entirely speculative pointer
+ * access and not reliable.
+ */
+int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
+{
+       if (!sched_feat(OWNER_SPIN))
+               return 0;
 
-               /*
-                * Is that owner really running on that cpu?
-                */
-               if (task_thread_info(rq->curr) != owner || need_resched())
+       while (owner_running(lock, owner)) {
+               if (need_resched())
                        return 0;
 
                arch_mutex_cpu_relax();
        }
 
+       /*
+        * If the owner changed to another task there is likely
+        * heavy contention, stop spinning.
+        */
+       if (lock->owner)
+               return 0;
+
        return 1;
 }
 #endif
@@ -4684,19 +4760,18 @@ EXPORT_SYMBOL(sleep_on_timeout);
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
-       unsigned long flags;
        int oldprio, on_rq, running;
        struct rq *rq;
        const struct sched_class *prev_class;
 
        BUG_ON(prio < 0 || prio > MAX_PRIO);
 
-       rq = task_rq_lock(p, &flags);
+       rq = __task_rq_lock(p);
 
        trace_sched_pi_setprio(p, prio);
        oldprio = p->prio;
        prev_class = p->sched_class;
-       on_rq = p->se.on_rq;
+       on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
                dequeue_task(rq, p, 0);
@@ -4716,7 +4791,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
                enqueue_task(rq, p, oldprio < prio ? ENQUEUE_HEAD : 0);
 
        check_class_changed(rq, p, prev_class, oldprio);
-       task_rq_unlock(rq, &flags);
+       __task_rq_unlock(rq);
 }
 
 #endif
@@ -4744,7 +4819,7 @@ void set_user_nice(struct task_struct *p, long nice)
                p->static_prio = NICE_TO_PRIO(nice);
                goto out_unlock;
        }
-       on_rq = p->se.on_rq;
+       on_rq = p->on_rq;
        if (on_rq)
                dequeue_task(rq, p, 0);
 
@@ -4764,7 +4839,7 @@ void set_user_nice(struct task_struct *p, long nice)
                        resched_task(rq->curr);
        }
 out_unlock:
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 }
 EXPORT_SYMBOL(set_user_nice);
 
@@ -4878,8 +4953,6 @@ static struct task_struct *find_process_by_pid(pid_t pid)
 static void
 __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
 {
-       BUG_ON(p->se.on_rq);
-
        p->policy = policy;
        p->rt_priority = prio;
        p->normal_prio = normal_prio(p);
@@ -4994,20 +5067,17 @@ recheck:
        /*
         * make sure no PI-waiters arrive (or leave) while we are
         * changing the priority of the task:
-        */
-       raw_spin_lock_irqsave(&p->pi_lock, flags);
-       /*
+        *
         * To be able to change p->policy safely, the appropriate
         * runqueue lock must be held.
         */
-       rq = __task_rq_lock(p);
+       rq = task_rq_lock(p, &flags);
 
        /*
         * Changing the policy of the stop threads its a very bad idea
         */
        if (p == rq->stop) {
-               __task_rq_unlock(rq);
-               raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+               task_rq_unlock(rq, p, &flags);
                return -EINVAL;
        }
 
@@ -5031,8 +5101,7 @@ recheck:
                if (rt_bandwidth_enabled() && rt_policy(policy) &&
                                task_group(p)->rt_bandwidth.rt_runtime == 0 &&
                                !task_group_is_autogroup(task_group(p))) {
-                       __task_rq_unlock(rq);
-                       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+                       task_rq_unlock(rq, p, &flags);
                        return -EPERM;
                }
        }
@@ -5041,11 +5110,10 @@ recheck:
        /* recheck policy now with rq lock held */
        if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
                policy = oldpolicy = -1;
-               __task_rq_unlock(rq);
-               raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+               task_rq_unlock(rq, p, &flags);
                goto recheck;
        }
-       on_rq = p->se.on_rq;
+       on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
                deactivate_task(rq, p, 0);
@@ -5064,8 +5132,7 @@ recheck:
                activate_task(rq, p, 0);
 
        check_class_changed(rq, p, prev_class, oldprio);
-       __task_rq_unlock(rq);
-       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+       task_rq_unlock(rq, p, &flags);
 
        rt_mutex_adjust_pi(p);
 
@@ -5316,7 +5383,6 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask)
 {
        struct task_struct *p;
        unsigned long flags;
-       struct rq *rq;
        int retval;
 
        get_online_cpus();
@@ -5331,9 +5397,9 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask)
        if (retval)
                goto out_unlock;
 
-       rq = task_rq_lock(p, &flags);
+       raw_spin_lock_irqsave(&p->pi_lock, flags);
        cpumask_and(mask, &p->cpus_allowed, cpu_online_mask);
-       task_rq_unlock(rq, &flags);
+       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
 out_unlock:
        rcu_read_unlock();
@@ -5658,7 +5724,7 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 
        rq = task_rq_lock(p, &flags);
        time_slice = p->sched_class->get_rr_interval(rq, p);
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        rcu_read_unlock();
        jiffies_to_timespec(time_slice, &t);
@@ -5776,17 +5842,14 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
        rcu_read_unlock();
 
        rq->curr = rq->idle = idle;
-#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
-       idle->oncpu = 1;
+#if defined(CONFIG_SMP)
+       idle->on_cpu = 1;
 #endif
        raw_spin_unlock_irqrestore(&rq->lock, flags);
 
        /* Set the preempt count _outside_ the spinlocks! */
-#if defined(CONFIG_PREEMPT)
-       task_thread_info(idle)->preempt_count = (idle->lock_depth >= 0);
-#else
        task_thread_info(idle)->preempt_count = 0;
-#endif
+
        /*
         * The idle tasks have their own, simple scheduling class:
         */
@@ -5881,26 +5944,17 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
        unsigned int dest_cpu;
        int ret = 0;
 
-       /*
-        * Serialize against TASK_WAKING so that ttwu() and wunt() can
-        * drop the rq->lock and still rely on ->cpus_allowed.
-        */
-again:
-       while (task_is_waking(p))
-               cpu_relax();
        rq = task_rq_lock(p, &flags);
-       if (task_is_waking(p)) {
-               task_rq_unlock(rq, &flags);
-               goto again;
-       }
+
+       if (cpumask_equal(&p->cpus_allowed, new_mask))
+               goto out;
 
        if (!cpumask_intersects(new_mask, cpu_active_mask)) {
                ret = -EINVAL;
                goto out;
        }
 
-       if (unlikely((p->flags & PF_THREAD_BOUND) && p != current &&
-                    !cpumask_equal(&p->cpus_allowed, new_mask))) {
+       if (unlikely((p->flags & PF_THREAD_BOUND) && p != current)) {
                ret = -EINVAL;
                goto out;
        }
@@ -5917,16 +5971,16 @@ again:
                goto out;
 
        dest_cpu = cpumask_any_and(cpu_active_mask, new_mask);
-       if (migrate_task(p, rq)) {
+       if (p->on_rq) {
                struct migration_arg arg = { p, dest_cpu };
                /* Need help from migration thread: drop lock and wait. */
-               task_rq_unlock(rq, &flags);
+               task_rq_unlock(rq, p, &flags);
                stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
                tlb_migrate_finish(p->mm);
                return 0;
        }
 out:
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        return ret;
 }
@@ -5954,6 +6008,7 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
        rq_src = cpu_rq(src_cpu);
        rq_dest = cpu_rq(dest_cpu);
 
+       raw_spin_lock(&p->pi_lock);
        double_rq_lock(rq_src, rq_dest);
        /* Already moved. */
        if (task_cpu(p) != src_cpu)
@@ -5966,7 +6021,7 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
         * If we're not on a rq, the next wake-up will ensure we're
         * placed properly.
         */
-       if (p->se.on_rq) {
+       if (p->on_rq) {
                deactivate_task(rq_src, p, 0);
                set_task_cpu(p, dest_cpu);
                activate_task(rq_dest, p, 0);
@@ -5976,6 +6031,7 @@ done:
        ret = 1;
 fail:
        double_rq_unlock(rq_src, rq_dest);
+       raw_spin_unlock(&p->pi_lock);
        return ret;
 }
 
@@ -6316,6 +6372,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DYING:
+               sched_ttwu_pending();
                /* Update our root-domain */
                raw_spin_lock_irqsave(&rq->lock, flags);
                if (rq->rd) {
@@ -6394,6 +6451,8 @@ early_initcall(migration_init);
 
 #ifdef CONFIG_SMP
 
+static cpumask_var_t sched_domains_tmpmask; /* sched_domains_mutex */
+
 #ifdef CONFIG_SCHED_DEBUG
 
 static __read_mostly int sched_domain_debug_enabled;
@@ -6489,7 +6548,6 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
 
 static void sched_domain_debug(struct sched_domain *sd, int cpu)
 {
-       cpumask_var_t groupmask;
        int level = 0;
 
        if (!sched_domain_debug_enabled)
@@ -6502,20 +6560,14 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
 
        printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
 
-       if (!alloc_cpumask_var(&groupmask, GFP_KERNEL)) {
-               printk(KERN_DEBUG "Cannot load-balance (out of memory)\n");
-               return;
-       }
-
        for (;;) {
-               if (sched_domain_debug_one(sd, cpu, level, groupmask))
+               if (sched_domain_debug_one(sd, cpu, level, sched_domains_tmpmask))
                        break;
                level++;
                sd = sd->parent;
                if (!sd)
                        break;
        }
-       free_cpumask_var(groupmask);
 }
 #else /* !CONFIG_SCHED_DEBUG */
 # define sched_domain_debug(sd, cpu) do { } while (0)
@@ -6572,12 +6624,11 @@ sd_parent_degenerate(struct sched_domain *sd, struct sched_domain *parent)
        return 1;
 }
 
-static void free_rootdomain(struct root_domain *rd)
+static void free_rootdomain(struct rcu_head *rcu)
 {
-       synchronize_sched();
+       struct root_domain *rd = container_of(rcu, struct root_domain, rcu);
 
        cpupri_cleanup(&rd->cpupri);
-
        free_cpumask_var(rd->rto_mask);
        free_cpumask_var(rd->online);
        free_cpumask_var(rd->span);
@@ -6618,7 +6669,7 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
        raw_spin_unlock_irqrestore(&rq->lock, flags);
 
        if (old_rd)
-               free_rootdomain(old_rd);
+               call_rcu_sched(&old_rd->rcu, free_rootdomain);
 }
 
 static int init_rootdomain(struct root_domain *rd)
@@ -6669,6 +6720,25 @@ static struct root_domain *alloc_rootdomain(void)
        return rd;
 }
 
+static void free_sched_domain(struct rcu_head *rcu)
+{
+       struct sched_domain *sd = container_of(rcu, struct sched_domain, rcu);
+       if (atomic_dec_and_test(&sd->groups->ref))
+               kfree(sd->groups);
+       kfree(sd);
+}
+
+static void destroy_sched_domain(struct sched_domain *sd, int cpu)
+{
+       call_rcu(&sd->rcu, free_sched_domain);
+}
+
+static void destroy_sched_domains(struct sched_domain *sd, int cpu)
+{
+       for (; sd; sd = sd->parent)
+               destroy_sched_domain(sd, cpu);
+}
+
 /*
  * Attach the domain 'sd' to 'cpu' as its base domain. Callers must
  * hold the hotplug lock.
@@ -6679,9 +6749,6 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
        struct rq *rq = cpu_rq(cpu);
        struct sched_domain *tmp;
 
-       for (tmp = sd; tmp; tmp = tmp->parent)
-               tmp->span_weight = cpumask_weight(sched_domain_span(tmp));
-
        /* Remove the sched domains which do not contribute to scheduling. */
        for (tmp = sd; tmp; ) {
                struct sched_domain *parent = tmp->parent;
@@ -6692,12 +6759,15 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
                        tmp->parent = parent->parent;
                        if (parent->parent)
                                parent->parent->child = tmp;
+                       destroy_sched_domain(parent, cpu);
                } else
                        tmp = tmp->parent;
        }
 
        if (sd && sd_degenerate(sd)) {
+               tmp = sd;
                sd = sd->parent;
+               destroy_sched_domain(tmp, cpu);
                if (sd)
                        sd->child = NULL;
        }
@@ -6705,7 +6775,9 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
        sched_domain_debug(sd, cpu);
 
        rq_attach_root(rq, rd);
+       tmp = rq->sd;
        rcu_assign_pointer(rq->sd, sd);
+       destroy_sched_domains(tmp, cpu);
 }
 
 /* cpus with isolated domains */
@@ -6721,56 +6793,6 @@ static int __init isolated_cpu_setup(char *str)
 
 __setup("isolcpus=", isolated_cpu_setup);
 
-/*
- * init_sched_build_groups takes the cpumask we wish to span, and a pointer
- * to a function which identifies what group(along with sched group) a CPU
- * belongs to. The return value of group_fn must be a >= 0 and < nr_cpu_ids
- * (due to the fact that we keep track of groups covered with a struct cpumask).
- *
- * init_sched_build_groups will build a circular linked list of the groups
- * covered by the given span, and will set each group's ->cpumask correctly,
- * and ->cpu_power to 0.
- */
-static void
-init_sched_build_groups(const struct cpumask *span,
-                       const struct cpumask *cpu_map,
-                       int (*group_fn)(int cpu, const struct cpumask *cpu_map,
-                                       struct sched_group **sg,
-                                       struct cpumask *tmpmask),
-                       struct cpumask *covered, struct cpumask *tmpmask)
-{
-       struct sched_group *first = NULL, *last = NULL;
-       int i;
-
-       cpumask_clear(covered);
-
-       for_each_cpu(i, span) {
-               struct sched_group *sg;
-               int group = group_fn(i, cpu_map, &sg, tmpmask);
-               int j;
-
-               if (cpumask_test_cpu(i, covered))
-                       continue;
-
-               cpumask_clear(sched_group_cpus(sg));
-               sg->cpu_power = 0;
-
-               for_each_cpu(j, span) {
-                       if (group_fn(j, cpu_map, NULL, tmpmask) != group)
-                               continue;
-
-                       cpumask_set_cpu(j, covered);
-                       cpumask_set_cpu(j, sched_group_cpus(sg));
-               }
-               if (!first)
-                       first = sg;
-               if (last)
-                       last->next = sg;
-               last = sg;
-       }
-       last->next = first;
-}
-
 #define SD_NODES_PER_DOMAIN 16
 
 #ifdef CONFIG_NUMA
@@ -6787,7 +6809,7 @@ init_sched_build_groups(const struct cpumask *span,
  */
 static int find_next_best_node(int node, nodemask_t *used_nodes)
 {
-       int i, n, val, min_val, best_node = 0;
+       int i, n, val, min_val, best_node = -1;
 
        min_val = INT_MAX;
 
@@ -6811,7 +6833,8 @@ static int find_next_best_node(int node, nodemask_t *used_nodes)
                }
        }
 
-       node_set(best_node, *used_nodes);
+       if (best_node != -1)
+               node_set(best_node, *used_nodes);
        return best_node;
 }
 
@@ -6837,315 +6860,130 @@ static void sched_domain_node_span(int node, struct cpumask *span)
 
        for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
                int next_node = find_next_best_node(node, &used_nodes);
-
+               if (next_node < 0)
+                       break;
                cpumask_or(span, span, cpumask_of_node(next_node));
        }
 }
+
+static const struct cpumask *cpu_node_mask(int cpu)
+{
+       lockdep_assert_held(&sched_domains_mutex);
+
+       sched_domain_node_span(cpu_to_node(cpu), sched_domains_tmpmask);
+
+       return sched_domains_tmpmask;
+}
+
+static const struct cpumask *cpu_allnodes_mask(int cpu)
+{
+       return cpu_possible_mask;
+}
 #endif /* CONFIG_NUMA */
 
-int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
+static const struct cpumask *cpu_cpu_mask(int cpu)
+{
+       return cpumask_of_node(cpu_to_node(cpu));
+}
 
-/*
- * The cpus mask in sched_group and sched_domain hangs off the end.
- *
- * ( See the the comments in include/linux/sched.h:struct sched_group
- *   and struct sched_domain. )
- */
-struct static_sched_group {
-       struct sched_group sg;
-       DECLARE_BITMAP(cpus, CONFIG_NR_CPUS);
-};
+int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
 
-struct static_sched_domain {
-       struct sched_domain sd;
-       DECLARE_BITMAP(span, CONFIG_NR_CPUS);
+struct sd_data {
+       struct sched_domain **__percpu sd;
+       struct sched_group **__percpu sg;
 };
 
 struct s_data {
-#ifdef CONFIG_NUMA
-       int                     sd_allnodes;
-       cpumask_var_t           domainspan;
-       cpumask_var_t           covered;
-       cpumask_var_t           notcovered;
-#endif
-       cpumask_var_t           nodemask;
-       cpumask_var_t           this_sibling_map;
-       cpumask_var_t           this_core_map;
-       cpumask_var_t           this_book_map;
-       cpumask_var_t           send_covered;
-       cpumask_var_t           tmpmask;
-       struct sched_group      **sched_group_nodes;
+       struct sched_domain ** __percpu sd;
        struct root_domain      *rd;
 };
 
 enum s_alloc {
-       sa_sched_groups = 0,
        sa_rootdomain,
-       sa_tmpmask,
-       sa_send_covered,
-       sa_this_book_map,
-       sa_this_core_map,
-       sa_this_sibling_map,
-       sa_nodemask,
-       sa_sched_group_nodes,
-#ifdef CONFIG_NUMA
-       sa_notcovered,
-       sa_covered,
-       sa_domainspan,
-#endif
+       sa_sd,
+       sa_sd_storage,
        sa_none,
 };
 
-/*
- * SMT sched-domains:
- */
-#ifdef CONFIG_SCHED_SMT
-static DEFINE_PER_CPU(struct static_sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct static_sched_group, sched_groups);
-
-static int
-cpu_to_cpu_group(int cpu, const struct cpumask *cpu_map,
-                struct sched_group **sg, struct cpumask *unused)
-{
-       if (sg)
-               *sg = &per_cpu(sched_groups, cpu).sg;
-       return cpu;
-}
-#endif /* CONFIG_SCHED_SMT */
+struct sched_domain_topology_level;
 
-/*
- * multi-core sched-domains:
- */
-#ifdef CONFIG_SCHED_MC
-static DEFINE_PER_CPU(struct static_sched_domain, core_domains);
-static DEFINE_PER_CPU(struct static_sched_group, sched_group_core);
+typedef struct sched_domain *(*sched_domain_init_f)(struct sched_domain_topology_level *tl, int cpu);
+typedef const struct cpumask *(*sched_domain_mask_f)(int cpu);
 
-static int
-cpu_to_core_group(int cpu, const struct cpumask *cpu_map,
-                 struct sched_group **sg, struct cpumask *mask)
-{
-       int group;
-#ifdef CONFIG_SCHED_SMT
-       cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#else
-       group = cpu;
-#endif
-       if (sg)
-               *sg = &per_cpu(sched_group_core, group).sg;
-       return group;
-}
-#endif /* CONFIG_SCHED_MC */
+struct sched_domain_topology_level {
+       sched_domain_init_f init;
+       sched_domain_mask_f mask;
+       struct sd_data      data;
+};
 
 /*
- * book sched-domains:
+ * Assumes the sched_domain tree is fully constructed
  */
-#ifdef CONFIG_SCHED_BOOK
-static DEFINE_PER_CPU(struct static_sched_domain, book_domains);
-static DEFINE_PER_CPU(struct static_sched_group, sched_group_book);
-
-static int
-cpu_to_book_group(int cpu, const struct cpumask *cpu_map,
-                 struct sched_group **sg, struct cpumask *mask)
+static int get_group(int cpu, struct sd_data *sdd, struct sched_group **sg)
 {
-       int group = cpu;
-#ifdef CONFIG_SCHED_MC
-       cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#elif defined(CONFIG_SCHED_SMT)
-       cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#endif
-       if (sg)
-               *sg = &per_cpu(sched_group_book, group).sg;
-       return group;
-}
-#endif /* CONFIG_SCHED_BOOK */
+       struct sched_domain *sd = *per_cpu_ptr(sdd->sd, cpu);
+       struct sched_domain *child = sd->child;
 
-static DEFINE_PER_CPU(struct static_sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys);
+       if (child)
+               cpu = cpumask_first(sched_domain_span(child));
 
-static int
-cpu_to_phys_group(int cpu, const struct cpumask *cpu_map,
-                 struct sched_group **sg, struct cpumask *mask)
-{
-       int group;
-#ifdef CONFIG_SCHED_BOOK
-       cpumask_and(mask, cpu_book_mask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#elif defined(CONFIG_SCHED_MC)
-       cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#elif defined(CONFIG_SCHED_SMT)
-       cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
-       group = cpumask_first(mask);
-#else
-       group = cpu;
-#endif
        if (sg)
-               *sg = &per_cpu(sched_group_phys, group).sg;
-       return group;
+               *sg = *per_cpu_ptr(sdd->sg, cpu);
+
+       return cpu;
 }
 
-#ifdef CONFIG_NUMA
 /*
- * The init_sched_build_groups can't handle what we want to do with node
- * groups, so roll our own. Now each node has its own list of groups which
- * gets dynamically allocated.
+ * build_sched_groups takes the cpumask we wish to span, and a pointer
+ * to a function which identifies what group(along with sched group) a CPU
+ * belongs to. The return value of group_fn must be a >= 0 and < nr_cpu_ids
+ * (due to the fact that we keep track of groups covered with a struct cpumask).
+ *
+ * build_sched_groups will build a circular linked list of the groups
+ * covered by the given span, and will set each group's ->cpumask correctly,
+ * and ->cpu_power to 0.
  */
-static DEFINE_PER_CPU(struct static_sched_domain, node_domains);
-static struct sched_group ***sched_group_nodes_bycpu;
-
-static DEFINE_PER_CPU(struct static_sched_domain, allnodes_domains);
-static DEFINE_PER_CPU(struct static_sched_group, sched_group_allnodes);
-
-static int cpu_to_allnodes_group(int cpu, const struct cpumask *cpu_map,
-                                struct sched_group **sg,
-                                struct cpumask *nodemask)
-{
-       int group;
-
-       cpumask_and(nodemask, cpumask_of_node(cpu_to_node(cpu)), cpu_map);
-       group = cpumask_first(nodemask);
-
-       if (sg)
-               *sg = &per_cpu(sched_group_allnodes, group).sg;
-       return group;
-}
-
-static void init_numa_sched_groups_power(struct sched_group *group_head)
-{
-       struct sched_group *sg = group_head;
-       int j;
-
-       if (!sg)
-               return;
-       do {
-               for_each_cpu(j, sched_group_cpus(sg)) {
-                       struct sched_domain *sd;
-
-                       sd = &per_cpu(phys_domains, j).sd;
-                       if (j != group_first_cpu(sd->groups)) {
-                               /*
-                                * Only add "power" once for each
-                                * physical package.
-                                */
-                               continue;
-                       }
-
-                       sg->cpu_power += sd->groups->cpu_power;
-               }
-               sg = sg->next;
-       } while (sg != group_head);
-}
-
-static int build_numa_sched_groups(struct s_data *d,
-                                  const struct cpumask *cpu_map, int num)
+static void
+build_sched_groups(struct sched_domain *sd)
 {
-       struct sched_domain *sd;
-       struct sched_group *sg, *prev;
-       int n, j;
-
-       cpumask_clear(d->covered);
-       cpumask_and(d->nodemask, cpumask_of_node(num), cpu_map);
-       if (cpumask_empty(d->nodemask)) {
-               d->sched_group_nodes[num] = NULL;
-               goto out;
-       }
-
-       sched_domain_node_span(num, d->domainspan);
-       cpumask_and(d->domainspan, d->domainspan, cpu_map);
-
-       sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(),
-                         GFP_KERNEL, num);
-       if (!sg) {
-               printk(KERN_WARNING "Can not alloc domain group for node %d\n",
-                      num);
-               return -ENOMEM;
-       }
-       d->sched_group_nodes[num] = sg;
-
-       for_each_cpu(j, d->nodemask) {
-               sd = &per_cpu(node_domains, j).sd;
-               sd->groups = sg;
-       }
-
-       sg->cpu_power = 0;
-       cpumask_copy(sched_group_cpus(sg), d->nodemask);
-       sg->next = sg;
-       cpumask_or(d->covered, d->covered, d->nodemask);
+       struct sched_group *first = NULL, *last = NULL;
+       struct sd_data *sdd = sd->private;
+       const struct cpumask *span = sched_domain_span(sd);
+       struct cpumask *covered;
+       int i;
 
-       prev = sg;
-       for (j = 0; j < nr_node_ids; j++) {
-               n = (num + j) % nr_node_ids;
-               cpumask_complement(d->notcovered, d->covered);
-               cpumask_and(d->tmpmask, d->notcovered, cpu_map);
-               cpumask_and(d->tmpmask, d->tmpmask, d->domainspan);
-               if (cpumask_empty(d->tmpmask))
-                       break;
-               cpumask_and(d->tmpmask, d->tmpmask, cpumask_of_node(n));
-               if (cpumask_empty(d->tmpmask))
-                       continue;
-               sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(),
-                                 GFP_KERNEL, num);
-               if (!sg) {
-                       printk(KERN_WARNING
-                              "Can not alloc domain group for node %d\n", j);
-                       return -ENOMEM;
-               }
-               sg->cpu_power = 0;
-               cpumask_copy(sched_group_cpus(sg), d->tmpmask);
-               sg->next = prev->next;
-               cpumask_or(d->covered, d->covered, d->tmpmask);
-               prev->next = sg;
-               prev = sg;
-       }
-out:
-       return 0;
-}
-#endif /* CONFIG_NUMA */
+       lockdep_assert_held(&sched_domains_mutex);
+       covered = sched_domains_tmpmask;
 
-#ifdef CONFIG_NUMA
-/* Free memory allocated for various sched_group structures */
-static void free_sched_groups(const struct cpumask *cpu_map,
-                             struct cpumask *nodemask)
-{
-       int cpu, i;
+       cpumask_clear(covered);
 
-       for_each_cpu(cpu, cpu_map) {
-               struct sched_group **sched_group_nodes
-                       = sched_group_nodes_bycpu[cpu];
+       for_each_cpu(i, span) {
+               struct sched_group *sg;
+               int group = get_group(i, sdd, &sg);
+               int j;
 
-               if (!sched_group_nodes)
+               if (cpumask_test_cpu(i, covered))
                        continue;
 
-               for (i = 0; i < nr_node_ids; i++) {
-                       struct sched_group *oldsg, *sg = sched_group_nodes[i];
+               cpumask_clear(sched_group_cpus(sg));
+               sg->cpu_power = 0;
 
-                       cpumask_and(nodemask, cpumask_of_node(i), cpu_map);
-                       if (cpumask_empty(nodemask))
+               for_each_cpu(j, span) {
+                       if (get_group(j, sdd, NULL) != group)
                                continue;
 
-                       if (sg == NULL)
-                               continue;
-                       sg = sg->next;
-next_sg:
-                       oldsg = sg;
-                       sg = sg->next;
-                       kfree(oldsg);
-                       if (oldsg != sched_group_nodes[i])
-                               goto next_sg;
+                       cpumask_set_cpu(j, covered);
+                       cpumask_set_cpu(j, sched_group_cpus(sg));
                }
-               kfree(sched_group_nodes);
-               sched_group_nodes_bycpu[cpu] = NULL;
+
+               if (!first)
+                       first = sg;
+               if (last)
+                       last->next = sg;
+               last = sg;
        }
+       last->next = first;
 }
-#else /* !CONFIG_NUMA */
-static void free_sched_groups(const struct cpumask *cpu_map,
-                             struct cpumask *nodemask)
-{
-}
-#endif /* CONFIG_NUMA */
 
 /*
  * Initialize sched groups cpu_power.
@@ -7159,11 +6997,6 @@ static void free_sched_groups(const struct cpumask *cpu_map,
  */
 static void init_sched_groups_power(int cpu, struct sched_domain *sd)
 {
-       struct sched_domain *child;
-       struct sched_group *group;
-       long power;
-       int weight;
-
        WARN_ON(!sd || !sd->groups);
 
        if (cpu != group_first_cpu(sd->groups))
@@ -7171,36 +7004,7 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
 
        sd->groups->group_weight = cpumask_weight(sched_group_cpus(sd->groups));
 
-       child = sd->child;
-
-       sd->groups->cpu_power = 0;
-
-       if (!child) {
-               power = SCHED_LOAD_SCALE;
-               weight = cpumask_weight(sched_domain_span(sd));
-               /*
-                * SMT siblings share the power of a single core.
-                * Usually multiple threads get a better yield out of
-                * that one core than a single thread would have,
-                * reflect that in sd->smt_gain.
-                */
-               if ((sd->flags & SD_SHARE_CPUPOWER) && weight > 1) {
-                       power *= sd->smt_gain;
-                       power /= weight;
-                       power >>= SCHED_LOAD_SHIFT;
-               }
-               sd->groups->cpu_power += power;
-               return;
-       }
-
-       /*
-        * Add cpu_power of each child group to this groups cpu_power.
-        */
-       group = child->groups;
-       do {
-               sd->groups->cpu_power += group->cpu_power;
-               group = group->next;
-       } while (group != child->groups);
+       update_group_power(sd, cpu);
 }
 
 /*
@@ -7214,15 +7018,15 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
 # define SD_INIT_NAME(sd, type)                do { } while (0)
 #endif
 
-#define        SD_INIT(sd, type)       sd_init_##type(sd)
-
-#define SD_INIT_FUNC(type)     \
-static noinline void sd_init_##type(struct sched_domain *sd)   \
-{                                                              \
-       memset(sd, 0, sizeof(*sd));                             \
-       *sd = SD_##type##_INIT;                                 \
-       sd->level = SD_LV_##type;                               \
-       SD_INIT_NAME(sd, type);                                 \
+#define SD_INIT_FUNC(type)                                             \
+static noinline struct sched_domain *                                  \
+sd_init_##type(struct sched_domain_topology_level *tl, int cpu)        \
+{                                                                      \
+       struct sched_domain *sd = *per_cpu_ptr(tl->data.sd, cpu);       \
+       *sd = SD_##type##_INIT;                                         \
+       SD_INIT_NAME(sd, type);                                         \
+       sd->private = &tl->data;                                        \
+       return sd;                                                      \
 }
 
 SD_INIT_FUNC(CPU)
@@ -7241,13 +7045,14 @@ SD_INIT_FUNC(CPU)
 #endif
 
 static int default_relax_domain_level = -1;
+int sched_domain_level_max;
 
 static int __init setup_relax_domain_level(char *str)
 {
        unsigned long val;
 
        val = simple_strtoul(str, NULL, 0);
-       if (val < SD_LV_MAX)
+       if (val < sched_domain_level_max)
                default_relax_domain_level = val;
 
        return 1;
@@ -7275,37 +7080,20 @@ static void set_domain_attribute(struct sched_domain *sd,
        }
 }
 
+static void __sdt_free(const struct cpumask *cpu_map);
+static int __sdt_alloc(const struct cpumask *cpu_map);
+
 static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
                                 const struct cpumask *cpu_map)
 {
        switch (what) {
-       case sa_sched_groups:
-               free_sched_groups(cpu_map, d->tmpmask); /* fall through */
-               d->sched_group_nodes = NULL;
        case sa_rootdomain:
-               free_rootdomain(d->rd); /* fall through */
-       case sa_tmpmask:
-               free_cpumask_var(d->tmpmask); /* fall through */
-       case sa_send_covered:
-               free_cpumask_var(d->send_covered); /* fall through */
-       case sa_this_book_map:
-               free_cpumask_var(d->this_book_map); /* fall through */
-       case sa_this_core_map:
-               free_cpumask_var(d->this_core_map); /* fall through */
-       case sa_this_sibling_map:
-               free_cpumask_var(d->this_sibling_map); /* fall through */
-       case sa_nodemask:
-               free_cpumask_var(d->nodemask); /* fall through */
-       case sa_sched_group_nodes:
-#ifdef CONFIG_NUMA
-               kfree(d->sched_group_nodes); /* fall through */
-       case sa_notcovered:
-               free_cpumask_var(d->notcovered); /* fall through */
-       case sa_covered:
-               free_cpumask_var(d->covered); /* fall through */
-       case sa_domainspan:
-               free_cpumask_var(d->domainspan); /* fall through */
-#endif
+               if (!atomic_read(&d->rd->refcount))
+                       free_rootdomain(&d->rd->rcu); /* fall through */
+       case sa_sd:
+               free_percpu(d->sd); /* fall through */
+       case sa_sd_storage:
+               __sdt_free(cpu_map); /* fall through */
        case sa_none:
                break;
        }
@@ -7314,308 +7102,212 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
 static enum s_alloc __visit_domain_allocation_hell(struct s_data *d,
                                                   const struct cpumask *cpu_map)
 {
-#ifdef CONFIG_NUMA
-       if (!alloc_cpumask_var(&d->domainspan, GFP_KERNEL))
-               return sa_none;
-       if (!alloc_cpumask_var(&d->covered, GFP_KERNEL))
-               return sa_domainspan;
-       if (!alloc_cpumask_var(&d->notcovered, GFP_KERNEL))
-               return sa_covered;
-       /* Allocate the per-node list of sched groups */
-       d->sched_group_nodes = kcalloc(nr_node_ids,
-                                     sizeof(struct sched_group *), GFP_KERNEL);
-       if (!d->sched_group_nodes) {
-               printk(KERN_WARNING "Can not alloc sched group node list\n");
-               return sa_notcovered;
-       }
-       sched_group_nodes_bycpu[cpumask_first(cpu_map)] = d->sched_group_nodes;
-#endif
-       if (!alloc_cpumask_var(&d->nodemask, GFP_KERNEL))
-               return sa_sched_group_nodes;
-       if (!alloc_cpumask_var(&d->this_sibling_map, GFP_KERNEL))
-               return sa_nodemask;
-       if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL))
-               return sa_this_sibling_map;
-       if (!alloc_cpumask_var(&d->this_book_map, GFP_KERNEL))
-               return sa_this_core_map;
-       if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL))
-               return sa_this_book_map;
-       if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL))
-               return sa_send_covered;
+       memset(d, 0, sizeof(*d));
+
+       if (__sdt_alloc(cpu_map))
+               return sa_sd_storage;
+       d->sd = alloc_percpu(struct sched_domain *);
+       if (!d->sd)
+               return sa_sd_storage;
        d->rd = alloc_rootdomain();
-       if (!d->rd) {
-               printk(KERN_WARNING "Cannot alloc root domain\n");
-               return sa_tmpmask;
-       }
+       if (!d->rd)
+               return sa_sd;
        return sa_rootdomain;
 }
 
-static struct sched_domain *__build_numa_sched_domains(struct s_data *d,
-       const struct cpumask *cpu_map, struct sched_domain_attr *attr, int i)
+/*
+ * NULL the sd_data elements we've used to build the sched_domain and
+ * sched_group structure so that the subsequent __free_domain_allocs()
+ * will not free the data we're using.
+ */
+static void claim_allocations(int cpu, struct sched_domain *sd)
 {
-       struct sched_domain *sd = NULL;
-#ifdef CONFIG_NUMA
-       struct sched_domain *parent;
-
-       d->sd_allnodes = 0;
-       if (cpumask_weight(cpu_map) >
-           SD_NODES_PER_DOMAIN * cpumask_weight(d->nodemask)) {
-               sd = &per_cpu(allnodes_domains, i).sd;
-               SD_INIT(sd, ALLNODES);
-               set_domain_attribute(sd, attr);
-               cpumask_copy(sched_domain_span(sd), cpu_map);
-               cpu_to_allnodes_group(i, cpu_map, &sd->groups, d->tmpmask);
-               d->sd_allnodes = 1;
-       }
-       parent = sd;
-
-       sd = &per_cpu(node_domains, i).sd;
-       SD_INIT(sd, NODE);
-       set_domain_attribute(sd, attr);
-       sched_domain_node_span(cpu_to_node(i), sched_domain_span(sd));
-       sd->parent = parent;
-       if (parent)
-               parent->child = sd;
-       cpumask_and(sched_domain_span(sd), sched_domain_span(sd), cpu_map);
-#endif
-       return sd;
-}
+       struct sd_data *sdd = sd->private;
+       struct sched_group *sg = sd->groups;
 
-static struct sched_domain *__build_cpu_sched_domain(struct s_data *d,
-       const struct cpumask *cpu_map, struct sched_domain_attr *attr,
-       struct sched_domain *parent, int i)
-{
-       struct sched_domain *sd;
-       sd = &per_cpu(phys_domains, i).sd;
-       SD_INIT(sd, CPU);
-       set_domain_attribute(sd, attr);
-       cpumask_copy(sched_domain_span(sd), d->nodemask);
-       sd->parent = parent;
-       if (parent)
-               parent->child = sd;
-       cpu_to_phys_group(i, cpu_map, &sd->groups, d->tmpmask);
-       return sd;
-}
+       WARN_ON_ONCE(*per_cpu_ptr(sdd->sd, cpu) != sd);
+       *per_cpu_ptr(sdd->sd, cpu) = NULL;
 
-static struct sched_domain *__build_book_sched_domain(struct s_data *d,
-       const struct cpumask *cpu_map, struct sched_domain_attr *attr,
-       struct sched_domain *parent, int i)
-{
-       struct sched_domain *sd = parent;
-#ifdef CONFIG_SCHED_BOOK
-       sd = &per_cpu(book_domains, i).sd;
-       SD_INIT(sd, BOOK);
-       set_domain_attribute(sd, attr);
-       cpumask_and(sched_domain_span(sd), cpu_map, cpu_book_mask(i));
-       sd->parent = parent;
-       parent->child = sd;
-       cpu_to_book_group(i, cpu_map, &sd->groups, d->tmpmask);
-#endif
-       return sd;
+       if (cpu == cpumask_first(sched_group_cpus(sg))) {
+               WARN_ON_ONCE(*per_cpu_ptr(sdd->sg, cpu) != sg);
+               *per_cpu_ptr(sdd->sg, cpu) = NULL;
+       }
 }
 
-static struct sched_domain *__build_mc_sched_domain(struct s_data *d,
-       const struct cpumask *cpu_map, struct sched_domain_attr *attr,
-       struct sched_domain *parent, int i)
+#ifdef CONFIG_SCHED_SMT
+static const struct cpumask *cpu_smt_mask(int cpu)
 {
-       struct sched_domain *sd = parent;
-#ifdef CONFIG_SCHED_MC
-       sd = &per_cpu(core_domains, i).sd;
-       SD_INIT(sd, MC);
-       set_domain_attribute(sd, attr);
-       cpumask_and(sched_domain_span(sd), cpu_map, cpu_coregroup_mask(i));
-       sd->parent = parent;
-       parent->child = sd;
-       cpu_to_core_group(i, cpu_map, &sd->groups, d->tmpmask);
-#endif
-       return sd;
+       return topology_thread_cpumask(cpu);
 }
-
-static struct sched_domain *__build_smt_sched_domain(struct s_data *d,
-       const struct cpumask *cpu_map, struct sched_domain_attr *attr,
-       struct sched_domain *parent, int i)
-{
-       struct sched_domain *sd = parent;
-#ifdef CONFIG_SCHED_SMT
-       sd = &per_cpu(cpu_domains, i).sd;
-       SD_INIT(sd, SIBLING);
-       set_domain_attribute(sd, attr);
-       cpumask_and(sched_domain_span(sd), cpu_map, topology_thread_cpumask(i));
-       sd->parent = parent;
-       parent->child = sd;
-       cpu_to_cpu_group(i, cpu_map, &sd->groups, d->tmpmask);
 #endif
-       return sd;
-}
 
-static void build_sched_groups(struct s_data *d, enum sched_domain_level l,
-                              const struct cpumask *cpu_map, int cpu)
-{
-       switch (l) {
+/*
+ * Topology list, bottom-up.
+ */
+static struct sched_domain_topology_level default_topology[] = {
 #ifdef CONFIG_SCHED_SMT
-       case SD_LV_SIBLING: /* set up CPU (sibling) groups */
-               cpumask_and(d->this_sibling_map, cpu_map,
-                           topology_thread_cpumask(cpu));
-               if (cpu == cpumask_first(d->this_sibling_map))
-                       init_sched_build_groups(d->this_sibling_map, cpu_map,
-                                               &cpu_to_cpu_group,
-                                               d->send_covered, d->tmpmask);
-               break;
+       { sd_init_SIBLING, cpu_smt_mask, },
 #endif
 #ifdef CONFIG_SCHED_MC
-       case SD_LV_MC: /* set up multi-core groups */
-               cpumask_and(d->this_core_map, cpu_map, cpu_coregroup_mask(cpu));
-               if (cpu == cpumask_first(d->this_core_map))
-                       init_sched_build_groups(d->this_core_map, cpu_map,
-                                               &cpu_to_core_group,
-                                               d->send_covered, d->tmpmask);
-               break;
+       { sd_init_MC, cpu_coregroup_mask, },
 #endif
 #ifdef CONFIG_SCHED_BOOK
-       case SD_LV_BOOK: /* set up book groups */
-               cpumask_and(d->this_book_map, cpu_map, cpu_book_mask(cpu));
-               if (cpu == cpumask_first(d->this_book_map))
-                       init_sched_build_groups(d->this_book_map, cpu_map,
-                                               &cpu_to_book_group,
-                                               d->send_covered, d->tmpmask);
-               break;
+       { sd_init_BOOK, cpu_book_mask, },
 #endif
-       case SD_LV_CPU: /* set up physical groups */
-               cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map);
-               if (!cpumask_empty(d->nodemask))
-                       init_sched_build_groups(d->nodemask, cpu_map,
-                                               &cpu_to_phys_group,
-                                               d->send_covered, d->tmpmask);
-               break;
+       { sd_init_CPU, cpu_cpu_mask, },
 #ifdef CONFIG_NUMA
-       case SD_LV_ALLNODES:
-               init_sched_build_groups(cpu_map, cpu_map, &cpu_to_allnodes_group,
-                                       d->send_covered, d->tmpmask);
-               break;
+       { sd_init_NODE, cpu_node_mask, },
+       { sd_init_ALLNODES, cpu_allnodes_mask, },
 #endif
-       default:
-               break;
+       { NULL, },
+};
+
+static struct sched_domain_topology_level *sched_domain_topology = default_topology;
+
+static int __sdt_alloc(const struct cpumask *cpu_map)
+{
+       struct sched_domain_topology_level *tl;
+       int j;
+
+       for (tl = sched_domain_topology; tl->init; tl++) {
+               struct sd_data *sdd = &tl->data;
+
+               sdd->sd = alloc_percpu(struct sched_domain *);
+               if (!sdd->sd)
+                       return -ENOMEM;
+
+               sdd->sg = alloc_percpu(struct sched_group *);
+               if (!sdd->sg)
+                       return -ENOMEM;
+
+               for_each_cpu(j, cpu_map) {
+                       struct sched_domain *sd;
+                       struct sched_group *sg;
+
+                       sd = kzalloc_node(sizeof(struct sched_domain) + cpumask_size(),
+                                       GFP_KERNEL, cpu_to_node(j));
+                       if (!sd)
+                               return -ENOMEM;
+
+                       *per_cpu_ptr(sdd->sd, j) = sd;
+
+                       sg = kzalloc_node(sizeof(struct sched_group) + cpumask_size(),
+                                       GFP_KERNEL, cpu_to_node(j));
+                       if (!sg)
+                               return -ENOMEM;
+
+                       *per_cpu_ptr(sdd->sg, j) = sg;
+               }
        }
+
+       return 0;
+}
+
+static void __sdt_free(const struct cpumask *cpu_map)
+{
+       struct sched_domain_topology_level *tl;
+       int j;
+
+       for (tl = sched_domain_topology; tl->init; tl++) {
+               struct sd_data *sdd = &tl->data;
+
+               for_each_cpu(j, cpu_map) {
+                       kfree(*per_cpu_ptr(sdd->sd, j));
+                       kfree(*per_cpu_ptr(sdd->sg, j));
+               }
+               free_percpu(sdd->sd);
+               free_percpu(sdd->sg);
+       }
+}
+
+struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
+               struct s_data *d, const struct cpumask *cpu_map,
+               struct sched_domain_attr *attr, struct sched_domain *child,
+               int cpu)
+{
+       struct sched_domain *sd = tl->init(tl, cpu);
+       if (!sd)
+               return child;
+
+       set_domain_attribute(sd, attr);
+       cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu));
+       if (child) {
+               sd->level = child->level + 1;
+               sched_domain_level_max = max(sched_domain_level_max, sd->level);
+               child->parent = sd;
+       }
+       sd->child = child;
+
+       return sd;
 }
 
 /*
  * Build sched domains for a given set of cpus and attach the sched domains
  * to the individual cpus
  */
-static int __build_sched_domains(const struct cpumask *cpu_map,
-                                struct sched_domain_attr *attr)
+static int build_sched_domains(const struct cpumask *cpu_map,
+                              struct sched_domain_attr *attr)
 {
        enum s_alloc alloc_state = sa_none;
-       struct s_data d;
        struct sched_domain *sd;
-       int i;
-#ifdef CONFIG_NUMA
-       d.sd_allnodes = 0;
-#endif
+       struct s_data d;
+       int i, ret = -ENOMEM;
 
        alloc_state = __visit_domain_allocation_hell(&d, cpu_map);
        if (alloc_state != sa_rootdomain)
                goto error;
-       alloc_state = sa_sched_groups;
-
-       /*
-        * Set up domains for cpus specified by the cpu_map.
-        */
-       for_each_cpu(i, cpu_map) {
-               cpumask_and(d.nodemask, cpumask_of_node(cpu_to_node(i)),
-                           cpu_map);
-
-               sd = __build_numa_sched_domains(&d, cpu_map, attr, i);
-               sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i);
-               sd = __build_book_sched_domain(&d, cpu_map, attr, sd, i);
-               sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i);
-               sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i);
-       }
 
+       /* Set up domains for cpus specified by the cpu_map. */
        for_each_cpu(i, cpu_map) {
-               build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i);
-               build_sched_groups(&d, SD_LV_BOOK, cpu_map, i);
-               build_sched_groups(&d, SD_LV_MC, cpu_map, i);
-       }
+               struct sched_domain_topology_level *tl;
 
-       /* Set up physical groups */
-       for (i = 0; i < nr_node_ids; i++)
-               build_sched_groups(&d, SD_LV_CPU, cpu_map, i);
+               sd = NULL;
+               for (tl = sched_domain_topology; tl->init; tl++)
+                       sd = build_sched_domain(tl, &d, cpu_map, attr, sd, i);
 
-#ifdef CONFIG_NUMA
-       /* Set up node groups */
-       if (d.sd_allnodes)
-               build_sched_groups(&d, SD_LV_ALLNODES, cpu_map, 0);
+               while (sd->child)
+                       sd = sd->child;
 
-       for (i = 0; i < nr_node_ids; i++)
-               if (build_numa_sched_groups(&d, cpu_map, i))
-                       goto error;
-#endif
-
-       /* Calculate CPU power for physical packages and nodes */
-#ifdef CONFIG_SCHED_SMT
-       for_each_cpu(i, cpu_map) {
-               sd = &per_cpu(cpu_domains, i).sd;
-               init_sched_groups_power(i, sd);
-       }
-#endif
-#ifdef CONFIG_SCHED_MC
-       for_each_cpu(i, cpu_map) {
-               sd = &per_cpu(core_domains, i).sd;
-               init_sched_groups_power(i, sd);
+               *per_cpu_ptr(d.sd, i) = sd;
        }
-#endif
-#ifdef CONFIG_SCHED_BOOK
-       for_each_cpu(i, cpu_map) {
-               sd = &per_cpu(book_domains, i).sd;
-               init_sched_groups_power(i, sd);
-       }
-#endif
 
+       /* Build the groups for the domains */
        for_each_cpu(i, cpu_map) {
-               sd = &per_cpu(phys_domains, i).sd;
-               init_sched_groups_power(i, sd);
-       }
+               for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent) {
+                       sd->span_weight = cpumask_weight(sched_domain_span(sd));
+                       get_group(i, sd->private, &sd->groups);
+                       atomic_inc(&sd->groups->ref);
 
-#ifdef CONFIG_NUMA
-       for (i = 0; i < nr_node_ids; i++)
-               init_numa_sched_groups_power(d.sched_group_nodes[i]);
+                       if (i != cpumask_first(sched_domain_span(sd)))
+                               continue;
 
-       if (d.sd_allnodes) {
-               struct sched_group *sg;
+                       build_sched_groups(sd);
+               }
+       }
 
-               cpu_to_allnodes_group(cpumask_first(cpu_map), cpu_map, &sg,
-                                                               d.tmpmask);
-               init_numa_sched_groups_power(sg);
+       /* Calculate CPU power for physical packages and nodes */
+       for (i = nr_cpumask_bits-1; i >= 0; i--) {
+               if (!cpumask_test_cpu(i, cpu_map))
+                       continue;
+
+               for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent) {
+                       claim_allocations(i, sd);
+                       init_sched_groups_power(i, sd);
+               }
        }
-#endif
 
        /* Attach the domains */
+       rcu_read_lock();
        for_each_cpu(i, cpu_map) {
-#ifdef CONFIG_SCHED_SMT
-               sd = &per_cpu(cpu_domains, i).sd;
-#elif defined(CONFIG_SCHED_MC)
-               sd = &per_cpu(core_domains, i).sd;
-#elif defined(CONFIG_SCHED_BOOK)
-               sd = &per_cpu(book_domains, i).sd;
-#else
-               sd = &per_cpu(phys_domains, i).sd;
-#endif
+               sd = *per_cpu_ptr(d.sd, i);
                cpu_attach_domain(sd, d.rd, i);
        }
+       rcu_read_unlock();
 
-       d.sched_group_nodes = NULL; /* don't free this we still need it */
-       __free_domain_allocs(&d, sa_tmpmask, cpu_map);
-       return 0;
-
+       ret = 0;
 error:
        __free_domain_allocs(&d, alloc_state, cpu_map);
-       return -ENOMEM;
-}
-
-static int build_sched_domains(const struct cpumask *cpu_map)
-{
-       return __build_sched_domains(cpu_map, NULL);
+       return ret;
 }
 
 static cpumask_var_t *doms_cur;        /* current sched domains */
@@ -7670,7 +7362,7 @@ void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms)
  * For now this just excludes isolated cpus, but could be used to
  * exclude other special cases in the future.
  */
-static int arch_init_sched_domains(const struct cpumask *cpu_map)
+static int init_sched_domains(const struct cpumask *cpu_map)
 {
        int err;
 
@@ -7681,32 +7373,24 @@ static int arch_init_sched_domains(const struct cpumask *cpu_map)
                doms_cur = &fallback_doms;
        cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map);
        dattr_cur = NULL;
-       err = build_sched_domains(doms_cur[0]);
+       err = build_sched_domains(doms_cur[0], NULL);
        register_sched_domain_sysctl();
 
        return err;
 }
 
-static void arch_destroy_sched_domains(const struct cpumask *cpu_map,
-                                      struct cpumask *tmpmask)
-{
-       free_sched_groups(cpu_map, tmpmask);
-}
-
 /*
  * Detach sched domains from a group of cpus specified in cpu_map
  * These cpus will now be attached to the NULL domain
  */
 static void detach_destroy_domains(const struct cpumask *cpu_map)
 {
-       /* Save because hotplug lock held. */
-       static DECLARE_BITMAP(tmpmask, CONFIG_NR_CPUS);
        int i;
 
+       rcu_read_lock();
        for_each_cpu(i, cpu_map)
                cpu_attach_domain(NULL, &def_root_domain, i);
-       synchronize_sched();
-       arch_destroy_sched_domains(cpu_map, to_cpumask(tmpmask));
+       rcu_read_unlock();
 }
 
 /* handle null as "default" */
@@ -7795,8 +7479,7 @@ match1:
                                goto match2;
                }
                /* no match - add a new doms_new */
-               __build_sched_domains(doms_new[i],
-                                       dattr_new ? dattr_new + i : NULL);
+               build_sched_domains(doms_new[i], dattr_new ? dattr_new + i : NULL);
 match2:
                ;
        }
@@ -7815,7 +7498,7 @@ match2:
 }
 
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-static void arch_reinit_sched_domains(void)
+static void reinit_sched_domains(void)
 {
        get_online_cpus();
 
@@ -7848,7 +7531,7 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
        else
                sched_mc_power_savings = level;
 
-       arch_reinit_sched_domains();
+       reinit_sched_domains();
 
        return count;
 }
@@ -7967,14 +7650,9 @@ void __init sched_init_smp(void)
        alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
        alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
 
-#if defined(CONFIG_NUMA)
-       sched_group_nodes_bycpu = kzalloc(nr_cpu_ids * sizeof(void **),
-                                                               GFP_KERNEL);
-       BUG_ON(sched_group_nodes_bycpu == NULL);
-#endif
        get_online_cpus();
        mutex_lock(&sched_domains_mutex);
-       arch_init_sched_domains(cpu_active_mask);
+       init_sched_domains(cpu_active_mask);
        cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map);
        if (cpumask_empty(non_isolated_cpus))
                cpumask_set_cpu(smp_processor_id(), non_isolated_cpus);
@@ -8281,6 +7959,7 @@ void __init sched_init(void)
        /* Allocate the nohz_cpu_mask if CONFIG_CPUMASK_OFFSTACK */
        zalloc_cpumask_var(&nohz_cpu_mask, GFP_NOWAIT);
 #ifdef CONFIG_SMP
+       zalloc_cpumask_var(&sched_domains_tmpmask, GFP_NOWAIT);
 #ifdef CONFIG_NO_HZ
        zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
        alloc_cpumask_var(&nohz.grp_idle_mask, GFP_NOWAIT);
@@ -8340,7 +8019,7 @@ static void normalize_task(struct rq *rq, struct task_struct *p)
        int old_prio = p->prio;
        int on_rq;
 
-       on_rq = p->se.on_rq;
+       on_rq = p->on_rq;
        if (on_rq)
                deactivate_task(rq, p, 0);
        __setscheduler(rq, p, SCHED_NORMAL, 0);
@@ -8553,7 +8232,6 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 {
        struct rt_rq *rt_rq;
        struct sched_rt_entity *rt_se;
-       struct rq *rq;
        int i;
 
        tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL);
@@ -8567,8 +8245,6 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
                        ktime_to_ns(def_rt_bandwidth.rt_period), 0);
 
        for_each_possible_cpu(i) {
-               rq = cpu_rq(i);
-
                rt_rq = kzalloc_node(sizeof(struct rt_rq),
                                     GFP_KERNEL, cpu_to_node(i));
                if (!rt_rq)
@@ -8683,7 +8359,7 @@ void sched_move_task(struct task_struct *tsk)
        rq = task_rq_lock(tsk, &flags);
 
        running = task_current(rq, tsk);
-       on_rq = tsk->se.on_rq;
+       on_rq = tsk->on_rq;
 
        if (on_rq)
                dequeue_task(rq, tsk, 0);
@@ -8702,7 +8378,7 @@ void sched_move_task(struct task_struct *tsk)
        if (on_rq)
                enqueue_task(rq, tsk, 0);
 
-       task_rq_unlock(rq, &flags);
+       task_rq_unlock(rq, tsk, &flags);
 }
 #endif /* CONFIG_CGROUP_SCHED */
 
index 7bacd83a4158ca7157ae60e5e0fcec2fe8ff1e82..a6710a112b4f94912dbe4512b30fe6b2d16f172f 100644 (file)
@@ -152,7 +152,7 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
        read_lock_irqsave(&tasklist_lock, flags);
 
        do_each_thread(g, p) {
-               if (!p->se.on_rq || task_cpu(p) != rq_cpu)
+               if (!p->on_rq || task_cpu(p) != rq_cpu)
                        continue;
 
                print_task(m, rq, p);
@@ -296,9 +296,6 @@ static void print_cpu(struct seq_file *m, int cpu)
        P(ttwu_count);
        P(ttwu_local);
 
-       SEQ_printf(m, "  .%-30s: %d\n", "bkl_count",
-                               rq->rq_sched_info.bkl_count);
-
 #undef P
 #undef P64
 #endif
@@ -441,7 +438,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
        P(se.statistics.wait_count);
        PN(se.statistics.iowait_sum);
        P(se.statistics.iowait_count);
-       P(sched_info.bkl_count);
        P(se.nr_migrations);
        P(se.statistics.nr_migrations_cold);
        P(se.statistics.nr_failed_migrations_affine);
index 6fa833ab2cb80ebac3e3f38007f0d7c47995769e..37f22626225eb1afa2911f78e259a71853701b87 100644 (file)
@@ -358,6 +358,10 @@ static void update_min_vruntime(struct cfs_rq *cfs_rq)
        }
 
        cfs_rq->min_vruntime = max_vruntime(cfs_rq->min_vruntime, vruntime);
+#ifndef CONFIG_64BIT
+       smp_wmb();
+       cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
+#endif
 }
 
 /*
@@ -1340,6 +1344,8 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
        hrtick_update(rq);
 }
 
+static void set_next_buddy(struct sched_entity *se);
+
 /*
  * The dequeue_task method is called before nr_running is
  * decreased. We remove the task from the rbtree and
@@ -1349,14 +1355,22 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 {
        struct cfs_rq *cfs_rq;
        struct sched_entity *se = &p->se;
+       int task_sleep = flags & DEQUEUE_SLEEP;
 
        for_each_sched_entity(se) {
                cfs_rq = cfs_rq_of(se);
                dequeue_entity(cfs_rq, se, flags);
 
                /* Don't dequeue parent if it has other entities besides us */
-               if (cfs_rq->load.weight)
+               if (cfs_rq->load.weight) {
+                       /*
+                        * Bias pick_next to pick a task from this cfs_rq, as
+                        * p is sleeping when it is within its sched_slice.
+                        */
+                       if (task_sleep && parent_entity(se))
+                               set_next_buddy(parent_entity(se));
                        break;
+               }
                flags |= DEQUEUE_SLEEP;
        }
 
@@ -1372,12 +1386,25 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 
 #ifdef CONFIG_SMP
 
-static void task_waking_fair(struct rq *rq, struct task_struct *p)
+static void task_waking_fair(struct task_struct *p)
 {
        struct sched_entity *se = &p->se;
        struct cfs_rq *cfs_rq = cfs_rq_of(se);
+       u64 min_vruntime;
 
-       se->vruntime -= cfs_rq->min_vruntime;
+#ifndef CONFIG_64BIT
+       u64 min_vruntime_copy;
+
+       do {
+               min_vruntime_copy = cfs_rq->min_vruntime_copy;
+               smp_rmb();
+               min_vruntime = cfs_rq->min_vruntime;
+       } while (min_vruntime != min_vruntime_copy);
+#else
+       min_vruntime = cfs_rq->min_vruntime;
+#endif
+
+       se->vruntime -= min_vruntime;
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -1622,6 +1649,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
        /*
         * Otherwise, iterate the domains and find an elegible idle cpu.
         */
+       rcu_read_lock();
        for_each_domain(target, sd) {
                if (!(sd->flags & SD_SHARE_PKG_RESOURCES))
                        break;
@@ -1641,6 +1669,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
                    cpumask_test_cpu(prev_cpu, sched_domain_span(sd)))
                        break;
        }
+       rcu_read_unlock();
 
        return target;
 }
@@ -1657,7 +1686,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
  * preempt must be disabled.
  */
 static int
-select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_flags)
+select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
 {
        struct sched_domain *tmp, *affine_sd = NULL, *sd = NULL;
        int cpu = smp_processor_id();
@@ -1673,6 +1702,7 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_
                new_cpu = prev_cpu;
        }
 
+       rcu_read_lock();
        for_each_domain(cpu, tmp) {
                if (!(tmp->flags & SD_LOAD_BALANCE))
                        continue;
@@ -1723,9 +1753,10 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_
 
        if (affine_sd) {
                if (cpu == prev_cpu || wake_affine(affine_sd, p, sync))
-                       return select_idle_sibling(p, cpu);
-               else
-                       return select_idle_sibling(p, prev_cpu);
+                       prev_cpu = cpu;
+
+               new_cpu = select_idle_sibling(p, prev_cpu);
+               goto unlock;
        }
 
        while (sd) {
@@ -1766,6 +1797,8 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_
                }
                /* while loop will break here if sd == NULL */
        }
+unlock:
+       rcu_read_unlock();
 
        return new_cpu;
 }
@@ -1789,10 +1822,7 @@ wakeup_gran(struct sched_entity *curr, struct sched_entity *se)
         * This is especially important for buddies when the leftmost
         * task is higher priority than the buddy.
         */
-       if (unlikely(se->load.weight != NICE_0_LOAD))
-               gran = calc_delta_fair(gran, se);
-
-       return gran;
+       return calc_delta_fair(gran, se);
 }
 
 /*
@@ -1826,26 +1856,26 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se)
 
 static void set_last_buddy(struct sched_entity *se)
 {
-       if (likely(task_of(se)->policy != SCHED_IDLE)) {
-               for_each_sched_entity(se)
-                       cfs_rq_of(se)->last = se;
-       }
+       if (entity_is_task(se) && unlikely(task_of(se)->policy == SCHED_IDLE))
+               return;
+
+       for_each_sched_entity(se)
+               cfs_rq_of(se)->last = se;
 }
 
 static void set_next_buddy(struct sched_entity *se)
 {
-       if (likely(task_of(se)->policy != SCHED_IDLE)) {
-               for_each_sched_entity(se)
-                       cfs_rq_of(se)->next = se;
-       }
+       if (entity_is_task(se) && unlikely(task_of(se)->policy == SCHED_IDLE))
+               return;
+
+       for_each_sched_entity(se)
+               cfs_rq_of(se)->next = se;
 }
 
 static void set_skip_buddy(struct sched_entity *se)
 {
-       if (likely(task_of(se)->policy != SCHED_IDLE)) {
-               for_each_sched_entity(se)
-                       cfs_rq_of(se)->skip = se;
-       }
+       for_each_sched_entity(se)
+               cfs_rq_of(se)->skip = se;
 }
 
 /*
@@ -1857,12 +1887,15 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
        struct sched_entity *se = &curr->se, *pse = &p->se;
        struct cfs_rq *cfs_rq = task_cfs_rq(curr);
        int scale = cfs_rq->nr_running >= sched_nr_latency;
+       int next_buddy_marked = 0;
 
        if (unlikely(se == pse))
                return;
 
-       if (sched_feat(NEXT_BUDDY) && scale && !(wake_flags & WF_FORK))
+       if (sched_feat(NEXT_BUDDY) && scale && !(wake_flags & WF_FORK)) {
                set_next_buddy(pse);
+               next_buddy_marked = 1;
+       }
 
        /*
         * We can come here with TIF_NEED_RESCHED already set from new task
@@ -1890,8 +1923,15 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
        update_curr(cfs_rq);
        find_matching_se(&se, &pse);
        BUG_ON(!pse);
-       if (wakeup_preempt_entity(se, pse) == 1)
+       if (wakeup_preempt_entity(se, pse) == 1) {
+               /*
+                * Bias pick_next to pick the sched entity that is
+                * triggering this preemption.
+                */
+               if (!next_buddy_marked)
+                       set_next_buddy(pse);
                goto preempt;
+       }
 
        return;
 
@@ -2102,7 +2142,7 @@ static unsigned long
 balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
              unsigned long max_load_move, struct sched_domain *sd,
              enum cpu_idle_type idle, int *all_pinned,
-             int *this_best_prio, struct cfs_rq *busiest_cfs_rq)
+             struct cfs_rq *busiest_cfs_rq)
 {
        int loops = 0, pulled = 0;
        long rem_load_move = max_load_move;
@@ -2140,9 +2180,6 @@ balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
                 */
                if (rem_load_move <= 0)
                        break;
-
-               if (p->prio < *this_best_prio)
-                       *this_best_prio = p->prio;
        }
 out:
        /*
@@ -2202,7 +2239,7 @@ static unsigned long
 load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
                  unsigned long max_load_move,
                  struct sched_domain *sd, enum cpu_idle_type idle,
-                 int *all_pinned, int *this_best_prio)
+                 int *all_pinned)
 {
        long rem_load_move = max_load_move;
        int busiest_cpu = cpu_of(busiest);
@@ -2227,7 +2264,7 @@ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
                rem_load = div_u64(rem_load, busiest_h_load + 1);
 
                moved_load = balance_tasks(this_rq, this_cpu, busiest,
-                               rem_load, sd, idle, all_pinned, this_best_prio,
+                               rem_load, sd, idle, all_pinned,
                                busiest_cfs_rq);
 
                if (!moved_load)
@@ -2253,11 +2290,11 @@ static unsigned long
 load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
                  unsigned long max_load_move,
                  struct sched_domain *sd, enum cpu_idle_type idle,
-                 int *all_pinned, int *this_best_prio)
+                 int *all_pinned)
 {
        return balance_tasks(this_rq, this_cpu, busiest,
                        max_load_move, sd, idle, all_pinned,
-                       this_best_prio, &busiest->cfs);
+                       &busiest->cfs);
 }
 #endif
 
@@ -2274,12 +2311,11 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
                      int *all_pinned)
 {
        unsigned long total_load_moved = 0, load_moved;
-       int this_best_prio = this_rq->curr->prio;
 
        do {
                load_moved = load_balance_fair(this_rq, this_cpu, busiest,
                                max_load_move - total_load_moved,
-                               sd, idle, all_pinned, &this_best_prio);
+                               sd, idle, all_pinned);
 
                total_load_moved += load_moved;
 
@@ -2648,7 +2684,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
        /*
         * Only siblings can have significantly less than SCHED_LOAD_SCALE
         */
-       if (sd->level != SD_LV_SIBLING)
+       if (!(sd->flags & SD_SHARE_CPUPOWER))
                return 0;
 
        /*
@@ -3465,6 +3501,7 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
        raw_spin_unlock(&this_rq->lock);
 
        update_shares(this_cpu);
+       rcu_read_lock();
        for_each_domain(this_cpu, sd) {
                unsigned long interval;
                int balance = 1;
@@ -3486,6 +3523,7 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
                        break;
                }
        }
+       rcu_read_unlock();
 
        raw_spin_lock(&this_rq->lock);
 
@@ -3534,6 +3572,7 @@ static int active_load_balance_cpu_stop(void *data)
        double_lock_balance(busiest_rq, target_rq);
 
        /* Search for an sd spanning us and the target CPU. */
+       rcu_read_lock();
        for_each_domain(target_cpu, sd) {
                if ((sd->flags & SD_LOAD_BALANCE) &&
                    cpumask_test_cpu(busiest_cpu, sched_domain_span(sd)))
@@ -3549,6 +3588,7 @@ static int active_load_balance_cpu_stop(void *data)
                else
                        schedstat_inc(sd, alb_failed);
        }
+       rcu_read_unlock();
        double_unlock_balance(busiest_rq, target_rq);
 out_unlock:
        busiest_rq->active_balance = 0;
@@ -3675,6 +3715,7 @@ static int find_new_ilb(int cpu)
 {
        struct sched_domain *sd;
        struct sched_group *ilb_group;
+       int ilb = nr_cpu_ids;
 
        /*
         * Have idle load balancer selection from semi-idle packages only
@@ -3690,20 +3731,25 @@ static int find_new_ilb(int cpu)
        if (cpumask_weight(nohz.idle_cpus_mask) < 2)
                goto out_done;
 
+       rcu_read_lock();
        for_each_flag_domain(cpu, sd, SD_POWERSAVINGS_BALANCE) {
                ilb_group = sd->groups;
 
                do {
-                       if (is_semi_idle_group(ilb_group))
-                               return cpumask_first(nohz.grp_idle_mask);
+                       if (is_semi_idle_group(ilb_group)) {
+                               ilb = cpumask_first(nohz.grp_idle_mask);
+                               goto unlock;
+                       }
 
                        ilb_group = ilb_group->next;
 
                } while (ilb_group != sd->groups);
        }
+unlock:
+       rcu_read_unlock();
 
 out_done:
-       return nr_cpu_ids;
+       return ilb;
 }
 #else /*  (CONFIG_SCHED_MC || CONFIG_SCHED_SMT) */
 static inline int find_new_ilb(int call_cpu)
@@ -3848,6 +3894,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
 
        update_shares(cpu);
 
+       rcu_read_lock();
        for_each_domain(cpu, sd) {
                if (!(sd->flags & SD_LOAD_BALANCE))
                        continue;
@@ -3893,6 +3940,7 @@ out:
                if (!balance)
                        break;
        }
+       rcu_read_unlock();
 
        /*
         * next_balance will be updated only when there is a need.
index 68e69acc29b9570b10ecf8a5892ea62c48700c5c..be40f7371ee1ac2e2d91c6679bafbf798606e08e 100644 (file)
@@ -64,3 +64,9 @@ SCHED_FEAT(OWNER_SPIN, 1)
  * Decrement CPU power based on irq activity
  */
 SCHED_FEAT(NONIRQ_POWER, 1)
+
+/*
+ * Queue remote wakeups on the target CPU and process them
+ * using the scheduler IPI. Reduces rq->lock contention/bounces.
+ */
+SCHED_FEAT(TTWU_QUEUE, 1)
index a776a6396427c4ea4347b2a3e814d2d61cf69bf8..0a51882534eadfea8cb0582c15867aac9c193a26 100644 (file)
@@ -7,7 +7,7 @@
 
 #ifdef CONFIG_SMP
 static int
-select_task_rq_idle(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
+select_task_rq_idle(struct task_struct *p, int sd_flag, int flags)
 {
        return task_cpu(p); /* IDLE tasks as never migrated */
 }
index e7cebdc65f82d50e9f426a82a928d85c41f560a7..64b2a37c07d0839ffe771ecaf4fa46cb73647750 100644 (file)
@@ -183,6 +183,14 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq)
        return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period);
 }
 
+typedef struct task_group *rt_rq_iter_t;
+
+#define for_each_rt_rq(rt_rq, iter, rq) \
+       for (iter = list_entry_rcu(task_groups.next, typeof(*iter), list); \
+            (&iter->list != &task_groups) && \
+            (rt_rq = iter->rt_rq[cpu_of(rq)]); \
+            iter = list_entry_rcu(iter->list.next, typeof(*iter), list))
+
 static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq)
 {
        list_add_rcu(&rt_rq->leaf_rt_rq_list,
@@ -288,6 +296,11 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq)
        return ktime_to_ns(def_rt_bandwidth.rt_period);
 }
 
+typedef struct rt_rq *rt_rq_iter_t;
+
+#define for_each_rt_rq(rt_rq, iter, rq) \
+       for ((void) iter, rt_rq = &rq->rt; rt_rq; rt_rq = NULL)
+
 static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq)
 {
 }
@@ -402,12 +415,13 @@ next:
 static void __disable_runtime(struct rq *rq)
 {
        struct root_domain *rd = rq->rd;
+       rt_rq_iter_t iter;
        struct rt_rq *rt_rq;
 
        if (unlikely(!scheduler_running))
                return;
 
-       for_each_leaf_rt_rq(rt_rq, rq) {
+       for_each_rt_rq(rt_rq, iter, rq) {
                struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
                s64 want;
                int i;
@@ -487,6 +501,7 @@ static void disable_runtime(struct rq *rq)
 
 static void __enable_runtime(struct rq *rq)
 {
+       rt_rq_iter_t iter;
        struct rt_rq *rt_rq;
 
        if (unlikely(!scheduler_running))
@@ -495,7 +510,7 @@ static void __enable_runtime(struct rq *rq)
        /*
         * Reset each runqueue's bandwidth settings
         */
-       for_each_leaf_rt_rq(rt_rq, rq) {
+       for_each_rt_rq(rt_rq, iter, rq) {
                struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
 
                raw_spin_lock(&rt_b->rt_runtime_lock);
@@ -562,6 +577,13 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
                        if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) {
                                rt_rq->rt_throttled = 0;
                                enqueue = 1;
+
+                               /*
+                                * Force a clock update if the CPU was idle,
+                                * lest wakeup -> unthrottle time accumulate.
+                                */
+                               if (rt_rq->rt_nr_running && rq->curr == rq->idle)
+                                       rq->skip_clock_update = -1;
                        }
                        if (rt_rq->rt_time || rt_rq->rt_nr_running)
                                idle = 0;
@@ -977,13 +999,23 @@ static void yield_task_rt(struct rq *rq)
 static int find_lowest_rq(struct task_struct *task);
 
 static int
-select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
+select_task_rq_rt(struct task_struct *p, int sd_flag, int flags)
 {
+       struct task_struct *curr;
+       struct rq *rq;
+       int cpu;
+
        if (sd_flag != SD_BALANCE_WAKE)
                return smp_processor_id();
 
+       cpu = task_cpu(p);
+       rq = cpu_rq(cpu);
+
+       rcu_read_lock();
+       curr = ACCESS_ONCE(rq->curr); /* unlocked access */
+
        /*
-        * If the current task is an RT task, then
+        * If the current task on @p's runqueue is an RT task, then
         * try to see if we can wake this RT task up on another
         * runqueue. Otherwise simply start this RT task
         * on its current runqueue.
@@ -997,21 +1029,25 @@ select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
         * lock?
         *
         * For equal prio tasks, we just let the scheduler sort it out.
+        *
+        * Otherwise, just let it ride on the affined RQ and the
+        * post-schedule router will push the preempted task away
+        *
+        * This test is optimistic, if we get it wrong the load-balancer
+        * will have to sort it out.
         */
-       if (unlikely(rt_task(rq->curr)) &&
-           (rq->curr->rt.nr_cpus_allowed < 2 ||
-            rq->curr->prio < p->prio) &&
+       if (curr && unlikely(rt_task(curr)) &&
+           (curr->rt.nr_cpus_allowed < 2 ||
+            curr->prio < p->prio) &&
            (p->rt.nr_cpus_allowed > 1)) {
-               int cpu = find_lowest_rq(p);
+               int target = find_lowest_rq(p);
 
-               return (cpu == -1) ? task_cpu(p) : cpu;
+               if (target != -1)
+                       cpu = target;
        }
+       rcu_read_unlock();
 
-       /*
-        * Otherwise, just let it ride on the affined RQ and the
-        * post-schedule router will push the preempted task away
-        */
-       return task_cpu(p);
+       return cpu;
 }
 
 static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
@@ -1136,7 +1172,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
         * The previous task needs to be made eligible for pushing
         * if it is still active
         */
-       if (p->se.on_rq && p->rt.nr_cpus_allowed > 1)
+       if (on_rt_rq(&p->rt) && p->rt.nr_cpus_allowed > 1)
                enqueue_pushable_task(rq, p);
 }
 
@@ -1287,7 +1323,7 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
                                     !cpumask_test_cpu(lowest_rq->cpu,
                                                       &task->cpus_allowed) ||
                                     task_running(rq, task) ||
-                                    !task->se.on_rq)) {
+                                    !task->on_rq)) {
 
                                raw_spin_unlock(&lowest_rq->lock);
                                lowest_rq = NULL;
@@ -1321,7 +1357,7 @@ static struct task_struct *pick_next_pushable_task(struct rq *rq)
        BUG_ON(task_current(rq, p));
        BUG_ON(p->rt.nr_cpus_allowed <= 1);
 
-       BUG_ON(!p->se.on_rq);
+       BUG_ON(!p->on_rq);
        BUG_ON(!rt_task(p));
 
        return p;
@@ -1467,7 +1503,7 @@ static int pull_rt_task(struct rq *this_rq)
                 */
                if (p && (p->prio < this_rq->rt.highest_prio.curr)) {
                        WARN_ON(p == src_rq->curr);
-                       WARN_ON(!p->se.on_rq);
+                       WARN_ON(!p->on_rq);
 
                        /*
                         * There's a chance that p is higher in priority
@@ -1538,7 +1574,7 @@ static void set_cpus_allowed_rt(struct task_struct *p,
         * Update the migration status of the RQ if we have an RT task
         * which is running AND changing its weight value.
         */
-       if (p->se.on_rq && (weight != p->rt.nr_cpus_allowed)) {
+       if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
                struct rq *rq = task_rq(p);
 
                if (!task_current(rq, p)) {
@@ -1608,7 +1644,7 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p)
         * we may need to handle the pulling of RT tasks
         * now.
         */
-       if (p->se.on_rq && !rq->rt.rt_nr_running)
+       if (p->on_rq && !rq->rt.rt_nr_running)
                pull_rt_task(rq);
 }
 
@@ -1638,7 +1674,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p)
         * If that current running task is also an RT task
         * then see if we can move to another run queue.
         */
-       if (p->se.on_rq && rq->curr != p) {
+       if (p->on_rq && rq->curr != p) {
 #ifdef CONFIG_SMP
                if (rq->rt.overloaded && push_rt_task(rq) &&
                    /* Don't resched if we changed runqueues */
@@ -1657,7 +1693,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p)
 static void
 prio_changed_rt(struct rq *rq, struct task_struct *p, int oldprio)
 {
-       if (!p->se.on_rq)
+       if (!p->on_rq)
                return;
 
        if (rq->curr == p) {
@@ -1796,10 +1832,11 @@ extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq);
 
 static void print_rt_stats(struct seq_file *m, int cpu)
 {
+       rt_rq_iter_t iter;
        struct rt_rq *rt_rq;
 
        rcu_read_lock();
-       for_each_leaf_rt_rq(rt_rq, cpu_rq(cpu))
+       for_each_rt_rq(rt_rq, iter, cpu_rq(cpu))
                print_rt_rq(m, cpu, rt_rq);
        rcu_read_unlock();
 }
index 1ba2bd40fdacf3f89e0b71f0f8c1020c0151a05c..6f437632afab93351f97bb3367b3b8841dcc9546 100644 (file)
@@ -9,8 +9,7 @@
 
 #ifdef CONFIG_SMP
 static int
-select_task_rq_stop(struct rq *rq, struct task_struct *p,
-                   int sd_flag, int flags)
+select_task_rq_stop(struct task_struct *p, int sd_flag, int flags)
 {
        return task_cpu(p); /* stop tasks as never migrate */
 }
@@ -26,7 +25,7 @@ static struct task_struct *pick_next_task_stop(struct rq *rq)
 {
        struct task_struct *stop = rq->stop;
 
-       if (stop && stop->se.on_rq)
+       if (stop && stop->on_rq)
                return stop;
 
        return NULL;
index 174f976c2874a19f1d06fee972468e2c730bc7f9..13960170cad4d91f0ec00dba8e0132d64e7c68fd 100644 (file)
@@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
 char *softirq_to_name[NR_SOFTIRQS] = {
        "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
-       "TASKLET", "SCHED", "HRTIMER",  "RCU"
+       "TASKLET", "SCHED", "HRTIMER"
 };
 
 /*
index 70c4c5159420a6b286fec5858547f3ac3591ce68..e4128b278f2375dc4e91c7244fbb4117b5230fea 100644 (file)
@@ -316,7 +316,6 @@ void kernel_restart_prepare(char *cmd)
        system_state = SYSTEM_RESTART;
        usermodehelper_disable();
        device_shutdown();
-       sysdev_shutdown();
        syscore_shutdown();
 }
 
@@ -356,7 +355,6 @@ static void kernel_shutdown_prepare(enum system_states state)
 void kernel_halt(void)
 {
        kernel_shutdown_prepare(SYSTEM_HALT);
-       sysdev_shutdown();
        syscore_shutdown();
        printk(KERN_EMERG "System halted.\n");
        kmsg_dump(KMSG_DUMP_HALT);
@@ -376,7 +374,6 @@ void kernel_power_off(void)
        if (pm_power_off_prepare)
                pm_power_off_prepare();
        disable_nonboot_cpus();
-       sysdev_shutdown();
        syscore_shutdown();
        printk(KERN_EMERG "Power down.\n");
        kmsg_dump(KMSG_DUMP_POWEROFF);
index b0425991e9acbc5278379171a7c759c7e773b2b0..e2fd74b8e8c250cb9de5ec5650eb32f5d4dcd93d 100644 (file)
@@ -1,5 +1,5 @@
 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
-obj-y += timeconv.o posix-clock.o
+obj-y += timeconv.o posix-clock.o alarmtimer.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)                += clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += tick-common.o
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
new file mode 100644 (file)
index 0000000..9265014
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * Alarmtimer interface
+ *
+ * This interface provides a timer which is similarto hrtimers,
+ * but triggers a RTC alarm if the box is suspend.
+ *
+ * This interface is influenced by the Android RTC Alarm timer
+ * interface.
+ *
+ * Copyright (C) 2010 IBM Corperation
+ *
+ * Author: John Stultz <john.stultz@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/timerqueue.h>
+#include <linux/rtc.h>
+#include <linux/alarmtimer.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/posix-timers.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+
+/**
+ * struct alarm_base - Alarm timer bases
+ * @lock:              Lock for syncrhonized access to the base
+ * @timerqueue:                Timerqueue head managing the list of events
+ * @timer:             hrtimer used to schedule events while running
+ * @gettime:           Function to read the time correlating to the base
+ * @base_clockid:      clockid for the base
+ */
+static struct alarm_base {
+       spinlock_t              lock;
+       struct timerqueue_head  timerqueue;
+       struct hrtimer          timer;
+       ktime_t                 (*gettime)(void);
+       clockid_t               base_clockid;
+} alarm_bases[ALARM_NUMTYPE];
+
+#ifdef CONFIG_RTC_CLASS
+/* rtc timer and device for setting alarm wakeups at suspend */
+static struct rtc_timer                rtctimer;
+static struct rtc_device       *rtcdev;
+#endif
+
+/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
+static ktime_t freezer_delta;
+static DEFINE_SPINLOCK(freezer_delta_lock);
+
+
+/**
+ * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue
+ * @base: pointer to the base where the timer is being run
+ * @alarm: pointer to alarm being enqueued.
+ *
+ * Adds alarm to a alarm_base timerqueue and if necessary sets
+ * an hrtimer to run.
+ *
+ * Must hold base->lock when calling.
+ */
+static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
+{
+       timerqueue_add(&base->timerqueue, &alarm->node);
+       if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
+               hrtimer_try_to_cancel(&base->timer);
+               hrtimer_start(&base->timer, alarm->node.expires,
+                               HRTIMER_MODE_ABS);
+       }
+}
+
+/**
+ * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue
+ * @base: pointer to the base where the timer is running
+ * @alarm: pointer to alarm being removed
+ *
+ * Removes alarm to a alarm_base timerqueue and if necessary sets
+ * a new timer to run.
+ *
+ * Must hold base->lock when calling.
+ */
+static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
+{
+       struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
+
+       timerqueue_del(&base->timerqueue, &alarm->node);
+       if (next == &alarm->node) {
+               hrtimer_try_to_cancel(&base->timer);
+               next = timerqueue_getnext(&base->timerqueue);
+               if (!next)
+                       return;
+               hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS);
+       }
+}
+
+
+/**
+ * alarmtimer_fired - Handles alarm hrtimer being fired.
+ * @timer: pointer to hrtimer being run
+ *
+ * When a alarm timer fires, this runs through the timerqueue to
+ * see which alarms expired, and runs those. If there are more alarm
+ * timers queued for the future, we set the hrtimer to fire when
+ * when the next future alarm timer expires.
+ */
+static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
+{
+       struct alarm_base *base = container_of(timer, struct alarm_base, timer);
+       struct timerqueue_node *next;
+       unsigned long flags;
+       ktime_t now;
+       int ret = HRTIMER_NORESTART;
+
+       spin_lock_irqsave(&base->lock, flags);
+       now = base->gettime();
+       while ((next = timerqueue_getnext(&base->timerqueue))) {
+               struct alarm *alarm;
+               ktime_t expired = next->expires;
+
+               if (expired.tv64 >= now.tv64)
+                       break;
+
+               alarm = container_of(next, struct alarm, node);
+
+               timerqueue_del(&base->timerqueue, &alarm->node);
+               alarm->enabled = 0;
+               /* Re-add periodic timers */
+               if (alarm->period.tv64) {
+                       alarm->node.expires = ktime_add(expired, alarm->period);
+                       timerqueue_add(&base->timerqueue, &alarm->node);
+                       alarm->enabled = 1;
+               }
+               spin_unlock_irqrestore(&base->lock, flags);
+               if (alarm->function)
+                       alarm->function(alarm);
+               spin_lock_irqsave(&base->lock, flags);
+       }
+
+       if (next) {
+               hrtimer_set_expires(&base->timer, next->expires);
+               ret = HRTIMER_RESTART;
+       }
+       spin_unlock_irqrestore(&base->lock, flags);
+
+       return ret;
+
+}
+
+#ifdef CONFIG_RTC_CLASS
+/**
+ * alarmtimer_suspend - Suspend time callback
+ * @dev: unused
+ * @state: unused
+ *
+ * When we are going into suspend, we look through the bases
+ * to see which is the soonest timer to expire. We then
+ * set an rtc timer to fire that far into the future, which
+ * will wake us from suspend.
+ */
+static int alarmtimer_suspend(struct device *dev)
+{
+       struct rtc_time tm;
+       ktime_t min, now;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&freezer_delta_lock, flags);
+       min = freezer_delta;
+       freezer_delta = ktime_set(0, 0);
+       spin_unlock_irqrestore(&freezer_delta_lock, flags);
+
+       /* If we have no rtcdev, just return */
+       if (!rtcdev)
+               return 0;
+
+       /* Find the soonest timer to expire*/
+       for (i = 0; i < ALARM_NUMTYPE; i++) {
+               struct alarm_base *base = &alarm_bases[i];
+               struct timerqueue_node *next;
+               ktime_t delta;
+
+               spin_lock_irqsave(&base->lock, flags);
+               next = timerqueue_getnext(&base->timerqueue);
+               spin_unlock_irqrestore(&base->lock, flags);
+               if (!next)
+                       continue;
+               delta = ktime_sub(next->expires, base->gettime());
+               if (!min.tv64 || (delta.tv64 < min.tv64))
+                       min = delta;
+       }
+       if (min.tv64 == 0)
+               return 0;
+
+       /* XXX - Should we enforce a minimum sleep time? */
+       WARN_ON(min.tv64 < NSEC_PER_SEC);
+
+       /* Setup an rtc timer to fire that far in the future */
+       rtc_timer_cancel(rtcdev, &rtctimer);
+       rtc_read_time(rtcdev, &tm);
+       now = rtc_tm_to_ktime(tm);
+       now = ktime_add(now, min);
+
+       rtc_timer_start(rtcdev, &rtctimer, now, ktime_set(0, 0));
+
+       return 0;
+}
+#else
+static int alarmtimer_suspend(struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
+{
+       ktime_t delta;
+       unsigned long flags;
+       struct alarm_base *base = &alarm_bases[type];
+
+       delta = ktime_sub(absexp, base->gettime());
+
+       spin_lock_irqsave(&freezer_delta_lock, flags);
+       if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
+               freezer_delta = delta;
+       spin_unlock_irqrestore(&freezer_delta_lock, flags);
+}
+
+
+/**
+ * alarm_init - Initialize an alarm structure
+ * @alarm: ptr to alarm to be initialized
+ * @type: the type of the alarm
+ * @function: callback that is run when the alarm fires
+ */
+void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
+               void (*function)(struct alarm *))
+{
+       timerqueue_init(&alarm->node);
+       alarm->period = ktime_set(0, 0);
+       alarm->function = function;
+       alarm->type = type;
+       alarm->enabled = 0;
+}
+
+/**
+ * alarm_start - Sets an alarm to fire
+ * @alarm: ptr to alarm to set
+ * @start: time to run the alarm
+ * @period: period at which the alarm will recur
+ */
+void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       unsigned long flags;
+
+       spin_lock_irqsave(&base->lock, flags);
+       if (alarm->enabled)
+               alarmtimer_remove(base, alarm);
+       alarm->node.expires = start;
+       alarm->period = period;
+       alarmtimer_enqueue(base, alarm);
+       alarm->enabled = 1;
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
+/**
+ * alarm_cancel - Tries to cancel an alarm timer
+ * @alarm: ptr to alarm to be canceled
+ */
+void alarm_cancel(struct alarm *alarm)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       unsigned long flags;
+
+       spin_lock_irqsave(&base->lock, flags);
+       if (alarm->enabled)
+               alarmtimer_remove(base, alarm);
+       alarm->enabled = 0;
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
+
+/**
+ * clock2alarm - helper that converts from clockid to alarmtypes
+ * @clockid: clockid.
+ */
+static enum alarmtimer_type clock2alarm(clockid_t clockid)
+{
+       if (clockid == CLOCK_REALTIME_ALARM)
+               return ALARM_REALTIME;
+       if (clockid == CLOCK_BOOTTIME_ALARM)
+               return ALARM_BOOTTIME;
+       return -1;
+}
+
+/**
+ * alarm_handle_timer - Callback for posix timers
+ * @alarm: alarm that fired
+ *
+ * Posix timer callback for expired alarm timers.
+ */
+static void alarm_handle_timer(struct alarm *alarm)
+{
+       struct k_itimer *ptr = container_of(alarm, struct k_itimer,
+                                               it.alarmtimer);
+       if (posix_timer_event(ptr, 0) != 0)
+               ptr->it_overrun++;
+}
+
+/**
+ * alarm_clock_getres - posix getres interface
+ * @which_clock: clockid
+ * @tp: timespec to fill
+ *
+ * Returns the granularity of underlying alarm base clock
+ */
+static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
+{
+       clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
+
+       return hrtimer_get_res(baseid, tp);
+}
+
+/**
+ * alarm_clock_get - posix clock_get interface
+ * @which_clock: clockid
+ * @tp: timespec to fill.
+ *
+ * Provides the underlying alarm base time.
+ */
+static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+       struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
+
+       *tp = ktime_to_timespec(base->gettime());
+       return 0;
+}
+
+/**
+ * alarm_timer_create - posix timer_create interface
+ * @new_timer: k_itimer pointer to manage
+ *
+ * Initializes the k_itimer structure.
+ */
+static int alarm_timer_create(struct k_itimer *new_timer)
+{
+       enum  alarmtimer_type type;
+       struct alarm_base *base;
+
+       if (!capable(CAP_WAKE_ALARM))
+               return -EPERM;
+
+       type = clock2alarm(new_timer->it_clock);
+       base = &alarm_bases[type];
+       alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer);
+       return 0;
+}
+
+/**
+ * alarm_timer_get - posix timer_get interface
+ * @new_timer: k_itimer pointer
+ * @cur_setting: itimerspec data to fill
+ *
+ * Copies the itimerspec data out from the k_itimer
+ */
+static void alarm_timer_get(struct k_itimer *timr,
+                               struct itimerspec *cur_setting)
+{
+       cur_setting->it_interval =
+                       ktime_to_timespec(timr->it.alarmtimer.period);
+       cur_setting->it_value =
+                       ktime_to_timespec(timr->it.alarmtimer.node.expires);
+       return;
+}
+
+/**
+ * alarm_timer_del - posix timer_del interface
+ * @timr: k_itimer pointer to be deleted
+ *
+ * Cancels any programmed alarms for the given timer.
+ */
+static int alarm_timer_del(struct k_itimer *timr)
+{
+       alarm_cancel(&timr->it.alarmtimer);
+       return 0;
+}
+
+/**
+ * alarm_timer_set - posix timer_set interface
+ * @timr: k_itimer pointer to be deleted
+ * @flags: timer flags
+ * @new_setting: itimerspec to be used
+ * @old_setting: itimerspec being replaced
+ *
+ * Sets the timer to new_setting, and starts the timer.
+ */
+static int alarm_timer_set(struct k_itimer *timr, int flags,
+                               struct itimerspec *new_setting,
+                               struct itimerspec *old_setting)
+{
+       /* Save old values */
+       old_setting->it_interval =
+                       ktime_to_timespec(timr->it.alarmtimer.period);
+       old_setting->it_value =
+                       ktime_to_timespec(timr->it.alarmtimer.node.expires);
+
+       /* If the timer was already set, cancel it */
+       alarm_cancel(&timr->it.alarmtimer);
+
+       /* start the timer */
+       alarm_start(&timr->it.alarmtimer,
+                       timespec_to_ktime(new_setting->it_value),
+                       timespec_to_ktime(new_setting->it_interval));
+       return 0;
+}
+
+/**
+ * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
+ * @alarm: ptr to alarm that fired
+ *
+ * Wakes up the task that set the alarmtimer
+ */
+static void alarmtimer_nsleep_wakeup(struct alarm *alarm)
+{
+       struct task_struct *task = (struct task_struct *)alarm->data;
+
+       alarm->data = NULL;
+       if (task)
+               wake_up_process(task);
+}
+
+/**
+ * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation
+ * @alarm: ptr to alarmtimer
+ * @absexp: absolute expiration time
+ *
+ * Sets the alarm timer and sleeps until it is fired or interrupted.
+ */
+static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
+{
+       alarm->data = (void *)current;
+       do {
+               set_current_state(TASK_INTERRUPTIBLE);
+               alarm_start(alarm, absexp, ktime_set(0, 0));
+               if (likely(alarm->data))
+                       schedule();
+
+               alarm_cancel(alarm);
+       } while (alarm->data && !signal_pending(current));
+
+       __set_current_state(TASK_RUNNING);
+
+       return (alarm->data == NULL);
+}
+
+
+/**
+ * update_rmtp - Update remaining timespec value
+ * @exp: expiration time
+ * @type: timer type
+ * @rmtp: user pointer to remaining timepsec value
+ *
+ * Helper function that fills in rmtp value with time between
+ * now and the exp value
+ */
+static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
+                       struct timespec __user *rmtp)
+{
+       struct timespec rmt;
+       ktime_t rem;
+
+       rem = ktime_sub(exp, alarm_bases[type].gettime());
+
+       if (rem.tv64 <= 0)
+               return 0;
+       rmt = ktime_to_timespec(rem);
+
+       if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+               return -EFAULT;
+
+       return 1;
+
+}
+
+/**
+ * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
+ * @restart: ptr to restart block
+ *
+ * Handles restarted clock_nanosleep calls
+ */
+static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
+{
+       enum  alarmtimer_type type = restart->nanosleep.index;
+       ktime_t exp;
+       struct timespec __user  *rmtp;
+       struct alarm alarm;
+       int ret = 0;
+
+       exp.tv64 = restart->nanosleep.expires;
+       alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+
+       if (alarmtimer_do_nsleep(&alarm, exp))
+               goto out;
+
+       if (freezing(current))
+               alarmtimer_freezerset(exp, type);
+
+       rmtp = restart->nanosleep.rmtp;
+       if (rmtp) {
+               ret = update_rmtp(exp, type, rmtp);
+               if (ret <= 0)
+                       goto out;
+       }
+
+
+       /* The other values in restart are already filled in */
+       ret = -ERESTART_RESTARTBLOCK;
+out:
+       return ret;
+}
+
+/**
+ * alarm_timer_nsleep - alarmtimer nanosleep
+ * @which_clock: clockid
+ * @flags: determins abstime or relative
+ * @tsreq: requested sleep time (abs or rel)
+ * @rmtp: remaining sleep time saved
+ *
+ * Handles clock_nanosleep calls against _ALARM clockids
+ */
+static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
+                    struct timespec *tsreq, struct timespec __user *rmtp)
+{
+       enum  alarmtimer_type type = clock2alarm(which_clock);
+       struct alarm alarm;
+       ktime_t exp;
+       int ret = 0;
+       struct restart_block *restart;
+
+       if (!capable(CAP_WAKE_ALARM))
+               return -EPERM;
+
+       alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+
+       exp = timespec_to_ktime(*tsreq);
+       /* Convert (if necessary) to absolute time */
+       if (flags != TIMER_ABSTIME) {
+               ktime_t now = alarm_bases[type].gettime();
+               exp = ktime_add(now, exp);
+       }
+
+       if (alarmtimer_do_nsleep(&alarm, exp))
+               goto out;
+
+       if (freezing(current))
+               alarmtimer_freezerset(exp, type);
+
+       /* abs timers don't set remaining time or restart */
+       if (flags == TIMER_ABSTIME) {
+               ret = -ERESTARTNOHAND;
+               goto out;
+       }
+
+       if (rmtp) {
+               ret = update_rmtp(exp, type, rmtp);
+               if (ret <= 0)
+                       goto out;
+       }
+
+       restart = &current_thread_info()->restart_block;
+       restart->fn = alarm_timer_nsleep_restart;
+       restart->nanosleep.index = type;
+       restart->nanosleep.expires = exp.tv64;
+       restart->nanosleep.rmtp = rmtp;
+       ret = -ERESTART_RESTARTBLOCK;
+
+out:
+       return ret;
+}
+
+
+/* Suspend hook structures */
+static const struct dev_pm_ops alarmtimer_pm_ops = {
+       .suspend = alarmtimer_suspend,
+};
+
+static struct platform_driver alarmtimer_driver = {
+       .driver = {
+               .name = "alarmtimer",
+               .pm = &alarmtimer_pm_ops,
+       }
+};
+
+/**
+ * alarmtimer_init - Initialize alarm timer code
+ *
+ * This function initializes the alarm bases and registers
+ * the posix clock ids.
+ */
+static int __init alarmtimer_init(void)
+{
+       int error = 0;
+       int i;
+       struct k_clock alarm_clock = {
+               .clock_getres   = alarm_clock_getres,
+               .clock_get      = alarm_clock_get,
+               .timer_create   = alarm_timer_create,
+               .timer_set      = alarm_timer_set,
+               .timer_del      = alarm_timer_del,
+               .timer_get      = alarm_timer_get,
+               .nsleep         = alarm_timer_nsleep,
+       };
+
+       posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
+       posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
+
+       /* Initialize alarm bases */
+       alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
+       alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real;
+       alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME;
+       alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime;
+       for (i = 0; i < ALARM_NUMTYPE; i++) {
+               timerqueue_init_head(&alarm_bases[i].timerqueue);
+               spin_lock_init(&alarm_bases[i].lock);
+               hrtimer_init(&alarm_bases[i].timer,
+                               alarm_bases[i].base_clockid,
+                               HRTIMER_MODE_ABS);
+               alarm_bases[i].timer.function = alarmtimer_fired;
+       }
+       error = platform_driver_register(&alarmtimer_driver);
+       platform_device_register_simple("alarmtimer", -1, NULL, 0);
+
+       return error;
+}
+device_initcall(alarmtimer_init);
+
+#ifdef CONFIG_RTC_CLASS
+/**
+ * has_wakealarm - check rtc device has wakealarm ability
+ * @dev: current device
+ * @name_ptr: name to be returned
+ *
+ * This helper function checks to see if the rtc device can wake
+ * from suspend.
+ */
+static int __init has_wakealarm(struct device *dev, void *name_ptr)
+{
+       struct rtc_device *candidate = to_rtc_device(dev);
+
+       if (!candidate->ops->set_alarm)
+               return 0;
+       if (!device_may_wakeup(candidate->dev.parent))
+               return 0;
+
+       *(const char **)name_ptr = dev_name(dev);
+       return 1;
+}
+
+/**
+ * alarmtimer_init_late - Late initializing of alarmtimer code
+ *
+ * This function locates a rtc device to use for wakealarms.
+ * Run as late_initcall to make sure rtc devices have been
+ * registered.
+ */
+static int __init alarmtimer_init_late(void)
+{
+       char *str;
+
+       /* Find an rtc device and init the rtc_timer */
+       class_find_device(rtc_class, NULL, &str, has_wakealarm);
+       if (str)
+               rtcdev = rtc_class_open(str);
+       if (!rtcdev) {
+               printk(KERN_WARNING "No RTC device found, ALARM timers will"
+                       " not wake from suspend");
+       }
+       rtc_timer_init(&rtctimer, NULL, NULL);
+
+       return 0;
+}
+#else
+static int __init alarmtimer_init_late(void)
+{
+       printk(KERN_WARNING "Kernel not built with RTC support, ALARM timers"
+               " will not wake from suspend");
+       return 0;
+}
+#endif
+late_initcall(alarmtimer_init_late);
index 0d74b9ba90c84e0474b28a71ea9d43b76e4263f9..22a9da9a9c96918861caea99521285e53572bab0 100644 (file)
@@ -194,6 +194,70 @@ void clockevents_register_device(struct clock_event_device *dev)
 }
 EXPORT_SYMBOL_GPL(clockevents_register_device);
 
+static void clockevents_config(struct clock_event_device *dev,
+                              u32 freq)
+{
+       unsigned long sec;
+
+       if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
+               return;
+
+       /*
+        * Calculate the maximum number of seconds we can sleep. Limit
+        * to 10 minutes for hardware which can program more than
+        * 32bit ticks so we still get reasonable conversion values.
+        */
+       sec = dev->max_delta_ticks;
+       do_div(sec, freq);
+       if (!sec)
+               sec = 1;
+       else if (sec > 600 && dev->max_delta_ticks > UINT_MAX)
+               sec = 600;
+
+       clockevents_calc_mult_shift(dev, freq, sec);
+       dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev);
+       dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev);
+}
+
+/**
+ * clockevents_config_and_register - Configure and register a clock event device
+ * @dev:       device to register
+ * @freq:      The clock frequency
+ * @min_delta: The minimum clock ticks to program in oneshot mode
+ * @max_delta: The maximum clock ticks to program in oneshot mode
+ *
+ * min/max_delta can be 0 for devices which do not support oneshot mode.
+ */
+void clockevents_config_and_register(struct clock_event_device *dev,
+                                    u32 freq, unsigned long min_delta,
+                                    unsigned long max_delta)
+{
+       dev->min_delta_ticks = min_delta;
+       dev->max_delta_ticks = max_delta;
+       clockevents_config(dev, freq);
+       clockevents_register_device(dev);
+}
+
+/**
+ * clockevents_update_freq - Update frequency and reprogram a clock event device.
+ * @dev:       device to modify
+ * @freq:      new device frequency
+ *
+ * Reconfigure and reprogram a clock event device in oneshot
+ * mode. Must be called on the cpu for which the device delivers per
+ * cpu timer events with interrupts disabled!  Returns 0 on success,
+ * -ETIME when the event is in the past.
+ */
+int clockevents_update_freq(struct clock_event_device *dev, u32 freq)
+{
+       clockevents_config(dev, freq);
+
+       if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
+               return 0;
+
+       return clockevents_program_event(dev, dev->next_event, ktime_get());
+}
+
 /*
  * Noop handler when we shut down an event device
  */
index 6519cf62d9cd99706bb59ce0e5776733396b22ab..d9d5f8c885f65d6ac1c942412c74cacfbabe8626 100644 (file)
@@ -626,19 +626,6 @@ static void clocksource_enqueue(struct clocksource *cs)
        list_add(&cs->list, entry);
 }
 
-
-/*
- * Maximum time we expect to go between ticks. This includes idle
- * tickless time. It provides the trade off between selecting a
- * mult/shift pair that is very precise but can only handle a short
- * period of time, vs. a mult/shift pair that can handle long periods
- * of time but isn't as precise.
- *
- * This is a subsystem constant, and actual hardware limitations
- * may override it (ie: clocksources that wrap every 3 seconds).
- */
-#define MAX_UPDATE_LENGTH 5 /* Seconds */
-
 /**
  * __clocksource_updatefreq_scale - Used update clocksource with new freq
  * @t:         clocksource to be registered
@@ -652,15 +639,28 @@ static void clocksource_enqueue(struct clocksource *cs)
  */
 void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
+       unsigned long sec;
+
        /*
-        * Ideally we want to use  some of the limits used in
-        * clocksource_max_deferment, to provide a more informed
-        * MAX_UPDATE_LENGTH. But for now this just gets the
-        * register interface working properly.
+        * Calc the maximum number of seconds which we can run before
+        * wrapping around. For clocksources which have a mask > 32bit
+        * we need to limit the max sleep time to have a good
+        * conversion precision. 10 minutes is still a reasonable
+        * amount. That results in a shift value of 24 for a
+        * clocksource with mask >= 40bit and f >= 4GHz. That maps to
+        * ~ 0.06ppm granularity for NTP. We apply the same 12.5%
+        * margin as we do in clocksource_max_deferment()
         */
+       sec = (cs->mask - (cs->mask >> 5));
+       do_div(sec, freq);
+       do_div(sec, scale);
+       if (!sec)
+               sec = 1;
+       else if (sec > 600 && cs->mask > UINT_MAX)
+               sec = 600;
+
        clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
-                                     NSEC_PER_SEC/scale,
-                                     MAX_UPDATE_LENGTH*scale);
+                              NSEC_PER_SEC / scale, sec * scale);
        cs->max_idle_ns = clocksource_max_deferment(cs);
 }
 EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale);
@@ -685,8 +685,8 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
        /* Add clocksource to the clcoksource list */
        mutex_lock(&clocksource_mutex);
        clocksource_enqueue(cs);
-       clocksource_select();
        clocksource_enqueue_watchdog(cs);
+       clocksource_select();
        mutex_unlock(&clocksource_mutex);
        return 0;
 }
@@ -706,8 +706,8 @@ int clocksource_register(struct clocksource *cs)
 
        mutex_lock(&clocksource_mutex);
        clocksource_enqueue(cs);
-       clocksource_select();
        clocksource_enqueue_watchdog(cs);
+       clocksource_select();
        mutex_unlock(&clocksource_mutex);
        return 0;
 }
index 25028dd4fa18044846caa1098bf87b28c1c81be4..c340ca658f37a0c09726a31a6f126f18c9380355 100644 (file)
@@ -19,7 +19,6 @@
  */
 #include <linux/device.h>
 #include <linux/file.h>
-#include <linux/mutex.h>
 #include <linux/posix-clock.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
@@ -34,19 +33,19 @@ static struct posix_clock *get_posix_clock(struct file *fp)
 {
        struct posix_clock *clk = fp->private_data;
 
-       mutex_lock(&clk->mutex);
+       down_read(&clk->rwsem);
 
        if (!clk->zombie)
                return clk;
 
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
 
        return NULL;
 }
 
 static void put_posix_clock(struct posix_clock *clk)
 {
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
 }
 
 static ssize_t posix_clock_read(struct file *fp, char __user *buf,
@@ -156,7 +155,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
        struct posix_clock *clk =
                container_of(inode->i_cdev, struct posix_clock, cdev);
 
-       mutex_lock(&clk->mutex);
+       down_read(&clk->rwsem);
 
        if (clk->zombie) {
                err = -ENODEV;
@@ -172,7 +171,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
                fp->private_data = clk;
        }
 out:
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
        return err;
 }
 
@@ -211,25 +210,20 @@ int posix_clock_register(struct posix_clock *clk, dev_t devid)
        int err;
 
        kref_init(&clk->kref);
-       mutex_init(&clk->mutex);
+       init_rwsem(&clk->rwsem);
 
        cdev_init(&clk->cdev, &posix_clock_file_operations);
        clk->cdev.owner = clk->ops.owner;
        err = cdev_add(&clk->cdev, devid, 1);
-       if (err)
-               goto no_cdev;
 
        return err;
-no_cdev:
-       mutex_destroy(&clk->mutex);
-       return err;
 }
 EXPORT_SYMBOL_GPL(posix_clock_register);
 
 static void delete_clock(struct kref *kref)
 {
        struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-       mutex_destroy(&clk->mutex);
+
        if (clk->release)
                clk->release(clk);
 }
@@ -238,9 +232,9 @@ void posix_clock_unregister(struct posix_clock *clk)
 {
        cdev_del(&clk->cdev);
 
-       mutex_lock(&clk->mutex);
+       down_write(&clk->rwsem);
        clk->zombie = true;
-       mutex_unlock(&clk->mutex);
+       up_write(&clk->rwsem);
 
        kref_put(&clk->kref, delete_clock);
 }
index da800ffa810c2f248ebcb6e8d1aa2395343bbd0a..723c7637e55a2376766776b869d8217fb367b044 100644 (file)
@@ -522,10 +522,11 @@ static void tick_broadcast_init_next_event(struct cpumask *mask,
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
+       int cpu = smp_processor_id();
+
        /* Set it up only once ! */
        if (bc->event_handler != tick_handle_oneshot_broadcast) {
                int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
-               int cpu = smp_processor_id();
 
                bc->event_handler = tick_handle_oneshot_broadcast;
                clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
@@ -551,6 +552,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
                        tick_broadcast_set_event(tick_next_period, 1);
                } else
                        bc->next_event.tv64 = KTIME_MAX;
+       } else {
+               /*
+                * The first cpu which switches to oneshot mode sets
+                * the bit for all other cpus which are in the general
+                * (periodic) broadcast mask. So the bit is set and
+                * would prevent the first broadcast enter after this
+                * to program the bc device.
+                */
+               tick_broadcast_clear_oneshot(cpu);
        }
 }
 
index 8ad5d576755ea82021749dc0dcfc686720c57d59..8e6a05a5915a27f3f340d7ff53b44b368dab1131 100644 (file)
@@ -595,6 +595,58 @@ void __init timekeeping_init(void)
 /* time in seconds when suspend began */
 static struct timespec timekeeping_suspend_time;
 
+/**
+ * __timekeeping_inject_sleeptime - Internal function to add sleep interval
+ * @delta: pointer to a timespec delta value
+ *
+ * Takes a timespec offset measuring a suspend interval and properly
+ * adds the sleep offset to the timekeeping variables.
+ */
+static void __timekeeping_inject_sleeptime(struct timespec *delta)
+{
+       xtime = timespec_add(xtime, *delta);
+       wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta);
+       total_sleep_time = timespec_add(total_sleep_time, *delta);
+}
+
+
+/**
+ * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values
+ * @delta: pointer to a timespec delta value
+ *
+ * This hook is for architectures that cannot support read_persistent_clock
+ * because their RTC/persistent clock is only accessible when irqs are enabled.
+ *
+ * This function should only be called by rtc_resume(), and allows
+ * a suspend offset to be injected into the timekeeping values.
+ */
+void timekeeping_inject_sleeptime(struct timespec *delta)
+{
+       unsigned long flags;
+       struct timespec ts;
+
+       /* Make sure we don't set the clock twice */
+       read_persistent_clock(&ts);
+       if (!(ts.tv_sec == 0 && ts.tv_nsec == 0))
+               return;
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+       timekeeping_forward_now();
+
+       __timekeeping_inject_sleeptime(delta);
+
+       timekeeper.ntp_error = 0;
+       ntp_clear();
+       update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
+                               timekeeper.mult);
+
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       /* signal hrtimers about time change */
+       clock_was_set();
+}
+
+
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  *
@@ -615,9 +667,7 @@ static void timekeeping_resume(void)
 
        if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) {
                ts = timespec_sub(ts, timekeeping_suspend_time);
-               xtime = timespec_add(xtime, ts);
-               wall_to_monotonic = timespec_sub(wall_to_monotonic, ts);
-               total_sleep_time = timespec_add(total_sleep_time, ts);
+               __timekeeping_inject_sleeptime(&ts);
        }
        /* re-base the last cycle value */
        timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
index 61d7d59f4a1ad5175cfb14a5922c14270919167b..2ad39e556cb4a408ca09ba408e8a1ecf85fd756b 100644 (file)
@@ -141,7 +141,7 @@ if FTRACE
 config FUNCTION_TRACER
        bool "Kernel Function Tracer"
        depends on HAVE_FUNCTION_TRACER
-       select FRAME_POINTER if !ARM_UNWIND && !S390
+       select FRAME_POINTER if !ARM_UNWIND && !S390 && !MICROBLAZE
        select KALLSYMS
        select GENERIC_TRACER
        select CONTEXT_SWITCH_TRACER
index ee24fa1935ac7d25ec593ebfe3824f6339c0cea5..d017c2c82c44a084fcfc88faf7c88b32463a82c4 100644 (file)
 #include "trace_stat.h"
 
 #define FTRACE_WARN_ON(cond)                   \
-       do {                                    \
-               if (WARN_ON(cond))              \
+       ({                                      \
+               int ___r = cond;                \
+               if (WARN_ON(___r))              \
                        ftrace_kill();          \
-       } while (0)
+               ___r;                           \
+       })
 
 #define FTRACE_WARN_ON_ONCE(cond)              \
-       do {                                    \
-               if (WARN_ON_ONCE(cond))         \
+       ({                                      \
+               int ___r = cond;                \
+               if (WARN_ON_ONCE(___r))         \
                        ftrace_kill();          \
-       } while (0)
+               ___r;                           \
+       })
 
 /* hash bits for specific function selection */
 #define FTRACE_HASH_BITS 7
 #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS)
+#define FTRACE_HASH_DEFAULT_BITS 10
+#define FTRACE_HASH_MAX_BITS 12
 
 /* ftrace_enabled is a method to turn ftrace on or off */
 int ftrace_enabled __read_mostly;
@@ -81,23 +87,29 @@ static struct ftrace_ops ftrace_list_end __read_mostly =
        .func           = ftrace_stub,
 };
 
-static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
+static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end;
+static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
+static struct ftrace_ops global_ops;
+
+static void
+ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip);
 
 /*
- * Traverse the ftrace_list, invoking all entries.  The reason that we
+ * Traverse the ftrace_global_list, invoking all entries.  The reason that we
  * can use rcu_dereference_raw() is that elements removed from this list
  * are simply leaked, so there is no need to interact with a grace-period
  * mechanism.  The rcu_dereference_raw() calls are needed to handle
- * concurrent insertions into the ftrace_list.
+ * concurrent insertions into the ftrace_global_list.
  *
  * Silly Alpha and silly pointer-speculation compiler optimizations!
  */
-static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
+static void ftrace_global_list_func(unsigned long ip,
+                                   unsigned long parent_ip)
 {
-       struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/
+       struct ftrace_ops *op = rcu_dereference_raw(ftrace_global_list); /*see above*/
 
        while (op != &ftrace_list_end) {
                op->func(ip, parent_ip);
@@ -147,46 +159,69 @@ static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip)
 }
 #endif
 
-static int __register_ftrace_function(struct ftrace_ops *ops)
+static void update_global_ops(void)
 {
-       ops->next = ftrace_list;
+       ftrace_func_t func;
+
        /*
-        * We are entering ops into the ftrace_list but another
-        * CPU might be walking that list. We need to make sure
-        * the ops->next pointer is valid before another CPU sees
-        * the ops pointer included into the ftrace_list.
+        * If there's only one function registered, then call that
+        * function directly. Otherwise, we need to iterate over the
+        * registered callers.
         */
-       rcu_assign_pointer(ftrace_list, ops);
+       if (ftrace_global_list == &ftrace_list_end ||
+           ftrace_global_list->next == &ftrace_list_end)
+               func = ftrace_global_list->func;
+       else
+               func = ftrace_global_list_func;
 
-       if (ftrace_enabled) {
-               ftrace_func_t func;
+       /* If we filter on pids, update to use the pid function */
+       if (!list_empty(&ftrace_pids)) {
+               set_ftrace_pid_function(func);
+               func = ftrace_pid_func;
+       }
 
-               if (ops->next == &ftrace_list_end)
-                       func = ops->func;
-               else
-                       func = ftrace_list_func;
+       global_ops.func = func;
+}
 
-               if (!list_empty(&ftrace_pids)) {
-                       set_ftrace_pid_function(func);
-                       func = ftrace_pid_func;
-               }
+static void update_ftrace_function(void)
+{
+       ftrace_func_t func;
+
+       update_global_ops();
+
+       /*
+        * If we are at the end of the list and this ops is
+        * not dynamic, then have the mcount trampoline call
+        * the function directly
+        */
+       if (ftrace_ops_list == &ftrace_list_end ||
+           (ftrace_ops_list->next == &ftrace_list_end &&
+            !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC)))
+               func = ftrace_ops_list->func;
+       else
+               func = ftrace_ops_list_func;
 
-               /*
-                * For one func, simply call it directly.
-                * For more than one func, call the chain.
-                */
 #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-               ftrace_trace_function = func;
+       ftrace_trace_function = func;
 #else
-               __ftrace_trace_function = func;
-               ftrace_trace_function = ftrace_test_stop_func;
+       __ftrace_trace_function = func;
+       ftrace_trace_function = ftrace_test_stop_func;
 #endif
-       }
+}
 
-       return 0;
+static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
+{
+       ops->next = *list;
+       /*
+        * We are entering ops into the list but another
+        * CPU might be walking that list. We need to make sure
+        * the ops->next pointer is valid before another CPU sees
+        * the ops pointer included into the list.
+        */
+       rcu_assign_pointer(*list, ops);
 }
 
-static int __unregister_ftrace_function(struct ftrace_ops *ops)
+static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
 {
        struct ftrace_ops **p;
 
@@ -194,13 +229,12 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
         * If we are removing the last function, then simply point
         * to the ftrace_stub.
         */
-       if (ftrace_list == ops && ops->next == &ftrace_list_end) {
-               ftrace_trace_function = ftrace_stub;
-               ftrace_list = &ftrace_list_end;
+       if (*list == ops && ops->next == &ftrace_list_end) {
+               *list = &ftrace_list_end;
                return 0;
        }
 
-       for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next)
+       for (p = list; *p != &ftrace_list_end; p = &(*p)->next)
                if (*p == ops)
                        break;
 
@@ -208,53 +242,83 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
                return -1;
 
        *p = (*p)->next;
+       return 0;
+}
 
-       if (ftrace_enabled) {
-               /* If we only have one func left, then call that directly */
-               if (ftrace_list->next == &ftrace_list_end) {
-                       ftrace_func_t func = ftrace_list->func;
+static int __register_ftrace_function(struct ftrace_ops *ops)
+{
+       if (ftrace_disabled)
+               return -ENODEV;
 
-                       if (!list_empty(&ftrace_pids)) {
-                               set_ftrace_pid_function(func);
-                               func = ftrace_pid_func;
-                       }
-#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-                       ftrace_trace_function = func;
-#else
-                       __ftrace_trace_function = func;
-#endif
-               }
-       }
+       if (FTRACE_WARN_ON(ops == &global_ops))
+               return -EINVAL;
+
+       if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED))
+               return -EBUSY;
+
+       if (!core_kernel_data((unsigned long)ops))
+               ops->flags |= FTRACE_OPS_FL_DYNAMIC;
+
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               int first = ftrace_global_list == &ftrace_list_end;
+               add_ftrace_ops(&ftrace_global_list, ops);
+               ops->flags |= FTRACE_OPS_FL_ENABLED;
+               if (first)
+                       add_ftrace_ops(&ftrace_ops_list, &global_ops);
+       } else
+               add_ftrace_ops(&ftrace_ops_list, ops);
+
+       if (ftrace_enabled)
+               update_ftrace_function();
 
        return 0;
 }
 
-static void ftrace_update_pid_func(void)
+static int __unregister_ftrace_function(struct ftrace_ops *ops)
 {
-       ftrace_func_t func;
+       int ret;
 
-       if (ftrace_trace_function == ftrace_stub)
-               return;
+       if (ftrace_disabled)
+               return -ENODEV;
 
-#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-       func = ftrace_trace_function;
-#else
-       func = __ftrace_trace_function;
-#endif
+       if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
+               return -EBUSY;
 
-       if (!list_empty(&ftrace_pids)) {
-               set_ftrace_pid_function(func);
-               func = ftrace_pid_func;
-       } else {
-               if (func == ftrace_pid_func)
-                       func = ftrace_pid_function;
-       }
+       if (FTRACE_WARN_ON(ops == &global_ops))
+               return -EINVAL;
 
-#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-       ftrace_trace_function = func;
-#else
-       __ftrace_trace_function = func;
-#endif
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ret = remove_ftrace_ops(&ftrace_global_list, ops);
+               if (!ret && ftrace_global_list == &ftrace_list_end)
+                       ret = remove_ftrace_ops(&ftrace_ops_list, &global_ops);
+               if (!ret)
+                       ops->flags &= ~FTRACE_OPS_FL_ENABLED;
+       } else
+               ret = remove_ftrace_ops(&ftrace_ops_list, ops);
+
+       if (ret < 0)
+               return ret;
+
+       if (ftrace_enabled)
+               update_ftrace_function();
+
+       /*
+        * Dynamic ops may be freed, we must make sure that all
+        * callers are done before leaving this function.
+        */
+       if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
+               synchronize_sched();
+
+       return 0;
+}
+
+static void ftrace_update_pid_func(void)
+{
+       /* Only do something if we are tracing something */
+       if (ftrace_trace_function == ftrace_stub)
+               return;
+
+       update_ftrace_function();
 }
 
 #ifdef CONFIG_FUNCTION_PROFILER
@@ -888,8 +952,35 @@ enum {
        FTRACE_START_FUNC_RET           = (1 << 3),
        FTRACE_STOP_FUNC_RET            = (1 << 4),
 };
+struct ftrace_func_entry {
+       struct hlist_node hlist;
+       unsigned long ip;
+};
+
+struct ftrace_hash {
+       unsigned long           size_bits;
+       struct hlist_head       *buckets;
+       unsigned long           count;
+       struct rcu_head         rcu;
+};
+
+/*
+ * We make these constant because no one should touch them,
+ * but they are used as the default "empty hash", to avoid allocating
+ * it all the time. These are in a read only section such that if
+ * anyone does try to modify it, it will cause an exception.
+ */
+static const struct hlist_head empty_buckets[1];
+static const struct ftrace_hash empty_hash = {
+       .buckets = (struct hlist_head *)empty_buckets,
+};
+#define EMPTY_HASH     ((struct ftrace_hash *)&empty_hash)
 
-static int ftrace_filtered;
+static struct ftrace_ops global_ops = {
+       .func                   = ftrace_stub,
+       .notrace_hash           = EMPTY_HASH,
+       .filter_hash            = EMPTY_HASH,
+};
 
 static struct dyn_ftrace *ftrace_new_addrs;
 
@@ -912,6 +1003,269 @@ static struct ftrace_page        *ftrace_pages;
 
 static struct dyn_ftrace *ftrace_free_records;
 
+static struct ftrace_func_entry *
+ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
+{
+       unsigned long key;
+       struct ftrace_func_entry *entry;
+       struct hlist_head *hhd;
+       struct hlist_node *n;
+
+       if (!hash->count)
+               return NULL;
+
+       if (hash->size_bits > 0)
+               key = hash_long(ip, hash->size_bits);
+       else
+               key = 0;
+
+       hhd = &hash->buckets[key];
+
+       hlist_for_each_entry_rcu(entry, n, hhd, hlist) {
+               if (entry->ip == ip)
+                       return entry;
+       }
+       return NULL;
+}
+
+static void __add_hash_entry(struct ftrace_hash *hash,
+                            struct ftrace_func_entry *entry)
+{
+       struct hlist_head *hhd;
+       unsigned long key;
+
+       if (hash->size_bits)
+               key = hash_long(entry->ip, hash->size_bits);
+       else
+               key = 0;
+
+       hhd = &hash->buckets[key];
+       hlist_add_head(&entry->hlist, hhd);
+       hash->count++;
+}
+
+static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip)
+{
+       struct ftrace_func_entry *entry;
+
+       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->ip = ip;
+       __add_hash_entry(hash, entry);
+
+       return 0;
+}
+
+static void
+free_hash_entry(struct ftrace_hash *hash,
+                 struct ftrace_func_entry *entry)
+{
+       hlist_del(&entry->hlist);
+       kfree(entry);
+       hash->count--;
+}
+
+static void
+remove_hash_entry(struct ftrace_hash *hash,
+                 struct ftrace_func_entry *entry)
+{
+       hlist_del(&entry->hlist);
+       hash->count--;
+}
+
+static void ftrace_hash_clear(struct ftrace_hash *hash)
+{
+       struct hlist_head *hhd;
+       struct hlist_node *tp, *tn;
+       struct ftrace_func_entry *entry;
+       int size = 1 << hash->size_bits;
+       int i;
+
+       if (!hash->count)
+               return;
+
+       for (i = 0; i < size; i++) {
+               hhd = &hash->buckets[i];
+               hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist)
+                       free_hash_entry(hash, entry);
+       }
+       FTRACE_WARN_ON(hash->count);
+}
+
+static void free_ftrace_hash(struct ftrace_hash *hash)
+{
+       if (!hash || hash == EMPTY_HASH)
+               return;
+       ftrace_hash_clear(hash);
+       kfree(hash->buckets);
+       kfree(hash);
+}
+
+static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
+{
+       struct ftrace_hash *hash;
+
+       hash = container_of(rcu, struct ftrace_hash, rcu);
+       free_ftrace_hash(hash);
+}
+
+static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
+{
+       if (!hash || hash == EMPTY_HASH)
+               return;
+       call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu);
+}
+
+static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
+{
+       struct ftrace_hash *hash;
+       int size;
+
+       hash = kzalloc(sizeof(*hash), GFP_KERNEL);
+       if (!hash)
+               return NULL;
+
+       size = 1 << size_bits;
+       hash->buckets = kzalloc(sizeof(*hash->buckets) * size, GFP_KERNEL);
+
+       if (!hash->buckets) {
+               kfree(hash);
+               return NULL;
+       }
+
+       hash->size_bits = size_bits;
+
+       return hash;
+}
+
+static struct ftrace_hash *
+alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
+{
+       struct ftrace_func_entry *entry;
+       struct ftrace_hash *new_hash;
+       struct hlist_node *tp;
+       int size;
+       int ret;
+       int i;
+
+       new_hash = alloc_ftrace_hash(size_bits);
+       if (!new_hash)
+               return NULL;
+
+       /* Empty hash? */
+       if (!hash || !hash->count)
+               return new_hash;
+
+       size = 1 << hash->size_bits;
+       for (i = 0; i < size; i++) {
+               hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) {
+                       ret = add_hash_entry(new_hash, entry->ip);
+                       if (ret < 0)
+                               goto free_hash;
+               }
+       }
+
+       FTRACE_WARN_ON(new_hash->count != hash->count);
+
+       return new_hash;
+
+ free_hash:
+       free_ftrace_hash(new_hash);
+       return NULL;
+}
+
+static int
+ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
+{
+       struct ftrace_func_entry *entry;
+       struct hlist_node *tp, *tn;
+       struct hlist_head *hhd;
+       struct ftrace_hash *old_hash;
+       struct ftrace_hash *new_hash;
+       unsigned long key;
+       int size = src->count;
+       int bits = 0;
+       int i;
+
+       /*
+        * If the new source is empty, just free dst and assign it
+        * the empty_hash.
+        */
+       if (!src->count) {
+               free_ftrace_hash_rcu(*dst);
+               rcu_assign_pointer(*dst, EMPTY_HASH);
+               return 0;
+       }
+
+       /*
+        * Make the hash size about 1/2 the # found
+        */
+       for (size /= 2; size; size >>= 1)
+               bits++;
+
+       /* Don't allocate too much */
+       if (bits > FTRACE_HASH_MAX_BITS)
+               bits = FTRACE_HASH_MAX_BITS;
+
+       new_hash = alloc_ftrace_hash(bits);
+       if (!new_hash)
+               return -ENOMEM;
+
+       size = 1 << src->size_bits;
+       for (i = 0; i < size; i++) {
+               hhd = &src->buckets[i];
+               hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) {
+                       if (bits > 0)
+                               key = hash_long(entry->ip, bits);
+                       else
+                               key = 0;
+                       remove_hash_entry(src, entry);
+                       __add_hash_entry(new_hash, entry);
+               }
+       }
+
+       old_hash = *dst;
+       rcu_assign_pointer(*dst, new_hash);
+       free_ftrace_hash_rcu(old_hash);
+
+       return 0;
+}
+
+/*
+ * Test the hashes for this ops to see if we want to call
+ * the ops->func or not.
+ *
+ * It's a match if the ip is in the ops->filter_hash or
+ * the filter_hash does not exist or is empty,
+ *  AND
+ * the ip is not in the ops->notrace_hash.
+ *
+ * This needs to be called with preemption disabled as
+ * the hashes are freed with call_rcu_sched().
+ */
+static int
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+{
+       struct ftrace_hash *filter_hash;
+       struct ftrace_hash *notrace_hash;
+       int ret;
+
+       filter_hash = rcu_dereference_raw(ops->filter_hash);
+       notrace_hash = rcu_dereference_raw(ops->notrace_hash);
+
+       if ((!filter_hash || !filter_hash->count ||
+            ftrace_lookup_ip(filter_hash, ip)) &&
+           (!notrace_hash || !notrace_hash->count ||
+            !ftrace_lookup_ip(notrace_hash, ip)))
+               ret = 1;
+       else
+               ret = 0;
+
+       return ret;
+}
+
 /*
  * This is a double for. Do not use 'break' to break out of the loop,
  * you must use a goto.
@@ -926,6 +1280,105 @@ static struct dyn_ftrace *ftrace_free_records;
                }                               \
        }
 
+static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
+                                    int filter_hash,
+                                    bool inc)
+{
+       struct ftrace_hash *hash;
+       struct ftrace_hash *other_hash;
+       struct ftrace_page *pg;
+       struct dyn_ftrace *rec;
+       int count = 0;
+       int all = 0;
+
+       /* Only update if the ops has been registered */
+       if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
+               return;
+
+       /*
+        * In the filter_hash case:
+        *   If the count is zero, we update all records.
+        *   Otherwise we just update the items in the hash.
+        *
+        * In the notrace_hash case:
+        *   We enable the update in the hash.
+        *   As disabling notrace means enabling the tracing,
+        *   and enabling notrace means disabling, the inc variable
+        *   gets inversed.
+        */
+       if (filter_hash) {
+               hash = ops->filter_hash;
+               other_hash = ops->notrace_hash;
+               if (!hash || !hash->count)
+                       all = 1;
+       } else {
+               inc = !inc;
+               hash = ops->notrace_hash;
+               other_hash = ops->filter_hash;
+               /*
+                * If the notrace hash has no items,
+                * then there's nothing to do.
+                */
+               if (hash && !hash->count)
+                       return;
+       }
+
+       do_for_each_ftrace_rec(pg, rec) {
+               int in_other_hash = 0;
+               int in_hash = 0;
+               int match = 0;
+
+               if (all) {
+                       /*
+                        * Only the filter_hash affects all records.
+                        * Update if the record is not in the notrace hash.
+                        */
+                       if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
+                               match = 1;
+               } else {
+                       in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip);
+                       in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip);
+
+                       /*
+                        *
+                        */
+                       if (filter_hash && in_hash && !in_other_hash)
+                               match = 1;
+                       else if (!filter_hash && in_hash &&
+                                (in_other_hash || !other_hash->count))
+                               match = 1;
+               }
+               if (!match)
+                       continue;
+
+               if (inc) {
+                       rec->flags++;
+                       if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX))
+                               return;
+               } else {
+                       if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
+                               return;
+                       rec->flags--;
+               }
+               count++;
+               /* Shortcut, if we handled all records, we are done. */
+               if (!all && count == hash->count)
+                       return;
+       } while_for_each_ftrace_rec();
+}
+
+static void ftrace_hash_rec_disable(struct ftrace_ops *ops,
+                                   int filter_hash)
+{
+       __ftrace_hash_rec_update(ops, filter_hash, 0);
+}
+
+static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
+                                  int filter_hash)
+{
+       __ftrace_hash_rec_update(ops, filter_hash, 1);
+}
+
 static void ftrace_free_rec(struct dyn_ftrace *rec)
 {
        rec->freelist = ftrace_free_records;
@@ -1047,18 +1500,18 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
        ftrace_addr = (unsigned long)FTRACE_ADDR;
 
        /*
-        * If this record is not to be traced or we want to disable it,
-        * then disable it.
+        * If we are enabling tracing:
+        *
+        *   If the record has a ref count, then we need to enable it
+        *   because someone is using it.
         *
-        * If we want to enable it and filtering is off, then enable it.
+        *   Otherwise we make sure its disabled.
         *
-        * If we want to enable it and filtering is on, enable it only if
-        * it's filtered
+        * If we are disabling tracing, then disable all records that
+        * are enabled.
         */
-       if (enable && !(rec->flags & FTRACE_FL_NOTRACE)) {
-               if (!ftrace_filtered || (rec->flags & FTRACE_FL_FILTER))
-                       flag = FTRACE_FL_ENABLED;
-       }
+       if (enable && (rec->flags & ~FTRACE_FL_MASK))
+               flag = FTRACE_FL_ENABLED;
 
        /* If the state of this record hasn't changed, then do nothing */
        if ((rec->flags & FTRACE_FL_ENABLED) == flag)
@@ -1079,19 +1532,16 @@ static void ftrace_replace_code(int enable)
        struct ftrace_page *pg;
        int failed;
 
+       if (unlikely(ftrace_disabled))
+               return;
+
        do_for_each_ftrace_rec(pg, rec) {
-               /*
-                * Skip over free records, records that have
-                * failed and not converted.
-                */
-               if (rec->flags & FTRACE_FL_FREE ||
-                   rec->flags & FTRACE_FL_FAILED ||
-                   !(rec->flags & FTRACE_FL_CONVERTED))
+               /* Skip over free records */
+               if (rec->flags & FTRACE_FL_FREE)
                        continue;
 
                failed = __ftrace_replace_code(rec, enable);
                if (failed) {
-                       rec->flags |= FTRACE_FL_FAILED;
                        ftrace_bug(failed, rec->ip);
                        /* Stop processing */
                        return;
@@ -1107,10 +1557,12 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
 
        ip = rec->ip;
 
+       if (unlikely(ftrace_disabled))
+               return 0;
+
        ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
        if (ret) {
                ftrace_bug(ret, ip);
-               rec->flags |= FTRACE_FL_FAILED;
                return 0;
        }
        return 1;
@@ -1171,6 +1623,7 @@ static void ftrace_run_update_code(int command)
 
 static ftrace_func_t saved_ftrace_func;
 static int ftrace_start_up;
+static int global_start_up;
 
 static void ftrace_startup_enable(int command)
 {
@@ -1185,19 +1638,36 @@ static void ftrace_startup_enable(int command)
        ftrace_run_update_code(command);
 }
 
-static void ftrace_startup(int command)
+static void ftrace_startup(struct ftrace_ops *ops, int command)
 {
+       bool hash_enable = true;
+
        if (unlikely(ftrace_disabled))
                return;
 
        ftrace_start_up++;
        command |= FTRACE_ENABLE_CALLS;
 
+       /* ops marked global share the filter hashes */
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ops = &global_ops;
+               /* Don't update hash if global is already set */
+               if (global_start_up)
+                       hash_enable = false;
+               global_start_up++;
+       }
+
+       ops->flags |= FTRACE_OPS_FL_ENABLED;
+       if (hash_enable)
+               ftrace_hash_rec_enable(ops, 1);
+
        ftrace_startup_enable(command);
 }
 
-static void ftrace_shutdown(int command)
+static void ftrace_shutdown(struct ftrace_ops *ops, int command)
 {
+       bool hash_disable = true;
+
        if (unlikely(ftrace_disabled))
                return;
 
@@ -1209,6 +1679,23 @@ static void ftrace_shutdown(int command)
         */
        WARN_ON_ONCE(ftrace_start_up < 0);
 
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ops = &global_ops;
+               global_start_up--;
+               WARN_ON_ONCE(global_start_up < 0);
+               /* Don't update hash if global still has users */
+               if (global_start_up) {
+                       WARN_ON_ONCE(!ftrace_start_up);
+                       hash_disable = false;
+               }
+       }
+
+       if (hash_disable)
+               ftrace_hash_rec_disable(ops, 1);
+
+       if (ops != &global_ops || !global_start_up)
+               ops->flags &= ~FTRACE_OPS_FL_ENABLED;
+
        if (!ftrace_start_up)
                command |= FTRACE_DISABLE_CALLS;
 
@@ -1273,10 +1760,10 @@ static int ftrace_update_code(struct module *mod)
                 */
                if (!ftrace_code_disable(mod, p)) {
                        ftrace_free_rec(p);
-                       continue;
+                       /* Game over */
+                       break;
                }
 
-               p->flags |= FTRACE_FL_CONVERTED;
                ftrace_update_cnt++;
 
                /*
@@ -1351,9 +1838,9 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
 enum {
        FTRACE_ITER_FILTER      = (1 << 0),
        FTRACE_ITER_NOTRACE     = (1 << 1),
-       FTRACE_ITER_FAILURES    = (1 << 2),
-       FTRACE_ITER_PRINTALL    = (1 << 3),
-       FTRACE_ITER_HASH        = (1 << 4),
+       FTRACE_ITER_PRINTALL    = (1 << 2),
+       FTRACE_ITER_HASH        = (1 << 3),
+       FTRACE_ITER_ENABLED     = (1 << 4),
 };
 
 #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
@@ -1365,6 +1852,8 @@ struct ftrace_iterator {
        struct dyn_ftrace               *func;
        struct ftrace_func_probe        *probe;
        struct trace_parser             parser;
+       struct ftrace_hash              *hash;
+       struct ftrace_ops               *ops;
        int                             hidx;
        int                             idx;
        unsigned                        flags;
@@ -1461,8 +1950,12 @@ static void *
 t_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct ftrace_iterator *iter = m->private;
+       struct ftrace_ops *ops = &global_ops;
        struct dyn_ftrace *rec = NULL;
 
+       if (unlikely(ftrace_disabled))
+               return NULL;
+
        if (iter->flags & FTRACE_ITER_HASH)
                return t_hash_next(m, pos);
 
@@ -1483,17 +1976,15 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                rec = &iter->pg->records[iter->idx++];
                if ((rec->flags & FTRACE_FL_FREE) ||
 
-                   (!(iter->flags & FTRACE_ITER_FAILURES) &&
-                    (rec->flags & FTRACE_FL_FAILED)) ||
-
-                   ((iter->flags & FTRACE_ITER_FAILURES) &&
-                    !(rec->flags & FTRACE_FL_FAILED)) ||
-
                    ((iter->flags & FTRACE_ITER_FILTER) &&
-                    !(rec->flags & FTRACE_FL_FILTER)) ||
+                    !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||
 
                    ((iter->flags & FTRACE_ITER_NOTRACE) &&
-                    !(rec->flags & FTRACE_FL_NOTRACE))) {
+                    !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) ||
+
+                   ((iter->flags & FTRACE_ITER_ENABLED) &&
+                    !(rec->flags & ~FTRACE_FL_MASK))) {
+
                        rec = NULL;
                        goto retry;
                }
@@ -1517,10 +2008,15 @@ static void reset_iter_read(struct ftrace_iterator *iter)
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
        struct ftrace_iterator *iter = m->private;
+       struct ftrace_ops *ops = &global_ops;
        void *p = NULL;
        loff_t l;
 
        mutex_lock(&ftrace_lock);
+
+       if (unlikely(ftrace_disabled))
+               return NULL;
+
        /*
         * If an lseek was done, then reset and start from beginning.
         */
@@ -1532,7 +2028,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
         * off, we can short cut and just print out that all
         * functions are enabled.
         */
-       if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) {
+       if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) {
                if (*pos > 0)
                        return t_hash_start(m, pos);
                iter->flags |= FTRACE_ITER_PRINTALL;
@@ -1590,7 +2086,11 @@ static int t_show(struct seq_file *m, void *v)
        if (!rec)
                return 0;
 
-       seq_printf(m, "%ps\n", (void *)rec->ip);
+       seq_printf(m, "%ps", (void *)rec->ip);
+       if (iter->flags & FTRACE_ITER_ENABLED)
+               seq_printf(m, " (%ld)",
+                          rec->flags & ~FTRACE_FL_MASK);
+       seq_printf(m, "\n");
 
        return 0;
 }
@@ -1603,7 +2103,34 @@ static const struct seq_operations show_ftrace_seq_ops = {
 };
 
 static int
-ftrace_avail_open(struct inode *inode, struct file *file)
+ftrace_avail_open(struct inode *inode, struct file *file)
+{
+       struct ftrace_iterator *iter;
+       int ret;
+
+       if (unlikely(ftrace_disabled))
+               return -ENODEV;
+
+       iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+       if (!iter)
+               return -ENOMEM;
+
+       iter->pg = ftrace_pages_start;
+
+       ret = seq_open(file, &show_ftrace_seq_ops);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+
+               m->private = iter;
+       } else {
+               kfree(iter);
+       }
+
+       return ret;
+}
+
+static int
+ftrace_enabled_open(struct inode *inode, struct file *file)
 {
        struct ftrace_iterator *iter;
        int ret;
@@ -1616,6 +2143,7 @@ ftrace_avail_open(struct inode *inode, struct file *file)
                return -ENOMEM;
 
        iter->pg = ftrace_pages_start;
+       iter->flags = FTRACE_ITER_ENABLED;
 
        ret = seq_open(file, &show_ftrace_seq_ops);
        if (!ret) {
@@ -1629,45 +2157,19 @@ ftrace_avail_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static int
-ftrace_failures_open(struct inode *inode, struct file *file)
-{
-       int ret;
-       struct seq_file *m;
-       struct ftrace_iterator *iter;
-
-       ret = ftrace_avail_open(inode, file);
-       if (!ret) {
-               m = file->private_data;
-               iter = m->private;
-               iter->flags = FTRACE_ITER_FAILURES;
-       }
-
-       return ret;
-}
-
-
-static void ftrace_filter_reset(int enable)
+static void ftrace_filter_reset(struct ftrace_hash *hash)
 {
-       struct ftrace_page *pg;
-       struct dyn_ftrace *rec;
-       unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
-
        mutex_lock(&ftrace_lock);
-       if (enable)
-               ftrace_filtered = 0;
-       do_for_each_ftrace_rec(pg, rec) {
-               if (rec->flags & FTRACE_FL_FAILED)
-                       continue;
-               rec->flags &= ~type;
-       } while_for_each_ftrace_rec();
+       ftrace_hash_clear(hash);
        mutex_unlock(&ftrace_lock);
 }
 
 static int
-ftrace_regex_open(struct inode *inode, struct file *file, int enable)
+ftrace_regex_open(struct ftrace_ops *ops, int flag,
+                 struct inode *inode, struct file *file)
 {
        struct ftrace_iterator *iter;
+       struct ftrace_hash *hash;
        int ret = 0;
 
        if (unlikely(ftrace_disabled))
@@ -1682,21 +2184,42 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
                return -ENOMEM;
        }
 
+       if (flag & FTRACE_ITER_NOTRACE)
+               hash = ops->notrace_hash;
+       else
+               hash = ops->filter_hash;
+
+       iter->ops = ops;
+       iter->flags = flag;
+
+       if (file->f_mode & FMODE_WRITE) {
+               mutex_lock(&ftrace_lock);
+               iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
+               mutex_unlock(&ftrace_lock);
+
+               if (!iter->hash) {
+                       trace_parser_put(&iter->parser);
+                       kfree(iter);
+                       return -ENOMEM;
+               }
+       }
+
        mutex_lock(&ftrace_regex_lock);
+
        if ((file->f_mode & FMODE_WRITE) &&
            (file->f_flags & O_TRUNC))
-               ftrace_filter_reset(enable);
+               ftrace_filter_reset(iter->hash);
 
        if (file->f_mode & FMODE_READ) {
                iter->pg = ftrace_pages_start;
-               iter->flags = enable ? FTRACE_ITER_FILTER :
-                       FTRACE_ITER_NOTRACE;
 
                ret = seq_open(file, &show_ftrace_seq_ops);
                if (!ret) {
                        struct seq_file *m = file->private_data;
                        m->private = iter;
                } else {
+                       /* Failed */
+                       free_ftrace_hash(iter->hash);
                        trace_parser_put(&iter->parser);
                        kfree(iter);
                }
@@ -1710,13 +2233,15 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
 static int
 ftrace_filter_open(struct inode *inode, struct file *file)
 {
-       return ftrace_regex_open(inode, file, 1);
+       return ftrace_regex_open(&global_ops, FTRACE_ITER_FILTER,
+                                inode, file);
 }
 
 static int
 ftrace_notrace_open(struct inode *inode, struct file *file)
 {
-       return ftrace_regex_open(inode, file, 0);
+       return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE,
+                                inode, file);
 }
 
 static loff_t
@@ -1761,86 +2286,99 @@ static int ftrace_match(char *str, char *regex, int len, int type)
 }
 
 static int
-ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
+enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not)
+{
+       struct ftrace_func_entry *entry;
+       int ret = 0;
+
+       entry = ftrace_lookup_ip(hash, rec->ip);
+       if (not) {
+               /* Do nothing if it doesn't exist */
+               if (!entry)
+                       return 0;
+
+               free_hash_entry(hash, entry);
+       } else {
+               /* Do nothing if it exists */
+               if (entry)
+                       return 0;
+
+               ret = add_hash_entry(hash, rec->ip);
+       }
+       return ret;
+}
+
+static int
+ftrace_match_record(struct dyn_ftrace *rec, char *mod,
+                   char *regex, int len, int type)
 {
        char str[KSYM_SYMBOL_LEN];
+       char *modname;
+
+       kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
+
+       if (mod) {
+               /* module lookup requires matching the module */
+               if (!modname || strcmp(modname, mod))
+                       return 0;
+
+               /* blank search means to match all funcs in the mod */
+               if (!len)
+                       return 1;
+       }
 
-       kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
        return ftrace_match(str, regex, len, type);
 }
 
-static int ftrace_match_records(char *buff, int len, int enable)
+static int
+match_records(struct ftrace_hash *hash, char *buff,
+             int len, char *mod, int not)
 {
-       unsigned int search_len;
+       unsigned search_len = 0;
        struct ftrace_page *pg;
        struct dyn_ftrace *rec;
-       unsigned long flag;
-       char *search;
-       int type;
-       int not;
+       int type = MATCH_FULL;
+       char *search = buff;
        int found = 0;
+       int ret;
 
-       flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
-       type = filter_parse_regex(buff, len, &search, &not);
-
-       search_len = strlen(search);
+       if (len) {
+               type = filter_parse_regex(buff, len, &search, &not);
+               search_len = strlen(search);
+       }
 
        mutex_lock(&ftrace_lock);
-       do_for_each_ftrace_rec(pg, rec) {
 
-               if (rec->flags & FTRACE_FL_FAILED)
-                       continue;
+       if (unlikely(ftrace_disabled))
+               goto out_unlock;
 
-               if (ftrace_match_record(rec, search, search_len, type)) {
-                       if (not)
-                               rec->flags &= ~flag;
-                       else
-                               rec->flags |= flag;
+       do_for_each_ftrace_rec(pg, rec) {
+
+               if (ftrace_match_record(rec, mod, search, search_len, type)) {
+                       ret = enter_record(hash, rec, not);
+                       if (ret < 0) {
+                               found = ret;
+                               goto out_unlock;
+                       }
                        found = 1;
                }
-               /*
-                * Only enable filtering if we have a function that
-                * is filtered on.
-                */
-               if (enable && (rec->flags & FTRACE_FL_FILTER))
-                       ftrace_filtered = 1;
        } while_for_each_ftrace_rec();
+ out_unlock:
        mutex_unlock(&ftrace_lock);
 
        return found;
 }
 
 static int
-ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
-                          char *regex, int len, int type)
+ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
 {
-       char str[KSYM_SYMBOL_LEN];
-       char *modname;
-
-       kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
-
-       if (!modname || strcmp(modname, mod))
-               return 0;
-
-       /* blank search means to match all funcs in the mod */
-       if (len)
-               return ftrace_match(str, regex, len, type);
-       else
-               return 1;
+       return match_records(hash, buff, len, NULL, 0);
 }
 
-static int ftrace_match_module_records(char *buff, char *mod, int enable)
+static int
+ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
 {
-       unsigned search_len = 0;
-       struct ftrace_page *pg;
-       struct dyn_ftrace *rec;
-       int type = MATCH_FULL;
-       char *search = buff;
-       unsigned long flag;
        int not = 0;
-       int found = 0;
-
-       flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
 
        /* blank or '*' mean the same */
        if (strcmp(buff, "*") == 0)
@@ -1852,32 +2390,7 @@ static int ftrace_match_module_records(char *buff, char *mod, int enable)
                not = 1;
        }
 
-       if (strlen(buff)) {
-               type = filter_parse_regex(buff, strlen(buff), &search, &not);
-               search_len = strlen(search);
-       }
-
-       mutex_lock(&ftrace_lock);
-       do_for_each_ftrace_rec(pg, rec) {
-
-               if (rec->flags & FTRACE_FL_FAILED)
-                       continue;
-
-               if (ftrace_match_module_record(rec, mod,
-                                              search, search_len, type)) {
-                       if (not)
-                               rec->flags &= ~flag;
-                       else
-                               rec->flags |= flag;
-                       found = 1;
-               }
-               if (enable && (rec->flags & FTRACE_FL_FILTER))
-                       ftrace_filtered = 1;
-
-       } while_for_each_ftrace_rec();
-       mutex_unlock(&ftrace_lock);
-
-       return found;
+       return match_records(hash, buff, strlen(buff), mod, not);
 }
 
 /*
@@ -1888,7 +2401,10 @@ static int ftrace_match_module_records(char *buff, char *mod, int enable)
 static int
 ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
 {
+       struct ftrace_ops *ops = &global_ops;
+       struct ftrace_hash *hash;
        char *mod;
+       int ret = -EINVAL;
 
        /*
         * cmd == 'mod' because we only registered this func
@@ -1900,15 +2416,24 @@ ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
 
        /* we must have a module name */
        if (!param)
-               return -EINVAL;
+               return ret;
 
        mod = strsep(&param, ":");
        if (!strlen(mod))
-               return -EINVAL;
+               return ret;
 
-       if (ftrace_match_module_records(func, mod, enable))
-               return 0;
-       return -EINVAL;
+       if (enable)
+               hash = ops->filter_hash;
+       else
+               hash = ops->notrace_hash;
+
+       ret = ftrace_match_module_records(hash, func, mod);
+       if (!ret)
+               ret = -EINVAL;
+       if (ret < 0)
+               return ret;
+
+       return 0;
 }
 
 static struct ftrace_func_command ftrace_mod_cmd = {
@@ -1959,6 +2484,7 @@ static int ftrace_probe_registered;
 
 static void __enable_ftrace_function_probe(void)
 {
+       int ret;
        int i;
 
        if (ftrace_probe_registered)
@@ -1973,13 +2499,16 @@ static void __enable_ftrace_function_probe(void)
        if (i == FTRACE_FUNC_HASHSIZE)
                return;
 
-       __register_ftrace_function(&trace_probe_ops);
-       ftrace_startup(0);
+       ret = __register_ftrace_function(&trace_probe_ops);
+       if (!ret)
+               ftrace_startup(&trace_probe_ops, 0);
+
        ftrace_probe_registered = 1;
 }
 
 static void __disable_ftrace_function_probe(void)
 {
+       int ret;
        int i;
 
        if (!ftrace_probe_registered)
@@ -1992,8 +2521,10 @@ static void __disable_ftrace_function_probe(void)
        }
 
        /* no more funcs left */
-       __unregister_ftrace_function(&trace_probe_ops);
-       ftrace_shutdown(0);
+       ret = __unregister_ftrace_function(&trace_probe_ops);
+       if (!ret)
+               ftrace_shutdown(&trace_probe_ops, 0);
+
        ftrace_probe_registered = 0;
 }
 
@@ -2029,12 +2560,13 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
                return -EINVAL;
 
        mutex_lock(&ftrace_lock);
-       do_for_each_ftrace_rec(pg, rec) {
 
-               if (rec->flags & FTRACE_FL_FAILED)
-                       continue;
+       if (unlikely(ftrace_disabled))
+               goto out_unlock;
+
+       do_for_each_ftrace_rec(pg, rec) {
 
-               if (!ftrace_match_record(rec, search, len, type))
+               if (!ftrace_match_record(rec, NULL, search, len, type))
                        continue;
 
                entry = kmalloc(sizeof(*entry), GFP_KERNEL);
@@ -2195,18 +2727,22 @@ int unregister_ftrace_command(struct ftrace_func_command *cmd)
        return ret;
 }
 
-static int ftrace_process_regex(char *buff, int len, int enable)
+static int ftrace_process_regex(struct ftrace_hash *hash,
+                               char *buff, int len, int enable)
 {
        char *func, *command, *next = buff;
        struct ftrace_func_command *p;
-       int ret = -EINVAL;
+       int ret;
 
        func = strsep(&next, ":");
 
        if (!next) {
-               if (ftrace_match_records(func, len, enable))
-                       return 0;
-               return ret;
+               ret = ftrace_match_records(hash, func, len);
+               if (!ret)
+                       ret = -EINVAL;
+               if (ret < 0)
+                       return ret;
+               return 0;
        }
 
        /* command found */
@@ -2239,6 +2775,10 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
 
        mutex_lock(&ftrace_regex_lock);
 
+       ret = -ENODEV;
+       if (unlikely(ftrace_disabled))
+               goto out_unlock;
+
        if (file->f_mode & FMODE_READ) {
                struct seq_file *m = file->private_data;
                iter = m->private;
@@ -2250,7 +2790,7 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
 
        if (read >= 0 && trace_parser_loaded(parser) &&
            !trace_parser_cont(parser)) {
-               ret = ftrace_process_regex(parser->buffer,
+               ret = ftrace_process_regex(iter->hash, parser->buffer,
                                           parser->idx, enable);
                trace_parser_clear(parser);
                if (ret)
@@ -2278,22 +2818,83 @@ ftrace_notrace_write(struct file *file, const char __user *ubuf,
        return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
 }
 
-static void
-ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
+static int
+ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
+                int reset, int enable)
 {
+       struct ftrace_hash **orig_hash;
+       struct ftrace_hash *hash;
+       int ret;
+
+       /* All global ops uses the global ops filters */
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL)
+               ops = &global_ops;
+
        if (unlikely(ftrace_disabled))
-               return;
+               return -ENODEV;
+
+       if (enable)
+               orig_hash = &ops->filter_hash;
+       else
+               orig_hash = &ops->notrace_hash;
+
+       hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
+       if (!hash)
+               return -ENOMEM;
 
        mutex_lock(&ftrace_regex_lock);
        if (reset)
-               ftrace_filter_reset(enable);
+               ftrace_filter_reset(hash);
        if (buf)
-               ftrace_match_records(buf, len, enable);
+               ftrace_match_records(hash, buf, len);
+
+       mutex_lock(&ftrace_lock);
+       ret = ftrace_hash_move(orig_hash, hash);
+       mutex_unlock(&ftrace_lock);
+
        mutex_unlock(&ftrace_regex_lock);
+
+       free_ftrace_hash(hash);
+       return ret;
+}
+
+/**
+ * ftrace_set_filter - set a function to filter on in ftrace
+ * @ops - the ops to set the filter with
+ * @buf - the string that holds the function filter text.
+ * @len - the length of the string.
+ * @reset - non zero to reset all filters before applying this filter.
+ *
+ * Filters denote which functions should be enabled when tracing is enabled.
+ * If @buf is NULL and reset is set, all functions will be enabled for tracing.
+ */
+void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
+                      int len, int reset)
+{
+       ftrace_set_regex(ops, buf, len, reset, 1);
 }
+EXPORT_SYMBOL_GPL(ftrace_set_filter);
 
+/**
+ * ftrace_set_notrace - set a function to not trace in ftrace
+ * @ops - the ops to set the notrace filter with
+ * @buf - the string that holds the function notrace text.
+ * @len - the length of the string.
+ * @reset - non zero to reset all filters before applying this filter.
+ *
+ * Notrace Filters denote which functions should not be enabled when tracing
+ * is enabled. If @buf is NULL and reset is set, all functions will be enabled
+ * for tracing.
+ */
+void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
+                       int len, int reset)
+{
+       ftrace_set_regex(ops, buf, len, reset, 0);
+}
+EXPORT_SYMBOL_GPL(ftrace_set_notrace);
 /**
  * ftrace_set_filter - set a function to filter on in ftrace
+ * @ops - the ops to set the filter with
  * @buf - the string that holds the function filter text.
  * @len - the length of the string.
  * @reset - non zero to reset all filters before applying this filter.
@@ -2301,13 +2902,15 @@ ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
  * Filters denote which functions should be enabled when tracing is enabled.
  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
  */
-void ftrace_set_filter(unsigned char *buf, int len, int reset)
+void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
 {
-       ftrace_set_regex(buf, len, reset, 1);
+       ftrace_set_regex(&global_ops, buf, len, reset, 1);
 }
+EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
 
 /**
  * ftrace_set_notrace - set a function to not trace in ftrace
+ * @ops - the ops to set the notrace filter with
  * @buf - the string that holds the function notrace text.
  * @len - the length of the string.
  * @reset - non zero to reset all filters before applying this filter.
@@ -2316,10 +2919,11 @@ void ftrace_set_filter(unsigned char *buf, int len, int reset)
  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
  * for tracing.
  */
-void ftrace_set_notrace(unsigned char *buf, int len, int reset)
+void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
 {
-       ftrace_set_regex(buf, len, reset, 0);
+       ftrace_set_regex(&global_ops, buf, len, reset, 0);
 }
+EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
 
 /*
  * command line interface to allow users to set filters on boot up.
@@ -2370,22 +2974,23 @@ static void __init set_ftrace_early_graph(char *buf)
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-static void __init set_ftrace_early_filter(char *buf, int enable)
+static void __init
+set_ftrace_early_filter(struct ftrace_ops *ops, char *buf, int enable)
 {
        char *func;
 
        while (buf) {
                func = strsep(&buf, ",");
-               ftrace_set_regex(func, strlen(func), 0, enable);
+               ftrace_set_regex(ops, func, strlen(func), 0, enable);
        }
 }
 
 static void __init set_ftrace_early_filters(void)
 {
        if (ftrace_filter_buf[0])
-               set_ftrace_early_filter(ftrace_filter_buf, 1);
+               set_ftrace_early_filter(&global_ops, ftrace_filter_buf, 1);
        if (ftrace_notrace_buf[0])
-               set_ftrace_early_filter(ftrace_notrace_buf, 0);
+               set_ftrace_early_filter(&global_ops, ftrace_notrace_buf, 0);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        if (ftrace_graph_buf[0])
                set_ftrace_early_graph(ftrace_graph_buf);
@@ -2393,11 +2998,14 @@ static void __init set_ftrace_early_filters(void)
 }
 
 static int
-ftrace_regex_release(struct inode *inode, struct file *file, int enable)
+ftrace_regex_release(struct inode *inode, struct file *file)
 {
        struct seq_file *m = (struct seq_file *)file->private_data;
        struct ftrace_iterator *iter;
+       struct ftrace_hash **orig_hash;
        struct trace_parser *parser;
+       int filter_hash;
+       int ret;
 
        mutex_lock(&ftrace_regex_lock);
        if (file->f_mode & FMODE_READ) {
@@ -2410,33 +3018,41 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
        parser = &iter->parser;
        if (trace_parser_loaded(parser)) {
                parser->buffer[parser->idx] = 0;
-               ftrace_match_records(parser->buffer, parser->idx, enable);
+               ftrace_match_records(iter->hash, parser->buffer, parser->idx);
        }
 
-       mutex_lock(&ftrace_lock);
-       if (ftrace_start_up && ftrace_enabled)
-               ftrace_run_update_code(FTRACE_ENABLE_CALLS);
-       mutex_unlock(&ftrace_lock);
-
        trace_parser_put(parser);
+
+       if (file->f_mode & FMODE_WRITE) {
+               filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
+
+               if (filter_hash)
+                       orig_hash = &iter->ops->filter_hash;
+               else
+                       orig_hash = &iter->ops->notrace_hash;
+
+               mutex_lock(&ftrace_lock);
+               /*
+                * Remove the current set, update the hash and add
+                * them back.
+                */
+               ftrace_hash_rec_disable(iter->ops, filter_hash);
+               ret = ftrace_hash_move(orig_hash, iter->hash);
+               if (!ret) {
+                       ftrace_hash_rec_enable(iter->ops, filter_hash);
+                       if (iter->ops->flags & FTRACE_OPS_FL_ENABLED
+                           && ftrace_enabled)
+                               ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+               }
+               mutex_unlock(&ftrace_lock);
+       }
+       free_ftrace_hash(iter->hash);
        kfree(iter);
 
        mutex_unlock(&ftrace_regex_lock);
        return 0;
 }
 
-static int
-ftrace_filter_release(struct inode *inode, struct file *file)
-{
-       return ftrace_regex_release(inode, file, 1);
-}
-
-static int
-ftrace_notrace_release(struct inode *inode, struct file *file)
-{
-       return ftrace_regex_release(inode, file, 0);
-}
-
 static const struct file_operations ftrace_avail_fops = {
        .open = ftrace_avail_open,
        .read = seq_read,
@@ -2444,8 +3060,8 @@ static const struct file_operations ftrace_avail_fops = {
        .release = seq_release_private,
 };
 
-static const struct file_operations ftrace_failures_fops = {
-       .open = ftrace_failures_open,
+static const struct file_operations ftrace_enabled_fops = {
+       .open = ftrace_enabled_open,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = seq_release_private,
@@ -2456,7 +3072,7 @@ static const struct file_operations ftrace_filter_fops = {
        .read = seq_read,
        .write = ftrace_filter_write,
        .llseek = ftrace_regex_lseek,
-       .release = ftrace_filter_release,
+       .release = ftrace_regex_release,
 };
 
 static const struct file_operations ftrace_notrace_fops = {
@@ -2464,7 +3080,7 @@ static const struct file_operations ftrace_notrace_fops = {
        .read = seq_read,
        .write = ftrace_notrace_write,
        .llseek = ftrace_regex_lseek,
-       .release = ftrace_notrace_release,
+       .release = ftrace_regex_release,
 };
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -2573,9 +3189,6 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
        bool exists;
        int i;
 
-       if (ftrace_disabled)
-               return -ENODEV;
-
        /* decode regex */
        type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
        if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
@@ -2584,12 +3197,18 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
        search_len = strlen(search);
 
        mutex_lock(&ftrace_lock);
+
+       if (unlikely(ftrace_disabled)) {
+               mutex_unlock(&ftrace_lock);
+               return -ENODEV;
+       }
+
        do_for_each_ftrace_rec(pg, rec) {
 
-               if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
+               if (rec->flags & FTRACE_FL_FREE)
                        continue;
 
-               if (ftrace_match_record(rec, search, search_len, type)) {
+               if (ftrace_match_record(rec, NULL, search, search_len, type)) {
                        /* if it is in the array */
                        exists = false;
                        for (i = 0; i < *idx; i++) {
@@ -2679,8 +3298,8 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
        trace_create_file("available_filter_functions", 0444,
                        d_tracer, NULL, &ftrace_avail_fops);
 
-       trace_create_file("failures", 0444,
-                       d_tracer, NULL, &ftrace_failures_fops);
+       trace_create_file("enabled_functions", 0444,
+                       d_tracer, NULL, &ftrace_enabled_fops);
 
        trace_create_file("set_ftrace_filter", 0644, d_tracer,
                        NULL, &ftrace_filter_fops);
@@ -2703,7 +3322,6 @@ static int ftrace_process_locs(struct module *mod,
 {
        unsigned long *p;
        unsigned long addr;
-       unsigned long flags;
 
        mutex_lock(&ftrace_lock);
        p = start;
@@ -2720,10 +3338,7 @@ static int ftrace_process_locs(struct module *mod,
                ftrace_record_ip(addr);
        }
 
-       /* disable interrupts to prevent kstop machine */
-       local_irq_save(flags);
        ftrace_update_code(mod);
-       local_irq_restore(flags);
        mutex_unlock(&ftrace_lock);
 
        return 0;
@@ -2735,10 +3350,11 @@ void ftrace_release_mod(struct module *mod)
        struct dyn_ftrace *rec;
        struct ftrace_page *pg;
 
+       mutex_lock(&ftrace_lock);
+
        if (ftrace_disabled)
-               return;
+               goto out_unlock;
 
-       mutex_lock(&ftrace_lock);
        do_for_each_ftrace_rec(pg, rec) {
                if (within_module_core(rec->ip, mod)) {
                        /*
@@ -2749,6 +3365,7 @@ void ftrace_release_mod(struct module *mod)
                        ftrace_free_rec(rec);
                }
        } while_for_each_ftrace_rec();
+ out_unlock:
        mutex_unlock(&ftrace_lock);
 }
 
@@ -2835,6 +3452,10 @@ void __init ftrace_init(void)
 
 #else
 
+static struct ftrace_ops global_ops = {
+       .func                   = ftrace_stub,
+};
+
 static int __init ftrace_nodyn_init(void)
 {
        ftrace_enabled = 1;
@@ -2845,12 +3466,38 @@ device_initcall(ftrace_nodyn_init);
 static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
 static inline void ftrace_startup_enable(int command) { }
 /* Keep as macros so we do not need to define the commands */
-# define ftrace_startup(command)       do { } while (0)
-# define ftrace_shutdown(command)      do { } while (0)
+# define ftrace_startup(ops, command)  do { } while (0)
+# define ftrace_shutdown(ops, command) do { } while (0)
 # define ftrace_startup_sysctl()       do { } while (0)
 # define ftrace_shutdown_sysctl()      do { } while (0)
+
+static inline int
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+{
+       return 1;
+}
+
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+static void
+ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip)
+{
+       struct ftrace_ops *op;
+
+       /*
+        * Some of the ops may be dynamically allocated,
+        * they must be freed after a synchronize_sched().
+        */
+       preempt_disable_notrace();
+       op = rcu_dereference_raw(ftrace_ops_list);
+       while (op != &ftrace_list_end) {
+               if (ftrace_ops_test(op, ip))
+                       op->func(ip, parent_ip);
+               op = rcu_dereference_raw(op->next);
+       };
+       preempt_enable_notrace();
+}
+
 static void clear_ftrace_swapper(void)
 {
        struct task_struct *p;
@@ -3143,19 +3790,23 @@ void ftrace_kill(void)
  */
 int register_ftrace_function(struct ftrace_ops *ops)
 {
-       int ret;
-
-       if (unlikely(ftrace_disabled))
-               return -1;
+       int ret = -1;
 
        mutex_lock(&ftrace_lock);
 
+       if (unlikely(ftrace_disabled))
+               goto out_unlock;
+
        ret = __register_ftrace_function(ops);
-       ftrace_startup(0);
+       if (!ret)
+               ftrace_startup(ops, 0);
 
+
+ out_unlock:
        mutex_unlock(&ftrace_lock);
        return ret;
 }
+EXPORT_SYMBOL_GPL(register_ftrace_function);
 
 /**
  * unregister_ftrace_function - unregister a function for profiling.
@@ -3169,25 +3820,27 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
 
        mutex_lock(&ftrace_lock);
        ret = __unregister_ftrace_function(ops);
-       ftrace_shutdown(0);
+       if (!ret)
+               ftrace_shutdown(ops, 0);
        mutex_unlock(&ftrace_lock);
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(unregister_ftrace_function);
 
 int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
                     void __user *buffer, size_t *lenp,
                     loff_t *ppos)
 {
-       int ret;
-
-       if (unlikely(ftrace_disabled))
-               return -ENODEV;
+       int ret = -ENODEV;
 
        mutex_lock(&ftrace_lock);
 
-       ret  = proc_dointvec(table, write, buffer, lenp, ppos);
+       if (unlikely(ftrace_disabled))
+               goto out;
+
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
 
        if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
                goto out;
@@ -3199,11 +3852,11 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
                ftrace_startup_sysctl();
 
                /* we are starting ftrace again */
-               if (ftrace_list != &ftrace_list_end) {
-                       if (ftrace_list->next == &ftrace_list_end)
-                               ftrace_trace_function = ftrace_list->func;
+               if (ftrace_ops_list != &ftrace_list_end) {
+                       if (ftrace_ops_list->next == &ftrace_list_end)
+                               ftrace_trace_function = ftrace_ops_list->func;
                        else
-                               ftrace_trace_function = ftrace_list_func;
+                               ftrace_trace_function = ftrace_ops_list_func;
                }
 
        } else {
@@ -3392,7 +4045,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
        ftrace_graph_return = retfunc;
        ftrace_graph_entry = entryfunc;
 
-       ftrace_startup(FTRACE_START_FUNC_RET);
+       ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
 
 out:
        mutex_unlock(&ftrace_lock);
@@ -3409,7 +4062,7 @@ void unregister_ftrace_graph(void)
        ftrace_graph_active--;
        ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
        ftrace_graph_entry = ftrace_graph_entry_stub;
-       ftrace_shutdown(FTRACE_STOP_FUNC_RET);
+       ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
        unregister_pm_notifier(&ftrace_suspend_notifier);
        unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
 
index d38c16a06a6fb25d4f31559af0c1544f6cae987f..ee9c921d7f21e4d0578e35032607e9bc542e219f 100644 (file)
@@ -1110,6 +1110,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
 
        entry->preempt_count            = pc & 0xff;
        entry->pid                      = (tsk) ? tsk->pid : 0;
+       entry->padding                  = 0;
        entry->flags =
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
                (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@ -2013,9 +2014,10 @@ enum print_line_t print_trace_line(struct trace_iterator *iter)
 {
        enum print_line_t ret;
 
-       if (iter->lost_events)
-               trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
-                                iter->cpu, iter->lost_events);
+       if (iter->lost_events &&
+           !trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
+                                iter->cpu, iter->lost_events))
+               return TRACE_TYPE_PARTIAL_LINE;
 
        if (iter->trace && iter->trace->print_line) {
                ret = iter->trace->print_line(iter);
@@ -3229,6 +3231,14 @@ waitagain:
 
                if (iter->seq.len >= cnt)
                        break;
+
+               /*
+                * Setting the full flag means we reached the trace_seq buffer
+                * size and we should leave by partial output condition above.
+                * One of the trace_seq_* functions is not used properly.
+                */
+               WARN_ONCE(iter->seq.full, "full flag set for trace type %d",
+                         iter->ent->type);
        }
        trace_access_unlock(iter->cpu_file);
        trace_event_read_unlock();
index 5e9dfc6286dd0eafed900906cccee1c83cf4f28c..6b69c4bd306f72cbbce93b9fe94827a8696c0fba 100644 (file)
@@ -419,6 +419,8 @@ extern void trace_find_cmdline(int pid, char comm[]);
 extern unsigned long ftrace_update_tot_cnt;
 #define DYN_FTRACE_TEST_NAME trace_selftest_dynamic_test_func
 extern int DYN_FTRACE_TEST_NAME(void);
+#define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2
+extern int DYN_FTRACE_TEST_NAME2(void);
 #endif
 
 extern int ring_buffer_expanded;
index e88f74fe1d4ce02fedf3e6052feaf2cbdd2017da..2fe110341359539b0498d49472bbdee19e344dc2 100644 (file)
@@ -116,6 +116,7 @@ static int trace_define_common_fields(void)
        __common_field(unsigned char, flags);
        __common_field(unsigned char, preempt_count);
        __common_field(int, pid);
+       __common_field(int, padding);
 
        return ret;
 }
index 16aee4d44e8fd3e121c2dc4910a120968d01d5d8..8d0e1cc4e9747281989e2b8f4f19f5fba5a8194c 100644 (file)
@@ -149,11 +149,13 @@ function_stack_trace_call(unsigned long ip, unsigned long parent_ip)
 static struct ftrace_ops trace_ops __read_mostly =
 {
        .func = function_trace_call,
+       .flags = FTRACE_OPS_FL_GLOBAL,
 };
 
 static struct ftrace_ops trace_stack_ops __read_mostly =
 {
        .func = function_stack_trace_call,
+       .flags = FTRACE_OPS_FL_GLOBAL,
 };
 
 /* Our two options */
index a4969b47afc1e8120b149d22e73357393be2056b..c77424be284d503c241a36d290af3a4c6e0ef98b 100644 (file)
@@ -153,6 +153,7 @@ irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
 static struct ftrace_ops trace_ops __read_mostly =
 {
        .func = irqsoff_tracer_call,
+       .flags = FTRACE_OPS_FL_GLOBAL,
 };
 #endif /* CONFIG_FUNCTION_TRACER */
 
index 35d55a386145aed31dcd698f16e1f38246c808fb..f925c45f0afa86d77c1c7b38cb174e72cba1aad6 100644 (file)
@@ -53,7 +53,6 @@ const char *reserved_field_names[] = {
        "common_preempt_count",
        "common_pid",
        "common_tgid",
-       "common_lock_depth",
        FIELD_STRING_IP,
        FIELD_STRING_RETIP,
        FIELD_STRING_FUNC,
index 456be9063c2d85664b6bb480c4b5d2c4c4a88f14..cf535ccedc86abe7732876860e59eb7e68686643 100644 (file)
@@ -830,6 +830,9 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_event);
 enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags,
                                  struct trace_event *event)
 {
+       if (!trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type))
+               return TRACE_TYPE_PARTIAL_LINE;
+
        return TRACE_TYPE_HANDLED;
 }
 
index 2547d8813cf0535048162db1d986263a638f188a..dff763b7baf172d9d7b90c8f0dddc0427a83a1c4 100644 (file)
@@ -32,7 +32,7 @@ static DEFINE_MUTEX(btrace_mutex);
 
 struct trace_bprintk_fmt {
        struct list_head list;
-       char fmt[0];
+       const char *fmt;
 };
 
 static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
@@ -49,6 +49,7 @@ static
 void hold_module_trace_bprintk_format(const char **start, const char **end)
 {
        const char **iter;
+       char *fmt;
 
        mutex_lock(&btrace_mutex);
        for (iter = start; iter < end; iter++) {
@@ -58,14 +59,18 @@ void hold_module_trace_bprintk_format(const char **start, const char **end)
                        continue;
                }
 
-               tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt)
-                               + strlen(*iter) + 1, GFP_KERNEL);
-               if (tb_fmt) {
+               tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL);
+               if (tb_fmt)
+                       fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL);
+               if (tb_fmt && fmt) {
                        list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
-                       strcpy(tb_fmt->fmt, *iter);
+                       strcpy(fmt, *iter);
+                       tb_fmt->fmt = fmt;
                        *iter = tb_fmt->fmt;
-               } else
+               } else {
+                       kfree(tb_fmt);
                        *iter = NULL;
+               }
        }
        mutex_unlock(&btrace_mutex);
 }
@@ -84,6 +89,76 @@ static int module_trace_bprintk_format_notify(struct notifier_block *self,
        return 0;
 }
 
+/*
+ * The debugfs/tracing/printk_formats file maps the addresses with
+ * the ASCII formats that are used in the bprintk events in the
+ * buffer. For userspace tools to be able to decode the events from
+ * the buffer, they need to be able to map the address with the format.
+ *
+ * The addresses of the bprintk formats are in their own section
+ * __trace_printk_fmt. But for modules we copy them into a link list.
+ * The code to print the formats and their addresses passes around the
+ * address of the fmt string. If the fmt address passed into the seq
+ * functions is within the kernel core __trace_printk_fmt section, then
+ * it simply uses the next pointer in the list.
+ *
+ * When the fmt pointer is outside the kernel core __trace_printk_fmt
+ * section, then we need to read the link list pointers. The trick is
+ * we pass the address of the string to the seq function just like
+ * we do for the kernel core formats. To get back the structure that
+ * holds the format, we simply use containerof() and then go to the
+ * next format in the list.
+ */
+static const char **
+find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
+{
+       struct trace_bprintk_fmt *mod_fmt;
+
+       if (list_empty(&trace_bprintk_fmt_list))
+               return NULL;
+
+       /*
+        * v will point to the address of the fmt record from t_next
+        * v will be NULL from t_start.
+        * If this is the first pointer or called from start
+        * then we need to walk the list.
+        */
+       if (!v || start_index == *pos) {
+               struct trace_bprintk_fmt *p;
+
+               /* search the module list */
+               list_for_each_entry(p, &trace_bprintk_fmt_list, list) {
+                       if (start_index == *pos)
+                               return &p->fmt;
+                       start_index++;
+               }
+               /* pos > index */
+               return NULL;
+       }
+
+       /*
+        * v points to the address of the fmt field in the mod list
+        * structure that holds the module print format.
+        */
+       mod_fmt = container_of(v, typeof(*mod_fmt), fmt);
+       if (mod_fmt->list.next == &trace_bprintk_fmt_list)
+               return NULL;
+
+       mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list);
+
+       return &mod_fmt->fmt;
+}
+
+static void format_mod_start(void)
+{
+       mutex_lock(&btrace_mutex);
+}
+
+static void format_mod_stop(void)
+{
+       mutex_unlock(&btrace_mutex);
+}
+
 #else /* !CONFIG_MODULES */
 __init static int
 module_trace_bprintk_format_notify(struct notifier_block *self,
@@ -91,6 +166,13 @@ module_trace_bprintk_format_notify(struct notifier_block *self,
 {
        return 0;
 }
+static inline const char **
+find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
+{
+       return NULL;
+}
+static inline void format_mod_start(void) { }
+static inline void format_mod_stop(void) { }
 #endif /* CONFIG_MODULES */
 
 
@@ -153,20 +235,33 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
 }
 EXPORT_SYMBOL_GPL(__ftrace_vprintk);
 
+static const char **find_next(void *v, loff_t *pos)
+{
+       const char **fmt = v;
+       int start_index;
+
+       if (!fmt)
+               fmt = __start___trace_bprintk_fmt + *pos;
+
+       start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt;
+
+       if (*pos < start_index)
+               return fmt;
+
+       return find_next_mod_format(start_index, v, fmt, pos);
+}
+
 static void *
 t_start(struct seq_file *m, loff_t *pos)
 {
-       const char **fmt = __start___trace_bprintk_fmt + *pos;
-
-       if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt)
-               return NULL;
-       return fmt;
+       format_mod_start();
+       return find_next(NULL, pos);
 }
 
 static void *t_next(struct seq_file *m, void * v, loff_t *pos)
 {
        (*pos)++;
-       return t_start(m, pos);
+       return find_next(v, pos);
 }
 
 static int t_show(struct seq_file *m, void *v)
@@ -205,6 +300,7 @@ static int t_show(struct seq_file *m, void *v)
 
 static void t_stop(struct seq_file *m, void *p)
 {
+       format_mod_stop();
 }
 
 static const struct seq_operations show_format_seq_ops = {
index 7319559ed59f0a10197a15dc9d62a99a1fa7aeb7..f029dd4fd2cac18eb309a9aab6b13009bd124305 100644 (file)
@@ -129,6 +129,7 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
 static struct ftrace_ops trace_ops __read_mostly =
 {
        .func = wakeup_tracer_call,
+       .flags = FTRACE_OPS_FL_GLOBAL,
 };
 #endif /* CONFIG_FUNCTION_TRACER */
 
index 659732eba07cf4bd6bdd35e1cec416de042c4cae..288541f977fb7f3b41e747a6b7c2de9e4ea0e1e9 100644 (file)
@@ -101,6 +101,206 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
+static int trace_selftest_test_probe1_cnt;
+static void trace_selftest_test_probe1_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe1_cnt++;
+}
+
+static int trace_selftest_test_probe2_cnt;
+static void trace_selftest_test_probe2_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe2_cnt++;
+}
+
+static int trace_selftest_test_probe3_cnt;
+static void trace_selftest_test_probe3_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_probe3_cnt++;
+}
+
+static int trace_selftest_test_global_cnt;
+static void trace_selftest_test_global_func(unsigned long ip,
+                                           unsigned long pip)
+{
+       trace_selftest_test_global_cnt++;
+}
+
+static int trace_selftest_test_dyn_cnt;
+static void trace_selftest_test_dyn_func(unsigned long ip,
+                                        unsigned long pip)
+{
+       trace_selftest_test_dyn_cnt++;
+}
+
+static struct ftrace_ops test_probe1 = {
+       .func                   = trace_selftest_test_probe1_func,
+};
+
+static struct ftrace_ops test_probe2 = {
+       .func                   = trace_selftest_test_probe2_func,
+};
+
+static struct ftrace_ops test_probe3 = {
+       .func                   = trace_selftest_test_probe3_func,
+};
+
+static struct ftrace_ops test_global = {
+       .func                   = trace_selftest_test_global_func,
+       .flags                  = FTRACE_OPS_FL_GLOBAL,
+};
+
+static void print_counts(void)
+{
+       printk("(%d %d %d %d %d) ",
+              trace_selftest_test_probe1_cnt,
+              trace_selftest_test_probe2_cnt,
+              trace_selftest_test_probe3_cnt,
+              trace_selftest_test_global_cnt,
+              trace_selftest_test_dyn_cnt);
+}
+
+static void reset_counts(void)
+{
+       trace_selftest_test_probe1_cnt = 0;
+       trace_selftest_test_probe2_cnt = 0;
+       trace_selftest_test_probe3_cnt = 0;
+       trace_selftest_test_global_cnt = 0;
+       trace_selftest_test_dyn_cnt = 0;
+}
+
+static int trace_selftest_ops(int cnt)
+{
+       int save_ftrace_enabled = ftrace_enabled;
+       struct ftrace_ops *dyn_ops;
+       char *func1_name;
+       char *func2_name;
+       int len1;
+       int len2;
+       int ret = -1;
+
+       printk(KERN_CONT "PASSED\n");
+       pr_info("Testing dynamic ftrace ops #%d: ", cnt);
+
+       ftrace_enabled = 1;
+       reset_counts();
+
+       /* Handle PPC64 '.' name */
+       func1_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
+       func2_name = "*" __stringify(DYN_FTRACE_TEST_NAME2);
+       len1 = strlen(func1_name);
+       len2 = strlen(func2_name);
+
+       /*
+        * Probe 1 will trace function 1.
+        * Probe 2 will trace function 2.
+        * Probe 3 will trace functions 1 and 2.
+        */
+       ftrace_set_filter(&test_probe1, func1_name, len1, 1);
+       ftrace_set_filter(&test_probe2, func2_name, len2, 1);
+       ftrace_set_filter(&test_probe3, func1_name, len1, 1);
+       ftrace_set_filter(&test_probe3, func2_name, len2, 0);
+
+       register_ftrace_function(&test_probe1);
+       register_ftrace_function(&test_probe2);
+       register_ftrace_function(&test_probe3);
+       register_ftrace_function(&test_global);
+
+       DYN_FTRACE_TEST_NAME();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe2_cnt != 0)
+               goto out;
+       if (trace_selftest_test_probe3_cnt != 1)
+               goto out;
+       if (trace_selftest_test_global_cnt == 0)
+               goto out;
+
+       DYN_FTRACE_TEST_NAME2();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe2_cnt != 1)
+               goto out;
+       if (trace_selftest_test_probe3_cnt != 2)
+               goto out;
+
+       /* Add a dynamic probe */
+       dyn_ops = kzalloc(sizeof(*dyn_ops), GFP_KERNEL);
+       if (!dyn_ops) {
+               printk("MEMORY ERROR ");
+               goto out;
+       }
+
+       dyn_ops->func = trace_selftest_test_dyn_func;
+
+       register_ftrace_function(dyn_ops);
+
+       trace_selftest_test_global_cnt = 0;
+
+       DYN_FTRACE_TEST_NAME();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe2_cnt != 1)
+               goto out_free;
+       if (trace_selftest_test_probe3_cnt != 3)
+               goto out_free;
+       if (trace_selftest_test_global_cnt == 0)
+               goto out;
+       if (trace_selftest_test_dyn_cnt == 0)
+               goto out_free;
+
+       DYN_FTRACE_TEST_NAME2();
+
+       print_counts();
+
+       if (trace_selftest_test_probe1_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe2_cnt != 2)
+               goto out_free;
+       if (trace_selftest_test_probe3_cnt != 4)
+               goto out_free;
+
+       ret = 0;
+ out_free:
+       unregister_ftrace_function(dyn_ops);
+       kfree(dyn_ops);
+
+ out:
+       /* Purposely unregister in the same order */
+       unregister_ftrace_function(&test_probe1);
+       unregister_ftrace_function(&test_probe2);
+       unregister_ftrace_function(&test_probe3);
+       unregister_ftrace_function(&test_global);
+
+       /* Make sure everything is off */
+       reset_counts();
+       DYN_FTRACE_TEST_NAME();
+       DYN_FTRACE_TEST_NAME();
+
+       if (trace_selftest_test_probe1_cnt ||
+           trace_selftest_test_probe2_cnt ||
+           trace_selftest_test_probe3_cnt ||
+           trace_selftest_test_global_cnt ||
+           trace_selftest_test_dyn_cnt)
+               ret = -1;
+
+       ftrace_enabled = save_ftrace_enabled;
+
+       return ret;
+}
+
 /* Test dynamic code modification and ftrace filters */
 int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
                                           struct trace_array *tr,
@@ -131,7 +331,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
        func_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
 
        /* filter only on our function */
-       ftrace_set_filter(func_name, strlen(func_name), 1);
+       ftrace_set_global_filter(func_name, strlen(func_name), 1);
 
        /* enable tracing */
        ret = tracer_init(trace, tr);
@@ -166,22 +366,30 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 
        /* check the trace buffer */
        ret = trace_test_buffer(tr, &count);
-       trace->reset(tr);
        tracing_start();
 
        /* we should only have one item */
        if (!ret && count != 1) {
+               trace->reset(tr);
                printk(KERN_CONT ".. filter failed count=%ld ..", count);
                ret = -1;
                goto out;
        }
 
+       /* Test the ops with global tracing running */
+       ret = trace_selftest_ops(1);
+       trace->reset(tr);
+
  out:
        ftrace_enabled = save_ftrace_enabled;
        tracer_enabled = save_tracer_enabled;
 
        /* Enable tracing on all functions again */
-       ftrace_set_filter(NULL, 0, 1);
+       ftrace_set_global_filter(NULL, 0, 1);
+
+       /* Test the ops with global tracing off */
+       if (!ret)
+               ret = trace_selftest_ops(2);
 
        return ret;
 }
index 54dd77cce5bfec6aa956c635f50f1061bea96a8a..b4c475a0a48b8932c2f659beec75ae7d73b1726d 100644 (file)
@@ -5,3 +5,9 @@ int DYN_FTRACE_TEST_NAME(void)
        /* used to call mcount */
        return 0;
 }
+
+int DYN_FTRACE_TEST_NAME2(void)
+{
+       /* used to call mcount */
+       return 0;
+}
index 4c5dead0c239fc7d47d23065cf033669d036efb1..b0b53b8e4c25ffbe23e4c8a1f40fa19ba4326682 100644 (file)
@@ -133,6 +133,7 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip)
 static struct ftrace_ops trace_ops __read_mostly =
 {
        .func = stack_trace_call,
+       .flags = FTRACE_OPS_FL_GLOBAL,
 };
 
 static ssize_t
index 68187af4889e0d303a67e8213cc64e402b437520..b219f1449c54f5a93cd83d8f22387b4ae1fe498f 100644 (file)
@@ -251,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry,
 {
        WARN_ON(strcmp((*entry)->name, elem->name) != 0);
 
-       if (elem->regfunc && !elem->state && active)
+       if (elem->regfunc && !jump_label_enabled(&elem->key) && active)
                elem->regfunc();
-       else if (elem->unregfunc && elem->state && !active)
+       else if (elem->unregfunc && jump_label_enabled(&elem->key) && !active)
                elem->unregfunc();
 
        /*
@@ -264,13 +264,10 @@ static void set_tracepoint(struct tracepoint_entry **entry,
         * is used.
         */
        rcu_assign_pointer(elem->funcs, (*entry)->funcs);
-       if (!elem->state && active) {
-               jump_label_enable(&elem->state);
-               elem->state = active;
-       } else if (elem->state && !active) {
-               jump_label_disable(&elem->state);
-               elem->state = active;
-       }
+       if (active && !jump_label_enabled(&elem->key))
+               jump_label_inc(&elem->key);
+       else if (!active && jump_label_enabled(&elem->key))
+               jump_label_dec(&elem->key);
 }
 
 /*
@@ -281,13 +278,11 @@ static void set_tracepoint(struct tracepoint_entry **entry,
  */
 static void disable_tracepoint(struct tracepoint *elem)
 {
-       if (elem->unregfunc && elem->state)
+       if (elem->unregfunc && jump_label_enabled(&elem->key))
                elem->unregfunc();
 
-       if (elem->state) {
-               jump_label_disable(&elem->state);
-               elem->state = 0;
-       }
+       if (jump_label_enabled(&elem->key))
+               jump_label_dec(&elem->key);
        rcu_assign_pointer(elem->funcs, NULL);
 }
 
index 140dce750450edc8db5285817c26fd354ec0c56a..14733d4d156b5e90603cafec70eb9907b141b6dd 100644 (file)
@@ -430,9 +430,12 @@ static int watchdog_enable(int cpu)
                p = kthread_create(watchdog, (void *)(unsigned long)cpu, "watchdog/%d", cpu);
                if (IS_ERR(p)) {
                        printk(KERN_ERR "softlockup watchdog for %i failed\n", cpu);
-                       if (!err)
+                       if (!err) {
                                /* if hardlockup hasn't already set this */
                                err = PTR_ERR(p);
+                               /* and disable the perf event */
+                               watchdog_nmi_disable(cpu);
+                       }
                        goto out;
                }
                kthread_bind(p, cpu);
index 8859a41806dddae875e1ceae1e6ed94a4e3aebff..e3378e8d3a5ce7e16fbbbb35ebd30a1c51fde650 100644 (file)
@@ -1291,8 +1291,14 @@ __acquires(&gcwq->lock)
                        return true;
                spin_unlock_irq(&gcwq->lock);
 
-               /* CPU has come up in between, retry migration */
+               /*
+                * We've raced with CPU hot[un]plug.  Give it a breather
+                * and retry migration.  cond_resched() is required here;
+                * otherwise, we might deadlock against cpu_stop trying to
+                * bring down the CPU on non-preemptive kernel.
+                */
                cpu_relax();
+               cond_resched();
        }
 }
 
index c768bcdda1b700331a991cad681c5c2d6862c419..10ef619811494aec89d69a0e6faa73694470192b 100644 (file)
@@ -238,6 +238,21 @@ config DETECT_HUNG_TASK
          enabled then all held locks will also be reported. This
          feature has negligible overhead.
 
+config DEFAULT_HUNG_TASK_TIMEOUT
+       int "Default timeout for hung task detection (in seconds)"
+       depends on DETECT_HUNG_TASK
+       default 120
+       help
+         This option controls the default timeout (in seconds) used
+         to determine when a task has become non-responsive and should
+         be considered hung.
+
+         It can be adjusted at runtime via the kernel.hung_task_timeout
+         sysctl or by writing a value to /proc/sys/kernel/hung_task_timeout.
+
+         A timeout of 0 disables the check.  The default is two minutes.
+         Keeping the default should be fine in most cases.
+
 config BOOTPARAM_HUNG_TASK_PANIC
        bool "Panic (Reboot) On Hung Tasks"
        depends on DETECT_HUNG_TASK
@@ -337,7 +352,7 @@ config DEBUG_OBJECTS_WORK
 
 config DEBUG_OBJECTS_RCU_HEAD
        bool "Debug RCU callbacks objects"
-       depends on DEBUG_OBJECTS && PREEMPT
+       depends on DEBUG_OBJECTS
        help
          Enable this to turn on debugging of RCU list heads (call_rcu() usage).
 
@@ -398,9 +413,9 @@ config SLUB_STATS
 config DEBUG_KMEMLEAK
        bool "Kernel memory leak detector"
        depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
-               (X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE)
+               (X86 || ARM || PPC || MIPS || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE)
 
-       select DEBUG_FS if SYSFS
+       select DEBUG_FS
        select STACKTRACE if STACKTRACE_SUPPORT
        select KALLSYMS
        select CRC32
@@ -875,22 +890,9 @@ config RCU_TORTURE_TEST_RUNNABLE
          Say N here if you want the RCU torture tests to start only
          after being manually enabled via /proc.
 
-config RCU_CPU_STALL_DETECTOR
-       bool "Check for stalled CPUs delaying RCU grace periods"
-       depends on TREE_RCU || TREE_PREEMPT_RCU
-       default y
-       help
-         This option causes RCU to printk information on which
-         CPUs are delaying the current grace period, but only when
-         the grace period extends for excessive time periods.
-
-         Say N if you want to disable such checks.
-
-         Say Y if you are unsure.
-
 config RCU_CPU_STALL_TIMEOUT
        int "RCU CPU stall timeout in seconds"
-       depends on RCU_CPU_STALL_DETECTOR
+       depends on TREE_RCU || TREE_PREEMPT_RCU
        range 3 300
        default 60
        help
@@ -899,22 +901,9 @@ config RCU_CPU_STALL_TIMEOUT
          RCU grace period persists, additional CPU stall warnings are
          printed at more widely spaced intervals.
 
-config RCU_CPU_STALL_DETECTOR_RUNNABLE
-       bool "RCU CPU stall checking starts automatically at boot"
-       depends on RCU_CPU_STALL_DETECTOR
-       default y
-       help
-         If set, start checking for RCU CPU stalls immediately on
-         boot.  Otherwise, RCU CPU stall checking must be manually
-         enabled.
-
-         Say Y if you are unsure.
-
-         Say N if you wish to suppress RCU CPU stall checking during boot.
-
 config RCU_CPU_STALL_VERBOSE
        bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
-       depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
+       depends on TREE_PREEMPT_RCU
        default y
        help
          This option causes RCU to printk detailed per-task information
index ef0f285711566f87a964e6f4c1908776f5f60e29..4b49a249064b5f747ebcec353c610536237e604a 100644 (file)
@@ -21,7 +21,8 @@ lib-y += kobject.o kref.o klist.o
 
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
-        string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o
+        string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \
+        bsearch.o
 obj-y += kstrtox.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 
diff --git a/lib/bsearch.c b/lib/bsearch.c
new file mode 100644 (file)
index 0000000..5b54758
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabbott@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/bsearch.h>
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+             int (*cmp)(const void *key, const void *elt))
+{
+       size_t start = 0, end = num;
+       int result;
+
+       while (start < end) {
+               size_t mid = start + (end - start) / 2;
+
+               result = cmp(key, base + mid * size);
+               if (result < 0)
+                       end = mid;
+               else if (result > 0)
+                       start = mid + 1;
+               else
+                       return (void *)base + mid * size;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(bsearch);
index 4bfb0471f10684f230e4351db489a1292b83f414..db07bfd9298ea93d4ddcdf76a8a0c868b955371b 100644 (file)
@@ -649,7 +649,7 @@ out_err:
        return -ENOMEM;
 }
 
-static int device_dma_allocations(struct device *dev)
+static int device_dma_allocations(struct device *dev, struct dma_debug_entry **out_entry)
 {
        struct dma_debug_entry *entry;
        unsigned long flags;
@@ -660,8 +660,10 @@ static int device_dma_allocations(struct device *dev)
        for (i = 0; i < HASH_SIZE; ++i) {
                spin_lock(&dma_entry_hash[i].lock);
                list_for_each_entry(entry, &dma_entry_hash[i].list, list) {
-                       if (entry->dev == dev)
+                       if (entry->dev == dev) {
                                count += 1;
+                               *out_entry = entry;
+                       }
                }
                spin_unlock(&dma_entry_hash[i].lock);
        }
@@ -674,6 +676,7 @@ static int device_dma_allocations(struct device *dev)
 static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data)
 {
        struct device *dev = data;
+       struct dma_debug_entry *uninitialized_var(entry);
        int count;
 
        if (global_disable)
@@ -681,12 +684,17 @@ static int dma_debug_device_change(struct notifier_block *nb, unsigned long acti
 
        switch (action) {
        case BUS_NOTIFY_UNBOUND_DRIVER:
-               count = device_dma_allocations(dev);
+               count = device_dma_allocations(dev, &entry);
                if (count == 0)
                        break;
-               err_printk(dev, NULL, "DMA-API: device driver has pending "
+               err_printk(dev, entry, "DMA-API: device driver has pending "
                                "DMA allocations while released from device "
-                               "[count=%d]\n", count);
+                               "[count=%d]\n"
+                               "One of leaked entries details: "
+                               "[device address=0x%016llx] [size=%llu bytes] "
+                               "[mapped with %s] [mapped as %s]\n",
+                       count, entry->dev_addr, entry->size,
+                       dir2name[entry->direction], type2name[entry->type]);
                break;
        default:
                break;
index c0ea40ba20828b67c10e29d790ca13846572b8a0..854b57bd7d9d346276fe83599f5cbd306c6e0fe4 100644 (file)
@@ -232,10 +232,10 @@ EXPORT_SYMBOL(flex_array_clear);
 
 /**
  * flex_array_prealloc - guarantee that array space exists
- * @fa:                the flex array for which to preallocate parts
- * @start:     index of first array element for which space is allocated
- * @end:       index of last (inclusive) element for which space is allocated
- * @flags:     page allocation flags
+ * @fa:                        the flex array for which to preallocate parts
+ * @start:             index of first array element for which space is allocated
+ * @nr_elements:       number of elements for which space is allocated
+ * @flags:             page allocation flags
  *
  * This will guarantee that no future calls to flex_array_put()
  * will allocate memory.  It can be used if you are expecting to
@@ -245,14 +245,24 @@ EXPORT_SYMBOL(flex_array_clear);
  * Locking must be provided by the caller.
  */
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-                       unsigned int end, gfp_t flags)
+                       unsigned int nr_elements, gfp_t flags)
 {
        int start_part;
        int end_part;
        int part_nr;
+       unsigned int end;
        struct flex_array_part *part;
 
-       if (start >= fa->total_nr_elements || end >= fa->total_nr_elements)
+       if (!start && !nr_elements)
+               return 0;
+       if (start >= fa->total_nr_elements)
+               return -ENOSPC;
+       if (!nr_elements)
+               return 0;
+
+       end = start + nr_elements - 1;
+
+       if (end >= fa->total_nr_elements)
                return -ENOSPC;
        if (elements_fit_in_base(fa))
                return 0;
@@ -343,6 +353,8 @@ int flex_array_shrink(struct flex_array *fa)
        int part_nr;
        int ret = 0;
 
+       if (!fa->total_nr_elements)
+               return 0;
        if (elements_fit_in_base(fa))
                return ret;
        for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) {
index bc0ac6b333dc95464da43485d40a5966ef60eeb6..dfd60192bc2ede37835fa8ed894bc024b0f1908a 100644 (file)
@@ -797,7 +797,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr,
        return string(buf, end, uuid, spec);
 }
 
-int kptr_restrict = 1;
+int kptr_restrict __read_mostly;
 
 /*
  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
index ea5fa4fe9d67879aa47be92ad9220a4d8d1beb31..a6cdc969ea42a7b5df5e74e8cb4d712f6f7bbd3b 100644 (file)
@@ -969,6 +969,9 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
                         */
                        tmp = b->in[b->in_pos++];
 
+                       if (tmp == 0x00)
+                               return XZ_STREAM_END;
+
                        if (tmp >= 0xE0 || tmp == 0x01) {
                                s->lzma2.need_props = true;
                                s->lzma2.need_dict_reset = false;
@@ -1001,9 +1004,6 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
                                                lzma_reset(s);
                                }
                        } else {
-                               if (tmp == 0x00)
-                                       return XZ_STREAM_END;
-
                                if (tmp > 0x02)
                                        return XZ_DATA_ERROR;
 
index 470dcda10addbc68e1470c9bc8c92b5dba103623..83326ad66d9b15df1027a0274d92886c85386394 100644 (file)
@@ -1408,6 +1408,9 @@ out:
        return ret;
 }
 
+#define VM_NO_THP (VM_SPECIAL|VM_INSERTPAGE|VM_MIXEDMAP|VM_SAO| \
+                  VM_HUGETLB|VM_SHARED|VM_MAYSHARE)
+
 int hugepage_madvise(struct vm_area_struct *vma,
                     unsigned long *vm_flags, int advice)
 {
@@ -1416,11 +1419,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_HUGEPAGE |
-                                VM_SHARED   | VM_MAYSHARE   |
-                                VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-                                VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-                                VM_MIXEDMAP | VM_SAO))
+               if (*vm_flags & (VM_HUGEPAGE | VM_NO_THP))
                        return -EINVAL;
                *vm_flags &= ~VM_NOHUGEPAGE;
                *vm_flags |= VM_HUGEPAGE;
@@ -1436,11 +1435,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_NOHUGEPAGE |
-                                VM_SHARED   | VM_MAYSHARE   |
-                                VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-                                VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-                                VM_MIXEDMAP | VM_SAO))
+               if (*vm_flags & (VM_NOHUGEPAGE | VM_NO_THP))
                        return -EINVAL;
                *vm_flags &= ~VM_HUGEPAGE;
                *vm_flags |= VM_NOHUGEPAGE;
@@ -1574,10 +1569,14 @@ int khugepaged_enter_vma_merge(struct vm_area_struct *vma)
                 * page fault if needed.
                 */
                return 0;
-       if (vma->vm_file || vma->vm_ops)
+       if (vma->vm_ops)
                /* khugepaged not yet working on file or special mappings */
                return 0;
-       VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+       /*
+        * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+        * true too, verify it here.
+        */
+       VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
        hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
        hend = vma->vm_end & HPAGE_PMD_MASK;
        if (hstart < hend)
@@ -1828,12 +1827,15 @@ static void collapse_huge_page(struct mm_struct *mm,
            (vma->vm_flags & VM_NOHUGEPAGE))
                goto out;
 
-       /* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-       if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+       if (!vma->anon_vma || vma->vm_ops)
                goto out;
        if (is_vma_temporary_stack(vma))
                goto out;
-       VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+       /*
+        * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+        * true too, verify it here.
+        */
+       VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
 
        pgd = pgd_offset(mm, address);
        if (!pgd_present(*pgd))
@@ -2066,13 +2068,16 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
                        progress++;
                        continue;
                }
-               /* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-               if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+               if (!vma->anon_vma || vma->vm_ops)
                        goto skip;
                if (is_vma_temporary_stack(vma))
                        goto skip;
-
-               VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+               /*
+                * If is_pfn_mapping() is true is_learn_pfn_mapping()
+                * must be true too, verify it here.
+                */
+               VM_BUG_ON(is_linear_pfn_mapping(vma) ||
+                         vma->vm_flags & VM_NO_THP);
 
                hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
                hend = vma->vm_end & HPAGE_PMD_MASK;
index c1d5867543e4da3962b8ee36bf191f89f6870e99..aacee45616fc44792f768135abc99dd6f429f003 100644 (file)
@@ -1414,9 +1414,12 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        ++(*pos);
 
        list_for_each_continue_rcu(n, &object_list) {
-               next_obj = list_entry(n, struct kmemleak_object, object_list);
-               if (get_object(next_obj))
+               struct kmemleak_object *obj =
+                       list_entry(n, struct kmemleak_object, object_list);
+               if (get_object(obj)) {
+                       next_obj = obj;
                        break;
+               }
        }
 
        put_object(prev_obj);
index ce22a250926f59711f51e634a565cb90256d969c..61e66f026563b4b473fc73922d58a984c490c827 100644 (file)
@@ -1359,7 +1359,7 @@ split_fallthrough:
                 */
                mark_page_accessed(page);
        }
-       if (flags & FOLL_MLOCK) {
+       if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
                /*
                 * The preliminary mapping check is mainly to avoid the
                 * pointless overhead of lock_page on the ZERO_PAGE
@@ -1412,9 +1412,8 @@ no_page_table:
 
 static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
 {
-       return (vma->vm_flags & VM_GROWSDOWN) &&
-               (vma->vm_start == addr) &&
-               !vma_stack_continue(vma->vm_prev, addr);
+       return stack_guard_page_start(vma, addr) ||
+              stack_guard_page_end(vma, addr+PAGE_SIZE);
 }
 
 /**
@@ -1551,13 +1550,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        continue;
                }
 
-               /*
-                * If we don't actually want the page itself,
-                * and it's the stack guard page, just skip it.
-                */
-               if (!pages && stack_guard_page(vma, start))
-                       goto next_page;
-
                do {
                        struct page *page;
                        unsigned int foll_flags = gup_flags;
@@ -1574,6 +1566,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                int ret;
                                unsigned int fault_flags = 0;
 
+                               /* For mlock, just skip the stack guard page. */
+                               if (foll_flags & FOLL_MLOCK) {
+                                       if (stack_guard_page(vma, start))
+                                               goto next_page;
+                               }
                                if (foll_flags & FOLL_WRITE)
                                        fault_flags |= FAULT_FLAG_WRITE;
                                if (nonblocking)
@@ -3396,7 +3393,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * run pte_offset_map on the pmd, if an huge pmd could
         * materialize from under us from a different thread.
         */
-       if (unlikely(__pte_alloc(mm, vma, pmd, address)))
+       if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
                return VM_FAULT_OOM;
        /* if an huge pmd materialized from under us just retry later */
        if (unlikely(pmd_trans_huge(*pmd)))
index 6b55e3efe0df4ebd9aafd71e9317bc664956006f..516b2c2ddd5a55b244a89af33eeb3b6f3b88d410 100644 (file)
@@ -162,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
        VM_BUG_ON(end   > vma->vm_end);
        VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
 
-       gup_flags = FOLL_TOUCH;
+       gup_flags = FOLL_TOUCH | FOLL_MLOCK;
        /*
         * We want to touch writable mappings with a write fault in order
         * to break COW, except for shared mappings because these don't COW
@@ -178,9 +178,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
        if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))
                gup_flags |= FOLL_FORCE;
 
-       if (vma->vm_flags & VM_LOCKED)
-               gup_flags |= FOLL_MLOCK;
-
        return __get_user_pages(current, mm, addr, nr_pages, gup_flags,
                                NULL, NULL, nonblocking);
 }
index e27e0cf0de03ccb81b252953932fc356c3499c10..772140c53ab185ebc76d1f185d6feb9fb8935c15 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1767,10 +1767,13 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                size = address - vma->vm_start;
                grow = (address - vma->vm_end) >> PAGE_SHIFT;
 
-               error = acct_stack_growth(vma, size, grow);
-               if (!error) {
-                       vma->vm_end = address;
-                       perf_event_mmap(vma);
+               error = -ENOMEM;
+               if (vma->vm_pgoff + (size >> PAGE_SHIFT) >= vma->vm_pgoff) {
+                       error = acct_stack_growth(vma, size, grow);
+                       if (!error) {
+                               vma->vm_end = address;
+                               perf_event_mmap(vma);
+                       }
                }
        }
        vma_unlock_anon_vma(vma);
index 83fb72c108b7947a7b18989455607e14ead0084f..f52e85c80e8d554fcae1a7ad40e0617c0bb1318f 100644 (file)
@@ -172,10 +172,13 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
 
        /*
         * The baseline for the badness score is the proportion of RAM that each
-        * task's rss and swap space use.
+        * task's rss, pagetable and swap space use.
         */
-       points = (get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS)) * 1000 /
-                       totalpages;
+       points = get_mm_rss(p->mm) + p->mm->nr_ptes;
+       points += get_mm_counter(p->mm, MM_SWAPENTS);
+
+       points *= 1000;
+       points /= totalpages;
        task_unlock(p);
 
        /*
index 9f8a97b9a350d17ec070d5e741c04f8d9998e7a8..3f8bce264df66f712e9a44092f871d9f90eafe22 100644 (file)
@@ -2317,6 +2317,21 @@ void free_pages(unsigned long addr, unsigned int order)
 
 EXPORT_SYMBOL(free_pages);
 
+static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size)
+{
+       if (addr) {
+               unsigned long alloc_end = addr + (PAGE_SIZE << order);
+               unsigned long used = addr + PAGE_ALIGN(size);
+
+               split_page(virt_to_page((void *)addr), order);
+               while (used < alloc_end) {
+                       free_page(used);
+                       used += PAGE_SIZE;
+               }
+       }
+       return (void *)addr;
+}
+
 /**
  * alloc_pages_exact - allocate an exact number physically-contiguous pages.
  * @size: the number of bytes to allocate
@@ -2336,21 +2351,32 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
        unsigned long addr;
 
        addr = __get_free_pages(gfp_mask, order);
-       if (addr) {
-               unsigned long alloc_end = addr + (PAGE_SIZE << order);
-               unsigned long used = addr + PAGE_ALIGN(size);
-
-               split_page(virt_to_page((void *)addr), order);
-               while (used < alloc_end) {
-                       free_page(used);
-                       used += PAGE_SIZE;
-               }
-       }
-
-       return (void *)addr;
+       return make_alloc_exact(addr, order, size);
 }
 EXPORT_SYMBOL(alloc_pages_exact);
 
+/**
+ * alloc_pages_exact_nid - allocate an exact number of physically-contiguous
+ *                        pages on a node.
+ * @nid: the preferred node ID where memory should be allocated
+ * @size: the number of bytes to allocate
+ * @gfp_mask: GFP flags for the allocation
+ *
+ * Like alloc_pages_exact(), but try to allocate on node nid first before falling
+ * back.
+ * Note this is not alloc_pages_exact_node() which allocates on a specific node,
+ * but is not exact.
+ */
+void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask)
+{
+       unsigned order = get_order(size);
+       struct page *p = alloc_pages_node(nid, gfp_mask, order);
+       if (!p)
+               return NULL;
+       return make_alloc_exact((unsigned long)page_address(p), order, size);
+}
+EXPORT_SYMBOL(alloc_pages_exact_nid);
+
 /**
  * free_pages_exact - release memory allocated via alloc_pages_exact()
  * @virt: the value returned by alloc_pages_exact.
@@ -3564,7 +3590,7 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 
        if (!slab_is_available()) {
                zone->wait_table = (wait_queue_head_t *)
-                       alloc_bootmem_node(pgdat, alloc_size);
+                       alloc_bootmem_node_nopanic(pgdat, alloc_size);
        } else {
                /*
                 * This case means that a zone whose size was 0 gets new memory
@@ -4141,7 +4167,8 @@ static void __init setup_usemap(struct pglist_data *pgdat,
        unsigned long usemapsize = usemap_size(zonesize);
        zone->pageblock_flags = NULL;
        if (usemapsize)
-               zone->pageblock_flags = alloc_bootmem_node(pgdat, usemapsize);
+               zone->pageblock_flags = alloc_bootmem_node_nopanic(pgdat,
+                                                                  usemapsize);
 }
 #else
 static inline void setup_usemap(struct pglist_data *pgdat,
@@ -4307,7 +4334,7 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
                size =  (end - start) * sizeof(struct page);
                map = alloc_remap(pgdat->node_id, size);
                if (!map)
-                       map = alloc_bootmem_node(pgdat, size);
+                       map = alloc_bootmem_node_nopanic(pgdat, size);
                pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
        }
 #ifndef CONFIG_NEED_MULTIPLE_NODES
index 99055010cecef74586af9490be326fbd8bd6b1e5..2daadc322ba61678cfc9120e3b65c551b5b96d2d 100644 (file)
@@ -134,7 +134,7 @@ static void *__init_refok alloc_page_cgroup(size_t size, int nid)
 {
        void *addr = NULL;
 
-       addr = alloc_pages_exact(size, GFP_KERNEL | __GFP_NOWARN);
+       addr = alloc_pages_exact_nid(nid, size, GFP_KERNEL | __GFP_NOWARN);
        if (addr)
                return addr;
 
index 8fa27e4e582a236886eba7d875e6c612130468fc..dfc7069102ee638215d7f494a0893c26e7687325 100644 (file)
@@ -852,7 +852,7 @@ static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *dir, swp_entry_
 
 static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
 {
-       struct inode *inode;
+       struct address_space *mapping;
        unsigned long idx;
        unsigned long size;
        unsigned long limit;
@@ -875,8 +875,10 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
        if (size > SHMEM_NR_DIRECT)
                size = SHMEM_NR_DIRECT;
        offset = shmem_find_swp(entry, ptr, ptr+size);
-       if (offset >= 0)
+       if (offset >= 0) {
+               shmem_swp_balance_unmap();
                goto found;
+       }
        if (!info->i_indirect)
                goto lost2;
 
@@ -914,11 +916,11 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
                        if (size > ENTRIES_PER_PAGE)
                                size = ENTRIES_PER_PAGE;
                        offset = shmem_find_swp(entry, ptr, ptr+size);
-                       shmem_swp_unmap(ptr);
                        if (offset >= 0) {
                                shmem_dir_unmap(dir);
                                goto found;
                        }
+                       shmem_swp_unmap(ptr);
                }
        }
 lost1:
@@ -928,8 +930,7 @@ lost2:
        return 0;
 found:
        idx += offset;
-       inode = igrab(&info->vfs_inode);
-       spin_unlock(&info->lock);
+       ptr += offset;
 
        /*
         * Move _head_ to start search for next from here.
@@ -940,37 +941,18 @@ found:
         */
        if (shmem_swaplist.next != &info->swaplist)
                list_move_tail(&shmem_swaplist, &info->swaplist);
-       mutex_unlock(&shmem_swaplist_mutex);
 
-       error = 1;
-       if (!inode)
-               goto out;
        /*
-        * Charge page using GFP_KERNEL while we can wait.
-        * Charged back to the user(not to caller) when swap account is used.
-        * add_to_page_cache() will be called with GFP_NOWAIT.
+        * We rely on shmem_swaplist_mutex, not only to protect the swaplist,
+        * but also to hold up shmem_evict_inode(): so inode cannot be freed
+        * beneath us (pagelock doesn't help until the page is in pagecache).
         */
-       error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
-       if (error)
-               goto out;
-       error = radix_tree_preload(GFP_KERNEL);
-       if (error) {
-               mem_cgroup_uncharge_cache_page(page);
-               goto out;
-       }
-       error = 1;
-
-       spin_lock(&info->lock);
-       ptr = shmem_swp_entry(info, idx, NULL);
-       if (ptr && ptr->val == entry.val) {
-               error = add_to_page_cache_locked(page, inode->i_mapping,
-                                               idx, GFP_NOWAIT);
-               /* does mem_cgroup_uncharge_cache_page on error */
-       } else  /* we must compensate for our precharge above */
-               mem_cgroup_uncharge_cache_page(page);
+       mapping = info->vfs_inode.i_mapping;
+       error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT);
+       /* which does mem_cgroup_uncharge_cache_page on error */
 
        if (error == -EEXIST) {
-               struct page *filepage = find_get_page(inode->i_mapping, idx);
+               struct page *filepage = find_get_page(mapping, idx);
                error = 1;
                if (filepage) {
                        /*
@@ -990,14 +972,8 @@ found:
                swap_free(entry);
                error = 1;      /* not an error, but entry was found */
        }
-       if (ptr)
-               shmem_swp_unmap(ptr);
+       shmem_swp_unmap(ptr);
        spin_unlock(&info->lock);
-       radix_tree_preload_end();
-out:
-       unlock_page(page);
-       page_cache_release(page);
-       iput(inode);            /* allows for NULL */
        return error;
 }
 
@@ -1009,6 +985,26 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
        struct list_head *p, *next;
        struct shmem_inode_info *info;
        int found = 0;
+       int error;
+
+       /*
+        * Charge page using GFP_KERNEL while we can wait, before taking
+        * the shmem_swaplist_mutex which might hold up shmem_writepage().
+        * Charged back to the user (not to caller) when swap account is used.
+        * add_to_page_cache() will be called with GFP_NOWAIT.
+        */
+       error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
+       if (error)
+               goto out;
+       /*
+        * Try to preload while we can wait, to not make a habit of
+        * draining atomic reserves; but don't latch on to this cpu,
+        * it's okay if sometimes we get rescheduled after this.
+        */
+       error = radix_tree_preload(GFP_KERNEL);
+       if (error)
+               goto uncharge;
+       radix_tree_preload_end();
 
        mutex_lock(&shmem_swaplist_mutex);
        list_for_each_safe(p, next, &shmem_swaplist) {
@@ -1016,17 +1012,19 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
                found = shmem_unuse_inode(info, entry, page);
                cond_resched();
                if (found)
-                       goto out;
+                       break;
        }
        mutex_unlock(&shmem_swaplist_mutex);
-       /*
-        * Can some race bring us here?  We've been holding page lock,
-        * so I think not; but would rather try again later than BUG()
-        */
+
+uncharge:
+       if (!found)
+               mem_cgroup_uncharge_cache_page(page);
+       if (found < 0)
+               error = found;
+out:
        unlock_page(page);
        page_cache_release(page);
-out:
-       return (found < 0) ? found : 0;
+       return error;
 }
 
 /*
@@ -1064,7 +1062,25 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
        else
                swap.val = 0;
 
+       /*
+        * Add inode to shmem_unuse()'s list of swapped-out inodes,
+        * if it's not already there.  Do it now because we cannot take
+        * mutex while holding spinlock, and must do so before the page
+        * is moved to swap cache, when its pagelock no longer protects
+        * the inode from eviction.  But don't unlock the mutex until
+        * we've taken the spinlock, because shmem_unuse_inode() will
+        * prune a !swapped inode from the swaplist under both locks.
+        */
+       if (swap.val) {
+               mutex_lock(&shmem_swaplist_mutex);
+               if (list_empty(&info->swaplist))
+                       list_add_tail(&info->swaplist, &shmem_swaplist);
+       }
+
        spin_lock(&info->lock);
+       if (swap.val)
+               mutex_unlock(&shmem_swaplist_mutex);
+
        if (index >= info->next_index) {
                BUG_ON(!(info->flags & SHMEM_TRUNCATE));
                goto unlock;
@@ -1084,21 +1100,10 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
                delete_from_page_cache(page);
                shmem_swp_set(info, entry, swap.val);
                shmem_swp_unmap(entry);
-               if (list_empty(&info->swaplist))
-                       inode = igrab(inode);
-               else
-                       inode = NULL;
                spin_unlock(&info->lock);
                swap_shmem_alloc(swap);
                BUG_ON(page_mapped(page));
                swap_writepage(page, wbc);
-               if (inode) {
-                       mutex_lock(&shmem_swaplist_mutex);
-                       /* move instead of add in case we're racing */
-                       list_move_tail(&info->swaplist, &shmem_swaplist);
-                       mutex_unlock(&shmem_swaplist_mutex);
-                       iput(inode);
-               }
                return 0;
        }
 
@@ -1400,20 +1405,14 @@ repeat:
                if (sbinfo->max_blocks) {
                        if (percpu_counter_compare(&sbinfo->used_blocks,
                                                sbinfo->max_blocks) >= 0 ||
-                           shmem_acct_block(info->flags)) {
-                               spin_unlock(&info->lock);
-                               error = -ENOSPC;
-                               goto failed;
-                       }
+                           shmem_acct_block(info->flags))
+                               goto nospace;
                        percpu_counter_inc(&sbinfo->used_blocks);
                        spin_lock(&inode->i_lock);
                        inode->i_blocks += BLOCKS_PER_PAGE;
                        spin_unlock(&inode->i_lock);
-               } else if (shmem_acct_block(info->flags)) {
-                       spin_unlock(&info->lock);
-                       error = -ENOSPC;
-                       goto failed;
-               }
+               } else if (shmem_acct_block(info->flags))
+                       goto nospace;
 
                if (!filepage) {
                        int ret;
@@ -1493,6 +1492,24 @@ done:
        error = 0;
        goto out;
 
+nospace:
+       /*
+        * Perhaps the page was brought in from swap between find_lock_page
+        * and taking info->lock?  We allow for that at add_to_page_cache_lru,
+        * but must also avoid reporting a spurious ENOSPC while working on a
+        * full tmpfs.  (When filepage has been passed in to shmem_getpage, it
+        * is already in page cache, which prevents this race from occurring.)
+        */
+       if (!filepage) {
+               struct page *page = find_get_page(mapping, idx);
+               if (page) {
+                       spin_unlock(&info->lock);
+                       page_cache_release(page);
+                       goto repeat;
+               }
+       }
+       spin_unlock(&info->lock);
+       error = -ENOSPC;
 failed:
        if (*pagep != filepage) {
                unlock_page(filepage);
index 94d2a33a866e153830bfd1dbb285e26006262f6f..9d2e5e46bf09b85f6038232b6b3f32f928862ea4 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1940,7 +1940,7 @@ redo:
                 * Since this is without lock semantics the protection is only against
                 * code executing on this cpu *not* from access by other cpus.
                 */
-               if (unlikely(!this_cpu_cmpxchg_double(
+               if (unlikely(!irqsafe_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                object, tid,
                                get_freepointer(s, object), next_tid(tid)))) {
@@ -2145,7 +2145,7 @@ redo:
                set_freepointer(s, object, c->freelist);
 
 #ifdef CONFIG_CMPXCHG_LOCAL
-               if (unlikely(!this_cpu_cmpxchg_double(
+               if (unlikely(!irqsafe_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                c->freelist, tid,
                                object, next_tid(tid)))) {
index a448db377cb046d0871506f156b430dceed818fe..5602f1a1b1e724ba547bdee3ef21d773fd24ee04 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -396,6 +396,9 @@ static void lru_deactivate_fn(struct page *page, void *arg)
        if (!PageLRU(page))
                return;
 
+       if (PageUnevictable(page))
+               return;
+
        /* Some processes are using the page */
        if (page_mapped(page))
                return;
index f6b435c80079337489b17122f0d0ab1b829e12c3..8bfd45050a61494f919e90dfb1538ea8310f4f20 100644 (file)
@@ -937,7 +937,7 @@ keep_lumpy:
         * back off and wait for congestion to clear because further reclaim
         * will encounter the same problem
         */
-       if (nr_dirty == nr_congested && nr_dirty != 0)
+       if (nr_dirty && nr_dirty == nr_congested && scanning_global_lru(sc))
                zone_set_flag(zone, ZONE_CONGESTED);
 
        free_page_list(&free_pages);
index 7850412f52b7e23f817969fea24a560bcbdda4e8..0eb1a886b370bb6f5db3935dae51d46fe0159cdc 100644 (file)
@@ -124,6 +124,9 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 
        grp->nr_vlans--;
 
+       if (vlan->flags & VLAN_FLAG_GVRP)
+               vlan_gvrp_request_leave(dev);
+
        vlan_group_set_device(grp, vlan_id, NULL);
        if (!grp->killall)
                synchronize_net();
index e34ea9e5e28bcefbe502fb81a4f23432294b65da..b2ff6c8d3603daffbdaaa1573e07f18e6e1cb1dc 100644 (file)
@@ -487,9 +487,6 @@ static int vlan_dev_stop(struct net_device *dev)
        struct vlan_dev_info *vlan = vlan_dev_info(dev);
        struct net_device *real_dev = vlan->real_dev;
 
-       if (vlan->flags & VLAN_FLAG_GVRP)
-               vlan_gvrp_request_leave(dev);
-
        dev_mc_unsync(real_dev, dev);
        dev_uc_unsync(real_dev, dev);
        if (dev->flags & IFF_ALLMULTI)
index 77367745be9bd4d03c3b7100c8108d71c8536d98..a9aa2dd66482d31add8af88598902429c1a56c34 100644 (file)
@@ -614,7 +614,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 
        err = c->trans_mod->request(c, req);
        if (err < 0) {
-               if (err != -ERESTARTSYS)
+               if (err != -ERESTARTSYS && err != -EFAULT)
                        c->status = Disconnected;
                goto reterr;
        }
index b58a501cf3d124a06939d266002bf48a92863ee1..a873277cb996810162ee875db9485952144541bb 100644 (file)
@@ -674,6 +674,7 @@ int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
        }
 
        strcpy(dirent->d_name, nameptr);
+       kfree(nameptr);
 
 out:
        return fake_pdu.offset;
index e883172f9aa2c1096d363483f252a603bba7f108..9a70ebdec56e11357ba1f78c0938385881c7d4b3 100644 (file)
@@ -63,7 +63,7 @@ p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
                int nr_pages, u8 rw)
 {
        uint32_t first_page_bytes = 0;
-       uint32_t pdata_mapped_pages;
+       int32_t pdata_mapped_pages;
        struct trans_rpage_info  *rpinfo;
 
        *pdata_off = (__force size_t)req->tc->pubuf & (PAGE_SIZE-1);
@@ -75,14 +75,9 @@ p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
        rpinfo = req->tc->private;
        pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf,
                        nr_pages, rw, &rpinfo->rp_data[0]);
+       if (pdata_mapped_pages <= 0)
+               return pdata_mapped_pages;
 
-       if (pdata_mapped_pages < 0) {
-               printk(KERN_ERR "get_user_pages_fast failed:%d udata:%p"
-                               "nr_pages:%d\n", pdata_mapped_pages,
-                               req->tc->pubuf, nr_pages);
-               pdata_mapped_pages = 0;
-               return -EIO;
-       }
        rpinfo->rp_nr_pages = pdata_mapped_pages;
        if (*pdata_off) {
                *pdata_len = first_page_bytes;
index 3cc43558cf9cbb0958d55f4f6ed236f9c3873322..150b6ce23df38d124d6d8cdef9f0f6d904f8f45f 100644 (file)
 #include <linux/udp.h>
 #include <linux/if_vlan.h>
 
-static void gw_node_free_rcu(struct rcu_head *rcu)
-{
-       struct gw_node *gw_node;
-
-       gw_node = container_of(rcu, struct gw_node, rcu);
-       kfree(gw_node);
-}
-
 static void gw_node_free_ref(struct gw_node *gw_node)
 {
        if (atomic_dec_and_test(&gw_node->refcount))
-               call_rcu(&gw_node->rcu, gw_node_free_rcu);
+               kfree_rcu(gw_node, rcu);
 }
 
 void *gw_get_selected(struct bat_priv *bat_priv)
index 0b9133022d2dd58f3f91d55940667ede6dab9e50..ed23a5895d6c416ea12e0c5bd87ee39859be0ed1 100644 (file)
@@ -56,18 +56,10 @@ err:
        return 0;
 }
 
-static void neigh_node_free_rcu(struct rcu_head *rcu)
-{
-       struct neigh_node *neigh_node;
-
-       neigh_node = container_of(rcu, struct neigh_node, rcu);
-       kfree(neigh_node);
-}
-
 void neigh_node_free_ref(struct neigh_node *neigh_node)
 {
        if (atomic_dec_and_test(&neigh_node->refcount))
-               call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
+               kfree_rcu(neigh_node, rcu);
 }
 
 struct neigh_node *create_neighbor(struct orig_node *orig_node,
index 824e1f6e50f2f702fb7de6887e573a8b9d4590d8..04efe022c13b5b438dbe16df3e217a29a8539ace 100644 (file)
@@ -76,18 +76,10 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len)
        return 0;
 }
 
-static void softif_neigh_free_rcu(struct rcu_head *rcu)
-{
-       struct softif_neigh *softif_neigh;
-
-       softif_neigh = container_of(rcu, struct softif_neigh, rcu);
-       kfree(softif_neigh);
-}
-
 static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
 {
        if (atomic_dec_and_test(&softif_neigh->refcount))
-               call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
+               kfree_rcu(softif_neigh, rcu);
 }
 
 void softif_neigh_purge(struct bat_priv *bat_priv)
index c83f618282f709e424bc30af470139e77586dd66..b5a8afc2be331f5ac5b26649e4609e21039f8b85 100644 (file)
@@ -587,10 +587,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        hci_req_cancel(hdev, ENODEV);
        hci_req_lock(hdev);
 
-       /* Stop timer, it might be running */
-       del_timer_sync(&hdev->cmd_timer);
-
        if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
+               del_timer_sync(&hdev->cmd_timer);
                hci_req_unlock(hdev);
                return 0;
        }
@@ -629,6 +627,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        /* Drop last sent command */
        if (hdev->sent_cmd) {
+               del_timer_sync(&hdev->cmd_timer);
                kfree_skb(hdev->sent_cmd);
                hdev->sent_cmd = NULL;
        }
index cebe7588469fe8a82150d7dd26bea5a981cdfbb1..b2570159a04418bf213a512f6f1e1589faf7ff8a 100644 (file)
@@ -2387,8 +2387,6 @@ static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *s
        if (!conn)
                goto unlock;
 
-       hci_conn_hold(conn);
-
        conn->remote_cap = ev->capability;
        conn->remote_oob = ev->oob_data;
        conn->remote_auth = ev->authentication;
index ca27f3a41536f35d4d608f9f0929b50105658f4d..2c8dd4494c63966ffd0e5df4f66546139dea2f81 100644 (file)
@@ -1051,6 +1051,7 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
        tx_skb = skb_clone(skb, GFP_ATOMIC);
        bt_cb(skb)->retries++;
        control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+       control &= L2CAP_CTRL_SAR;
 
        if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
                control |= L2CAP_CTRL_FINAL;
index e2160792e1bce49869fb5137a73deeabed8e1135..0c7badad62af07ab3e983c0871311a9212c481a3 100644 (file)
@@ -164,7 +164,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
                        goto drop;
 
                /* If STP is turned off, then forward */
-               if (p->br->stp_enabled == BR_NO_STP)
+               if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
                        goto forward;
 
                if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
index 008ff6c4eecf3da16c55901afd9e9fbde9f5ee2f..74ef4d4846a4f93bb11b048a20940d75acf56f2f 100644 (file)
@@ -249,11 +249,9 @@ static int br_parse_ip_options(struct sk_buff *skb)
                goto drop;
        }
 
-       /* Zero out the CB buffer if no options present */
-       if (iph->ihl == 5) {
-               memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+       memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+       if (iph->ihl == 5)
                return 0;
-       }
 
        opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
        if (ip_options_compile(dev_net(dev), opt, skb))
@@ -739,7 +737,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
                nf_bridge->mask |= BRNF_PKT_TYPE;
        }
 
-       if (br_parse_ip_options(skb))
+       if (pf == PF_INET && br_parse_ip_options(skb))
                return NF_DROP;
 
        /* The physdev module checks on this */
index 893669caa8de6c56960f804da8d2125f07823fb3..1a92b369c8202c8706c42452950594233882ca06 100644 (file)
@@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info,
 
        newinfo->entries_size = size;
 
-       xt_compat_init_offsets(AF_INET, info->nentries);
+       xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries);
        return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
                                                        entries, newinfo);
 }
@@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
        struct xt_match *match;
        struct xt_target *wt;
        void *dst = NULL;
-       int off, pad = 0, ret = 0;
+       int off, pad = 0;
        unsigned int size_kern, entry_offset, match_size = mwt->match_size;
 
        strlcpy(name, mwt->u.name, sizeof(name));
@@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
                break;
        }
 
-       if (!dst) {
-               ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
-                                       off + ebt_compat_entry_padsize());
-               if (ret < 0)
-                       return ret;
-       }
-
        state->buf_kern_offset += match_size + off;
        state->buf_user_offset += match_size;
        pad = XT_ALIGN(size_kern) - size_kern;
@@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
        return growth;
 }
 
-#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...)          \
-({                                                          \
-       unsigned int __i;                                   \
-       int __ret = 0;                                      \
-       struct compat_ebt_entry_mwt *__watcher;             \
-                                                           \
-       for (__i = e->watchers_offset;                      \
-            __i < (e)->target_offset;                      \
-            __i += __watcher->watcher_size +               \
-            sizeof(struct compat_ebt_entry_mwt)) {         \
-               __watcher = (void *)(e) + __i;              \
-               __ret = fn(__watcher , ## args);            \
-               if (__ret != 0)                             \
-                       break;                              \
-       }                                                   \
-       if (__ret == 0) {                                   \
-               if (__i != (e)->target_offset)              \
-                       __ret = -EINVAL;                    \
-       }                                                   \
-       __ret;                                              \
-})
-
-#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...)            \
-({                                                          \
-       unsigned int __i;                                   \
-       int __ret = 0;                                      \
-       struct compat_ebt_entry_mwt *__match;               \
-                                                           \
-       for (__i = sizeof(struct ebt_entry);                \
-            __i < (e)->watchers_offset;                    \
-            __i += __match->match_size +                   \
-            sizeof(struct compat_ebt_entry_mwt)) {         \
-               __match = (void *)(e) + __i;                \
-               __ret = fn(__match , ## args);              \
-               if (__ret != 0)                             \
-                       break;                              \
-       }                                                   \
-       if (__ret == 0) {                                   \
-               if (__i != (e)->watchers_offset)            \
-                       __ret = -EINVAL;                    \
-       }                                                   \
-       __ret;                                              \
-})
-
 /* called for all ebt_entry structures. */
 static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
                          unsigned int *total,
@@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
                }
        }
 
+       if (state->buf_kern_start == NULL) {
+               unsigned int offset = buf_start - (char *) base;
+
+               ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset);
+               if (ret < 0)
+                       return ret;
+       }
+
        startoff = state->buf_user_offset - startoff;
 
        BUG_ON(*total < startoff);
@@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
+       xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
                goto out_unlock;
index 27dab26ad3b84ff213497bcd9029b7af75688560..054fdb5aeb88073d89293a424fcf7c6458f4bd51 100644 (file)
@@ -13,6 +13,7 @@
 #include <net/caif/cfsrvl.h>
 #include <net/caif/cfpkt.h>
 
+
 #define container_obj(layr) ((struct cfsrvl *) layr)
 
 #define DGM_CMD_BIT  0x80
@@ -83,6 +84,7 @@ static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt)
 
 static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
 {
+       u8 packet_type;
        u32 zero = 0;
        struct caif_payload_info *info;
        struct cfsrvl *service = container_obj(layr);
@@ -94,7 +96,9 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
        if (cfpkt_getlen(pkt) > DGM_MTU)
                return -EMSGSIZE;
 
-       cfpkt_add_head(pkt, &zero, 4);
+       cfpkt_add_head(pkt, &zero, 3);
+       packet_type = 0x08; /* B9 set - UNCLASSIFIED */
+       cfpkt_add_head(pkt, &packet_type, 1);
 
        /* Add info for MUX-layer to route the packet out. */
        info = cfpkt_info(pkt);
index 46f34b2e04784d8fd379384851c3d5b19377ddee..24f1ffa74b06dbc17a751eef251f1c73f111d064 100644 (file)
@@ -244,9 +244,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
                                int phyid)
 {
        struct cfmuxl *muxl = container_obj(layr);
-       struct list_head *node;
+       struct list_head *node, *next;
        struct cflayer *layer;
-       list_for_each(node, &muxl->srvl_list) {
+       list_for_each_safe(node, next, &muxl->srvl_list) {
                layer = list_entry(node, struct cflayer, node);
                if (cfsrvl_phyid_match(layer, phyid))
                        layer->ctrlcmd(layer, ctrl, phyid);
index 57b1aed79014cdd6022fa04175a1344139f57334..8a6a05e7c3c8de434caf5ffbbb42316086c847b2 100644 (file)
@@ -1427,9 +1427,14 @@ static int bcm_init(struct sock *sk)
 static int bcm_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct bcm_sock *bo = bcm_sk(sk);
+       struct bcm_sock *bo;
        struct bcm_op *op, *next;
 
+       if (sk == NULL)
+               return 0;
+
+       bo = bcm_sk(sk);
+
        /* remove bcm_ops, timer, rx_unregister(), etc. */
 
        unregister_netdevice_notifier(&bo->notifier);
index 649acfa7c70a98ceb5fd3f131544f02e3cf838c8..0eb39a7fdf64afff51c7e59bd0985433302c60ee 100644 (file)
@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk)
 static int raw_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct raw_sock *ro = raw_sk(sk);
+       struct raw_sock *ro;
+
+       if (!sk)
+               return 0;
+
+       ro = raw_sk(sk);
 
        unregister_netdevice_notifier(&ro->notifier);
 
index 05f357828a2fb8de1bb2be9f4103c90058484259..e15a82ccc05f69789e162c5caa51d4bb2cc082a5 100644 (file)
@@ -2267,6 +2267,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
        m->more_to_follow = false;
        m->pool = NULL;
 
+       /* middle */
+       m->middle = NULL;
+
+       /* data */
+       m->nr_pages = 0;
+       m->page_alignment = 0;
+       m->pages = NULL;
+       m->pagelist = NULL;
+       m->bio = NULL;
+       m->bio_iter = NULL;
+       m->bio_seg = 0;
+       m->trail = NULL;
+
        /* front */
        if (front_len) {
                if (front_len > PAGE_CACHE_SIZE) {
@@ -2286,19 +2299,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
        }
        m->front.iov_len = front_len;
 
-       /* middle */
-       m->middle = NULL;
-
-       /* data */
-       m->nr_pages = 0;
-       m->page_alignment = 0;
-       m->pages = NULL;
-       m->pagelist = NULL;
-       m->bio = NULL;
-       m->bio_iter = NULL;
-       m->bio_seg = 0;
-       m->trail = NULL;
-
        dout("ceph_msg_new %p front %d\n", m, front_len);
        return m;
 
index 5a80f41c0cbaf207cf71310161856b5a31e65b4a..6b5dda1cb5df1a7adf6b93a49201b34d81eb8dcb 100644 (file)
@@ -470,8 +470,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                         snapc, ops,
                                         use_mempool,
                                         GFP_NOFS, NULL, NULL);
-       if (IS_ERR(req))
-               return req;
+       if (!req)
+               return NULL;
 
        /* calculate max write size */
        calc_layout(osdc, vino, layout, off, plen, req, ops);
index 956d3b006e8b96598acb655c383de5d964167697..b624fe4d9bd7ce408ab93d324ad7cc8413d8f4b8 100644 (file)
@@ -1284,11 +1284,13 @@ static int dev_close_many(struct list_head *head)
  */
 int dev_close(struct net_device *dev)
 {
-       LIST_HEAD(single);
+       if (dev->flags & IFF_UP) {
+               LIST_HEAD(single);
 
-       list_add(&dev->unreg_list, &single);
-       dev_close_many(&single);
-       list_del(&single);
+               list_add(&dev->unreg_list, &single);
+               dev_close_many(&single);
+               list_del(&single);
+       }
        return 0;
 }
 EXPORT_SYMBOL(dev_close);
@@ -4773,7 +4775,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm
                 * is never reached
                 */
                WARN_ON(1);
-               err = -EINVAL;
+               err = -ENOTTY;
                break;
 
        }
@@ -5041,7 +5043,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Set the per device memory buffer space.
                 * Not applicable in our case */
        case SIOCSIFLINK:
-               return -EINVAL;
+               return -ENOTTY;
 
        /*
         *      Unknown or private ioctl.
@@ -5062,7 +5064,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Take care of Wireless Extensions */
                if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
                        return wext_handle_ioctl(net, &ifr, cmd, arg);
-               return -EINVAL;
+               return -ENOTTY;
        }
 }
 
@@ -5184,33 +5186,37 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
        /* Fix illegal checksum combinations */
        if ((features & NETIF_F_HW_CSUM) &&
            (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-               netdev_info(dev, "mixed HW and IP checksum settings.\n");
+               netdev_warn(dev, "mixed HW and IP checksum settings.\n");
                features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
        }
 
        if ((features & NETIF_F_NO_CSUM) &&
            (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-               netdev_info(dev, "mixed no checksumming and other settings.\n");
+               netdev_warn(dev, "mixed no checksumming and other settings.\n");
                features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
        }
 
        /* Fix illegal SG+CSUM combinations. */
        if ((features & NETIF_F_SG) &&
            !(features & NETIF_F_ALL_CSUM)) {
-               netdev_info(dev,
-                           "Dropping NETIF_F_SG since no checksum feature.\n");
+               netdev_dbg(dev,
+                       "Dropping NETIF_F_SG since no checksum feature.\n");
                features &= ~NETIF_F_SG;
        }
 
        /* TSO requires that SG is present as well. */
-       if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n");
-               features &= ~NETIF_F_TSO;
+       if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) {
+               netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
+               features &= ~NETIF_F_ALL_TSO;
        }
 
+       /* TSO ECN requires that TSO is present as well. */
+       if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN)
+               features &= ~NETIF_F_TSO_ECN;
+
        /* Software GSO depends on SG. */
        if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
+               netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
                features &= ~NETIF_F_GSO;
        }
 
@@ -5220,13 +5226,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
                if (!((features & NETIF_F_GEN_CSUM) ||
                    (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
                            == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-                       netdev_info(dev,
+                       netdev_dbg(dev,
                                "Dropping NETIF_F_UFO since no checksum offload features.\n");
                        features &= ~NETIF_F_UFO;
                }
 
                if (!(features & NETIF_F_SG)) {
-                       netdev_info(dev,
+                       netdev_dbg(dev,
                                "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n");
                        features &= ~NETIF_F_UFO;
                }
@@ -5408,12 +5414,6 @@ int register_netdevice(struct net_device *dev)
        dev->features |= NETIF_F_SOFT_FEATURES;
        dev->wanted_features = dev->features & dev->hw_features;
 
-       /* Avoid warning from netdev_fix_features() for GSO without SG */
-       if (!(dev->wanted_features & NETIF_F_SG)) {
-               dev->wanted_features &= ~NETIF_F_GSO;
-               dev->features &= ~NETIF_F_GSO;
-       }
-
        /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
         * vlan_dev_init() will do the dev->features check, so these features
         * are enabled only if supported by underlying device.
index 7b39f3ed2fdaede3f79a03eb7728f07fdf643596..e2e66939ed009df93fe61b22c07d33c892fdeb4e 100644 (file)
@@ -68,14 +68,6 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
        return __hw_addr_add_ex(list, addr, addr_len, addr_type, false);
 }
 
-static void ha_rcu_free(struct rcu_head *head)
-{
-       struct netdev_hw_addr *ha;
-
-       ha = container_of(head, struct netdev_hw_addr, rcu_head);
-       kfree(ha);
-}
-
 static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
                            unsigned char *addr, int addr_len,
                            unsigned char addr_type, bool global)
@@ -94,7 +86,7 @@ static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
                        if (--ha->refcount)
                                return 0;
                        list_del_rcu(&ha->list);
-                       call_rcu(&ha->rcu_head, ha_rcu_free);
+                       kfree_rcu(ha, rcu_head);
                        list->count--;
                        return 0;
                }
@@ -197,7 +189,7 @@ void __hw_addr_flush(struct netdev_hw_addr_list *list)
 
        list_for_each_entry_safe(ha, tmp, &list->list, list) {
                list_del_rcu(&ha->list);
-               call_rcu(&ha->rcu_head, ha_rcu_free);
+               kfree_rcu(ha, rcu_head);
        }
        list->count = 0;
 }
index 706502ff64aa884548bf5122bd71085aea098a45..7f36b38e060fcfbf98ed35cd1dff84067f75d11c 100644 (file)
@@ -207,14 +207,6 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi)
        rcu_read_unlock();
 }
 
-
-static void free_dm_hw_stat(struct rcu_head *head)
-{
-       struct dm_hw_stat_delta *n;
-       n = container_of(head, struct dm_hw_stat_delta, rcu);
-       kfree(n);
-}
-
 static int set_all_monitor_traces(int state)
 {
        int rc = 0;
@@ -245,7 +237,7 @@ static int set_all_monitor_traces(int state)
                list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) {
                        if (new_stat->dev == NULL) {
                                list_del_rcu(&new_stat->list);
-                               call_rcu(&new_stat->rcu, free_dm_hw_stat);
+                               kfree_rcu(new_stat, rcu);
                        }
                }
                break;
@@ -314,7 +306,7 @@ static int dropmon_net_event(struct notifier_block *ev_block,
                                new_stat->dev = NULL;
                                if (trace_state == TRACE_OFF) {
                                        list_del_rcu(&new_stat->list);
-                                       call_rcu(&new_stat->rcu, free_dm_hw_stat);
+                                       kfree_rcu(new_stat, rcu);
                                        break;
                                }
                        }
index 7c2373321b74317c1c36918c20726cba10490768..43b03dd71e85da9b6d2043beb531cd4289d0531a 100644 (file)
@@ -249,13 +249,6 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
 }
 EXPORT_SYMBOL(gen_new_estimator);
 
-static void __gen_kill_estimator(struct rcu_head *head)
-{
-       struct gen_estimator *e = container_of(head,
-                                       struct gen_estimator, e_rcu);
-       kfree(e);
-}
-
 /**
  * gen_kill_estimator - remove a rate estimator
  * @bstats: basic statistics
@@ -279,7 +272,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                write_unlock(&est_lock);
 
                list_del_rcu(&e->list);
-               call_rcu(&e->e_rcu, __gen_kill_estimator);
+               kfree_rcu(e, e_rcu);
        }
        spin_unlock_bh(&est_tree_lock);
 }
index 5ceb257e860c18cbabe352f67cb8760d95bcba84..80b2aad3b73d4dda35fb59b8090e9d3c06450ea5 100644 (file)
@@ -565,13 +565,6 @@ static ssize_t show_rps_map(struct netdev_rx_queue *queue,
        return len;
 }
 
-static void rps_map_release(struct rcu_head *rcu)
-{
-       struct rps_map *map = container_of(rcu, struct rps_map, rcu);
-
-       kfree(map);
-}
-
 static ssize_t store_rps_map(struct netdev_rx_queue *queue,
                      struct rx_queue_attribute *attribute,
                      const char *buf, size_t len)
@@ -619,7 +612,7 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue,
        spin_unlock(&rps_map_lock);
 
        if (old_map)
-               call_rcu(&old_map->rcu, rps_map_release);
+               kfree_rcu(old_map, rcu);
 
        free_cpumask_var(mask);
        return len;
@@ -728,7 +721,7 @@ static void rx_queue_release(struct kobject *kobj)
        map = rcu_dereference_raw(queue->rps_map);
        if (map) {
                RCU_INIT_POINTER(queue->rps_map, NULL);
-               call_rcu(&map->rcu, rps_map_release);
+               kfree_rcu(map, rcu);
        }
 
        flow_table = rcu_dereference_raw(queue->rps_flow_table);
@@ -898,21 +891,6 @@ static ssize_t show_xps_map(struct netdev_queue *queue,
        return len;
 }
 
-static void xps_map_release(struct rcu_head *rcu)
-{
-       struct xps_map *map = container_of(rcu, struct xps_map, rcu);
-
-       kfree(map);
-}
-
-static void xps_dev_maps_release(struct rcu_head *rcu)
-{
-       struct xps_dev_maps *dev_maps =
-           container_of(rcu, struct xps_dev_maps, rcu);
-
-       kfree(dev_maps);
-}
-
 static DEFINE_MUTEX(xps_map_mutex);
 #define xmap_dereference(P)            \
        rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
@@ -1009,7 +987,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
                map = dev_maps ?
                        xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
                if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map)
-                       call_rcu(&map->rcu, xps_map_release);
+                       kfree_rcu(map, rcu);
                if (new_dev_maps->cpu_map[cpu])
                        nonempty = 1;
        }
@@ -1022,7 +1000,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
        }
 
        if (dev_maps)
-               call_rcu(&dev_maps->rcu, xps_dev_maps_release);
+               kfree_rcu(dev_maps, rcu);
 
        netdev_queue_numa_node_write(queue, (numa_node >= 0) ? numa_node :
                                            NUMA_NO_NODE);
@@ -1084,7 +1062,7 @@ static void netdev_queue_release(struct kobject *kobj)
                                else {
                                        RCU_INIT_POINTER(dev_maps->cpu_map[i],
                                            NULL);
-                                       call_rcu(&map->rcu, xps_map_release);
+                                       kfree_rcu(map, rcu);
                                        map = NULL;
                                }
                        }
@@ -1094,7 +1072,7 @@ static void netdev_queue_release(struct kobject *kobj)
 
                if (!nonempty) {
                        RCU_INIT_POINTER(dev->xps_maps, NULL);
-                       call_rcu(&dev_maps->rcu, xps_dev_maps_release);
+                       kfree_rcu(dev_maps, rcu);
                }
        }
 
index 3f860261c5eea2be402ed0556a3a8b3f6fd7fc9b..297bb92722407f573bd8446154f773e74166bcc4 100644 (file)
@@ -27,14 +27,6 @@ EXPORT_SYMBOL(init_net);
 
 #define INITIAL_NET_GEN_PTRS   13 /* +1 for len +2 for rcu_head */
 
-static void net_generic_release(struct rcu_head *rcu)
-{
-       struct net_generic *ng;
-
-       ng = container_of(rcu, struct net_generic, rcu);
-       kfree(ng);
-}
-
 static int net_assign_generic(struct net *net, int id, void *data)
 {
        struct net_generic *ng, *old_ng;
@@ -68,7 +60,7 @@ static int net_assign_generic(struct net *net, int id, void *data)
        memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
 
        rcu_assign_pointer(net->gen, ng);
-       call_rcu(&old_ng->rcu, net_generic_release);
+       kfree_rcu(old_ng, rcu);
 assign:
        ng->ptr[id - 1] = data;
        return 0;
index f06ffcfc8d712421040c71a56513b90dcfca96c7..4b2ab657ac8e616f415312d96a2b9c0189489a18 100644 (file)
@@ -123,6 +123,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
                case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
                        if (pkt_type == DCCP_PKT_DATA)      /* RFC 4340, 6 */
                                break;
+                       if (len == 0)
+                               goto out_invalid_option;
                        rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
                                                    *value, value + 1, len - 1);
                        if (rc)
index 0dcaa903e00e0f4ce4eb53ebfe150878f7d26e06..4c27615340dc25987e0f3f3b3070790cad16c902 100644 (file)
@@ -332,14 +332,9 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void)
        return ifa;
 }
 
-static void dn_dev_free_ifa_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct dn_ifaddr, rcu));
-}
-
 static void dn_dev_free_ifa(struct dn_ifaddr *ifa)
 {
-       call_rcu(&ifa->rcu, dn_dev_free_ifa_rcu);
+       kfree_rcu(ifa, rcu);
 }
 
 static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy)
index 87bb5f4de0e84601817a0f63733a725ebb478b03..c53ded2a98dfbcd26113a2265fc14f22fa352971 100644 (file)
@@ -41,12 +41,12 @@ config NET_DSA_MV88E6XXX_NEED_PPU
        default n
 
 config NET_DSA_MV88E6131
-       bool "Marvell 88E6095/6095F/6131 ethernet switch chip support"
+       bool "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
        select NET_DSA_MV88E6XXX
        select NET_DSA_MV88E6XXX_NEED_PPU
        select NET_DSA_TAG_DSA
        ---help---
-         This enables support for the Marvell 88E6095/6095F/6131
+         This enables support for the Marvell 88E6085/6095/6095F/6131
          ethernet switch chips.
 
 config NET_DSA_MV88E6123_61_65
index 3da418894efcc715ceca776061028c7e7ce4d551..45f7411e90baf02fbed1642676f6448b74d024cb 100644 (file)
@@ -207,8 +207,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
         * mode, but do not enable forwarding of unknown unicasts.
         */
        val = 0x0433;
-       if (p == dsa_upstream_port(ds))
+       if (p == dsa_upstream_port(ds)) {
                val |= 0x0104;
+               /*
+                * On 6085, unknown multicast forward is controlled
+                * here rather than in Port Control 2 register.
+                */
+               if (ps->id == ID_6085)
+                       val |= 0x0008;
+       }
        if (ds->dsa_port_mask & (1 << p))
                val |= 0x0100;
        REG_WRITE(addr, 0x04, val);
@@ -251,10 +258,19 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
         * If this is the upstream port for this switch, enable
         * forwarding of unknown multicast addresses.
         */
-       val = 0x0080 | dsa_upstream_port(ds);
-       if (p == dsa_upstream_port(ds))
-               val |= 0x0040;
-       REG_WRITE(addr, 0x08, val);
+       if (ps->id == ID_6085)
+               /*
+                * on 6085, bits 3:0 are reserved, bit 6 control ARP
+                * mirroring, and multicast forward is handled in
+                * Port Control register.
+                */
+               REG_WRITE(addr, 0x08, 0x0080);
+       else {
+               val = 0x0080 | dsa_upstream_port(ds);
+               if (p == dsa_upstream_port(ds))
+                       val |= 0x0040;
+               REG_WRITE(addr, 0x08, val);
+       }
 
        /*
         * Rate Control: disable ingress rate limiting.
index ce2d33582859df2dd139941f79a70340c4775edc..5761185f884e8d72d32257476e94b273da0190d0 100644 (file)
@@ -1,5 +1,3 @@
 obj-$(CONFIG_IEEE802154) +=    ieee802154.o af_802154.o
 ieee802154-y           := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
 af_802154-y            := af_ieee802154.o raw.o dgram.o
-
-ccflags-y += -Wall -DDEBUG
index 5345b0bee6df816858c1424d0ccb50988d133aa2..cd9ca0811cfaf30a179db870bfe628d4d0261a2e 100644 (file)
@@ -1680,7 +1680,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
                return;
 
        cnf->sysctl = NULL;
-       unregister_sysctl_table(t->sysctl_header);
+       unregister_net_sysctl_table(t->sysctl_header);
        kfree(t->dev_name);
        kfree(t);
 }
index 641a5a2a9f9c4e7b9e1c2b11bebee5cb98ea43de..33e2c35b74b770f526045776e355e01114477fd9 100644 (file)
@@ -141,18 +141,8 @@ const struct fib_prop fib_props[RTN_MAX + 1] = {
        },
 };
 
-
 /* Release a nexthop info record */
 
-static void free_fib_info_rcu(struct rcu_head *head)
-{
-       struct fib_info *fi = container_of(head, struct fib_info, rcu);
-
-       if (fi->fib_metrics != (u32 *) dst_default_metrics)
-               kfree(fi->fib_metrics);
-       kfree(fi);
-}
-
 void free_fib_info(struct fib_info *fi)
 {
        if (fi->fib_dead == 0) {
@@ -166,7 +156,7 @@ void free_fib_info(struct fib_info *fi)
        } endfor_nexthops(fi);
        fib_info_cnt--;
        release_net(fi->fib_net);
-       call_rcu(&fi->rcu, free_fib_info_rcu);
+       kfree_rcu(fi, rcu);
 }
 
 void fib_release_info(struct fib_info *fi)
index e9013d6c1f513adfbde31e16041a5c82235b6af4..11d4d28190bddcf462d9e0859745d3bdcbb7bdb8 100644 (file)
@@ -350,14 +350,9 @@ static inline void free_leaf(struct leaf *l)
        call_rcu_bh(&l->rcu, __leaf_free_rcu);
 }
 
-static void __leaf_info_free_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct leaf_info, rcu));
-}
-
 static inline void free_leaf_info(struct leaf_info *leaf)
 {
-       call_rcu(&leaf->rcu, __leaf_info_free_rcu);
+       kfree_rcu(leaf, rcu);
 }
 
 static struct tnode *tnode_alloc(size_t size)
@@ -1978,9 +1973,6 @@ struct fib_table *fib_trie_table(u32 id)
        t = (struct trie *) tb->tb_data;
        memset(t, 0, sizeof(*t));
 
-       if (id == RT_TABLE_LOCAL)
-               pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION);
-
        return tb;
 }
 
index 1fd3d9ce8398053588a45086ba813adfc7744de4..8f62d66d085756c3525e12101d462873edfa8a49 100644 (file)
@@ -149,17 +149,11 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc);
 static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                         int sfcount, __be32 *psfsrc, int delta);
 
-
-static void ip_mc_list_reclaim(struct rcu_head *head)
-{
-       kfree(container_of(head, struct ip_mc_list, rcu));
-}
-
 static void ip_ma_put(struct ip_mc_list *im)
 {
        if (atomic_dec_and_test(&im->refcnt)) {
                in_dev_put(im->interface);
-               call_rcu(&im->rcu, ip_mc_list_reclaim);
+               kfree_rcu(im, rcu);
        }
 }
 
@@ -1836,12 +1830,6 @@ done:
 }
 EXPORT_SYMBOL(ip_mc_join_group);
 
-static void ip_sf_socklist_reclaim(struct rcu_head *rp)
-{
-       kfree(container_of(rp, struct ip_sf_socklist, rcu));
-       /* sk_omem_alloc should have been decreased by the caller*/
-}
-
 static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
                           struct in_device *in_dev)
 {
@@ -1858,18 +1846,10 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
        rcu_assign_pointer(iml->sflist, NULL);
        /* decrease mem now to avoid the memleak warning */
        atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc);
-       call_rcu(&psf->rcu, ip_sf_socklist_reclaim);
+       kfree_rcu(psf, rcu);
        return err;
 }
 
-
-static void ip_mc_socklist_reclaim(struct rcu_head *rp)
-{
-       kfree(container_of(rp, struct ip_mc_socklist, rcu));
-       /* sk_omem_alloc should have been decreased by the caller*/
-}
-
-
 /*
  *     Ask a socket to leave a group.
  */
@@ -1909,7 +1889,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
                rtnl_unlock();
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
-               call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
+               kfree_rcu(iml, rcu);
                return 0;
        }
        if (!in_dev)
@@ -2026,7 +2006,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                                newpsl->sl_addr[i] = psl->sl_addr[i];
                        /* decrease mem now to avoid the memleak warning */
                        atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
-                       call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
+                       kfree_rcu(psl, rcu);
                }
                rcu_assign_pointer(pmc->sflist, newpsl);
                psl = newpsl;
@@ -2127,7 +2107,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
                        psl->sl_count, psl->sl_addr, 0);
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
-               call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
+               kfree_rcu(psl, rcu);
        } else
                (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
                        0, NULL, 0);
@@ -2324,7 +2304,7 @@ void ip_mc_drop_socket(struct sock *sk)
                        ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
-               call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
+               kfree_rcu(iml, rcu);
        }
        rtnl_unlock();
 }
index 6c0b7f4a3d7d3c97e83a197e16809e6fdb071234..38f23e721b80108d0a9ae3716fca5212cf8f737d 100644 (file)
@@ -73,7 +73,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
                        if (!reuse || !sk2->sk_reuse ||
-                           ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) {
+                           sk2->sk_state == TCP_LISTEN) {
                                const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2);
                                if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) ||
                                    sk2_rcv_saddr == sk_rcv_saddr(sk))
@@ -122,8 +122,7 @@ again:
                                            (tb->num_owners < smallest_size || smallest_size == -1)) {
                                                smallest_size = tb->num_owners;
                                                smallest_rover = rover;
-                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 &&
-                                                   !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
                                                        spin_unlock(&head->lock);
                                                        snum = smallest_rover;
                                                        goto have_snum;
index dd1b20eca1a25fd845e03ecc077a1e0f43412eff..9df4e635fb5fe5d4a0c92526ad68b845094aa39d 100644 (file)
@@ -354,7 +354,8 @@ static void inetpeer_free_rcu(struct rcu_head *head)
 }
 
 /* May be called with local BH enabled. */
-static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
+static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
+                            struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
        int do_free;
 
@@ -368,7 +369,6 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
         * We use refcnt=-1 to alert lockless readers this entry is deleted.
         */
        if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
-               struct inet_peer __rcu **stack[PEER_MAXDEPTH];
                struct inet_peer __rcu ***stackptr, ***delp;
                if (lookup(&p->daddr, stack, base) != p)
                        BUG();
@@ -422,7 +422,7 @@ static struct inet_peer_base *peer_to_base(struct inet_peer *p)
 }
 
 /* May be called with local BH enabled. */
-static int cleanup_once(unsigned long ttl)
+static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
        struct inet_peer *p = NULL;
 
@@ -454,7 +454,7 @@ static int cleanup_once(unsigned long ttl)
                 * happen because of entry limits in route cache. */
                return -1;
 
-       unlink_from_pool(p, peer_to_base(p));
+       unlink_from_pool(p, peer_to_base(p), stack);
        return 0;
 }
 
@@ -524,7 +524,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 
        if (base->total >= inet_peer_threshold)
                /* Remove one less-recently-used entry. */
-               cleanup_once(0);
+               cleanup_once(0, stack);
 
        return p;
 }
@@ -540,6 +540,7 @@ static void peer_check_expire(unsigned long dummy)
 {
        unsigned long now = jiffies;
        int ttl, total;
+       struct inet_peer __rcu **stack[PEER_MAXDEPTH];
 
        total = compute_total();
        if (total >= inet_peer_threshold)
@@ -548,7 +549,7 @@ static void peer_check_expire(unsigned long dummy)
                ttl = inet_peer_maxttl
                                - (inet_peer_maxttl - inet_peer_minttl) / HZ *
                                        total / inet_peer_threshold * HZ;
-       while (!cleanup_once(ttl)) {
+       while (!cleanup_once(ttl, stack)) {
                if (jiffies != now)
                        break;
        }
index a1151b8adf3c6d65409ea8944973432187e49fe0..b1d282f11be7e23ae4099901ac4be00c5fd8cd12 100644 (file)
@@ -223,31 +223,30 @@ static void ip_expire(unsigned long arg)
 
        if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
                struct sk_buff *head = qp->q.fragments;
+               const struct iphdr *iph;
+               int err;
 
                rcu_read_lock();
                head->dev = dev_get_by_index_rcu(net, qp->iif);
                if (!head->dev)
                        goto out_rcu_unlock;
 
+               /* skb dst is stale, drop it, and perform route lookup again */
+               skb_dst_drop(head);
+               iph = ip_hdr(head);
+               err = ip_route_input_noref(head, iph->daddr, iph->saddr,
+                                          iph->tos, head->dev);
+               if (err)
+                       goto out_rcu_unlock;
+
                /*
-                * Only search router table for the head fragment,
-                * when defraging timeout at PRE_ROUTING HOOK.
+                * Only an end host needs to send an ICMP
+                * "Fragment Reassembly Timeout" message, per RFC792.
                 */
-               if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) {
-                       const struct iphdr *iph = ip_hdr(head);
-                       int err = ip_route_input(head, iph->daddr, iph->saddr,
-                                                iph->tos, head->dev);
-                       if (unlikely(err))
-                               goto out_rcu_unlock;
-
-                       /*
-                        * Only an end host needs to send an ICMP
-                        * "Fragment Reassembly Timeout" message, per RFC792.
-                        */
-                       if (skb_rtable(head)->rt_type != RTN_LOCAL)
-                               goto out_rcu_unlock;
+               if (qp->user == IP_DEFRAG_CONNTRACK_IN &&
+                   skb_rtable(head)->rt_type != RTN_LOCAL)
+                       goto out_rcu_unlock;
 
-               }
 
                /* Send an ICMP "Fragment Reassembly Timeout" message. */
                icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
index 28a736f3442f456c1abd7b7d56eb2e9c4ffdb493..2391b24e8251e62e2c71eadad172a673a1e76c2f 100644 (file)
@@ -329,7 +329,7 @@ int ip_options_compile(struct net *net,
                                        pp_ptr = optptr + 2;
                                        goto error;
                                }
-                               if (skb) {
+                               if (rt) {
                                        memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
                                        opt->is_changed = 1;
                                }
@@ -371,7 +371,7 @@ int ip_options_compile(struct net *net,
                                                goto error;
                                        }
                                        opt->ts = optptr - iph;
-                                       if (skb) {
+                                       if (rt)  {
                                                memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
                                                timeptr = (__be32*)&optptr[optptr[2]+3];
                                        }
@@ -603,7 +603,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
        unsigned long orefdst;
        int err;
 
-       if (!opt->srr)
+       if (!opt->srr || !rt)
                return 0;
 
        if (skb->pkt_type != PACKET_HOST)
index c1acf69858fd722e6a755c8bf029a56039605b67..99e6e4bb1c72d044b97ba93ad6c0bd944d170edd 100644 (file)
@@ -2690,6 +2690,12 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
 
+static u32 *ipv4_rt_blackhole_cow_metrics(struct dst_entry *dst,
+                                         unsigned long old)
+{
+       return NULL;
+}
+
 static struct dst_ops ipv4_dst_blackhole_ops = {
        .family                 =       AF_INET,
        .protocol               =       cpu_to_be16(ETH_P_IP),
@@ -2698,6 +2704,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
        .default_mtu            =       ipv4_blackhole_default_mtu,
        .default_advmss         =       ipv4_default_advmss,
        .update_pmtu            =       ipv4_rt_blackhole_update_pmtu,
+       .cow_metrics            =       ipv4_rt_blackhole_cow_metrics,
 };
 
 struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
index 1a456652086b7b4837b8e1035f0a96bb12eb6700..321e6e84dbccb93e08741263815aaae82610b0a8 100644 (file)
@@ -311,7 +311,6 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_do_large_bitmap,
        },
-#ifdef CONFIG_IP_MULTICAST
        {
                .procname       = "igmp_max_memberships",
                .data           = &sysctl_igmp_max_memberships,
@@ -319,8 +318,6 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
-
-#endif
        {
                .procname       = "igmp_max_msf",
                .data           = &sysctl_igmp_max_msf,
index 34340c9c95fab4f3c9aa108fbed4dd7f69028cd9..f376b05cca818fd9496fe0cb8540a051e3e7e50a 100644 (file)
@@ -93,6 +93,7 @@ struct bictcp {
        u32     ack_cnt;        /* number of acks */
        u32     tcp_cwnd;       /* estimated tcp cwnd */
 #define ACK_RATIO_SHIFT        4
+#define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT)
        u16     delayed_ack;    /* estimate the ratio of Packets/ACKs << 4 */
        u8      sample_cnt;     /* number of samples to decide curr_rtt */
        u8      found;          /* the exit point is found? */
@@ -398,8 +399,12 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
        u32 delay;
 
        if (icsk->icsk_ca_state == TCP_CA_Open) {
-               cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT;
-               ca->delayed_ack += cnt;
+               u32 ratio = ca->delayed_ack;
+
+               ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT;
+               ratio += cnt;
+
+               ca->delayed_ack = min(ratio, ACK_RATIO_LIMIT);
        }
 
        /* Some calls are for duplicates without timetamps */
index 571aa96a175c956fb81728030441309286b938c9..2d51840e53a114be661abd42200a632b9ebf791e 100644 (file)
@@ -69,7 +69,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(xfrm4_prepare_output);
 
-static int xfrm4_output_finish(struct sk_buff *skb)
+int xfrm4_output_finish(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER
        if (!skb_dst(skb)->xfrm) {
@@ -86,7 +86,11 @@ static int xfrm4_output_finish(struct sk_buff *skb)
 
 int xfrm4_output(struct sk_buff *skb)
 {
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x = dst->xfrm;
+
        return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
-                           NULL, skb_dst(skb)->dev, xfrm4_output_finish,
+                           NULL, dst->dev,
+                           x->outer_mode->afinfo->output_finish,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
index 1717c64628d1c5c4625ca7b25a2b02422b52c61b..805d63ef4340fae1176ee8c2c0be0e24d1b60ef6 100644 (file)
@@ -78,6 +78,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .init_tempsel           = __xfrm4_init_tempsel,
        .init_temprop           = xfrm4_init_temprop,
        .output                 = xfrm4_output,
+       .output_finish          = xfrm4_output_finish,
        .extract_input          = xfrm4_extract_input,
        .extract_output         = xfrm4_extract_output,
        .transport_finish       = xfrm4_transport_finish,
index 1493534116df489b8a41411face52d2b06279928..8f13d88d7dba489739f60c8a64ec6df22ce59d6e 100644 (file)
@@ -317,12 +317,6 @@ static void snmp6_free_dev(struct inet6_dev *idev)
 
 /* Nobody refers to this device, we may destroy it. */
 
-static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
-{
-       struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
-       kfree(idev);
-}
-
 void in6_dev_finish_destroy(struct inet6_dev *idev)
 {
        struct net_device *dev = idev->dev;
@@ -339,7 +333,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
                return;
        }
        snmp6_free_dev(idev);
-       call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
+       kfree_rcu(idev, rcu);
 }
 
 EXPORT_SYMBOL(in6_dev_finish_destroy);
@@ -535,12 +529,6 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 }
 #endif
 
-static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head)
-{
-       struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu);
-       kfree(ifp);
-}
-
 /* Nobody refers to this ifaddr, destroy it */
 void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
 {
@@ -561,7 +549,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
        }
        dst_release(&ifp->rt->dst);
 
-       call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu);
+       kfree_rcu(ifp, rcu);
 }
 
 static void
@@ -4537,7 +4525,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
        t = p->sysctl;
        p->sysctl = NULL;
-       unregister_sysctl_table(t->sysctl_header);
+       unregister_net_sysctl_table(t->sysctl_header);
        kfree(t->dev_name);
        kfree(t);
 }
index 5aa8ec88f1946296ce4f776f8927f764cf4edbc1..59dccfbb5b11332f7f3957d2fb80a0f94a2784da 100644 (file)
@@ -371,7 +371,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
        iv = esp_tmp_iv(aead, tmp, seqhilen);
        req = esp_tmp_req(aead, iv);
        asg = esp_req_sg(aead, req);
-       sg = asg + 1;
+       sg = asg + sglists;
 
        skb->ip_summed = CHECKSUM_NONE;
 
index 1660546504668a1c0378e23fec57112cc9710826..f2c5b0fc0f218a0294b1c4308a46374bc3410d99 100644 (file)
@@ -44,7 +44,7 @@ int inet6_csk_bind_conflict(const struct sock *sk,
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
                    (!sk->sk_reuse || !sk2->sk_reuse ||
-                    ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) &&
+                    sk2->sk_state == TCP_LISTEN) &&
                     ipv6_rcv_saddr_equal(sk, sk2))
                        break;
        }
index 76b893771e6e04f618b6d37d273e6c4578d3e053..f2d98ca7588a4fd621a13e614ed507b2e7e7d1d9 100644 (file)
@@ -201,10 +201,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
        return 0;
 }
 
-static void ipv6_mc_socklist_reclaim(struct rcu_head *head)
-{
-       kfree(container_of(head, struct ipv6_mc_socklist, rcu));
-}
 /*
  *     socket leave on multicast group
  */
@@ -239,7 +235,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
                                (void) ip6_mc_leave_src(sk, mc_lst, NULL);
                        rcu_read_unlock();
                        atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
-                       call_rcu(&mc_lst->rcu, ipv6_mc_socklist_reclaim);
+                       kfree_rcu(mc_lst, rcu);
                        return 0;
                }
        }
@@ -307,7 +303,7 @@ void ipv6_sock_mc_close(struct sock *sk)
                rcu_read_unlock();
 
                atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
-               call_rcu(&mc_lst->rcu, ipv6_mc_socklist_reclaim);
+               kfree_rcu(mc_lst, rcu);
 
                spin_lock(&ipv6_sk_mc_lock);
        }
index 28e74488a329770597426c98a3d3b06b58267ef3..a5a4c5dd53961cf1b2432c8317592d1099eafda2 100644 (file)
@@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
        int tcphoff, needs_ack;
        const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
        struct ipv6hdr *ip6h;
+#define DEFAULT_TOS_VALUE      0x0U
+       const __u8 tclass = DEFAULT_TOS_VALUE;
        struct dst_entry *dst = NULL;
        u8 proto;
        struct flowi6 fl6;
@@ -124,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
        skb_put(nskb, sizeof(struct ipv6hdr));
        skb_reset_network_header(nskb);
        ip6h = ipv6_hdr(nskb);
-       ip6h->version = 6;
+       *(__be32 *)ip6h =  htonl(0x60000000 | (tclass << 20));
        ip6h->hop_limit = ip6_dst_hoplimit(dst);
        ip6h->nexthdr = IPPROTO_TCP;
        ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
index 843406f14d7b2b37ac33b039f52fe80feb132cba..fd0eec6f88c6d71d9eba6f1d104001d23bcb2721 100644 (file)
@@ -153,6 +153,12 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
 
+static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
+                                        unsigned long old)
+{
+       return NULL;
+}
+
 static struct dst_ops ip6_dst_blackhole_ops = {
        .family                 =       AF_INET6,
        .protocol               =       cpu_to_be16(ETH_P_IPV6),
@@ -161,6 +167,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .default_mtu            =       ip6_blackhole_default_mtu,
        .default_advmss         =       ip6_default_advmss,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
+       .cow_metrics            =       ip6_rt_blackhole_cow_metrics,
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
@@ -2012,7 +2019,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        rt->dst.output = ip6_output;
        rt->rt6i_dev = net->loopback_dev;
        rt->rt6i_idev = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
        rt->dst.obsolete = -1;
 
        rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
index 43b33373adb2ec8e30420f0acea1367da404d820..5f35d595e4a53d36bcf9d8be8ad3c726932722ef 100644 (file)
@@ -401,11 +401,6 @@ out:
        return err;
 }
 
-static void prl_entry_destroy_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct ip_tunnel_prl_entry, rcu_head));
-}
-
 static void prl_list_destroy_rcu(struct rcu_head *head)
 {
        struct ip_tunnel_prl_entry *p, *n;
@@ -433,7 +428,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
                     p = &x->next) {
                        if (x->addr == a->addr) {
                                *p = x->next;
-                               call_rcu(&x->rcu_head, prl_entry_destroy_rcu);
+                               kfree_rcu(x, rcu_head);
                                t->prl_count--;
                                goto out;
                        }
index 15c37746845ed1ad678866756b4057421b7f3f0a..9e305d74b3d41a99a065da67fe54bd3a4a9ebaa6 100644 (file)
@@ -1335,7 +1335,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Check if there is enough headroom to insert fragment header. */
-       if ((skb_headroom(skb) < frag_hdr_sz) &&
+       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
            pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
                goto out;
 
index 8e688b3de9abc62ec03c7dd90b33c951791c5587..49a91c5f5623b80298001b11927eb763883c1553 100644 (file)
@@ -79,7 +79,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(xfrm6_prepare_output);
 
-static int xfrm6_output_finish(struct sk_buff *skb)
+int xfrm6_output_finish(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER
        IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
@@ -97,9 +97,9 @@ static int __xfrm6_output(struct sk_buff *skb)
        if ((x && x->props.mode == XFRM_MODE_TUNNEL) &&
            ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
                dst_allfrag(skb_dst(skb)))) {
-                       return ip6_fragment(skb, xfrm6_output_finish);
+                       return ip6_fragment(skb, x->outer_mode->afinfo->output_finish);
        }
-       return xfrm6_output_finish(skb);
+       return x->outer_mode->afinfo->output_finish(skb);
 }
 
 int xfrm6_output(struct sk_buff *skb)
index afe941e9415cdd895c08059f9ca76770187f9c2b..248f0b2a7ee93448b30e55a884f15ec7f897a240 100644 (file)
@@ -178,6 +178,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
        .tmpl_sort              = __xfrm6_tmpl_sort,
        .state_sort             = __xfrm6_state_sort,
        .output                 = xfrm6_output,
+       .output_finish          = xfrm6_output_finish,
        .extract_input          = xfrm6_extract_input,
        .extract_output         = xfrm6_extract_output,
        .transport_finish       = xfrm6_transport_finish,
index c9890e25cd4c9681b14f838976a97ed4db560ac7..cc616974a447d582a66c837a09c8c95b1fb8900a 100644 (file)
@@ -1297,8 +1297,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
        /* Note : socket.c set MSG_EOR on SEQPACKET sockets */
        if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
                               MSG_NOSIGNAL)) {
-               err = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        lock_sock(sk);
index fce9bd3bd3feb61c3b6a2fbc078d9a5b8f7462c5..5c04f3e42704feda18993bcac15dc29b0f66c933 100644 (file)
@@ -667,7 +667,7 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
 
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like
+/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
  * enums
  */
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
index 058f1e9a91281859bf39501619da6eb5ece8d16a..903242111317f14438bc84881358875729e21948 100644 (file)
@@ -121,8 +121,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
                s32 data_size = ntohs(pdulen) - llc_len;
 
                if (data_size < 0 ||
-                   ((skb_tail_pointer(skb) -
-                     (u8 *)pdu) - llc_len) < data_size)
+                   !pskb_may_pull(skb, data_size))
                        return 0;
                if (unlikely(pskb_trim_rcsum(skb, data_size)))
                        return 0;
index 63d852cb4ca2e55e3a6f70721e4487ec656862ce..53defafb9aae3c28db654da04198aecf1ae71273 100644 (file)
@@ -136,14 +136,6 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
        ieee80211_tx_skb(sdata, skb);
 }
 
-static void kfree_tid_tx(struct rcu_head *rcu_head)
-{
-       struct tid_ampdu_tx *tid_tx =
-           container_of(rcu_head, struct tid_ampdu_tx, rcu_head);
-
-       kfree(tid_tx);
-}
-
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                                    enum ieee80211_back_parties initiator,
                                    bool tx)
@@ -163,7 +155,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                /* not even started yet! */
                rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
                spin_unlock_bh(&sta->lock);
-               call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
+               kfree_rcu(tid_tx, rcu_head);
                return 0;
        }
 
@@ -322,7 +314,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
                spin_unlock_bh(&sta->lock);
 
                ieee80211_wake_queue_agg(local, tid);
-               call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
+               kfree_rcu(tid_tx, rcu_head);
                return;
        }
 
@@ -701,7 +693,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
 
        ieee80211_agg_splice_finish(local, tid);
 
-       call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
+       kfree_rcu(tid_tx, rcu_head);
 
  unlock_sta:
        spin_unlock_bh(&sta->lock);
index 334213571ad0ef9257c73a7d6ab81febb3ef9c36..44049733c4eaf6ab450e9ea48e676102669531ba 100644 (file)
@@ -1504,6 +1504,8 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
        enum ieee80211_smps_mode old_req;
        int err;
 
+       lockdep_assert_held(&sdata->u.mgd.mtx);
+
        old_req = sdata->u.mgd.req_smps;
        sdata->u.mgd.req_smps = smps_mode;
 
index dacace6b139301ad5625a738465190e2827af160..9ea7c0d0103f8d9f15fc5b7d04109316ee675ea2 100644 (file)
@@ -177,9 +177,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
 
-       mutex_lock(&local->iflist_mtx);
+       mutex_lock(&sdata->u.mgd.mtx);
        err = __ieee80211_request_smps(sdata, smps_mode);
-       mutex_unlock(&local->iflist_mtx);
+       mutex_unlock(&sdata->u.mgd.mtx);
 
        return err;
 }
index ce4596ed1268ca9039298f7a05c280a9e3fca190..bd1224fd216aeb034278d6cc34f3c38287ac754c 100644 (file)
@@ -237,6 +237,10 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
                                     &local->dynamic_ps_disable_work);
        }
 
+       /* Don't restart the timer if we're not disassociated */
+       if (!ifmgd->associated)
+               return TX_CONTINUE;
+
        mod_timer(&local->dynamic_ps_timer, jiffies +
                  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 
index e73c8cae036b42fec668d3473922164b3e22ef26..ac3549690b8eec8dd37366f29f04d740dc3c34b8 100644 (file)
@@ -65,17 +65,9 @@ static void run_again(struct ieee80211_local *local,
                mod_timer(&local->work_timer, timeout);
 }
 
-static void work_free_rcu(struct rcu_head *head)
-{
-       struct ieee80211_work *wk =
-               container_of(head, struct ieee80211_work, rcu_head);
-
-       kfree(wk);
-}
-
 void free_work(struct ieee80211_work *wk)
 {
-       call_rcu(&wk->rcu_head, work_free_rcu);
+       kfree_rcu(wk, rcu_head);
 }
 
 static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
index 00a33242e90c2e89994a0711fcae7a61809225e5..a274300b6a566faee28c3e10d31fdba1bbd212c0 100644 (file)
@@ -343,6 +343,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct ipmac data;
 
+       /* MAC can be src only */
+       if (!(flags & IPSET_DIM_TWO_SRC))
+               return 0;
+
        data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
        if (data.id < map->first_ip || data.id > map->last_ip)
                return -IPSET_ERR_BITMAP_RANGE;
index 9152e69a162d75f2e5d779169c2c0b2ab3c6e0d6..72d1ac611fdc8e70124c6fca29686ffa416e9cd3 100644 (file)
@@ -1022,8 +1022,9 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
        if (cb->args[1] >= ip_set_max)
                goto out;
 
-       pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
        max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+dump_last:
+       pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
        for (; cb->args[1] < max; cb->args[1]++) {
                index = (ip_set_id_t) cb->args[1];
                set = ip_set_list[index];
@@ -1038,8 +1039,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
                 * so that lists (unions of sets) are dumped last.
                 */
                if (cb->args[0] != DUMP_ONE &&
-                   !((cb->args[0] == DUMP_ALL) ^
-                     (set->type->features & IPSET_DUMP_LAST)))
+                   ((cb->args[0] == DUMP_ALL) ==
+                    !!(set->type->features & IPSET_DUMP_LAST)))
                        continue;
                pr_debug("List set: %s\n", set->name);
                if (!cb->args[2]) {
@@ -1083,6 +1084,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
                        goto release_refcount;
                }
        }
+       /* If we dump all sets, continue with dumping last ones */
+       if (cb->args[0] == DUMP_ALL) {
+               cb->args[0] = DUMP_LAST;
+               cb->args[1] = 0;
+               goto dump_last;
+       }
        goto out;
 
 nla_put_failure:
@@ -1093,11 +1100,6 @@ release_refcount:
                pr_debug("release set %s\n", ip_set_list[index]->name);
                ip_set_put_byindex(index);
        }
-
-       /* If we dump all sets, continue with dumping last ones */
-       if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2])
-               cb->args[0] = DUMP_LAST;
-
 out:
        if (nlh) {
                nlmsg_end(skb, nlh);
index 2dc6de13ac1890d586d1e9a3d70817b329afbec8..059af3120be741ecce63e07ebaa9c9e428281343 100644 (file)
@@ -572,11 +572,11 @@ static const struct file_operations ip_vs_app_fops = {
        .open    = ip_vs_app_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 #endif
 
-static int __net_init __ip_vs_app_init(struct net *net)
+int __net_init __ip_vs_app_init(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net)
        return 0;
 }
 
-static void __net_exit __ip_vs_app_cleanup(struct net *net)
+void __net_exit __ip_vs_app_cleanup(struct net *net)
 {
        proc_net_remove(net, "ip_vs_app");
 }
 
-static struct pernet_operations ip_vs_app_ops = {
-       .init = __ip_vs_app_init,
-       .exit = __ip_vs_app_cleanup,
-};
-
 int __init ip_vs_app_init(void)
 {
-       int rv;
-
-       rv = register_pernet_subsys(&ip_vs_app_ops);
-       return rv;
+       return 0;
 }
 
 
 void ip_vs_app_cleanup(void)
 {
-       unregister_pernet_subsys(&ip_vs_app_ops);
 }
index c97bd45975bed636c99dd55e263869f8be11a98b..bf28ac2fc99b7cf164d82417e6248049787ff923 100644 (file)
@@ -1046,7 +1046,7 @@ static const struct file_operations ip_vs_conn_fops = {
        .open    = ip_vs_conn_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 static const char *ip_vs_origin_name(unsigned flags)
@@ -1114,7 +1114,7 @@ static const struct file_operations ip_vs_conn_sync_fops = {
        .open    = ip_vs_conn_sync_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 #endif
@@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net)
        return 0;
 }
 
-static void __net_exit __ip_vs_conn_cleanup(struct net *net)
+void __net_exit __ip_vs_conn_cleanup(struct net *net)
 {
        /* flush all the connection entries first */
        ip_vs_conn_flush(net);
        proc_net_remove(net, "ip_vs_conn");
        proc_net_remove(net, "ip_vs_conn_sync");
 }
-static struct pernet_operations ipvs_conn_ops = {
-       .init = __ip_vs_conn_init,
-       .exit = __ip_vs_conn_cleanup,
-};
 
 int __init ip_vs_conn_init(void)
 {
        int idx;
-       int retc;
 
        /* Compute size and mask */
        ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
@@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void)
                rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
        }
 
-       retc = register_pernet_subsys(&ipvs_conn_ops);
-
        /* calculate the random value for connection hash */
        get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
 
-       return retc;
+       return 0;
 }
 
 void ip_vs_conn_cleanup(void)
 {
-       unregister_pernet_subsys(&ipvs_conn_ops);
        /* Release the empty cache */
        kmem_cache_destroy(ip_vs_conn_cachep);
        vfree(ip_vs_conn_tab);
index 07accf6b2401a05aa89b4a543e89741781547ff6..a74dae6c5dbce9f184e52e29298662d1ebc76c51 100644 (file)
@@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
                return NF_ACCEPT;
 
        net = skb_net(skb);
+       if (!net_ipvs(net)->enable)
+               return NF_ACCEPT;
+
        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6) {
@@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
                return NF_ACCEPT; /* The packet looks wrong, ignore */
 
        net = skb_net(skb);
+
        pd = ip_vs_proto_data_get(net, cih->protocol);
        if (!pd)
                return NF_ACCEPT;
@@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
                              IP_VS_DBG_ADDR(af, &iph.daddr), hooknum);
                return NF_ACCEPT;
        }
+       /* ipvs enabled in this netns ? */
+       net = skb_net(skb);
+       if (!net_ipvs(net)->enable)
+               return NF_ACCEPT;
+
        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 
        /* Bad... Do not break raw sockets */
@@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
                        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
                }
 
-       net = skb_net(skb);
        /* Protocol supported? */
        pd = ip_vs_proto_data_get(net, iph.protocol);
        if (unlikely(!pd))
@@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        }
 
        IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
-       net = skb_net(skb);
        ipvs = net_ipvs(net);
        /* Check the server status */
        if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
@@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
                   int (*okfn)(struct sk_buff *))
 {
        int r;
+       struct net *net;
 
        if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
                return NF_ACCEPT;
 
+       /* ipvs enabled in this netns ? */
+       net = skb_net(skb);
+       if (!net_ipvs(net)->enable)
+               return NF_ACCEPT;
+
        return ip_vs_in_icmp(skb, &r, hooknum);
 }
 
@@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
                      int (*okfn)(struct sk_buff *))
 {
        int r;
+       struct net *net;
 
        if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
                return NF_ACCEPT;
 
+       /* ipvs enabled in this netns ? */
+       net = skb_net(skb);
+       if (!net_ipvs(net)->enable)
+               return NF_ACCEPT;
+
        return ip_vs_in_icmp_v6(skb, &r, hooknum);
 }
 #endif
@@ -1884,19 +1903,70 @@ static int __net_init __ip_vs_init(struct net *net)
                pr_err("%s(): no memory.\n", __func__);
                return -ENOMEM;
        }
+       /* Hold the beast until a service is registerd */
+       ipvs->enable = 0;
        ipvs->net = net;
        /* Counters used for creating unique names */
        ipvs->gen = atomic_read(&ipvs_netns_cnt);
        atomic_inc(&ipvs_netns_cnt);
        net->ipvs = ipvs;
+
+       if (__ip_vs_estimator_init(net) < 0)
+               goto estimator_fail;
+
+       if (__ip_vs_control_init(net) < 0)
+               goto control_fail;
+
+       if (__ip_vs_protocol_init(net) < 0)
+               goto protocol_fail;
+
+       if (__ip_vs_app_init(net) < 0)
+               goto app_fail;
+
+       if (__ip_vs_conn_init(net) < 0)
+               goto conn_fail;
+
+       if (__ip_vs_sync_init(net) < 0)
+               goto sync_fail;
+
        printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
                         sizeof(struct netns_ipvs), ipvs->gen);
        return 0;
+/*
+ * Error handling
+ */
+
+sync_fail:
+       __ip_vs_conn_cleanup(net);
+conn_fail:
+       __ip_vs_app_cleanup(net);
+app_fail:
+       __ip_vs_protocol_cleanup(net);
+protocol_fail:
+       __ip_vs_control_cleanup(net);
+control_fail:
+       __ip_vs_estimator_cleanup(net);
+estimator_fail:
+       return -ENOMEM;
 }
 
 static void __net_exit __ip_vs_cleanup(struct net *net)
 {
-       IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
+       __ip_vs_service_cleanup(net);   /* ip_vs_flush() with locks */
+       __ip_vs_conn_cleanup(net);
+       __ip_vs_app_cleanup(net);
+       __ip_vs_protocol_cleanup(net);
+       __ip_vs_control_cleanup(net);
+       __ip_vs_estimator_cleanup(net);
+       IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
+}
+
+static void __net_exit __ip_vs_dev_cleanup(struct net *net)
+{
+       EnterFunction(2);
+       net_ipvs(net)->enable = 0;      /* Disable packet reception */
+       __ip_vs_sync_cleanup(net);
+       LeaveFunction(2);
 }
 
 static struct pernet_operations ipvs_core_ops = {
@@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = {
        .size = sizeof(struct netns_ipvs),
 };
 
+static struct pernet_operations ipvs_core_dev_ops = {
+       .exit = __ip_vs_dev_cleanup,
+};
+
 /*
  *     Initialize IP Virtual Server
  */
@@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void)
 {
        int ret;
 
-       ret = register_pernet_subsys(&ipvs_core_ops);   /* Alloc ip_vs struct */
-       if (ret < 0)
-               return ret;
-
        ip_vs_estimator_init();
        ret = ip_vs_control_init();
        if (ret < 0) {
@@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void)
                goto cleanup_conn;
        }
 
+       ret = register_pernet_subsys(&ipvs_core_ops);   /* Alloc ip_vs struct */
+       if (ret < 0)
+               goto cleanup_sync;
+
+       ret = register_pernet_device(&ipvs_core_dev_ops);
+       if (ret < 0)
+               goto cleanup_sub;
+
        ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
        if (ret < 0) {
                pr_err("can't register hooks.\n");
-               goto cleanup_sync;
+               goto cleanup_dev;
        }
 
        pr_info("ipvs loaded.\n");
+
        return ret;
 
+cleanup_dev:
+       unregister_pernet_device(&ipvs_core_dev_ops);
+cleanup_sub:
+       unregister_pernet_subsys(&ipvs_core_ops);
 cleanup_sync:
        ip_vs_sync_cleanup();
   cleanup_conn:
@@ -1964,20 +2047,20 @@ cleanup_sync:
        ip_vs_control_cleanup();
   cleanup_estimator:
        ip_vs_estimator_cleanup();
-       unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
        return ret;
 }
 
 static void __exit ip_vs_cleanup(void)
 {
        nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+       unregister_pernet_device(&ipvs_core_dev_ops);
+       unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
        ip_vs_sync_cleanup();
        ip_vs_conn_cleanup();
        ip_vs_app_cleanup();
        ip_vs_protocol_cleanup();
        ip_vs_control_cleanup();
        ip_vs_estimator_cleanup();
-       unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
        pr_info("ipvs unloaded.\n");
 }
 
index ae47090bf45fe1fdfbf99192950aacb951cb1af1..37890f228b19852272e022621a707740d9fe0f71 100644 (file)
@@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void)
 }
 #endif
 
+
+/*  Protos */
+static void __ip_vs_del_service(struct ip_vs_service *svc);
+
+
 #ifdef CONFIG_IP_VS_IPV6
 /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */
 static int __ip_vs_addr_is_local_v6(struct net *net,
@@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
        write_unlock_bh(&__ip_vs_svc_lock);
 
        *svc_p = svc;
+       /* Now there is a service - full throttle */
+       ipvs->enable = 1;
        return 0;
 
 
@@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net)
        return 0;
 }
 
+/*
+ *     Delete service by {netns} in the service table.
+ *     Called by __ip_vs_cleanup()
+ */
+void __ip_vs_service_cleanup(struct net *net)
+{
+       EnterFunction(2);
+       /* Check for "full" addressed entries */
+       mutex_lock(&__ip_vs_mutex);
+       ip_vs_flush(net);
+       mutex_unlock(&__ip_vs_mutex);
+       LeaveFunction(2);
+}
+/*
+ * Release dst hold by dst_cache
+ */
+static inline void
+__ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev)
+{
+       spin_lock_bh(&dest->dst_lock);
+       if (dest->dst_cache && dest->dst_cache->dev == dev) {
+               IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n",
+                             dev->name,
+                             IP_VS_DBG_ADDR(dest->af, &dest->addr),
+                             ntohs(dest->port),
+                             atomic_read(&dest->refcnt));
+               ip_vs_dst_reset(dest);
+       }
+       spin_unlock_bh(&dest->dst_lock);
+
+}
+/*
+ * Netdev event receiver
+ * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to
+ * a device that is "unregister" it must be released.
+ */
+static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
+                           void *ptr)
+{
+       struct net_device *dev = ptr;
+       struct net *net = dev_net(dev);
+       struct ip_vs_service *svc;
+       struct ip_vs_dest *dest;
+       unsigned int idx;
+
+       if (event != NETDEV_UNREGISTER)
+               return NOTIFY_DONE;
+       IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name);
+       EnterFunction(2);
+       mutex_lock(&__ip_vs_mutex);
+       for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+               list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
+                       if (net_eq(svc->net, net)) {
+                               list_for_each_entry(dest, &svc->destinations,
+                                                   n_list) {
+                                       __ip_vs_dev_reset(dest, dev);
+                               }
+                       }
+               }
+
+               list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
+                       if (net_eq(svc->net, net)) {
+                               list_for_each_entry(dest, &svc->destinations,
+                                                   n_list) {
+                                       __ip_vs_dev_reset(dest, dev);
+                               }
+                       }
+
+               }
+       }
+
+       list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) {
+               __ip_vs_dev_reset(dest, dev);
+       }
+       mutex_unlock(&__ip_vs_mutex);
+       LeaveFunction(2);
+       return NOTIFY_DONE;
+}
 
 /*
  *     Zero counters in a service or all services
@@ -1981,7 +2066,7 @@ static const struct file_operations ip_vs_info_fops = {
        .open    = ip_vs_info_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release_private,
+       .release = seq_release_net,
 };
 
 #endif
@@ -2024,7 +2109,7 @@ static const struct file_operations ip_vs_stats_fops = {
        .open = ip_vs_stats_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 
 static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
@@ -2093,7 +2178,7 @@ static const struct file_operations ip_vs_stats_percpu_fops = {
        .open = ip_vs_stats_percpu_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 #endif
 
@@ -3588,6 +3673,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
 
 #endif
 
+static struct notifier_block ip_vs_dst_notifier = {
+       .notifier_call = ip_vs_dst_event,
+};
+
 int __net_init __ip_vs_control_init(struct net *net)
 {
        int idx;
@@ -3626,7 +3715,7 @@ err:
        return -ENOMEM;
 }
 
-static void __net_exit __ip_vs_control_cleanup(struct net *net)
+void __net_exit __ip_vs_control_cleanup(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -3639,11 +3728,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net)
        free_percpu(ipvs->tot_stats.cpustats);
 }
 
-static struct pernet_operations ipvs_control_ops = {
-       .init = __ip_vs_control_init,
-       .exit = __ip_vs_control_cleanup,
-};
-
 int __init ip_vs_control_init(void)
 {
        int idx;
@@ -3657,33 +3741,32 @@ int __init ip_vs_control_init(void)
                INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
        }
 
-       ret = register_pernet_subsys(&ipvs_control_ops);
-       if (ret) {
-               pr_err("cannot register namespace.\n");
-               goto err;
-       }
-
        smp_wmb();      /* Do we really need it now ? */
 
        ret = nf_register_sockopt(&ip_vs_sockopts);
        if (ret) {
                pr_err("cannot register sockopt.\n");
-               goto err_net;
+               goto err_sock;
        }
 
        ret = ip_vs_genl_register();
        if (ret) {
                pr_err("cannot register Generic Netlink interface.\n");
-               nf_unregister_sockopt(&ip_vs_sockopts);
-               goto err_net;
+               goto err_genl;
        }
 
+       ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+       if (ret < 0)
+               goto err_notf;
+
        LeaveFunction(2);
        return 0;
 
-err_net:
-       unregister_pernet_subsys(&ipvs_control_ops);
-err:
+err_notf:
+       ip_vs_genl_unregister();
+err_genl:
+       nf_unregister_sockopt(&ip_vs_sockopts);
+err_sock:
        return ret;
 }
 
@@ -3691,7 +3774,6 @@ err:
 void ip_vs_control_cleanup(void)
 {
        EnterFunction(2);
-       unregister_pernet_subsys(&ipvs_control_ops);
        ip_vs_genl_unregister();
        nf_unregister_sockopt(&ip_vs_sockopts);
        LeaveFunction(2);
index 8c8766ca56ada43698df6e51bcaad8338e4ef40a..508cce98777c743558eecaa66d479889db6d8c50 100644 (file)
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
        dst->outbps = (e->outbps + 0xF) >> 5;
 }
 
-static int __net_init __ip_vs_estimator_init(struct net *net)
+int __net_init __ip_vs_estimator_init(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net)
        return 0;
 }
 
-static void __net_exit __ip_vs_estimator_exit(struct net *net)
+void __net_exit __ip_vs_estimator_cleanup(struct net *net)
 {
        del_timer_sync(&net_ipvs(net)->est_timer);
 }
-static struct pernet_operations ip_vs_app_ops = {
-       .init = __ip_vs_estimator_init,
-       .exit = __ip_vs_estimator_exit,
-};
 
 int __init ip_vs_estimator_init(void)
 {
-       int rv;
-
-       rv = register_pernet_subsys(&ip_vs_app_ops);
-       return rv;
+       return 0;
 }
 
 void ip_vs_estimator_cleanup(void)
 {
-       unregister_pernet_subsys(&ip_vs_app_ops);
 }
index 17484a4416ef91158d03d868ee3c698e3179cf6e..eb86028536fc94debd108fdea43ab8f36aa00fcd 100644 (file)
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
 /*
  * per network name-space init
  */
-static int __net_init __ip_vs_protocol_init(struct net *net)
+int __net_init __ip_vs_protocol_init(struct net *net)
 {
 #ifdef CONFIG_IP_VS_PROTO_TCP
        register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
@@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net)
        return 0;
 }
 
-static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+void __net_exit __ip_vs_protocol_cleanup(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_proto_data *pd;
@@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
        }
 }
 
-static struct pernet_operations ipvs_proto_ops = {
-       .init = __ip_vs_protocol_init,
-       .exit = __ip_vs_protocol_cleanup,
-};
-
 int __init ip_vs_protocol_init(void)
 {
        char protocols[64];
@@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void)
        REGISTER_PROTOCOL(&ip_vs_protocol_esp);
 #endif
        pr_info("Registered protocols (%s)\n", &protocols[2]);
-       return register_pernet_subsys(&ipvs_proto_ops);
 
        return 0;
 }
@@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void)
        struct ip_vs_protocol *pp;
        int i;
 
-       unregister_pernet_subsys(&ipvs_proto_ops);
        /* unregister all the ipvs protocols */
        for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
                while ((pp = ip_vs_proto_table[i]) != NULL)
index 3e7961e85e9caaf63d92615a3ffab970775583c4..e292e5bddc7000d3fbbb9f1b130dd3039dcee296 100644 (file)
@@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net)
        struct socket *sock;
        int result;
 
-       /* First create a socket */
-       result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
+       /* First create a socket move it to right name space later */
+       result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
        if (result < 0) {
                pr_err("Error during creation of socket; terminating\n");
                return ERR_PTR(result);
        }
-
+       /*
+        * Kernel sockets that are a part of a namespace, should not
+        * hold a reference to a namespace in order to allow to stop it.
+        * After sk_change_net should be released using sk_release_kernel.
+        */
+       sk_change_net(sock->sk, net);
        result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn);
        if (result < 0) {
                pr_err("Error setting outbound mcast interface\n");
@@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net)
 
        return sock;
 
-  error:
-       sock_release(sock);
+error:
+       sk_release_kernel(sock->sk);
        return ERR_PTR(result);
 }
 
@@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net)
        int result;
 
        /* First create a socket */
-       result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
+       result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
        if (result < 0) {
                pr_err("Error during creation of socket; terminating\n");
                return ERR_PTR(result);
        }
-
+       /*
+        * Kernel sockets that are a part of a namespace, should not
+        * hold a reference to a namespace in order to allow to stop it.
+        * After sk_change_net should be released using sk_release_kernel.
+        */
+       sk_change_net(sock->sk, net);
        /* it is equivalent to the REUSEADDR option in user-space */
        sock->sk->sk_reuse = 1;
 
@@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net)
 
        return sock;
 
-  error:
-       sock_release(sock);
+error:
+       sk_release_kernel(sock->sk);
        return ERR_PTR(result);
 }
 
@@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data)
                ip_vs_sync_buff_release(sb);
 
        /* release the sending multicast socket */
-       sock_release(tinfo->sock);
+       sk_release_kernel(tinfo->sock->sk);
        kfree(tinfo);
 
        return 0;
@@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data)
        }
 
        /* release the sending multicast socket */
-       sock_release(tinfo->sock);
+       sk_release_kernel(tinfo->sock->sk);
        kfree(tinfo->buf);
        kfree(tinfo);
 
@@ -1601,7 +1611,7 @@ outtinfo:
 outbuf:
        kfree(buf);
 outsocket:
-       sock_release(sock);
+       sk_release_kernel(sock->sk);
 out:
        return result;
 }
@@ -1610,6 +1620,7 @@ out:
 int stop_sync_thread(struct net *net, int state)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
+       int retc = -EINVAL;
 
        IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
 
@@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state)
                spin_lock_bh(&ipvs->sync_lock);
                ipvs->sync_state &= ~IP_VS_STATE_MASTER;
                spin_unlock_bh(&ipvs->sync_lock);
-               kthread_stop(ipvs->master_thread);
+               retc = kthread_stop(ipvs->master_thread);
                ipvs->master_thread = NULL;
        } else if (state == IP_VS_STATE_BACKUP) {
                if (!ipvs->backup_thread)
@@ -1639,22 +1650,20 @@ int stop_sync_thread(struct net *net, int state)
                        task_pid_nr(ipvs->backup_thread));
 
                ipvs->sync_state &= ~IP_VS_STATE_BACKUP;
-               kthread_stop(ipvs->backup_thread);
+               retc = kthread_stop(ipvs->backup_thread);
                ipvs->backup_thread = NULL;
-       } else {
-               return -EINVAL;
        }
 
        /* decrease the module use count */
        ip_vs_use_count_dec();
 
-       return 0;
+       return retc;
 }
 
 /*
  * Initialize data struct for each netns
  */
-static int __net_init __ip_vs_sync_init(struct net *net)
+int __net_init __ip_vs_sync_init(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -1668,24 +1677,24 @@ static int __net_init __ip_vs_sync_init(struct net *net)
        return 0;
 }
 
-static void __ip_vs_sync_cleanup(struct net *net)
+void __ip_vs_sync_cleanup(struct net *net)
 {
-       stop_sync_thread(net, IP_VS_STATE_MASTER);
-       stop_sync_thread(net, IP_VS_STATE_BACKUP);
-}
+       int retc;
 
-static struct pernet_operations ipvs_sync_ops = {
-       .init = __ip_vs_sync_init,
-       .exit = __ip_vs_sync_cleanup,
-};
+       retc = stop_sync_thread(net, IP_VS_STATE_MASTER);
+       if (retc && retc != -ESRCH)
+               pr_err("Failed to stop Master Daemon\n");
 
+       retc = stop_sync_thread(net, IP_VS_STATE_BACKUP);
+       if (retc && retc != -ESRCH)
+               pr_err("Failed to stop Backup Daemon\n");
+}
 
 int __init ip_vs_sync_init(void)
 {
-       return register_pernet_subsys(&ipvs_sync_ops);
+       return 0;
 }
 
 void ip_vs_sync_cleanup(void)
 {
-       unregister_pernet_subsys(&ipvs_sync_ops);
 }
index 80a23ed62bb0739c2d9d97f195dbea57216230b5..05ecdc281a53da8b7e524ca80fdd7c85e882302b 100644 (file)
@@ -68,12 +68,6 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
        return (void *)(*ext) + off;
 }
 
-static void __nf_ct_ext_free_rcu(struct rcu_head *head)
-{
-       struct nf_ct_ext *ext = container_of(head, struct nf_ct_ext, rcu);
-       kfree(ext);
-}
-
 void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
 {
        struct nf_ct_ext *old, *new;
@@ -114,7 +108,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
                                        (void *)old + old->offset[i]);
                        rcu_read_unlock();
                }
-               call_rcu(&old->rcu, __nf_ct_ext_free_rcu);
+               kfree_rcu(old, rcu);
                ct->ext = new;
        }
 
index 30bf8a167fc8800ff26b4ab72cafe3e219f38139..482e90c6185087f2827b9f27448c74ac87eb0ef6 100644 (file)
@@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
        struct nf_conn *ct;
        int err = -EINVAL;
        struct nf_conntrack_helper *helper;
+       struct nf_conn_tstamp *tstamp;
 
        ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
        if (IS_ERR(ct))
@@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
                __set_bit(IPS_EXPECTED_BIT, &ct->status);
                ct->master = master_ct;
        }
+       tstamp = nf_conn_tstamp_find(ct);
+       if (tstamp)
+               tstamp->start = ktime_to_ns(ktime_get_real());
 
        add_timer(&ct->timeout);
        nf_conntrack_hash_insert(ct);
index a9adf4c6b299ee35a72c4617e0d3e565031de940..8a025a585d2f7c6d45dd07bcdfc9680826c88edd 100644 (file)
@@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af)
                vfree(xt[af].compat_tab);
                xt[af].compat_tab = NULL;
                xt[af].number = 0;
+               xt[af].cur = 0;
        }
 }
 EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
@@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
                else
                        return mid ? tmp[mid - 1].delta : 0;
        }
-       WARN_ON_ONCE(1);
-       return 0;
+       return left ? tmp[left - 1].delta : 0;
 }
 EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
 
index 0a229191e55b2f8e15e00e459b2ceb20fe226893..ae8271652efa9cf5a6f939fcedc3238ca6c865c7 100644 (file)
@@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par)
        u_int8_t orig, nv;
 
        orig = ipv6_get_dsfield(iph);
-       nv   = (orig & info->tos_mask) ^ info->tos_value;
+       nv   = (orig & ~info->tos_mask) ^ info->tos_value;
 
        if (orig != nv) {
                if (!skb_make_writable(skb, sizeof(struct iphdr)))
index 481a86fdc40973bb43f62cfd2a36b0d4746f8a63..61805d7b38aa62e880c1e8f4e32f79d1bf5ffdc2 100644 (file)
@@ -272,11 +272,6 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par)
 {
        int ret;
 
-       if (strcmp(par->table, "raw") == 0) {
-               pr_info("state is undetermined at the time of raw table\n");
-               return -EINVAL;
-       }
-
        ret = nf_ct_l3proto_try_module_get(par->family);
        if (ret < 0)
                pr_info("cannot load conntrack support for proto=%u\n",
index 4327e101c047ff1f9c1469a1cfa1dc544dbda5b8..846f895cb656ddf48989d28900c55b2bae9f475e 100644 (file)
@@ -62,13 +62,6 @@ static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = {
        [OSF_ATTR_FINGER]       = { .len = sizeof(struct xt_osf_user_finger) },
 };
 
-static void xt_osf_finger_free_rcu(struct rcu_head *rcu_head)
-{
-       struct xt_osf_finger *f = container_of(rcu_head, struct xt_osf_finger, rcu_head);
-
-       kfree(f);
-}
-
 static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb,
                               const struct nlmsghdr *nlh,
                               const struct nlattr * const osf_attrs[])
@@ -133,7 +126,7 @@ static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb,
                 * We are protected by nfnl mutex.
                 */
                list_del_rcu(&sf->finger_entry);
-               call_rcu(&sf->rcu_head, xt_osf_finger_free_rcu);
+               kfree_rcu(sf, rcu_head);
 
                err = 0;
                break;
@@ -414,7 +407,7 @@ static void __exit xt_osf_fini(void)
 
                list_for_each_entry_rcu(f, &xt_osf_fingers[i], finger_entry) {
                        list_del_rcu(&f->finger_entry);
-                       call_rcu(&f->rcu_head, xt_osf_finger_free_rcu);
+                       kfree_rcu(f, rcu_head);
                }
        }
        rcu_read_unlock();
index 061d48cec137e3a88a3a98153d6d5cbd9d1c3464..b3babaed7719b770e02d478091885e7692eac68a 100644 (file)
@@ -81,6 +81,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return -ERANGE;
        }
 
@@ -135,6 +136,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return -ENOENT;
                }
        }
@@ -142,6 +145,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
            info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return -ERANGE;
        }
 
@@ -192,6 +199,7 @@ set_match_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return -ERANGE;
        }
 
@@ -219,7 +227,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par)
        if (info->del_set.index != IPSET_INVALID_ID)
                ip_set_del(info->del_set.index,
                           skb, par->family,
-                          info->add_set.dim,
+                          info->del_set.dim,
                           info->del_set.flags);
 
        return XT_CONTINUE;
@@ -245,13 +253,19 @@ set_target_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return -ENOENT;
                }
        }
        if (info->add_set.dim > IPSET_DIM_MAX ||
-           info->del_set.flags > IPSET_DIM_MAX) {
+           info->del_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return -ERANGE;
        }
 
index e2b0a680dd562912e3f1540d64d669147b2b11f1..9c38658fba8b9afc61fdf5a158331a8f8a69c167 100644 (file)
@@ -153,44 +153,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1
  * Unlabeled Connection Hash Table Functions
  */
 
-/**
- * netlbl_unlhsh_free_addr4 - Frees an IPv4 address entry from the hash table
- * @entry: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that memory allocated to a hash table address entry can be
- * released safely.
- *
- */
-static void netlbl_unlhsh_free_addr4(struct rcu_head *entry)
-{
-       struct netlbl_unlhsh_addr4 *ptr;
-
-       ptr = container_of(entry, struct netlbl_unlhsh_addr4, rcu);
-       kfree(ptr);
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-/**
- * netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table
- * @entry: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that memory allocated to a hash table address entry can be
- * released safely.
- *
- */
-static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
-{
-       struct netlbl_unlhsh_addr6 *ptr;
-
-       ptr = container_of(entry, struct netlbl_unlhsh_addr6, rcu);
-       kfree(ptr);
-}
-#endif /* IPv6 */
-
 /**
  * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table
  * @entry: the entry's RCU field
@@ -568,7 +530,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
        if (entry == NULL)
                return -ENOENT;
 
-       call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
+       kfree_rcu(entry, rcu);
        return 0;
 }
 
@@ -629,7 +591,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
        if (entry == NULL)
                return -ENOENT;
 
-       call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
+       kfree_rcu(entry, rcu);
        return 0;
 }
 #endif /* IPv6 */
index c8f35b5d2ee9b4398eb28a8fe3de02b9f532f947..5fe4f3b04ed37e8d0cc46d456804aef6044c3150 100644 (file)
@@ -1566,12 +1566,6 @@ netlink_kernel_release(struct sock *sk)
 }
 EXPORT_SYMBOL(netlink_kernel_release);
 
-
-static void listeners_free_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct listeners, rcu));
-}
-
 int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
 {
        struct listeners *new, *old;
@@ -1588,7 +1582,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
-               call_rcu(&old->rcu, listeners_free_rcu);
+               kfree_rcu(old, rcu);
        }
        tbl->groups = groups;
 
index 947038ddd04cb0e0b763a5048d0bf553125a3914..1566672235ddb13af63fc7fc6c4380f1da5aa154 100644 (file)
@@ -162,14 +162,6 @@ int phonet_address_add(struct net_device *dev, u8 addr)
        return err;
 }
 
-static void phonet_device_rcu_free(struct rcu_head *head)
-{
-       struct phonet_device *pnd;
-
-       pnd = container_of(head, struct phonet_device, rcu);
-       kfree(pnd);
-}
-
 int phonet_address_del(struct net_device *dev, u8 addr)
 {
        struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
@@ -188,7 +180,7 @@ int phonet_address_del(struct net_device *dev, u8 addr)
        mutex_unlock(&pndevs->lock);
 
        if (pnd)
-               call_rcu(&pnd->rcu, phonet_device_rcu_free);
+               kfree_rcu(pnd, rcu);
 
        return err;
 }
index 14b42f4ad791eaf9191adb67e2b6d62d994c4e84..a606025814a1a99650d0793c4f3db468b829aaca 100644 (file)
 #include <net/act_api.h>
 #include <net/netlink.h>
 
-static void tcf_common_free_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct tcf_common, tcfc_rcu));
-}
-
 void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
 {
        unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
@@ -47,7 +42,7 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
                         * gen_estimator est_timer() might access p->tcfc_lock
                         * or bstats, wait a RCU grace period before freeing p
                         */
-                       call_rcu(&p->tcfc_rcu, tcf_common_free_rcu);
+                       kfree_rcu(p, tcfc_rcu);
                        return;
                }
        }
index 8a1630774fd6bdd6536f199b9665517e67312381..b3b9b32f4e007de4b04af3385604a984c4cb88ca 100644 (file)
@@ -96,11 +96,6 @@ nla_put_failure:
        goto done;
 }
 
-static void tcf_police_free_rcu(struct rcu_head *head)
-{
-       kfree(container_of(head, struct tcf_police, tcf_rcu));
-}
-
 static void tcf_police_destroy(struct tcf_police *p)
 {
        unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
@@ -121,7 +116,7 @@ static void tcf_police_destroy(struct tcf_police *p)
                         * gen_estimator est_timer() might access p->tcf_lock
                         * or bstats, wait a RCU grace period before freeing p
                         */
-                       call_rcu(&p->tcf_rcu, tcf_police_free_rcu);
+                       kfree_rcu(p, tcf_rcu);
                        return;
                }
        }
@@ -401,7 +396,6 @@ static void __exit
 police_cleanup_module(void)
 {
        tcf_unregister_action(&act_police_ops);
-       rcu_barrier(); /* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */
 }
 
 module_init(police_init_module);
index 0698cad6176367c5a0ad6dffefcf07133304e9fb..1a21c571aa034fc90db2a38d4606681af03f0669 100644 (file)
@@ -569,6 +569,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
                sctp_assoc_set_primary(asoc, transport);
        if (asoc->peer.active_path == peer)
                asoc->peer.active_path = transport;
+       if (asoc->peer.retran_path == peer)
+               asoc->peer.retran_path = transport;
        if (asoc->peer.last_data_from == peer)
                asoc->peer.last_data_from = transport;
 
@@ -1323,6 +1325,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
 
        if (t)
                asoc->peer.retran_path = t;
+       else
+               t = asoc->peer.retran_path;
 
        SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
                                 " %p addr: ",
index faf71d179e4641137f8d8d477e4a9773321d4bdd..3c06c87cd2807996d018012a63c09fae167284ec 100644 (file)
@@ -219,7 +219,7 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
        }
 
        if (found) {
-               call_rcu(&addr->rcu, sctp_local_addr_free);
+               kfree_rcu(addr, rcu);
                SCTP_DBG_OBJCNT_DEC(addr);
                return 0;
        }
index 865ce7ba4e14eb2c6b9ace3b3a90380db0fff949..185fe058db11e64e270ba81d0c6ecddd7946d6d6 100644 (file)
@@ -123,7 +123,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
                }
                spin_unlock_bh(&sctp_local_addr_lock);
                if (found)
-                       call_rcu(&addr->rcu, sctp_local_addr_free);
+                       kfree_rcu(addr, rcu);
                break;
        }
 
index d5bf91d04f631380bfd78d59bff7da42ee1718db..065d99958cedb995a78ab51d0e0b1e3b1c36523c 100644 (file)
@@ -230,13 +230,6 @@ static void sctp_free_local_addr_list(void)
        }
 }
 
-void sctp_local_addr_free(struct rcu_head *head)
-{
-       struct sctp_sockaddr_entry *e = container_of(head,
-                               struct sctp_sockaddr_entry, rcu);
-       kfree(e);
-}
-
 /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
 int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
                              gfp_t gfp, int copy_flags)
@@ -681,7 +674,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
                }
                spin_unlock_bh(&sctp_local_addr_lock);
                if (found)
-                       call_rcu(&addr->rcu, sctp_local_addr_free);
+                       kfree_rcu(addr, rcu);
                break;
        }
 
index dff27d5e22fdbe57433489cecb7cb70df8328449..61b1f5ada96a92aeb403c02c64694cb5e801106c 100644 (file)
@@ -554,7 +554,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
        memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
 
        /* Per TSVWG discussion with Randy. Allow the application to
-        * resemble a fragmented message.
+        * reassemble a fragmented message.
         */
        ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags;
 
index 310d16b1b3c9cbbb1d401f19f24c6a61d0df4404..c2ed7c95ce870a13e86cf4771ae8d07ff9563ce3 100644 (file)
@@ -263,15 +263,6 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
        return &ei->vfs_inode;
 }
 
-
-
-static void wq_free_rcu(struct rcu_head *head)
-{
-       struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
-
-       kfree(wq);
-}
-
 static void sock_destroy_inode(struct inode *inode)
 {
        struct socket_alloc *ei;
@@ -279,7 +270,7 @@ static void sock_destroy_inode(struct inode *inode)
 
        ei = container_of(inode, struct socket_alloc, vfs_inode);
        wq = rcu_dereference_protected(ei->socket.wq, 1);
-       call_rcu(&wq->rcu, wq_free_rcu);
+       kfree_rcu(wq, rcu);
        kmem_cache_free(sock_inode_cachep, ei);
 }
 
index 8873fd8ddacd261ac03bc1bb7d5b7a236579baee..b2198e65d8bbec47798ccd841707e40c844dc908 100644 (file)
@@ -18,14 +18,13 @@ config SUNRPC_XPRT_RDMA
          If unsure, say N.
 
 config RPCSEC_GSS_KRB5
-       tristate
+       tristate "Secure RPC: Kerberos V mechanism"
        depends on SUNRPC && CRYPTO
-       prompt "Secure RPC: Kerberos V mechanism" if !(NFS_V4 || NFSD_V4)
+       depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS
+       depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES
+       depends on CRYPTO_ARC4
        default y
        select SUNRPC_GSS
-       select CRYPTO_MD5
-       select CRYPTO_DES
-       select CRYPTO_CBC
        help
          Choose Y here to enable Secure RPC using the Kerberos version 5
          GSS-API mechanism (RFC 1964).
index f3914d0c5079596d04af62417ca909693675a64f..339ba64cce1e2ee7134a2c9d09cd64f5fb9cb85e 100644 (file)
@@ -520,7 +520,7 @@ gss_refresh_upcall(struct rpc_task *task)
                warn_gssd();
                task->tk_timeout = 15*HZ;
                rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL);
-               return 0;
+               return -EAGAIN;
        }
        if (IS_ERR(gss_msg)) {
                err = PTR_ERR(gss_msg);
@@ -563,10 +563,12 @@ retry:
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                err = wait_event_interruptible_timeout(pipe_version_waitqueue,
                                pipe_version >= 0, 15*HZ);
+               if (pipe_version < 0) {
+                       warn_gssd();
+                       err = -EACCES;
+               }
                if (err)
                        goto out;
-               if (pipe_version < 0)
-                       warn_gssd();
                goto retry;
        }
        if (IS_ERR(gss_msg)) {
index e7a96e478f63a74da8e90e0f80748857f5c18fb0..8d83f9d487130bb7789fe0dc53201ec3aedc5a95 100644 (file)
@@ -1508,7 +1508,10 @@ call_timeout(struct rpc_task *task)
                if (clnt->cl_chatty)
                        printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
                                clnt->cl_protname, clnt->cl_server);
-               rpc_exit(task, -EIO);
+               if (task->tk_flags & RPC_TASK_TIMEOUT)
+                       rpc_exit(task, -ETIMEDOUT);
+               else
+                       rpc_exit(task, -EIO);
                return;
        }
 
index 9494c376735618c0f67fb3b9a0f88c70875062a4..ce5eb68a9664f6a93776304b304c80029efce84d 100644 (file)
@@ -906,6 +906,7 @@ void xprt_transmit(struct rpc_task *task)
        }
 
        dprintk("RPC: %5u xmit complete\n", task->tk_pid);
+       task->tk_flags |= RPC_TASK_SENT;
        spin_lock_bh(&xprt->transport_lock);
 
        xprt->ops->set_retrans_timeout(task);
index 3a43a830476884464abbaba9eae091b166ecabe8..b1d75beb7e20e8e3155a84be37161871023396ac 100644 (file)
@@ -524,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *,
                              int, int);
 static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t);
+static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
+                                 struct msghdr *, size_t, int);
 
 static const struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
@@ -583,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = {
        .setsockopt =   sock_no_setsockopt,
        .getsockopt =   sock_no_getsockopt,
        .sendmsg =      unix_seqpacket_sendmsg,
-       .recvmsg =      unix_dgram_recvmsg,
+       .recvmsg =      unix_seqpacket_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
 };
@@ -1699,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
        return unix_dgram_sendmsg(kiocb, sock, msg, len);
 }
 
+static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
+                             struct msghdr *msg, size_t size,
+                             int flags)
+{
+       struct sock *sk = sock->sk;
+
+       if (sk->sk_state != TCP_ESTABLISHED)
+               return -ENOTCONN;
+
+       return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
+}
+
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
        struct unix_sock *u = unix_sk(sk);
index 15792d8b62721f2ce3b33ccb24556942063a966b..b4d745ea8ee14acb200b0e4dc4f5685d012d9e30 100644 (file)
@@ -1406,6 +1406,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
        struct net *net = xp_net(policy);
        unsigned long now = jiffies;
        struct net_device *dev;
+       struct xfrm_mode *inner_mode;
        struct dst_entry *dst_prev = NULL;
        struct dst_entry *dst0 = NULL;
        int i = 0;
@@ -1436,6 +1437,17 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                        goto put_states;
                }
 
+               if (xfrm[i]->sel.family == AF_UNSPEC) {
+                       inner_mode = xfrm_ip2inner_mode(xfrm[i],
+                                                       xfrm_af2proto(family));
+                       if (!inner_mode) {
+                               err = -EAFNOSUPPORT;
+                               dst_release(dst);
+                               goto put_states;
+                       }
+               } else
+                       inner_mode = xfrm[i]->inner_mode;
+
                if (!dst_prev)
                        dst0 = dst1;
                else {
@@ -1464,7 +1476,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                dst1->lastuse = now;
 
                dst1->input = dst_discard;
-               dst1->output = xfrm[i]->outer_mode->afinfo->output;
+               dst1->output = inner_mode->afinfo->output;
 
                dst1->next = dst_prev;
                dst_prev = dst1;
index f218385950ca06a3a8b6830c51c29ac370ca2ea0..47f1b8638df9987dca1cf7ad2bbce5c674044881 100644 (file)
@@ -532,9 +532,12 @@ int xfrm_init_replay(struct xfrm_state *x)
 
        if (replay_esn) {
                if (replay_esn->replay_window >
-                   replay_esn->bmp_len * sizeof(__u32))
+                   replay_esn->bmp_len * sizeof(__u32) * 8)
                        return -EINVAL;
 
+       if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0)
+               return -EINVAL;
+
        if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
                x->repl = &xfrm_replay_esn;
        else
index 5d1d60d3ca832c419bd41bf7b70d84bacb222494..c658cb3bc7c3ccf213fffee288f8b211a2c93293 100644 (file)
@@ -124,6 +124,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
 {
        struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
 
+       if ((p->flags & XFRM_STATE_ESN) && !rt)
+               return -EINVAL;
+
        if (!rt)
                return 0;
 
index d5f925abe4d29710ab0b314bf28d29752b35dc8d..6165622c3e29ae4cb395a1182045a905b603d7f4 100644 (file)
@@ -244,14 +244,19 @@ endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
 ifdef BUILD_C_RECORDMCOUNT
+ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
+  RECORDMCOUNT_FLAGS = -w
+endif
 # Due to recursion, we must skip empty.o.
 # The empty.o file is created in the make process in order to determine
 #  the target endianness and word size. It is made before all other C
 #  files, including recordmcount.
 sub_cmd_record_mcount =                                        \
        if [ $(@) != "scripts/mod/empty.o" ]; then      \
-               $(objtree)/scripts/recordmcount "$(@)"; \
+               $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)";   \
        fi;
+recordmcount_source := $(srctree)/scripts/recordmcount.c \
+                   $(srctree)/scripts/recordmcount.h
 else
 sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
        "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
@@ -259,6 +264,7 @@ sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH
        "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
        "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
        "$(if $(part-of-module),1,0)" "$(@)";
+recordmcount_source := $(srctree)/scripts/recordmcount.pl
 endif
 cmd_record_mcount =                                            \
        if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then    \
@@ -279,13 +285,13 @@ define rule_cc_o_c
 endef
 
 # Built-in and composite module parts
-$(obj)/%.o: $(src)/%.c FORCE
+$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
-$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
+$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
        @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
index 659326c3e89579b09f86077dbcbe5e1eb3a12d28..006ad817cd5f003023a7308b471eb9c4e46ba5de 100644 (file)
@@ -332,7 +332,7 @@ static int conf_choice(struct menu *menu)
                }
                if (!child)
                        continue;
-               if (line[strlen(line) - 1] == '?') {
+               if (line[0] && line[strlen(line) - 1] == '?') {
                        print_help(child);
                        continue;
                }
index cd104afcc5f27d8dca823ae33edeece2868e28d5..413c53693e62d818544c4c931ccf2c6ef48fbb8b 100644 (file)
@@ -420,11 +420,10 @@ static int parse_elf(struct elf_info *info, const char *filename)
                return 0;
        }
 
-       if (hdr->e_shnum == 0) {
+       if (hdr->e_shnum == SHN_UNDEF) {
                /*
                 * There are more than 64k sections,
                 * read count from .sh_size.
-                * note: it doesn't need shndx2secindex()
                 */
                info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
        }
@@ -432,8 +431,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
                info->num_sections = hdr->e_shnum;
        }
        if (hdr->e_shstrndx == SHN_XINDEX) {
-               info->secindex_strings =
-                   shndx2secindex(TO_NATIVE(sechdrs[0].sh_link));
+               info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link);
        }
        else {
                info->secindex_strings = hdr->e_shstrndx;
@@ -489,7 +487,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
                            sechdrs[i].sh_offset;
                        info->symtab_stop  = (void *)hdr +
                            sechdrs[i].sh_offset + sechdrs[i].sh_size;
-                       sh_link_idx = shndx2secindex(sechdrs[i].sh_link);
+                       sh_link_idx = sechdrs[i].sh_link;
                        info->strtab       = (void *)hdr +
                            sechdrs[sh_link_idx].sh_offset;
                }
@@ -516,11 +514,9 @@ static int parse_elf(struct elf_info *info, const char *filename)
 
        if (symtab_shndx_idx != ~0U) {
                Elf32_Word *p;
-               if (symtab_idx !=
-                   shndx2secindex(sechdrs[symtab_shndx_idx].sh_link))
+               if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link)
                        fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
-                             filename,
-                             shndx2secindex(sechdrs[symtab_shndx_idx].sh_link),
+                             filename, sechdrs[symtab_shndx_idx].sh_link,
                              symtab_idx);
                /* Fix endianness */
                for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
@@ -1446,7 +1442,7 @@ static unsigned int *reloc_location(struct elf_info *elf,
                                    Elf_Shdr *sechdr, Elf_Rela *r)
 {
        Elf_Shdr *sechdrs = elf->sechdrs;
-       int section = shndx2secindex(sechdr->sh_info);
+       int section = sechdr->sh_info;
 
        return (void *)elf->hdr + sechdrs[section].sh_offset +
                r->r_offset;
index 0388cfccac8db64818b12732e519d6d233557908..2031119080dce2ac5d8ca63aeb967f0505cc5f74 100644 (file)
@@ -145,33 +145,22 @@ static inline int is_shndx_special(unsigned int i)
        return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
 }
 
-/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus:
- * shndx == 0               <=> sechdrs[0]
- * ......
- * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1]
- * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE]
- * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1]
- * ......
- * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff,
- * so basically we map  0000..feff -> 0000..feff
- *                      ff00..ffff -> (you are a bad boy, dont do it)
- *                     10000..xxxx -> ff00..(xxxx-0x100)
+/*
+ * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+ * the way to -256..-1, to avoid conflicting with real section
+ * indices.
  */
-static inline unsigned int shndx2secindex(unsigned int i)
-{
-       if (i <= SHN_HIRESERVE)
-               return i;
-       return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE);
-}
+#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
 
 /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
 static inline unsigned int get_secindex(const struct elf_info *info,
                                        const Elf_Sym *sym)
 {
+       if (is_shndx_special(sym->st_shndx))
+               return SPECIAL(sym->st_shndx);
        if (sym->st_shndx != SHN_XINDEX)
                return sym->st_shndx;
-       return shndx2secindex(info->symtab_shndx_start[sym -
-                                                      info->symtab_start]);
+       return info->symtab_shndx_start[sym - info->symtab_start];
 }
 
 /* file2alias.c */
index 47a1f9ae0edebc9df457dd2b0e924d6e5ddc73de..0865b3e752be8f99b61c927d5cff2a398dd6f8dd 100644 (file)
@@ -5,4 +5,15 @@
  */
 SECTIONS {
        /DISCARD/ : { *(.discard) }
+
+       __ksymtab               : { *(SORT(___ksymtab+*)) }
+       __ksymtab_gpl           : { *(SORT(___ksymtab_gpl+*)) }
+       __ksymtab_unused        : { *(SORT(___ksymtab_unused+*)) }
+       __ksymtab_unused_gpl    : { *(SORT(___ksymtab_unused_gpl+*)) }
+       __ksymtab_gpl_future    : { *(SORT(___ksymtab_gpl_future+*)) }
+       __kcrctab               : { *(SORT(___kcrctab+*)) }
+       __kcrctab_gpl           : { *(SORT(___kcrctab_gpl+*)) }
+       __kcrctab_unused        : { *(SORT(___kcrctab_unused+*)) }
+       __kcrctab_unused_gpl    : { *(SORT(___kcrctab_unused_gpl+*)) }
+       __kcrctab_gpl_future    : { *(SORT(___kcrctab_gpl_future+*)) }
 }
index f9f6f52db772830c4712d080063773a6187020c5..ee52cb8e17adf1d8d842559fb66dbd3ad5c2fe52 100644 (file)
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <getopt.h>
 #include <elf.h>
 #include <fcntl.h>
 #include <setjmp.h>
@@ -39,6 +40,7 @@ static char gpfx;     /* prefix for global symbol name (sometimes '_') */
 static struct stat sb; /* Remember .st_size, etc. */
 static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
 static const char *altmcount;  /* alternate mcount symbol name */
+static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 
 /* setjmp() return values */
 enum {
@@ -78,7 +80,7 @@ static off_t
 ulseek(int const fd, off_t const offset, int const whence)
 {
        off_t const w = lseek(fd, offset, whence);
-       if ((off_t)-1 == w) {
+       if (w == (off_t)-1) {
                perror("lseek");
                fail_file();
        }
@@ -111,13 +113,41 @@ static void *
 umalloc(size_t size)
 {
        void *const addr = malloc(size);
-       if (0 == addr) {
+       if (addr == 0) {
                fprintf(stderr, "malloc failed: %zu bytes\n", size);
                fail_file();
        }
        return addr;
 }
 
+static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
+static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
+static unsigned char *ideal_nop;
+
+static char rel_type_nop;
+
+static int (*make_nop)(void *map, size_t const offset);
+
+static int make_nop_x86(void *map, size_t const offset)
+{
+       uint32_t *ptr;
+       unsigned char *op;
+
+       /* Confirm we have 0xe8 0x0 0x0 0x0 0x0 */
+       ptr = map + offset;
+       if (*ptr != 0)
+               return -1;
+
+       op = map + offset - 1;
+       if (*op != 0xe8)
+               return -1;
+
+       /* convert to nop */
+       ulseek(fd_map, offset - 1, SEEK_SET);
+       uwrite(fd_map, ideal_nop, 5);
+       return 0;
+}
+
 /*
  * Get the whole file as a programming convenience in order to avoid
  * malloc+lseek+read+free of many pieces.  If successful, then mmap
@@ -136,7 +166,7 @@ static void *mmap_file(char const *fname)
        void *addr;
 
        fd_map = open(fname, O_RDWR);
-       if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
+       if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
                perror(fname);
                fail_file();
        }
@@ -147,7 +177,7 @@ static void *mmap_file(char const *fname)
        addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
                    fd_map, 0);
        mmap_failed = 0;
-       if (MAP_FAILED == addr) {
+       if (addr == MAP_FAILED) {
                mmap_failed = 1;
                addr = umalloc(sb.st_size);
                uread(fd_map, addr, sb.st_size);
@@ -206,12 +236,13 @@ static uint32_t (*w2)(uint16_t);
 static int
 is_mcounted_section_name(char const *const txtname)
 {
-       return 0 == strcmp(".text",           txtname) ||
-               0 == strcmp(".ref.text",      txtname) ||
-               0 == strcmp(".sched.text",    txtname) ||
-               0 == strcmp(".spinlock.text", txtname) ||
-               0 == strcmp(".irqentry.text", txtname) ||
-               0 == strcmp(".text.unlikely", txtname);
+       return strcmp(".text",           txtname) == 0 ||
+               strcmp(".ref.text",      txtname) == 0 ||
+               strcmp(".sched.text",    txtname) == 0 ||
+               strcmp(".spinlock.text", txtname) == 0 ||
+               strcmp(".irqentry.text", txtname) == 0 ||
+               strcmp(".kprobes.text", txtname) == 0 ||
+               strcmp(".text.unlikely", txtname) == 0;
 }
 
 /* 32 bit and 64 bit are very similar */
@@ -264,43 +295,48 @@ do_file(char const *const fname)
        w8 = w8nat;
        switch (ehdr->e_ident[EI_DATA]) {
                static unsigned int const endian = 1;
-       default: {
+       default:
                fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
                        ehdr->e_ident[EI_DATA], fname);
                fail_file();
-       } break;
-       case ELFDATA2LSB: {
-               if (1 != *(unsigned char const *)&endian) {
+               break;
+       case ELFDATA2LSB:
+               if (*(unsigned char const *)&endian != 1) {
                        /* main() is big endian, file.o is little endian. */
                        w = w4rev;
                        w2 = w2rev;
                        w8 = w8rev;
                }
-       } break;
-       case ELFDATA2MSB: {
-               if (0 != *(unsigned char const *)&endian) {
+               break;
+       case ELFDATA2MSB:
+               if (*(unsigned char const *)&endian != 0) {
                        /* main() is little endian, file.o is big endian. */
                        w = w4rev;
                        w2 = w2rev;
                        w8 = w8rev;
                }
-       } break;
+               break;
        }  /* end switch */
-       if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
-       ||  ET_REL != w2(ehdr->e_type)
-       ||  EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
+       if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
+       ||  w2(ehdr->e_type) != ET_REL
+       ||  ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
                fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
                fail_file();
        }
 
        gpfx = 0;
        switch (w2(ehdr->e_machine)) {
-       default: {
+       default:
                fprintf(stderr, "unrecognized e_machine %d %s\n",
                        w2(ehdr->e_machine), fname);
                fail_file();
-       } break;
-       case EM_386:     reltype = R_386_32;                   break;
+               break;
+       case EM_386:
+               reltype = R_386_32;
+               make_nop = make_nop_x86;
+               ideal_nop = ideal_nop5_x86_32;
+               mcount_adjust_32 = -1;
+               break;
        case EM_ARM:     reltype = R_ARM_ABS32;
                         altmcount = "__gnu_mcount_nc";
                         break;
@@ -311,67 +347,91 @@ do_file(char const *const fname)
        case EM_S390:    /* reltype: e_class    */ gpfx = '_'; break;
        case EM_SH:      reltype = R_SH_DIR32;                 break;
        case EM_SPARCV9: reltype = R_SPARC_64;     gpfx = '_'; break;
-       case EM_X86_64:  reltype = R_X86_64_64;                break;
+       case EM_X86_64:
+               make_nop = make_nop_x86;
+               ideal_nop = ideal_nop5_x86_64;
+               reltype = R_X86_64_64;
+               mcount_adjust_64 = -1;
+               break;
        }  /* end switch */
 
        switch (ehdr->e_ident[EI_CLASS]) {
-       default: {
+       default:
                fprintf(stderr, "unrecognized ELF class %d %s\n",
                        ehdr->e_ident[EI_CLASS], fname);
                fail_file();
-       } break;
-       case ELFCLASS32: {
-               if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
-               ||  sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
+               break;
+       case ELFCLASS32:
+               if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
+               ||  w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
                        fprintf(stderr,
                                "unrecognized ET_REL file: %s\n", fname);
                        fail_file();
                }
-               if (EM_S390 == w2(ehdr->e_machine))
+               if (w2(ehdr->e_machine) == EM_S390) {
                        reltype = R_390_32;
-               if (EM_MIPS == w2(ehdr->e_machine)) {
+                       mcount_adjust_32 = -4;
+               }
+               if (w2(ehdr->e_machine) == EM_MIPS) {
                        reltype = R_MIPS_32;
                        is_fake_mcount32 = MIPS32_is_fake_mcount;
                }
                do32(ehdr, fname, reltype);
-       } break;
+               break;
        case ELFCLASS64: {
                Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
-               if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
-               ||  sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
+               if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
+               ||  w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
                        fprintf(stderr,
                                "unrecognized ET_REL file: %s\n", fname);
                        fail_file();
                }
-               if (EM_S390 == w2(ghdr->e_machine))
+               if (w2(ghdr->e_machine) == EM_S390) {
                        reltype = R_390_64;
-               if (EM_MIPS == w2(ghdr->e_machine)) {
+                       mcount_adjust_64 = -8;
+               }
+               if (w2(ghdr->e_machine) == EM_MIPS) {
                        reltype = R_MIPS_64;
                        Elf64_r_sym = MIPS64_r_sym;
                        Elf64_r_info = MIPS64_r_info;
                        is_fake_mcount64 = MIPS64_is_fake_mcount;
                }
                do64(ghdr, fname, reltype);
-       } break;
+               break;
+       }
        }  /* end switch */
 
        cleanup();
 }
 
 int
-main(int argc, char const *argv[])
+main(int argc, char *argv[])
 {
        const char ftrace[] = "/ftrace.o";
        int ftrace_size = sizeof(ftrace) - 1;
        int n_error = 0;  /* gcc-4.3.0 false positive complaint */
+       int c;
+       int i;
+
+       while ((c = getopt(argc, argv, "w")) >= 0) {
+               switch (c) {
+               case 'w':
+                       warn_on_notrace_sect = 1;
+                       break;
+               default:
+                       fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
+                       return 0;
+               }
+       }
 
-       if (argc <= 1) {
-               fprintf(stderr, "usage: recordmcount file.o...\n");
+       if ((argc - optind) < 1) {
+               fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
                return 0;
        }
 
        /* Process each file in turn, allowing deep failure. */
-       for (--argc, ++argv; 0 < argc; --argc, ++argv) {
+       for (i = optind; i < argc; i++) {
+               char *file = argv[i];
                int const sjval = setjmp(jmpenv);
                int len;
 
@@ -380,29 +440,29 @@ main(int argc, char const *argv[])
                 * function but does not call it. Since ftrace.o should
                 * not be traced anyway, we just skip it.
                 */
-               len = strlen(argv[0]);
+               len = strlen(file);
                if (len >= ftrace_size &&
-                   strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
+                   strcmp(file + (len - ftrace_size), ftrace) == 0)
                        continue;
 
                switch (sjval) {
-               default: {
-                       fprintf(stderr, "internal error: %s\n", argv[0]);
+               default:
+                       fprintf(stderr, "internal error: %s\n", file);
                        exit(1);
-               } break;
-               case SJ_SETJMP: {  /* normal sequence */
+                       break;
+               case SJ_SETJMP:    /* normal sequence */
                        /* Avoid problems if early cleanup() */
                        fd_map = -1;
                        ehdr_curr = NULL;
                        mmap_failed = 1;
-                       do_file(argv[0]);
-               } break;
-               case SJ_FAIL: {  /* error in do_file or below */
+                       do_file(file);
+                       break;
+               case SJ_FAIL:    /* error in do_file or below */
                        ++n_error;
-               } break;
-               case SJ_SUCCEED: {  /* premature success */
+                       break;
+               case SJ_SUCCEED:    /* premature success */
                        /* do nothing */
-               } break;
+                       break;
                }  /* end switch */
        }
        return !!n_error;
index baf187bee983c33b6323cfea1b8591ca963fc934..4be60364a40509eac1269eafc97393aadc1ac5e8 100644 (file)
 #undef is_fake_mcount
 #undef fn_is_fake_mcount
 #undef MIPS_is_fake_mcount
+#undef mcount_adjust
 #undef sift_rel_mcount
+#undef nop_mcount
 #undef find_secsym_ndx
 #undef __has_rel_mcount
 #undef has_rel_mcount
 #undef tot_relsize
+#undef get_mcountsym
+#undef get_sym_str_and_relp
 #undef do_func
 #undef Elf_Addr
 #undef Elf_Ehdr
 #ifdef RECORD_MCOUNT_64
 # define append_func           append64
 # define sift_rel_mcount       sift64_rel_mcount
+# define nop_mcount            nop_mcount_64
 # define find_secsym_ndx       find64_secsym_ndx
 # define __has_rel_mcount      __has64_rel_mcount
 # define has_rel_mcount                has64_rel_mcount
 # define tot_relsize           tot64_relsize
+# define get_sym_str_and_relp  get_sym_str_and_relp_64
 # define do_func               do64
+# define get_mcountsym         get_mcountsym_64
 # define is_fake_mcount                is_fake_mcount64
 # define fn_is_fake_mcount     fn_is_fake_mcount64
 # define MIPS_is_fake_mcount   MIPS64_is_fake_mcount
+# define mcount_adjust         mcount_adjust_64
 # define Elf_Addr              Elf64_Addr
 # define Elf_Ehdr              Elf64_Ehdr
 # define Elf_Shdr              Elf64_Shdr
 #else
 # define append_func           append32
 # define sift_rel_mcount       sift32_rel_mcount
+# define nop_mcount            nop_mcount_32
 # define find_secsym_ndx       find32_secsym_ndx
 # define __has_rel_mcount      __has32_rel_mcount
 # define has_rel_mcount                has32_rel_mcount
 # define tot_relsize           tot32_relsize
+# define get_sym_str_and_relp  get_sym_str_and_relp_32
 # define do_func               do32
+# define get_mcountsym         get_mcountsym_32
 # define is_fake_mcount                is_fake_mcount32
 # define fn_is_fake_mcount     fn_is_fake_mcount32
 # define MIPS_is_fake_mcount   MIPS32_is_fake_mcount
+# define mcount_adjust         mcount_adjust_32
 # define Elf_Addr              Elf32_Addr
 # define Elf_Ehdr              Elf32_Ehdr
 # define Elf_Shdr              Elf32_Shdr
@@ -123,6 +135,8 @@ static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
+static int mcount_adjust = 0;
+
 /*
  * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
  * _mcount symbol is needed for dynamic function tracer, with it, to disable
@@ -234,6 +248,49 @@ static void append_func(Elf_Ehdr *const ehdr,
        uwrite(fd_map, ehdr, sizeof(*ehdr));
 }
 
+static unsigned get_mcountsym(Elf_Sym const *const sym0,
+                             Elf_Rel const *relp,
+                             char const *const str0)
+{
+       unsigned mcountsym = 0;
+
+       Elf_Sym const *const symp =
+               &sym0[Elf_r_sym(relp)];
+       char const *symname = &str0[w(symp->st_name)];
+       char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
+
+       if (symname[0] == '.')
+               ++symname;  /* ppc64 hack */
+       if (strcmp(mcount, symname) == 0 ||
+           (altmcount && strcmp(altmcount, symname) == 0))
+               mcountsym = Elf_r_sym(relp);
+
+       return mcountsym;
+}
+
+static void get_sym_str_and_relp(Elf_Shdr const *const relhdr,
+                                Elf_Ehdr const *const ehdr,
+                                Elf_Sym const **sym0,
+                                char const **str0,
+                                Elf_Rel const **relp)
+{
+       Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+               + (void *)ehdr);
+       unsigned const symsec_sh_link = w(relhdr->sh_link);
+       Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
+       Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
+       Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
+               + (void *)ehdr);
+
+       *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
+                                 + (void *)ehdr);
+
+       *str0 = (char const *)(_w(strsec->sh_offset)
+                              + (void *)ehdr);
+
+       *relp = rel0;
+}
+
 /*
  * Look at the relocations in order to find the calls to mcount.
  * Accumulate the section offsets that are found, and their relocation info,
@@ -250,47 +307,27 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 {
        uint_t *const mloc0 = mlocp;
        Elf_Rel *mrelp = *mrelpp;
-       Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
-               + (void *)ehdr);
-       unsigned const symsec_sh_link = w(relhdr->sh_link);
-       Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
-       Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
-               + (void *)ehdr);
-
-       Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
-       char const *const str0 = (char const *)(_w(strsec->sh_offset)
-               + (void *)ehdr);
-
-       Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
-               + (void *)ehdr);
+       Elf_Sym const *sym0;
+       char const *str0;
+       Elf_Rel const *relp;
        unsigned rel_entsize = _w(relhdr->sh_entsize);
        unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
-       Elf_Rel const *relp = rel0;
-
        unsigned mcountsym = 0;
        unsigned t;
 
+       get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
+
        for (t = nrel; t; --t) {
-               if (!mcountsym) {
-                       Elf_Sym const *const symp =
-                               &sym0[Elf_r_sym(relp)];
-                       char const *symname = &str0[w(symp->st_name)];
-                       char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
-
-                       if ('.' == symname[0])
-                               ++symname;  /* ppc64 hack */
-                       if (0 == strcmp(mcount, symname) ||
-                           (altmcount && 0 == strcmp(altmcount, symname)))
-                               mcountsym = Elf_r_sym(relp);
-               }
+               if (!mcountsym)
+                       mcountsym = get_mcountsym(sym0, relp, str0);
 
                if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
-                       uint_t const addend = _w(_w(relp->r_offset) - recval);
-
+                       uint_t const addend =
+                               _w(_w(relp->r_offset) - recval + mcount_adjust);
                        mrelp->r_offset = _w(offbase
                                + ((void *)mlocp - (void *)mloc0));
                        Elf_r_info(mrelp, recsym, reltype);
-                       if (sizeof(Elf_Rela) == rel_entsize) {
+                       if (rel_entsize == sizeof(Elf_Rela)) {
                                ((Elf_Rela *)mrelp)->r_addend = addend;
                                *mlocp++ = 0;
                        } else
@@ -304,6 +341,63 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
        return mlocp;
 }
 
+/*
+ * Read the relocation table again, but this time its called on sections
+ * that are not going to be traced. The mcount calls here will be converted
+ * into nops.
+ */
+static void nop_mcount(Elf_Shdr const *const relhdr,
+                      Elf_Ehdr const *const ehdr,
+                      const char *const txtname)
+{
+       Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+               + (void *)ehdr);
+       Elf_Sym const *sym0;
+       char const *str0;
+       Elf_Rel const *relp;
+       Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)];
+       unsigned rel_entsize = _w(relhdr->sh_entsize);
+       unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+       unsigned mcountsym = 0;
+       unsigned t;
+       int once = 0;
+
+       get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
+
+       for (t = nrel; t; --t) {
+               int ret = -1;
+
+               if (!mcountsym)
+                       mcountsym = get_mcountsym(sym0, relp, str0);
+
+               if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
+                       if (make_nop)
+                               ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
+                       if (warn_on_notrace_sect && !once) {
+                               printf("Section %s has mcount callers being ignored\n",
+                                      txtname);
+                               once = 1;
+                               /* just warn? */
+                               if (!make_nop)
+                                       return;
+                       }
+               }
+
+               /*
+                * If we successfully removed the mcount, mark the relocation
+                * as a nop (don't do anything with it).
+                */
+               if (!ret) {
+                       Elf_Rel rel;
+                       rel = *(Elf_Rel *)relp;
+                       Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
+                       ulseek(fd_map, (void *)relp - (void *)ehdr, SEEK_SET);
+                       uwrite(fd_map, &rel, sizeof(rel));
+               }
+               relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
+       }
+}
+
 
 /*
  * Find a symbol in the given section, to be used as the base for relocating
@@ -354,13 +448,13 @@ __has_rel_mcount(Elf_Shdr const *const relhdr,  /* is SHT_REL or SHT_RELA */
        Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
        char const *const txtname = &shstrtab[w(txthdr->sh_name)];
 
-       if (0 == strcmp("__mcount_loc", txtname)) {
+       if (strcmp("__mcount_loc", txtname) == 0) {
                fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
                        fname);
                succeed_file();
        }
-       if (SHT_PROGBITS != w(txthdr->sh_type) ||
-           !is_mcounted_section_name(txtname))
+       if (w(txthdr->sh_type) != SHT_PROGBITS ||
+           !(w(txthdr->sh_flags) & SHF_EXECINSTR))
                return NULL;
        return txtname;
 }
@@ -370,7 +464,7 @@ static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
                                  char const *const shstrtab,
                                  char const *const fname)
 {
-       if (SHT_REL  != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
+       if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA)
                return NULL;
        return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
 }
@@ -383,9 +477,11 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
 {
        unsigned totrelsz = 0;
        Elf_Shdr const *shdrp = shdr0;
+       char const *txtname;
 
        for (; nhdr; --nhdr, ++shdrp) {
-               if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
+               txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
+               if (txtname && is_mcounted_section_name(txtname))
                        totrelsz += _w(shdrp->sh_size);
        }
        return totrelsz;
@@ -421,7 +517,7 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
        for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
                char const *const txtname = has_rel_mcount(relhdr, shdr0,
                        shstrtab, fname);
-               if (txtname) {
+               if (txtname && is_mcounted_section_name(txtname)) {
                        uint_t recval = 0;
                        unsigned const recsym = find_secsym_ndx(
                                w(relhdr->sh_info), txtname, &recval,
@@ -432,6 +528,12 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
                        mlocp = sift_rel_mcount(mlocp,
                                (void *)mlocp - (void *)mloc0, &mrelp,
                                relhdr, ehdr, recsym, recval, reltype);
+               } else if (txtname && (warn_on_notrace_sect || make_nop)) {
+                       /*
+                        * This section is ignored by ftrace, but still
+                        * has mcount calls. Convert them to nops now.
+                        */
+                       nop_mcount(relhdr, ehdr, txtname);
                }
        }
        if (mloc0 != mlocp) {
index 4be0deea71ca6f947b6c1d47c28c431cae88c3c7..858966ab019cc1951724b3a2f47b4bfd5b892bf6 100755 (executable)
@@ -134,6 +134,7 @@ my %text_sections = (
      ".sched.text" => 1,
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
+     ".kprobes.text" => 1,
      ".text.unlikely" => 1,
 );
 
@@ -222,6 +223,7 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$";
     $type = ".quad";
     $alignment = 8;
+    $mcount_adjust = -1;
 
     # force flags for this arch
     $ld .= " -m elf_x86_64";
@@ -231,6 +233,7 @@ if ($arch eq "x86_64") {
 
 } elsif ($arch eq "i386") {
     $alignment = 4;
+    $mcount_adjust = -1;
 
     # force flags for this arch
     $ld .= " -m elf_i386";
@@ -240,12 +243,14 @@ if ($arch eq "x86_64") {
 
 } elsif ($arch eq "s390" && $bits == 32) {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$";
+    $mcount_adjust = -4;
     $alignment = 4;
     $ld .= " -m elf_s390";
     $cc .= " -m31";
 
 } elsif ($arch eq "s390" && $bits == 64) {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
+    $mcount_adjust = -8;
     $alignment = 8;
     $type = ".quad";
     $ld .= " -m elf64_s390";
index 2984ea4f776f0c6cd683d36eb64d096be1ebe337..bbb51156261b723904499c81d563e5632e758bb2 100644 (file)
@@ -181,7 +181,7 @@ static int cap_inode_follow_link(struct dentry *dentry,
        return 0;
 }
 
-static int cap_inode_permission(struct inode *inode, int mask)
+static int cap_inode_permission(struct inode *inode, int mask, unsigned flags)
 {
        return 0;
 }
index c6ca8662a4685bd162205938eafae39bef25fbbf..f66baf44f32d16344756635321fffb98b34f0034 100644 (file)
@@ -68,18 +68,6 @@ error:
 
 EXPORT_SYMBOL_GPL(user_instantiate);
 
-/*
- * dispose of the old data from an updated user defined key
- */
-static void user_update_rcu_disposal(struct rcu_head *rcu)
-{
-       struct user_key_payload *upayload;
-
-       upayload = container_of(rcu, struct user_key_payload, rcu);
-
-       kfree(upayload);
-}
-
 /*
  * update a user defined key
  * - the key's semaphore is write-locked
@@ -114,7 +102,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
                key->expiry = 0;
        }
 
-       call_rcu(&zap->rcu, user_update_rcu_disposal);
+       kfree_rcu(zap, rcu);
 
 error:
        return ret;
@@ -145,7 +133,7 @@ void user_revoke(struct key *key)
 
        if (upayload) {
                rcu_assign_pointer(key->payload.data, NULL);
-               call_rcu(&upayload->rcu, user_update_rcu_disposal);
+               kfree_rcu(upayload, rcu);
        }
 }
 
index 101142369db45c0846ca3dbe064b90a2ea83fbf9..4ba6d4cc061f294142b126b962a99986a1285a6c 100644 (file)
@@ -518,16 +518,14 @@ int security_inode_permission(struct inode *inode, int mask)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return security_ops->inode_permission(inode, mask);
+       return security_ops->inode_permission(inode, mask, 0);
 }
 
 int security_inode_exec_permission(struct inode *inode, unsigned int flags)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       if (flags)
-               return -ECHILD;
-       return security_ops->inode_permission(inode, MAY_EXEC);
+       return security_ops->inode_permission(inode, MAY_EXEC, flags);
 }
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
index 9da6420e2056541f330d85e41be66f4742691e2b..1d027e29ce8d5400c9d4a681d52f2f28025aacd2 100644 (file)
@@ -471,6 +471,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
  * @avd: access vector decisions
  * @result: result from avc_has_perm_noaudit
  * @a:  auxiliary audit data
+ * @flags: VFS walk flags
  *
  * Audit the granting or denial of permissions in accordance
  * with the policy.  This function is typically called by
@@ -481,9 +482,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
  * be performed under a lock, to allow the lock to be released
  * before calling the auditing code.
  */
-void avc_audit(u32 ssid, u32 tsid,
+int avc_audit(u32 ssid, u32 tsid,
               u16 tclass, u32 requested,
-              struct av_decision *avd, int result, struct common_audit_data *a)
+              struct av_decision *avd, int result, struct common_audit_data *a,
+              unsigned flags)
 {
        struct common_audit_data stack_data;
        u32 denied, audited;
@@ -515,11 +517,24 @@ void avc_audit(u32 ssid, u32 tsid,
        else
                audited = requested & avd->auditallow;
        if (!audited)
-               return;
+               return 0;
+
        if (!a) {
                a = &stack_data;
                COMMON_AUDIT_DATA_INIT(a, NONE);
        }
+
+       /*
+        * When in a RCU walk do the audit on the RCU retry.  This is because
+        * the collection of the dname in an inode audit message is not RCU
+        * safe.  Note this may drop some audits when the situation changes
+        * during retry. However this is logically just as if the operation
+        * happened a little later.
+        */
+       if ((a->type == LSM_AUDIT_DATA_FS) &&
+           (flags & IPERM_FLAG_RCU))
+               return -ECHILD;
+
        a->selinux_audit_data.tclass = tclass;
        a->selinux_audit_data.requested = requested;
        a->selinux_audit_data.ssid = ssid;
@@ -529,6 +544,7 @@ void avc_audit(u32 ssid, u32 tsid,
        a->lsm_pre_audit = avc_audit_pre_callback;
        a->lsm_post_audit = avc_audit_post_callback;
        common_lsm_audit(a);
+       return 0;
 }
 
 /**
@@ -793,6 +809,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
  * @auditdata: auxiliary audit data
+ * @flags: VFS walk flags
  *
  * Check the AVC to determine whether the @requested permissions are granted
  * for the SID pair (@ssid, @tsid), interpreting the permissions
@@ -802,14 +819,19 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * permissions are granted, -%EACCES if any permissions are denied, or
  * another -errno upon other errors.
  */
-int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
-                u32 requested, struct common_audit_data *auditdata)
+int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass,
+                      u32 requested, struct common_audit_data *auditdata,
+                      unsigned flags)
 {
        struct av_decision avd;
-       int rc;
+       int rc, rc2;
 
        rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
-       avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
+
+       rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata,
+                       flags);
+       if (rc2)
+               return rc2;
        return rc;
 }
 
index f9c3764e48590e5737a0afddb63043b25675f23b..8fb248843009de5e6b71a01cae7b884cd597ba36 100644 (file)
@@ -1446,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk,
        }
 
        rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
-       if (audit == SECURITY_CAP_AUDIT)
-               avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
+       if (audit == SECURITY_CAP_AUDIT) {
+               int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
+               if (rc2)
+                       return rc2;
+       }
        return rc;
 }
 
@@ -1467,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk,
 static int inode_has_perm(const struct cred *cred,
                          struct inode *inode,
                          u32 perms,
-                         struct common_audit_data *adp)
+                         struct common_audit_data *adp,
+                         unsigned flags)
 {
        struct inode_security_struct *isec;
        struct common_audit_data ad;
@@ -1487,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred,
                ad.u.fs.inode = inode;
        }
 
-       return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
+       return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
 }
 
 /* Same as inode_has_perm, but pass explicit audit data containing
@@ -1504,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred,
        COMMON_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.mnt = mnt;
        ad.u.fs.path.dentry = dentry;
-       return inode_has_perm(cred, inode, av, &ad);
+       return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
 /* Check whether a task can use an open file descriptor to
@@ -1540,7 +1544,7 @@ static int file_has_perm(const struct cred *cred,
        /* av is zero if only checking access to the descriptor. */
        rc = 0;
        if (av)
-               rc = inode_has_perm(cred, inode, av, &ad);
+               rc = inode_has_perm(cred, inode, av, &ad, 0);
 
 out:
        return rc;
@@ -1574,7 +1578,8 @@ static int may_create(struct inode *dir,
                return rc;
 
        if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
-               rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);
+               rc = security_transition_sid(sid, dsec->sid, tclass,
+                                            &dentry->d_name, &newsid);
                if (rc)
                        return rc;
        }
@@ -2103,7 +2108,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                        file = file_priv->file;
                        inode = file->f_path.dentry->d_inode;
                        if (inode_has_perm(cred, inode,
-                                          FILE__READ | FILE__WRITE, NULL)) {
+                                          FILE__READ | FILE__WRITE, NULL, 0)) {
                                drop_tty = 1;
                        }
                }
@@ -2635,7 +2640,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
        return dentry_has_perm(cred, NULL, dentry, FILE__READ);
 }
 
-static int selinux_inode_permission(struct inode *inode, int mask)
+static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
@@ -2657,7 +2662,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
 
        perms = file_mask_to_av(inode->i_mode, mask);
 
-       return inode_has_perm(cred, inode, perms, &ad);
+       return inode_has_perm(cred, inode, perms, &ad, flags);
 }
 
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -3205,7 +3210,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
-       return inode_has_perm(cred, inode, open_file_to_av(file), NULL);
+       return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0);
 }
 
 /* task security operations */
index 5615081b73eca403e438678fcea782dc06e580e3..e77b2ac2908b7f754113bb6dd5023427da5f35fb 100644 (file)
@@ -54,11 +54,11 @@ struct avc_cache_stats {
 
 void __init avc_init(void);
 
-void avc_audit(u32 ssid, u32 tsid,
+int avc_audit(u32 ssid, u32 tsid,
               u16 tclass, u32 requested,
               struct av_decision *avd,
               int result,
-              struct common_audit_data *a);
+             struct common_audit_data *a, unsigned flags);
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -66,9 +66,17 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                         unsigned flags,
                         struct av_decision *avd);
 
-int avc_has_perm(u32 ssid, u32 tsid,
-                u16 tclass, u32 requested,
-                struct common_audit_data *auditdata);
+int avc_has_perm_flags(u32 ssid, u32 tsid,
+                      u16 tclass, u32 requested,
+                      struct common_audit_data *auditdata,
+                      unsigned);
+
+static inline int avc_has_perm(u32 ssid, u32 tsid,
+                              u16 tclass, u32 requested,
+                              struct common_audit_data *auditdata)
+{
+       return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0);
+}
 
 u32 avc_policy_seqno(void);
 
index d6095d63d831a63999f1921fbed460a94140fc39..58cc481c93d5e580e554cd9b3b61bc9214128193 100644 (file)
@@ -103,22 +103,6 @@ static int sel_netif_insert(struct sel_netif *netif)
        return 0;
 }
 
-/**
- * sel_netif_free - Frees an interface entry
- * @p: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that memory allocated to a hash table interface entry can be
- * released safely.
- *
- */
-static void sel_netif_free(struct rcu_head *p)
-{
-       struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
-       kfree(netif);
-}
-
 /**
  * sel_netif_destroy - Remove an interface record from the table
  * @netif: the existing interface record
@@ -131,7 +115,7 @@ static void sel_netif_destroy(struct sel_netif *netif)
 {
        list_del_rcu(&netif->list);
        sel_netif_total--;
-       call_rcu(&netif->rcu_head, sel_netif_free);
+       kfree_rcu(netif, rcu_head);
 }
 
 /**
index e7b850ad57ee1547018ff37c4c3bb496d6bccb21..7102457661d645cd499d770819ad92e3970f6831 100644 (file)
@@ -502,7 +502,7 @@ static int policydb_index(struct policydb *p)
                goto out;
 
        rc = flex_array_prealloc(p->type_val_to_struct_array, 0,
-                                p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO);
+                                p->p_types.nprim, GFP_KERNEL | __GFP_ZERO);
        if (rc)
                goto out;
 
@@ -519,7 +519,7 @@ static int policydb_index(struct policydb *p)
                        goto out;
 
                rc = flex_array_prealloc(p->sym_val_to_name[i],
-                                        0, p->symtab[i].nprim - 1,
+                                        0, p->symtab[i].nprim,
                                         GFP_KERNEL | __GFP_ZERO);
                if (rc)
                        goto out;
@@ -1819,8 +1819,6 @@ static int filename_trans_read(struct policydb *p, void *fp)
                goto out;
        nel = le32_to_cpu(buf[0]);
 
-       printk(KERN_ERR "%s: nel=%d\n", __func__, nel);
-
        last = p->filename_trans;
        while (last && last->next)
                last = last->next;
@@ -1857,8 +1855,6 @@ static int filename_trans_read(struct policydb *p, void *fp)
                        goto out;
                name[len] = 0;
 
-               printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name);
-
                rc = next_entry(buf, fp, sizeof(u32) * 4);
                if (rc)
                        goto out;
@@ -2375,7 +2371,7 @@ int policydb_read(struct policydb *p, void *fp)
                goto bad;
 
        /* preallocate so we don't have to worry about the put ever failing */
-       rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
+       rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim,
                                 GFP_KERNEL | __GFP_ZERO);
        if (rc)
                goto bad;
index c6f8fcadae07787f8f04204bff0a34fb7672829e..400a5d5cde6183c9bc3c6d348f58b623e2821b46 100644 (file)
@@ -686,7 +686,7 @@ static int smack_inode_rename(struct inode *old_inode,
  *
  * Returns 0 if access is permitted, -EACCES otherwise
  */
-static int smack_inode_permission(struct inode *inode, int mask)
+static int smack_inode_permission(struct inode *inode, int mask, unsigned flags)
 {
        struct smk_audit_info ad;
 
@@ -696,6 +696,10 @@ static int smack_inode_permission(struct inode *inode, int mask)
         */
        if (mask == 0)
                return 0;
+
+       /* May be droppable after audit */
+       if (flags & IPERM_FLAG_RCU)
+               return -ECHILD;
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
        smk_ad_setfield_u_fs_inode(&ad, inode);
        return smk_curacc(smk_of_inode(inode), mask, &ad);
index 58804c7acfcf63acde8c445d33e24ebb5f246d35..fd2188c3df2b4c436c9a6112cbc577c309d2898e 100644 (file)
@@ -170,7 +170,7 @@ static void tas_set_volume(struct tas *tas)
        /* analysing the volume and mixer tables shows
         * that they are similar enough when we shift
         * the mixer table down by 4 bits. The error
-        * is minuscule, in just one item the error
+        * is miniscule, in just one item the error
         * is 1, at a value of 0x07f17b (mixer table
         * value is 0x07f17a) */
        tmp = tas_gaintable[left];
index 33f0ba5559a77201ab8bf7752f7e242cf0bcc1ac..62e959120c44cc82542ccca98f0df7791e99b022 100644 (file)
@@ -44,10 +44,10 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
        .channels_min = 1,
        .channels_max = 2,
        .buffer_bytes_max = 0x10000,
-       .period_bytes_min = 0x1,
+       .period_bytes_min = 0x20,
        .period_bytes_max = 0x1000,
        .periods_min = 2,
-       .periods_max = 32,
+       .periods_max = 1024,
 };
 
 #ifndef CHIP_AU8820
@@ -140,6 +140,9 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
                return err;
 
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);
+
        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 #ifndef CHIP_AU8820
                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {
index 430f41db60446404f322f026d4c50ce6d69f4d5d..759ade12e758e541749ad04c199de4e97b069a8f 100644 (file)
@@ -937,6 +937,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
 
+#ifdef SND_HDA_NEEDS_RESUME
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
 static void restore_shutup_pins(struct hda_codec *codec)
 {
@@ -953,6 +954,7 @@ static void restore_shutup_pins(struct hda_codec *codec)
        }
        codec->pins_shutup = 0;
 }
+#endif
 
 static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
@@ -1329,6 +1331,7 @@ static void purify_inactive_streams(struct hda_codec *codec)
        }
 }
 
+#ifdef SND_HDA_NEEDS_RESUME
 /* clean up all streams; called from suspend */
 static void hda_cleanup_all_streams(struct hda_codec *codec)
 {
@@ -1340,6 +1343,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec)
                        really_cleanup_stream(codec, p);
        }
 }
+#endif
 
 /*
  * amp access functions
index 52928d9a72dacf3dfc42636212a523f658df5e95..c82979a8cd0930026e84eced9fa684d4c4ccac84 100644 (file)
@@ -1704,11 +1704,11 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
                                   codec->chip_name, fix->type);
                        break;
                }
-               if (!fix[id].chained)
+               if (!fix->chained)
                        break;
                if (++depth > 10)
                        break;
-               id = fix[id].chain_id;
+               id = fix->chain_id;
        }
 }
 
@@ -5645,6 +5645,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
 static struct snd_pci_quirk beep_white_list[] = {
        SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
+       SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
        SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
        {}
 };
@@ -9863,6 +9864,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
 
        SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
@@ -10699,7 +10701,6 @@ enum {
        PINFIX_LENOVO_Y530,
        PINFIX_PB_M5210,
        PINFIX_ACER_ASPIRE_7736,
-       PINFIX_GIGABYTE_880GM,
 };
 
 static const struct alc_fixup alc882_fixups[] = {
@@ -10731,13 +10732,6 @@ static const struct alc_fixup alc882_fixups[] = {
                .type = ALC_FIXUP_SKU,
                .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
-       [PINFIX_GIGABYTE_880GM] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x1114410 }, /* set as speaker */
-                       { }
-               }
-       },
 };
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -10745,7 +10739,6 @@ static struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
        {}
 };
 
@@ -14868,6 +14861,23 @@ static void alc269_fixup_hweq(struct hda_codec *codec,
        alc_write_coef_idx(codec, 0x1e, coef | 0x80);
 }
 
+static void alc271_fixup_dmic(struct hda_codec *codec,
+                             const struct alc_fixup *fix, int action)
+{
+       static struct hda_verb verbs[] = {
+               {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
+               {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
+               {}
+       };
+       unsigned int cfg;
+
+       if (strcmp(codec->chip_name, "ALC271X"))
+               return;
+       cfg = snd_hda_codec_get_pincfg(codec, 0x12);
+       if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
+               snd_hda_sequence_write(codec, verbs);
+}
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -14876,6 +14886,7 @@ enum {
        ALC269_FIXUP_ASUS_G73JW,
        ALC269_FIXUP_LENOVO_EAPD,
        ALC275_FIXUP_SONY_HWEQ,
+       ALC271_FIXUP_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14929,7 +14940,11 @@ static const struct alc_fixup alc269_fixups[] = {
                .v.func = alc269_fixup_hweq,
                .chained = true,
                .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
-       }
+       },
+       [ALC271_FIXUP_DMIC] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc271_fixup_dmic,
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -14938,6 +14953,7 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -18782,6 +18798,8 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
                      ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
        SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
+                     ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
        SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
@@ -19455,7 +19473,7 @@ enum {
        ALC662_FIXUP_IDEAPAD,
        ALC272_FIXUP_MARIO,
        ALC662_FIXUP_CZC_P10T,
-       ALC662_FIXUP_GIGABYTE,
+       ALC662_FIXUP_SKU_IGNORE,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19484,20 +19502,17 @@ static const struct alc_fixup alc662_fixups[] = {
                        {}
                }
        },
-       [ALC662_FIXUP_GIGABYTE] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x1114410 }, /* set as speaker */
-                       { }
-               }
+       [ALC662_FIXUP_SKU_IGNORE] = {
+               .type = ALC_FIXUP_SKU,
+               .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
 };
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
+       SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
index 1371b57c11e823209336a3a2f86b6274e550a0b9..0997031c48d228e3e0a2af8d9b1fde55ab54ed8d 100644 (file)
@@ -1292,14 +1292,18 @@ static void notify_aa_path_ctls(struct hda_codec *codec)
 {
        int i;
        struct snd_ctl_elem_id id;
-       const char *labels[] = {"Mic", "Front Mic", "Line"};
+       const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"};
+       struct snd_kcontrol *ctl;
 
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        for (i = 0; i < ARRAY_SIZE(labels); i++) {
                sprintf(id.name, "%s Playback Volume", labels[i]);
-               snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &id);
+               ctl = snd_hda_find_mixer_ctl(codec, id.name);
+               if (ctl)
+                       snd_ctl_notify(codec->bus->card,
+                                       SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &ctl->id);
        }
 }
 
index f7cd346fd7275d4dee46261a06f52f877923d30b..f5ccdbf7ebc6e1fb0630b5ef6db426db5c2ba3e8 100644 (file)
@@ -308,8 +308,6 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
        snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes,
                ARRAY_SIZE(jz4740_codec_dapm_routes));
 
-       snd_soc_dapm_new_widgets(codec);
-
        jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
index a54d2a5b28f646765b29d2c08ffaa59015fb6ebc..4d9fb279e14673344c305a938959a4c6921f7d6f 100644 (file)
@@ -927,7 +927,7 @@ static struct platform_driver sn95031_codec_driver = {
                .owner          = THIS_MODULE,
        },
        .probe          = sn95031_device_probe,
-       .remove         = sn95031_device_remove,
+       .remove         = __devexit_p(sn95031_device_remove),
 };
 
 static int __init sn95031_init(void)
index 2727befd158ecfd253ce25072439bf6d01e43ff0..b04d28039c1665d42473bf79df2936938e20acfc 100644 (file)
@@ -139,7 +139,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0),
 SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
 
 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
-SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
+SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0),
 SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
 
 SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
@@ -602,7 +602,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
        .read = ssm2602_read_reg_cache,
        .write = ssm2602_write,
        .set_bias_level = ssm2602_set_bias_level,
-       .reg_cache_size = sizeof(ssm2602_reg),
+       .reg_cache_size = ARRAY_SIZE(ssm2602_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = ssm2602_reg,
 };
@@ -614,7 +614,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static int ssm2602_i2c_probe(struct i2c_client *i2c,
+static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
        struct ssm2602_priv *ssm2602;
@@ -635,7 +635,7 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int ssm2602_i2c_remove(struct i2c_client *client)
+static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        kfree(i2c_get_clientdata(client));
@@ -655,7 +655,7 @@ static struct i2c_driver ssm2602_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ssm2602_i2c_probe,
-       .remove = ssm2602_i2c_remove,
+       .remove = __devexit_p(ssm2602_i2c_remove),
        .id_table = ssm2602_i2c_id,
 };
 #endif
index 48ffd406a71d18e2170a7b8ca69214a9de4ee8a6..a7b8f301bad39b3ef7a691273d4d3ba4bf4b9097 100644 (file)
@@ -601,9 +601,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
        .reg_cache_step = 1,
        .read = uda134x_read_reg_cache,
        .write = uda134x_write,
-#ifdef POWER_OFF_ON_STANDBY
        .set_bias_level = uda134x_set_bias_level,
-#endif
 };
 
 static int __devinit uda134x_codec_probe(struct platform_device *pdev)
index ae1cadfae84c1fe173c6ef09939c7b2a6cd70f7f..824d1c8c8a3536b8d2d8b5f36a699c5f808aa2f4 100644 (file)
@@ -247,8 +247,6 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re
        case WM8903_REVISION_NUMBER:
        case WM8903_INTERRUPT_STATUS_1:
        case WM8903_WRITE_SEQUENCER_4:
-       case WM8903_POWER_MANAGEMENT_3:
-       case WM8903_POWER_MANAGEMENT_2:
        case WM8903_DC_SERVO_READBACK_1:
        case WM8903_DC_SERVO_READBACK_2:
        case WM8903_DC_SERVO_READBACK_3:
@@ -694,7 +692,7 @@ SOC_ENUM("DRC Smoothing Threshold", drc_smoothing),
 SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup),
 
 SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
-                WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv),
+                WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
 SOC_ENUM("ADC Companding Mode", adc_companding),
 SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
 
@@ -875,34 +873,40 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0,
 SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
                   right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
 
-SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
-                  4, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
+SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2,
+                  1, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2,
                   0, 0, NULL, 0),
 
-SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0,
+SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 1, 0,
                   NULL, 0),
-SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0,
+SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 0, 0,
                   NULL, 0),
 
 SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPL_ENA", 1, WM8903_ANALOGUE_HP_0, 4, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPR_ENA", 1, WM8903_ANALOGUE_HP_0, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0,
                   NULL, 0),
 SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0,
                   NULL, 0),
-SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0,
+SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 5, 0,
+                  NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTL_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 4, 0,
                   NULL, 0),
 SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0,
                   NULL, 0),
 SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0,
                   NULL, 0),
-SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0,
+SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 1, 0,
+                  NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTR_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 0, 0,
                   NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0),
@@ -1037,10 +1041,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        { "Left Speaker PGA", NULL, "Left Speaker Mixer" },
        { "Right Speaker PGA", NULL, "Right Speaker Mixer" },
 
-       { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" },
-       { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" },
-       { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" },
-       { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" },
+       { "HPL_ENA", NULL, "Left Headphone Output PGA" },
+       { "HPR_ENA", NULL, "Right Headphone Output PGA" },
+       { "HPL_ENA_DLY", NULL, "HPL_ENA" },
+       { "HPR_ENA_DLY", NULL, "HPR_ENA" },
+       { "LINEOUTL_ENA", NULL, "Left Line Output PGA" },
+       { "LINEOUTR_ENA", NULL, "Right Line Output PGA" },
+       { "LINEOUTL_ENA_DLY", NULL, "LINEOUTL_ENA" },
+       { "LINEOUTR_ENA_DLY", NULL, "LINEOUTR_ENA" },
 
        { "HPL_DCS", NULL, "DCS Master" },
        { "HPR_DCS", NULL, "DCS Master" },
index 3290333b2bb9c676b122cb00f31367f88ef355d6..84e1bd1d2822fcfe7eca4a0bfb8749eff28a7fec 100644 (file)
@@ -3261,20 +3261,36 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch volume updates (right only; we always do left then right). */
+       snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
+                           WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
                            WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME,
+                           WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME,
                            WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU);
+       snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME,
+                           WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU);
        snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME,
                            WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME,
+                           WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME,
                            WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME,
+                           WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME,
                            WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU);
+       snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME,
+                           WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME,
                            WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU);
+       snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME,
+                           WM8994_DAC1_VU, WM8994_DAC1_VU);
        snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME,
                            WM8994_DAC1_VU, WM8994_DAC1_VU);
+       snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME,
+                           WM8994_DAC2_VU, WM8994_DAC2_VU);
        snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME,
                            WM8994_DAC2_VU, WM8994_DAC2_VU);
 
index 7b6b3c18e2999ae971fe5d5e418289d939d70699..4005e9af5d61acae8ce40c05b2862fcfa20ae4c0 100644 (file)
@@ -740,12 +740,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
 
        { "SPKL", "Input Switch", "MIXINL" },
        { "SPKL", "IN1LP Switch", "IN1LP" },
-       { "SPKL", "Output Switch", "Left Output Mixer" },
+       { "SPKL", "Output Switch", "Left Output PGA" },
        { "SPKL", NULL, "TOCLK" },
 
        { "SPKR", "Input Switch", "MIXINR" },
        { "SPKR", "IN1RP Switch", "IN1RP" },
-       { "SPKR", "Output Switch", "Right Output Mixer" },
+       { "SPKR", "Output Switch", "Right Output PGA" },
        { "SPKR", NULL, "TOCLK" },
 
        { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
@@ -767,8 +767,8 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "SPKOUTRP", NULL, "SPKR Driver" },
        { "SPKOUTRN", NULL, "SPKR Driver" },
 
-       { "Left Headphone Mux", "Mixer", "Left Output Mixer" },
-       { "Right Headphone Mux", "Mixer", "Right Output Mixer" },
+       { "Left Headphone Mux", "Mixer", "Left Output PGA" },
+       { "Right Headphone Mux", "Mixer", "Right Output PGA" },
 
        { "Headphone PGA", NULL, "Left Headphone Mux" },
        { "Headphone PGA", NULL, "Right Headphone Mux" },
index a5af834c8ef52088c9a735b85cceebe095b95300..4ddc6d3b66786a14738b99049f17cfb140a6d598 100644 (file)
@@ -434,17 +434,21 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
+                               ACLKX | AHCLKX | AFSX);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
                mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
+               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
+                               ACLKX | ACLKR);
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
+                               AFSX | AFSR);
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                /* codec is clock and frame master */
@@ -454,7 +458,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
+               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
+                               ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
                break;
 
        default:
@@ -644,7 +649,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
                mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
-               if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
+               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
                        mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
                                        FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
                else
@@ -660,7 +665,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                                AHCLKRE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
 
-               if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
+               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
                        mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
                                        FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
                else
index 419bf4f5534a6c082f8e5b5aa7a1a9ce3e43bcf7..cd22a54b2f14b3cd408d64acbbc519786320f573 100644 (file)
@@ -133,7 +133,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
        struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf;
 
-       if (!dai->active)
+       if (dai->active)
                return;
 
        conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
index b2e9198a983a01115fe31c6e32570d31c0fb3aaa..6b1f9d3bf34e2ba37056216fa9635d592435e843 100644 (file)
@@ -116,18 +116,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = {
 static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
                                        int state)
 {
-       spin_lock(&stream->status_lock);
+       unsigned long flags;
+       spin_lock_irqsave(&stream->status_lock, flags);
        stream->stream_status = state;
-       spin_unlock(&stream->status_lock);
+       spin_unlock_irqrestore(&stream->status_lock, flags);
 }
 
 static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
 {
        int state;
+       unsigned long flags;
 
-       spin_lock(&stream->status_lock);
+       spin_lock_irqsave(&stream->status_lock, flags);
        state = stream->stream_status;
-       spin_unlock(&stream->status_lock);
+       spin_unlock_irqrestore(&stream->status_lock, flags);
        return state;
 }
 
@@ -374,6 +376,11 @@ static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
 static struct snd_pcm_ops sst_platform_ops = {
        .open = sst_platform_open,
        .close = sst_platform_close,
@@ -382,6 +389,7 @@ static struct snd_pcm_ops sst_platform_ops = {
        .trigger = sst_platform_pcm_trigger,
        .pointer = sst_platform_pcm_pointer,
        .hw_params = sst_platform_pcm_hw_params,
+       .hw_free = sst_platform_pcm_hw_free,
 };
 
 static void sst_pcm_free(struct snd_pcm *pcm)
index f6b3a3ce59196078e11c670c94a417edc1517b5b..0e80daee8b6f5e01c669bbd45fc59a168e51e873 100644 (file)
@@ -236,18 +236,18 @@ static struct snd_soc_dai_link goni_dai[] = {
        .name = "WM8994",
        .stream_name = "WM8994 HiFi",
        .cpu_dai_name = "samsung-i2s.0",
-       .codec_dai_name = "wm8994-hifi",
+       .codec_dai_name = "wm8994-aif1",
        .platform_name = "samsung-audio",
-       .codec_name = "wm8994-codec.0-0x1a",
+       .codec_name = "wm8994-codec.0-001a",
        .init = goni_wm8994_init,
        .ops = &goni_hifi_ops,
 }, {
        .name = "WM8994 Voice",
        .stream_name = "Voice",
        .cpu_dai_name = "goni-voice-dai",
-       .codec_dai_name = "wm8994-voice",
+       .codec_dai_name = "wm8994-aif2",
        .platform_name = "samsung-audio",
-       .codec_name = "wm8994-codec.0-0x1a",
+       .codec_name = "wm8994-codec.0-001a",
        .ops = &goni_voice_ops,
 },
 };
index 38aac7d57a59213a2663cb8bbfab8cacd630fe30..9c7e8b48aed6a4dc2bbc76d1955a5d56025eae9b 100644 (file)
@@ -350,8 +350,8 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
        ctl = readl(regs + S3C_PCM_CTL);
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-       case SND_SOC_DAIFMT_NB_NF:
-               /* Nothing to do, NB_NF by default */
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Nothing to do, IB_NF by default */
                break;
        default:
                dev_err(pcm->dev, "Unsupported clock inversion!\n");
index 0c9997e2d8c05d7407b63cff18b3786ad28b28fa..23c0e83d4c19244dc6da7ec326d10f8bce840b5c 100644 (file)
@@ -1200,10 +1200,11 @@ static int fsi_probe(struct platform_device *pdev)
        master->fsib.master     = master;
 
        pm_runtime_enable(&pdev->dev);
-       pm_runtime_resume(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
 
+       pm_runtime_get_sync(&pdev->dev);
        fsi_soft_all_reset(master);
+       pm_runtime_put_sync(&pdev->dev);
 
        ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
                          id_entry->name, master);
@@ -1218,8 +1219,17 @@ static int fsi_probe(struct platform_device *pdev)
                goto exit_free_irq;
        }
 
-       return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
+       ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
+                                   ARRAY_SIZE(fsi_soc_dai));
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot snd dai register\n");
+               goto exit_snd_soc;
+       }
+
+       return ret;
 
+exit_snd_soc:
+       snd_soc_unregister_platform(&pdev->dev);
 exit_free_irq:
        free_irq(irq, master);
 exit_iounmap:
@@ -1238,12 +1248,11 @@ static int fsi_remove(struct platform_device *pdev)
 
        master = dev_get_drvdata(&pdev->dev);
 
-       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
-       snd_soc_unregister_platform(&pdev->dev);
-
+       free_irq(master->irq, master);
        pm_runtime_disable(&pdev->dev);
 
-       free_irq(master->irq, master);
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
+       snd_soc_unregister_platform(&pdev->dev);
 
        iounmap(master->base);
        kfree(master);
@@ -1321,3 +1330,4 @@ module_exit(fsi_mobile_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
 MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+MODULE_ALIAS("platform:fsi-pcm-audio");
index b76b74db0968d18d360e02aeb59ebc6e802c99fe..dd55d1069468d6a41dd60ae6263f26e3f4efca45 100644 (file)
@@ -629,6 +629,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        runtime->hw.rates |= codec_dai_drv->capture.rates;
        }
 
+       ret = -EINVAL;
        snd_pcm_limit_hw_rates(runtime);
        if (!runtime->hw.rates) {
                printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
@@ -640,7 +641,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        codec_dai->name, cpu_dai->name);
                goto config_err;
        }
-       if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
+       if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
+           runtime->hw.channels_min > runtime->hw.channels_max) {
                printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
                                codec_dai->name, cpu_dai->name);
                goto config_err;
@@ -2060,6 +2062,7 @@ const struct dev_pm_ops snd_soc_pm_ops = {
        .resume = snd_soc_resume,
        .poweroff = snd_soc_poweroff,
 };
+EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
 
 /* ASoC platform driver */
 static struct platform_driver soc_driver = {
@@ -3288,6 +3291,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
        if (!card->name || !card->dev)
                return -EINVAL;
 
+       dev_set_drvdata(card->dev, card);
+
        snd_soc_initialize_card_lists(card);
 
        soc_init_card_debugfs(card);
index 8585957477eb4425f26a7d87d2a33ea36e260d85..556a5713392511cef367595b9d9df3f4cf2abfdc 100644 (file)
@@ -370,6 +370,7 @@ static struct platform_driver tegra_snd_harmony_driver = {
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
        },
        .probe = tegra_snd_harmony_probe,
        .remove = __devexit_p(tegra_snd_harmony_remove),
index 5b792d2c8061aa0292595186d8cf60fadf8456dc..f079b5e2ab287cd0d726216bd6b656fd15c2e6d6 100644 (file)
@@ -176,9 +176,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                        if (!rate)
                                continue;
                        /* C-Media CM6501 mislabels its 96 kHz altsetting */
+                       /* Terratec Aureon 7.1 USB C-Media 6206, too */
                        if (rate == 48000 && nr_rates == 1 &&
                            (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
-                            chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
+                            chip->usb_id == USB_ID(0x0d8c, 0x0102) ||
+                            chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
                            fp->altsetting == 5 && fp->maxpacksize == 392)
                                rate = 96000;
                        /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
index ec07e62e53f317e5751b1dcd7a1427ed3288b6a6..1b94ec3a3368bd01c622f686edc74957cee4d36d 100644 (file)
@@ -533,6 +533,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 
        case USB_ID(0x0d8c, 0x0102):
                /* C-Media CM6206 / CM106-Like Sound Device */
+       case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
                return snd_usb_cm6206_boot_quirk(dev);
 
        case USB_ID(0x133e, 0x0815):
index 5bb41e55a3ac3cbf98d728ec4de3df655d77ff61..3152cca15501b19f2ee4608a418e47c082420cfc 100644 (file)
@@ -63,7 +63,6 @@ The format file for the sched_wakep event defines the following fields
         field:unsigned char common_flags;
         field:unsigned char common_preempt_count;
         field:int common_pid;
-        field:int common_lock_depth;
 
         field:char comm[TASK_COMM_LEN];
         field:pid_t pid;
index 36b38277422c8a9973c3a3fec671271ffeb23ffa..47102206911921be0d956e910d9efa230a65c3f3 100644 (file)
@@ -463,7 +463,6 @@ The format file for the sched_wakep event defines the following fields
         field:unsigned char common_flags;
         field:unsigned char common_preempt_count;
         field:int common_pid;
-        field:int common_lock_depth;
 
         field:char comm[TASK_COMM_LEN];
         field:pid_t pid;
index 66f040b30729d3a3ec0cadab896c1df63160efa1..86c87e214b11d295ed07ce6fa5005f906484d8f7 100644 (file)
@@ -113,13 +113,61 @@ OPTIONS
         Do various checks like samples ordering and lost events.
 
 -f::
---fields
+--fields::
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, sym. Field
-        list must be prepended with the type, trace, sw or hw,
+        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,sym  and -f trace:time,cpu,trace
 
+               perf script -f <fields>
+
+       is equivalent to:
+
+               perf script -f trace:<fields> -f sw:<fields> -f hw:<fields>
+    
+       i.e., the specified fields apply to all event types if the type string
+       is not given.
+    
+       The arguments are processed in the order received. A later usage can
+       reset a prior request. e.g.:
+    
+               -f trace: -f comm,tid,time,sym
+    
+       The first -f suppresses trace events (field list is ""), but then the
+       second invocation sets the fields to comm,tid,time,sym. In this case a
+       warning is given to the user:
+    
+               "Overriding previous field request for all events."
+    
+       Alternativey, consider the order:
+    
+               -f comm,tid,time,sym -f trace:
+    
+       The first -f sets the fields for all events and the second -f
+       suppresses trace events. The user is given a warning message about
+       the override, and the result of the above is that only S/W and H/W
+       events are displayed with the given fields.
+    
+       For the 'wildcard' option if a user selected field is invalid for an
+       event type, a message is displayed to the user that the option is
+       ignored for that type. For example:
+    
+               $ perf script -f comm,tid,trace
+               'trace' not valid for hardware events. Ignoring.
+               'trace' not valid for software events. Ignoring.
+    
+       Alternatively, if the type is given an invalid field is specified it
+       is an error. For example:
+    
+        perf script -v -f sw:comm,tid,trace
+        'trace' not valid for software events.
+    
+       At this point usage is displayed, and perf-script exits.
+    
+       Finally, a user may not set fields to none for all event types.
+       i.e., -f "" is not allowed.
+
 -k::
 --vmlinux=<file>::
         vmlinux pathname
index 207dee5c5b163fd51ceafbb6b171df9c0708893f..1455413ec7a74ed5ebea22c70863fb8dc1545d3c 100644 (file)
@@ -5,6 +5,8 @@ endif
 # The default target of this Makefile is...
 all:
 
+include config/utilities.mak
+
 ifneq ($(OUTPUT),)
 # check that the output directory actually exists
 OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
@@ -13,6 +15,12 @@ endif
 
 # Define V to have a more verbose compile.
 #
+# Define PYTHON to point to the python binary if the default
+# `python' is not correct; for example: PYTHON=python2
+#
+# Define PYTHON_CONFIG to point to the python-config binary if
+# the default `$(PYTHON)-config' is not correct.
+#
 # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
 #
 # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
@@ -35,15 +43,21 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                                  -e s/sh[234].*/sh/ )
 
+CC = $(CROSS_COMPILE)gcc
+AR = $(CROSS_COMPILE)ar
+
 # Additional ARCH settings for x86
 ifeq ($(ARCH),i386)
         ARCH := x86
 endif
 ifeq ($(ARCH),x86_64)
-       RAW_ARCH := x86_64
-        ARCH := x86
-       ARCH_CFLAGS := -DARCH_X86_64
-       ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
+       ARCH := x86
+       IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
+       ifeq (${IS_X86_64}, 1)
+               RAW_ARCH := x86_64
+               ARCH_CFLAGS := -DARCH_X86_64
+               ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
+       endif
 endif
 
 #
@@ -119,8 +133,6 @@ lib = lib
 
 export prefix bindir sharedir sysconfdir
 
-CC = $(CROSS_COMPILE)gcc
-AR = $(CROSS_COMPILE)ar
 RM = rm -f
 MKDIR = mkdir
 FIND = find
@@ -130,7 +142,7 @@ INSTALL = install
 # explicitly what architecture to check for. Fix this up for yours..
 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
--include feature-tests.mak
+-include config/feature-tests.mak
 
 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
        CFLAGS := $(CFLAGS) -fstack-protector-all
@@ -165,12 +177,10 @@ grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
 
 $(OUTPUT)python/perf.so: $(PYRF_OBJS)
-       $(QUIET_GEN)( \
-               export CFLAGS="$(BASIC_CFLAGS)"; \
-               python util/setup.py --quiet  build_ext --build-lib='$(OUTPUT)python' \
-                       --build-temp='$(OUTPUT)python/temp' \
-       )
-
+       $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
+         --quiet build_ext \
+         --build-lib='$(OUTPUT)python' \
+         --build-temp='$(OUTPUT)python/temp'
 #
 # No Perl scripts right now:
 #
@@ -475,24 +485,74 @@ else
        endif
 endif
 
-ifdef NO_LIBPYTHON
-       BASIC_CFLAGS += -DNO_LIBPYTHON
+disable-python = $(eval $(disable-python_code))
+define disable-python_code
+  BASIC_CFLAGS += -DNO_LIBPYTHON
+  $(if $(1),$(warning No $(1) was found))
+  $(warning Python support won't be built)
+endef
+
+override PYTHON := \
+  $(call get-executable-or-default,PYTHON,python)
+
+ifndef PYTHON
+  $(call disable-python,python interpreter)
+  python-clean :=
 else
-       PYTHON_EMBED_LDOPTS = $(shell python-config --ldflags 2>/dev/null)
-       PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
-       PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
-       PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null`
-       FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
-       ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
-               msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings)
-               BASIC_CFLAGS += -DNO_LIBPYTHON
-       else
-               ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
-               EXTLIBS += $(PYTHON_EMBED_LIBADD)
-               LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
-               LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
-               LANG_BINDINGS += $(OUTPUT)python/perf.so
-       endif
+
+  PYTHON_WORD := $(call shell-wordify,$(PYTHON))
+
+  python-clean := $(PYTHON_WORD) util/setup.py clean \
+    --build-lib='$(OUTPUT)python' \
+    --build-temp='$(OUTPUT)python/temp'
+
+  ifdef NO_LIBPYTHON
+    $(call disable-python)
+  else
+
+    override PYTHON_CONFIG := \
+      $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
+
+    ifndef PYTHON_CONFIG
+      $(call disable-python,python-config tool)
+    else
+
+      PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
+
+      PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
+      PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
+      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)
+
+      ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
+        $(call disable-python,Python.h (for Python 2.x))
+      else
+
+        ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y)
+          $(warning Python 3 is not yet supported; please set)
+          $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
+          $(warning If you also have Python 2 installed, then)
+          $(warning try something like:)
+          $(warning $(and ,))
+          $(warning $(and ,)  make PYTHON=python2)
+          $(warning $(and ,))
+          $(warning Otherwise, disable Python support entirely:)
+          $(warning $(and ,))
+          $(warning $(and ,)  make NO_LIBPYTHON=1)
+          $(warning $(and ,))
+          $(error   $(and ,))
+        else
+          ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
+          EXTLIBS += $(PYTHON_EMBED_LIBADD)
+          LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
+          LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
+          LANG_BINDINGS += $(OUTPUT)python/perf.so
+        endif
+
+      endif
+    endif
+  endif
 endif
 
 ifdef NO_DEMANGLE
@@ -833,8 +893,7 @@ clean:
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
        $(MAKE) -C Documentation/ clean
        $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
-       @python util/setup.py clean --build-lib='$(OUTPUT)python' \
-                                  --build-temp='$(OUTPUT)python/temp'
+       $(python-clean)
 
 .PHONY: all install clean strip
 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
index 17d1dcb3c66771cb1d7603cff6a5ed981d44ca69..0974f957b8fa2634409ff46e8de915b1380e87a8 100644 (file)
@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
        struct perf_event_attr *attr = &evsel->attr;
        int track = !evsel->idx; /* only the first counter needs these */
 
+       attr->inherit           = !no_inherit;
        attr->read_format       = PERF_FORMAT_TOTAL_TIME_ENABLED |
                                  PERF_FORMAT_TOTAL_TIME_RUNNING |
                                  PERF_FORMAT_ID;
@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
 {
        struct perf_evsel *pos;
 
+       if (evlist->cpus->map[0] < 0)
+               no_inherit = true;
+
        list_for_each_entry(pos, &evlist->entries, node) {
                struct perf_event_attr *attr = &pos->attr;
                /*
@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
 retry_sample_id:
                attr->sample_id_all = sample_id_all_avail ? 1 : 0;
 try_again:
-               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
-                                    !no_inherit) < 0) {
+               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
@@ -424,7 +427,7 @@ static void mmap_read_all(void)
 {
        int i;
 
-       for (i = 0; i < evsel_list->cpus->nr; i++) {
+       for (i = 0; i < evsel_list->nr_mmaps; i++) {
                if (evsel_list->mmap[i].base)
                        mmap_read(&evsel_list->mmap[i]);
        }
index ac574ea23917e13e8f02c4db33f74a13ee14d825..974f6d3f4e53544b5e408aa64d70f4274ed56845 100644 (file)
@@ -49,57 +49,169 @@ struct output_option {
 };
 
 /* default set to maintain compatibility with current format */
-static u64 output_fields[PERF_TYPE_MAX] = {
-       [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
-                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
-                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
-
-       [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
-                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
-                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
-
-       [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
-                                PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
-                                PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
+static struct {
+       bool user_set;
+       bool wildcard_set;
+       u64 fields;
+       u64 invalid_fields;
+} output[PERF_TYPE_MAX] = {
+
+       [PERF_TYPE_HARDWARE] = {
+               .user_set = false,
+
+               .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+                             PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+
+               .invalid_fields = PERF_OUTPUT_TRACE,
+       },
+
+       [PERF_TYPE_SOFTWARE] = {
+               .user_set = false,
+
+               .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+                             PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+
+               .invalid_fields = PERF_OUTPUT_TRACE,
+       },
+
+       [PERF_TYPE_TRACEPOINT] = {
+               .user_set = false,
+
+               .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+                                 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+                                 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
+       },
+
+       [PERF_TYPE_RAW] = {
+               .user_set = false,
+
+               .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+                             PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+
+               .invalid_fields = PERF_OUTPUT_TRACE,
+       },
 };
 
-static bool output_set_by_user;
+static bool output_set_by_user(void)
+{
+       int j;
+       for (j = 0; j < PERF_TYPE_MAX; ++j) {
+               if (output[j].user_set)
+                       return true;
+       }
+       return false;
+}
+
+static const char *output_field2str(enum perf_output_field field)
+{
+       int i, imax = ARRAY_SIZE(all_output_options);
+       const char *str = "";
+
+       for (i = 0; i < imax; ++i) {
+               if (all_output_options[i].field == field) {
+                       str = all_output_options[i].str;
+                       break;
+               }
+       }
+       return str;
+}
 
-#define PRINT_FIELD(x)  (output_fields[attr->type] & PERF_OUTPUT_##x)
+#define PRINT_FIELD(x)  (output[attr->type].fields & PERF_OUTPUT_##x)
 
-static int perf_session__check_attr(struct perf_session *session,
-                                   struct perf_event_attr *attr)
+static int perf_event_attr__check_stype(struct perf_event_attr *attr,
+                                 u64 sample_type, const char *sample_msg,
+                                 enum perf_output_field field)
 {
+       int type = attr->type;
+       const char *evname;
+
+       if (attr->sample_type & sample_type)
+               return 0;
+
+       if (output[type].user_set) {
+               evname = __event_name(attr->type, attr->config);
+               pr_err("Samples for '%s' event do not have %s attribute set. "
+                      "Cannot print '%s' field.\n",
+                      evname, sample_msg, output_field2str(field));
+               return -1;
+       }
+
+       /* user did not ask for it explicitly so remove from the default list */
+       output[type].fields &= ~field;
+       evname = __event_name(attr->type, attr->config);
+       pr_debug("Samples for '%s' event do not have %s attribute set. "
+                "Skipping '%s' field.\n",
+                evname, sample_msg, output_field2str(field));
+
+       return 0;
+}
+
+static int perf_evsel__check_attr(struct perf_evsel *evsel,
+                                 struct perf_session *session)
+{
+       struct perf_event_attr *attr = &evsel->attr;
+
        if (PRINT_FIELD(TRACE) &&
                !perf_session__has_traces(session, "record -R"))
                return -EINVAL;
 
        if (PRINT_FIELD(SYM)) {
-               if (!(session->sample_type & PERF_SAMPLE_IP)) {
-                       pr_err("Samples do not contain IP data.\n");
+               if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
+                                          PERF_OUTPUT_SYM))
                        return -EINVAL;
-               }
+
                if (!no_callchain &&
-                   !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
+                   !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
                        symbol_conf.use_callchain = false;
        }
 
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
-               !(session->sample_type & PERF_SAMPLE_TID)) {
-               pr_err("Samples do not contain TID/PID data.\n");
+               perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
+                                      PERF_OUTPUT_TID|PERF_OUTPUT_PID))
                return -EINVAL;
-       }
 
        if (PRINT_FIELD(TIME) &&
-               !(session->sample_type & PERF_SAMPLE_TIME)) {
-               pr_err("Samples do not contain timestamps.\n");
+               perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
+                                      PERF_OUTPUT_TIME))
                return -EINVAL;
-       }
 
        if (PRINT_FIELD(CPU) &&
-               !(session->sample_type & PERF_SAMPLE_CPU)) {
-               pr_err("Samples do not contain cpu.\n");
+               perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
+                                      PERF_OUTPUT_CPU))
                return -EINVAL;
+
+       return 0;
+}
+
+/*
+ * verify all user requested events exist and the samples
+ * have the expected data
+ */
+static int perf_session__check_output_opt(struct perf_session *session)
+{
+       int j;
+       struct perf_evsel *evsel;
+
+       for (j = 0; j < PERF_TYPE_MAX; ++j) {
+               evsel = perf_session__find_first_evtype(session, j);
+
+               /*
+                * even if fields is set to 0 (ie., show nothing) event must
+                * exist if user explicitly includes it on the command line
+                */
+               if (!evsel && output[j].user_set && !output[j].wildcard_set) {
+                       pr_err("%s events do not exist. "
+                              "Remove corresponding -f option to proceed.\n",
+                              event_type(j));
+                       return -1;
+               }
+
+               if (evsel && output[j].fields &&
+                       perf_evsel__check_attr(evsel, session))
+                       return -1;
        }
 
        return 0;
@@ -168,10 +280,7 @@ static void process_event(union perf_event *event __unused,
 {
        struct perf_event_attr *attr = &evsel->attr;
 
-       if (output_fields[attr->type] == 0)
-               return;
-
-       if (perf_session__check_attr(session, attr) < 0)
+       if (output[attr->type].fields == 0)
                return;
 
        print_sample_start(sample, thread, attr);
@@ -451,6 +560,7 @@ static int parse_output_fields(const struct option *opt __used,
 {
        char *tok;
        int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
+       int j;
        int rc = 0;
        char *str = strdup(arg);
        int type = -1;
@@ -458,52 +568,99 @@ static int parse_output_fields(const struct option *opt __used,
        if (!str)
                return -ENOMEM;
 
-       tok = strtok(str, ":");
-       if (!tok) {
-               fprintf(stderr,
-                       "Invalid field string - not prepended with type.");
-               return -EINVAL;
-       }
-
-       /* first word should state which event type user
-        * is specifying the fields
+       /* first word can state for which event type the user is specifying
+        * the fields. If no type exists, the specified fields apply to all
+        * event types found in the file minus the invalid fields for a type.
         */
-       if (!strcmp(tok, "hw"))
-               type = PERF_TYPE_HARDWARE;
-       else if (!strcmp(tok, "sw"))
-               type = PERF_TYPE_SOFTWARE;
-       else if (!strcmp(tok, "trace"))
-               type = PERF_TYPE_TRACEPOINT;
-       else {
-               fprintf(stderr, "Invalid event type in field string.");
-               return -EINVAL;
+       tok = strchr(str, ':');
+       if (tok) {
+               *tok = '\0';
+               tok++;
+               if (!strcmp(str, "hw"))
+                       type = PERF_TYPE_HARDWARE;
+               else if (!strcmp(str, "sw"))
+                       type = PERF_TYPE_SOFTWARE;
+               else if (!strcmp(str, "trace"))
+                       type = PERF_TYPE_TRACEPOINT;
+               else if (!strcmp(str, "raw"))
+                       type = PERF_TYPE_RAW;
+               else {
+                       fprintf(stderr, "Invalid event type in field string.\n");
+                       return -EINVAL;
+               }
+
+               if (output[type].user_set)
+                       pr_warning("Overriding previous field request for %s events.\n",
+                                  event_type(type));
+
+               output[type].fields = 0;
+               output[type].user_set = true;
+               output[type].wildcard_set = false;
+
+       } else {
+               tok = str;
+               if (strlen(str) == 0) {
+                       fprintf(stderr,
+                               "Cannot set fields to 'none' for all event types.\n");
+                       rc = -EINVAL;
+                       goto out;
+               }
+
+               if (output_set_by_user())
+                       pr_warning("Overriding previous field request for all events.\n");
+
+               for (j = 0; j < PERF_TYPE_MAX; ++j) {
+                       output[j].fields = 0;
+                       output[j].user_set = true;
+                       output[j].wildcard_set = true;
+               }
        }
 
-       output_fields[type] = 0;
-       while (1) {
-               tok = strtok(NULL, ",");
-               if (!tok)
-                       break;
+       tok = strtok(tok, ",");
+       while (tok) {
                for (i = 0; i < imax; ++i) {
-                       if (strcmp(tok, all_output_options[i].str) == 0) {
-                               output_fields[type] |= all_output_options[i].field;
+                       if (strcmp(tok, all_output_options[i].str) == 0)
                                break;
-                       }
                }
                if (i == imax) {
-                       fprintf(stderr, "Invalid field requested.");
+                       fprintf(stderr, "Invalid field requested.\n");
                        rc = -EINVAL;
-                       break;
+                       goto out;
                }
-       }
 
-       if (output_fields[type] == 0) {
-               pr_debug("No fields requested for %s type. "
-                        "Events will not be displayed\n", event_type(type));
+               if (type == -1) {
+                       /* add user option to all events types for
+                        * which it is valid
+                        */
+                       for (j = 0; j < PERF_TYPE_MAX; ++j) {
+                               if (output[j].invalid_fields & all_output_options[i].field) {
+                                       pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
+                                                  all_output_options[i].str, event_type(j));
+                               } else
+                                       output[j].fields |= all_output_options[i].field;
+                       }
+               } else {
+                       if (output[type].invalid_fields & all_output_options[i].field) {
+                               fprintf(stderr, "\'%s\' not valid for %s events.\n",
+                                        all_output_options[i].str, event_type(type));
+
+                               rc = -EINVAL;
+                               goto out;
+                       }
+                       output[type].fields |= all_output_options[i].field;
+               }
+
+               tok = strtok(NULL, ",");
        }
 
-       output_set_by_user = true;
+       if (type >= 0) {
+               if (output[type].fields == 0) {
+                       pr_debug("No fields requested for %s type. "
+                                "Events will not be displayed.\n", event_type(type));
+               }
+       }
 
+out:
        free(str);
        return rc;
 }
@@ -829,7 +986,7 @@ static const struct option options[] = {
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
        OPT_CALLBACK('f', "fields", NULL, "str",
-                    "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym",
+                    "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym",
                     parse_output_fields),
 
        OPT_END()
@@ -1020,7 +1177,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                struct stat perf_stat;
                int input;
 
-               if (output_set_by_user) {
+               if (output_set_by_user()) {
                        fprintf(stderr,
                                "custom fields not supported for generated scripts");
                        return -1;
@@ -1060,6 +1217,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                pr_debug("perf script started with script %s\n\n", script_name);
        }
 
+
+       err = perf_session__check_output_opt(session);
+       if (err < 0)
+               goto out;
+
        err = __cmd_script(session);
 
        perf_session__delete(session);
index e2109f9b43eb3ed99a5239805087277b229739d3..a9f06715e44d021567131317310bc6096547e666 100644 (file)
@@ -6,24 +6,28 @@
  *
  * Sample output:
 
-   $ perf stat ~/hackbench 10
-   Time: 0.104
+   $ perf stat ./hackbench 10
 
-    Performance counter stats for '/home/mingo/hackbench':
+  Time: 0.118
 
-       1255.538611  task clock ticks     #      10.143 CPU utilization factor
-             54011  context switches     #       0.043 M/sec
-               385  CPU migrations       #       0.000 M/sec
-             17755  pagefaults           #       0.014 M/sec
-        3808323185  CPU cycles           #    3033.219 M/sec
-        1575111190  instructions         #    1254.530 M/sec
-          17367895  cache references     #      13.833 M/sec
-           7674421  cache misses         #       6.112 M/sec
+  Performance counter stats for './hackbench 10':
 
-    Wall-clock time elapsed:   123.786620 msecs
+       1708.761321 task-clock                #   11.037 CPUs utilized
+            41,190 context-switches          #    0.024 M/sec
+             6,735 CPU-migrations            #    0.004 M/sec
+            17,318 page-faults               #    0.010 M/sec
+     5,205,202,243 cycles                    #    3.046 GHz
+     3,856,436,920 stalled-cycles-frontend   #   74.09% frontend cycles idle
+     1,600,790,871 stalled-cycles-backend    #   30.75% backend  cycles idle
+     2,603,501,247 instructions              #    0.50  insns per cycle
+                                             #    1.48  stalled cycles per insn
+       484,357,498 branches                  #  283.455 M/sec
+         6,388,934 branch-misses             #    1.32% of all branches
+
+        0.154822978  seconds time elapsed
 
  *
- * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
+ * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
  *
  * Improvements and fixes by:
  *
@@ -46,6 +50,7 @@
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/debug.h"
+#include "util/color.h"
 #include "util/header.h"
 #include "util/cpumap.h"
 #include "util/thread.h"
@@ -65,14 +70,107 @@ static struct perf_event_attr default_attrs[] = {
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS            },
 
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES             },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND        },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS           },
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS    },
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES          },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES       },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES           },
 
 };
 
+/*
+ * Detailed stats (-d), covering the L1 and last level data caches:
+ */
+static struct perf_event_attr detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_LL                 <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_LL                 <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+};
+
+/*
+ * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
+ */
+static struct perf_event_attr very_detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1I                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1I                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+};
+
+/*
+ * Very, very detailed stats (-d -d -d), adding prefetch events:
+ */
+static struct perf_event_attr very_very_detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+};
+
+
+
 struct perf_evlist             *evsel_list;
 
 static bool                    system_wide                     =  false;
@@ -86,6 +184,8 @@ static pid_t                 target_pid                      = -1;
 static pid_t                   target_tid                      = -1;
 static pid_t                   child_pid                       = -1;
 static bool                    null_run                        =  false;
+static int                     detailed_run                    =  0;
+static bool                    sync_run                        =  false;
 static bool                    big_num                         =  true;
 static int                     big_num_opt                     =  -1;
 static const char              *cpu_list;
@@ -156,7 +256,15 @@ static double stddev_stats(struct stats *stats)
 
 struct stats                   runtime_nsecs_stats[MAX_NR_CPUS];
 struct stats                   runtime_cycles_stats[MAX_NR_CPUS];
+struct stats                   runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
+struct stats                   runtime_stalled_cycles_back_stats[MAX_NR_CPUS];
 struct stats                   runtime_branches_stats[MAX_NR_CPUS];
+struct stats                   runtime_cacherefs_stats[MAX_NR_CPUS];
+struct stats                   runtime_l1_dcache_stats[MAX_NR_CPUS];
+struct stats                   runtime_l1_icache_stats[MAX_NR_CPUS];
+struct stats                   runtime_ll_cache_stats[MAX_NR_CPUS];
+struct stats                   runtime_itlb_cache_stats[MAX_NR_CPUS];
+struct stats                   runtime_dtlb_cache_stats[MAX_NR_CPUS];
 struct stats                   walltime_nsecs_stats;
 
 static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -167,16 +275,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
                attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
                                    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
+       attr->inherit = !no_inherit;
+
        if (system_wide)
-               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
+               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
 
-       attr->inherit = !no_inherit;
        if (target_pid == -1 && target_tid == -1) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
 }
 
 /*
@@ -191,6 +300,37 @@ static inline int nsec_counter(struct perf_evsel *evsel)
        return 0;
 }
 
+/*
+ * Update various tracking values we maintain to print
+ * more semantic information such as miss/hit ratios,
+ * instruction rates, etc:
+ */
+static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
+{
+       if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
+               update_stats(&runtime_nsecs_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
+               update_stats(&runtime_cycles_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
+               update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
+               update_stats(&runtime_stalled_cycles_back_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
+               update_stats(&runtime_branches_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
+               update_stats(&runtime_cacherefs_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
+               update_stats(&runtime_l1_dcache_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
+               update_stats(&runtime_l1_icache_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
+               update_stats(&runtime_ll_cache_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
+               update_stats(&runtime_dtlb_cache_stats[0], count[0]);
+       else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
+               update_stats(&runtime_itlb_cache_stats[0], count[0]);
+}
+
 /*
  * Read out the results of a single counter:
  * aggregate counts across CPUs in system-wide mode
@@ -216,12 +356,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
        /*
         * Save the full runtime - to allow normalization during printout:
         */
-       if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
-               update_stats(&runtime_nsecs_stats[0], count[0]);
-       if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-               update_stats(&runtime_cycles_stats[0], count[0]);
-       if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
-               update_stats(&runtime_branches_stats[0], count[0]);
+       update_shadow_stats(counter, count);
 
        return 0;
 }
@@ -241,12 +376,7 @@ static int read_counter(struct perf_evsel *counter)
 
                count = counter->counts->cpu[cpu].values;
 
-               if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
-                       update_stats(&runtime_nsecs_stats[cpu], count[0]);
-               if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-                       update_stats(&runtime_cycles_stats[cpu], count[0]);
-               if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
-                       update_stats(&runtime_branches_stats[cpu], count[0]);
+               update_shadow_stats(counter, count);
        }
 
        return 0;
@@ -314,13 +444,18 @@ static int run_perf_stat(int argc __used, const char **argv)
 
        list_for_each_entry(counter, &evsel_list->entries, node) {
                if (create_perf_stat_counter(counter) < 0) {
-                       if (errno == -EPERM || errno == -EACCES) {
+                       if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) {
+                               if (verbose)
+                                       ui__warning("%s event is not supported by the kernel.\n",
+                                                   event_name(counter));
+                               continue;
+                       }
+
+                       if (errno == EPERM || errno == EACCES) {
                                error("You may not have permission to collect %sstats.\n"
                                      "\t Consider tweaking"
                                      " /proc/sys/kernel/perf_event_paranoid or running as root.",
                                      system_wide ? "system-wide " : "");
-                       } else if (errno == ENOENT) {
-                               error("%s event is not supported. ", event_name(counter));
                        } else {
                                error("open_counter returned with %d (%s). "
                                      "/bin/dmesg may provide additional information.\n",
@@ -371,6 +506,16 @@ static int run_perf_stat(int argc __used, const char **argv)
        return WEXITSTATUS(status);
 }
 
+static void print_noise_pct(double total, double avg)
+{
+       double pct = 0.0;
+
+       if (avg)
+               pct = 100.0*total/avg;
+
+       fprintf(stderr, "  ( +-%6.2f%% )", pct);
+}
+
 static void print_noise(struct perf_evsel *evsel, double avg)
 {
        struct perf_stat *ps;
@@ -379,15 +524,14 @@ static void print_noise(struct perf_evsel *evsel, double avg)
                return;
 
        ps = evsel->priv;
-       fprintf(stderr, "   ( +- %7.3f%% )",
-                       100 * stddev_stats(&ps->res_stats[0]) / avg);
+       print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
 }
 
 static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
 {
        double msecs = avg / 1e6;
        char cpustr[16] = { '\0', };
-       const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
+       const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s";
 
        if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
@@ -403,8 +547,191 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
                return;
 
        if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
-               fprintf(stderr, " # %10.3f CPUs ",
-                               avg / avg_stats(&walltime_nsecs_stats));
+               fprintf(stderr, " # %8.3f CPUs utilized          ", avg / avg_stats(&walltime_nsecs_stats));
+}
+
+static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_cycles_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 50.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 30.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " frontend cycles idle   ");
+}
+
+static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_cycles_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 75.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 50.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 20.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " backend  cycles idle   ");
+}
+
+static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_branches_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all branches        ");
+}
+
+static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_l1_dcache_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all L1-dcache hits  ");
+}
+
+static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_l1_icache_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all L1-icache hits  ");
+}
+
+static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_dtlb_cache_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all dTLB cache hits ");
+}
+
+static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_itlb_cache_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all iTLB cache hits ");
+}
+
+static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
+{
+       double total, ratio = 0.0;
+       const char *color;
+
+       total = avg_stats(&runtime_ll_cache_stats[cpu]);
+
+       if (total)
+               ratio = avg / total * 100.0;
+
+       color = PERF_COLOR_NORMAL;
+       if (ratio > 20.0)
+               color = PERF_COLOR_RED;
+       else if (ratio > 10.0)
+               color = PERF_COLOR_MAGENTA;
+       else if (ratio > 5.0)
+               color = PERF_COLOR_YELLOW;
+
+       fprintf(stderr, " #  ");
+       color_fprintf(stderr, color, "%6.2f%%", ratio);
+       fprintf(stderr, " of all LL-cache hits   ");
 }
 
 static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
@@ -416,9 +743,9 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        if (csv_output)
                fmt = "%s%.0f%s%s";
        else if (big_num)
-               fmt = "%s%'18.0f%s%-24s";
+               fmt = "%s%'18.0f%s%-25s";
        else
-               fmt = "%s%18.0f%s%-24s";
+               fmt = "%s%18.0f%s%-25s";
 
        if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
@@ -441,23 +768,83 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
                if (total)
                        ratio = avg / total;
 
-               fprintf(stderr, " # %10.3f IPC  ", ratio);
+               fprintf(stderr, " #   %5.2f  insns per cycle        ", ratio);
+
+               total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
+               total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
+
+               if (total && avg) {
+                       ratio = total / avg;
+                       fprintf(stderr, "\n                                             #   %5.2f  stalled cycles per insn", ratio);
+               }
+
        } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
                        runtime_branches_stats[cpu].n != 0) {
-               total = avg_stats(&runtime_branches_stats[cpu]);
+               print_branch_misses(cpu, evsel, avg);
+       } else if (
+               evsel->attr.type == PERF_TYPE_HW_CACHE &&
+               evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
+                                       ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
+                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
+                       runtime_l1_dcache_stats[cpu].n != 0) {
+               print_l1_dcache_misses(cpu, evsel, avg);
+       } else if (
+               evsel->attr.type == PERF_TYPE_HW_CACHE &&
+               evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
+                                       ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
+                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
+                       runtime_l1_icache_stats[cpu].n != 0) {
+               print_l1_icache_misses(cpu, evsel, avg);
+       } else if (
+               evsel->attr.type == PERF_TYPE_HW_CACHE &&
+               evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
+                                       ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
+                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
+                       runtime_dtlb_cache_stats[cpu].n != 0) {
+               print_dtlb_cache_misses(cpu, evsel, avg);
+       } else if (
+               evsel->attr.type == PERF_TYPE_HW_CACHE &&
+               evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
+                                       ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
+                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
+                       runtime_itlb_cache_stats[cpu].n != 0) {
+               print_itlb_cache_misses(cpu, evsel, avg);
+       } else if (
+               evsel->attr.type == PERF_TYPE_HW_CACHE &&
+               evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
+                                       ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
+                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
+                       runtime_ll_cache_stats[cpu].n != 0) {
+               print_ll_cache_misses(cpu, evsel, avg);
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
+                       runtime_cacherefs_stats[cpu].n != 0) {
+               total = avg_stats(&runtime_cacherefs_stats[cpu]);
 
                if (total)
                        ratio = avg * 100 / total;
 
-               fprintf(stderr, " # %10.3f %%    ", ratio);
+               fprintf(stderr, " # %8.3f %% of all cache refs    ", ratio);
 
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
+               print_stalled_cycles_frontend(cpu, evsel, avg);
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
+               print_stalled_cycles_backend(cpu, evsel, avg);
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
+               total = avg_stats(&runtime_nsecs_stats[cpu]);
+
+               if (total)
+                       ratio = 1.0 * avg / total;
+
+               fprintf(stderr, " # %8.3f GHz                    ", ratio);
        } else if (runtime_nsecs_stats[cpu].n != 0) {
                total = avg_stats(&runtime_nsecs_stats[cpu]);
 
                if (total)
                        ratio = 1000.0 * avg / total;
 
-               fprintf(stderr, " # %10.3f M/sec", ratio);
+               fprintf(stderr, " # %8.3f M/sec                  ", ratio);
+       } else {
+               fprintf(stderr, "                                   ");
        }
 }
 
@@ -504,8 +891,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
                avg_enabled = avg_stats(&ps->res_stats[1]);
                avg_running = avg_stats(&ps->res_stats[2]);
 
-               fprintf(stderr, "  (scaled from %.2f%%)",
-                               100 * avg_running / avg_enabled);
+               fprintf(stderr, " [%5.2f%%]", 100 * avg_running / avg_enabled);
        }
        fprintf(stderr, "\n");
 }
@@ -547,10 +933,8 @@ static void print_counter(struct perf_evsel *counter)
                if (!csv_output) {
                        print_noise(counter, 1.0);
 
-                       if (run != ena) {
-                               fprintf(stderr, "  (scaled from %.2f%%)",
-                                       100.0 * run / ena);
-                       }
+                       if (run != ena)
+                               fprintf(stderr, "  (%.2f%%)", 100.0 * run / ena);
                }
                fputc('\n', stderr);
        }
@@ -590,13 +974,14 @@ static void print_stat(int argc, const char **argv)
        }
 
        if (!csv_output) {
-               fprintf(stderr, "\n");
-               fprintf(stderr, " %18.9f  seconds time elapsed",
+               if (!null_run)
+                       fprintf(stderr, "\n");
+               fprintf(stderr, " %17.9f seconds time elapsed",
                                avg_stats(&walltime_nsecs_stats)/1e9);
                if (run_count > 1) {
-                       fprintf(stderr, "   ( +- %7.3f%% )",
-                               100*stddev_stats(&walltime_nsecs_stats) /
-                               avg_stats(&walltime_nsecs_stats));
+                       fprintf(stderr, "                                        ");
+                       print_noise_pct(stddev_stats(&walltime_nsecs_stats),
+                                       avg_stats(&walltime_nsecs_stats));
                }
                fprintf(stderr, "\n\n");
        }
@@ -658,6 +1043,10 @@ static const struct option options[] = {
                    "repeat command and print average + stddev (max: 100)"),
        OPT_BOOLEAN('n', "null", &null_run,
                    "null run - dont start any counters"),
+       OPT_INCR('d', "detailed", &detailed_run,
+                   "detailed run - start a lot of events"),
+       OPT_BOOLEAN('S', "sync", &sync_run,
+                   "call sync() before starting a run"),
        OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
                           "print large numbers with thousands\' separators",
                           stat__set_big_num),
@@ -673,6 +1062,70 @@ static const struct option options[] = {
        OPT_END()
 };
 
+/*
+ * Add default attributes, if there were no attributes specified or
+ * if -d/--detailed, -d -d or -d -d -d is used:
+ */
+static int add_default_attributes(void)
+{
+       struct perf_evsel *pos;
+       size_t attr_nr = 0;
+       size_t c;
+
+       /* Set attrs if no event is selected and !null_run: */
+       if (null_run)
+               return 0;
+
+       if (!evsel_list->nr_entries) {
+               for (c = 0; c < ARRAY_SIZE(default_attrs); c++) {
+                       pos = perf_evsel__new(default_attrs + c, c + attr_nr);
+                       if (pos == NULL)
+                               return -1;
+                       perf_evlist__add(evsel_list, pos);
+               }
+               attr_nr += c;
+       }
+
+       /* Detailed events get appended to the event list: */
+
+       if (detailed_run <  1)
+               return 0;
+
+       /* Append detailed run extra attributes: */
+       for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) {
+               pos = perf_evsel__new(detailed_attrs + c, c + attr_nr);
+               if (pos == NULL)
+                       return -1;
+               perf_evlist__add(evsel_list, pos);
+       }
+       attr_nr += c;
+
+       if (detailed_run < 2)
+               return 0;
+
+       /* Append very detailed run extra attributes: */
+       for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) {
+               pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr);
+               if (pos == NULL)
+                       return -1;
+               perf_evlist__add(evsel_list, pos);
+       }
+
+       if (detailed_run < 3)
+               return 0;
+
+       /* Append very, very detailed run extra attributes: */
+       for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) {
+               pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr);
+               if (pos == NULL)
+                       return -1;
+               perf_evlist__add(evsel_list, pos);
+       }
+
+
+       return 0;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __used)
 {
        struct perf_evsel *pos;
@@ -718,17 +1171,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
                usage_with_options(stat_usage, options);
        }
 
-       /* Set attrs and nr_counters if no event is selected and !null_run */
-       if (!null_run && !evsel_list->nr_entries) {
-               size_t c;
-
-               for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
-                       pos = perf_evsel__new(&default_attrs[c], c);
-                       if (pos == NULL)
-                               goto out;
-                       perf_evlist__add(evsel_list, pos);
-               }
-       }
+       if (add_default_attributes())
+               goto out;
 
        if (target_pid != -1)
                target_tid = target_pid;
@@ -772,6 +1216,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
        for (run_idx = 0; run_idx < run_count; run_idx++) {
                if (run_count != 1 && verbose)
                        fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
+
+               if (sync_run)
+                       sync();
+
                status = run_perf_stat(argc, argv);
        }
 
index 1b2106c58f660c83a858636df0862c458d127eb8..2f9a337b182fe98e66a70128a6661c2be3e0342c 100644 (file)
@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) {
+       if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
        }
 
        if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
-               pr_debug("perf_evsel__open_read_on_cpu\n");
+               pr_debug("perf_evsel__read_on_cpu\n");
                goto out_close_fd;
        }
 
@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) {
+       if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
                        continue;
 
                if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
-                       pr_debug("perf_evsel__open_read_on_cpu\n");
+                       pr_debug("perf_evsel__read_on_cpu\n");
                        err = -1;
                        break;
                }
@@ -529,7 +529,7 @@ static int test__basic_mmap(void)
 
                perf_evlist__add(evlist, evsels[i]);
 
-               if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) {
+               if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
                        pr_debug("failed to open counter: %s, "
                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                                 strerror(errno));
@@ -549,7 +549,7 @@ static int test__basic_mmap(void)
                        ++foo;
                }
 
-       while ((event = perf_evlist__read_on_cpu(evlist, 0)) != NULL) {
+       while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
                struct perf_sample sample;
 
                if (event->header.type != PERF_RECORD_SAMPLE) {
index fc1273e976c58f4c25d6321abf578392ba1126ad..ebfc7cf5f63bd94256165ed1d5b2a5f2e1c25ee0 100644 (file)
@@ -801,12 +801,12 @@ static void perf_event__process_sample(const union perf_event *event,
        }
 }
 
-static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu)
+static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 {
        struct perf_sample sample;
        union perf_event *event;
 
-       while ((event = perf_evlist__read_on_cpu(top.evlist, cpu)) != NULL) {
+       while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) {
                perf_session__parse_sample(self, event, &sample);
 
                if (event->header.type == PERF_RECORD_SAMPLE)
@@ -820,8 +820,8 @@ static void perf_session__mmap_read(struct perf_session *self)
 {
        int i;
 
-       for (i = 0; i < top.evlist->cpus->nr; i++)
-               perf_session__mmap_read_cpu(self, i);
+       for (i = 0; i < top.evlist->nr_mmaps; i++)
+               perf_session__mmap_read_idx(self, i);
 }
 
 static void start_counters(struct perf_evlist *evlist)
@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
                }
 
                attr->mmap = 1;
+               attr->inherit = inherit;
 try_again:
                if (perf_evsel__open(counter, top.evlist->cpus,
-                                    top.evlist->threads, group, inherit) < 0) {
+                                    top.evlist->threads, group) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
similarity index 86%
rename from tools/perf/feature-tests.mak
rename to tools/perf/config/feature-tests.mak
index b041ca67a2cbdee01c87ff92ec21deda82ae1b5c..6170fd2531b5e681ca1986fa0b231d3b3029382b 100644 (file)
@@ -79,9 +79,15 @@ endef
 endif
 
 ifndef NO_LIBPYTHON
+define SOURCE_PYTHON_VERSION
+#include <Python.h>
+#if PY_VERSION_HEX >= 0x03000000
+       #error
+#endif
+int main(void){}
+endef
 define SOURCE_PYTHON_EMBED
 #include <Python.h>
-
 int main(void)
 {
        Py_Initialize();
@@ -120,11 +126,3 @@ int main(void)
        return 0;
 }
 endef
-
-# try-cc
-# Usage: option = $(call try-cc, source-to-build, cc-options)
-try-cc = $(shell sh -c                                           \
-       'TMP="$(OUTPUT)$(TMPOUT).$$$$";                           \
-        echo "$(1)" |                                            \
-        $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
-        rm -f "$$TMP"')
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
new file mode 100644 (file)
index 0000000..8046182
--- /dev/null
@@ -0,0 +1,188 @@
+# This allows us to work with the newline character:
+define newline
+
+
+endef
+newline := $(newline)
+
+# nl-escape
+#
+# Usage: escape = $(call nl-escape[,escape])
+#
+# This is used as the common way to specify
+# what should replace a newline when escaping
+# newlines; the default is a bizarre string.
+#
+nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n)
+
+# escape-nl
+#
+# Usage: escaped-text = $(call escape-nl,text[,escape])
+#
+# GNU make's $(shell ...) function converts to a
+# single space each newline character in the output
+# produced during the expansion; this may not be
+# desirable.
+#
+# The only solution is to change each newline into
+# something that won't be converted, so that the
+# information can be recovered later with
+# $(call unescape-nl...)
+#
+escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1))
+
+# unescape-nl
+#
+# Usage: text = $(call unescape-nl,escaped-text[,escape])
+#
+# See escape-nl.
+#
+unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1))
+
+# shell-escape-nl
+#
+# Usage: $(shell some-command | $(call shell-escape-nl[,escape]))
+#
+# Use this to escape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as a string constant
+#       in an `awk' program that is delimited by shell
+#       single-quotes, so be wary of the characters
+#       that are chosen.
+#
+define shell-escape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}'
+endef
+
+# shell-unescape-nl
+#
+# Usage: $(shell some-command | $(call shell-unescape-nl[,escape]))
+#
+# Use this to unescape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as an extended regular
+#       expression constant in an `awk' program that is
+#       delimited by shell single-quotes, so be wary
+#       of the characters that are chosen.
+#
+# (The bash shell has a bug where `{gsub(...),...}' is
+#  misinterpreted as a brace expansion; this can be
+#  overcome by putting a space between `{' and `gsub').
+#
+define shell-unescape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }'
+endef
+
+# escape-for-shell-sq
+#
+# Usage: embeddable-text = $(call escape-for-shell-sq,text)
+#
+# This function produces text that is suitable for
+# embedding in a shell string that is delimited by
+# single-quotes.
+#
+escape-for-shell-sq =  $(subst ','\'',$(1))
+
+# shell-sq
+#
+# Usage: single-quoted-and-escaped-text = $(call shell-sq,text)
+#
+shell-sq = '$(escape-for-shell-sq)'
+
+# shell-wordify
+#
+# Usage: wordified-text = $(call shell-wordify,text)
+#
+# For instance:
+#
+#  |define text
+#  |hello
+#  |world
+#  |endef
+#  |
+#  |target:
+#  |   echo $(call shell-wordify,$(text))
+#
+# At least GNU make gets confused by expanding a newline
+# within the context of a command line of a makefile rule
+# (this is in constrast to a `$(shell ...)' function call,
+# which can handle it just fine).
+#
+# This function avoids the problem by producing a string
+# that works as a shell word, regardless of whether or
+# not it contains a newline.
+#
+# If the text to be wordified contains a newline, then
+# an intrictate shell command substitution is constructed
+# to render the text as a single line; when the shell
+# processes the resulting escaped text, it transforms
+# it into the original unescaped text.
+#
+# If the text does not contain a newline, then this function
+# produces the same results as the `$(shell-sq)' function.
+#
+shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq))
+define _sw-esc-nl
+"$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))"
+endef
+
+# is-absolute
+#
+# Usage: bool-value = $(call is-absolute,path)
+#
+is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y)
+
+# lookup
+#
+# Usage: absolute-executable-path-or-empty = $(call lookup,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+lookup = $(call unescape-nl,$(shell sh -c $(_l-sh)))
+_l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,))
+
+# is-executable
+#
+# Usage: bool-value = $(call is-executable,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+is-executable = $(call _is-executable-helper,$(shell-sq))
+_is-executable-helper = $(shell sh -c $(_is-executable-sh))
+_is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y)
+
+# get-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable,path)
+#
+# The goal is to get an absolute path for an executable;
+# the `command -v' is defined by POSIX, but it's not
+# necessarily very portable, so it's only used if
+# relative path resolution is requested, as determined
+# by the presence of a leading `/'.
+#
+get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup)))
+_ge-abspath = $(if $(is-executable),$(1))
+
+# get-supplied-or-default-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
+#
+define get-executable-or-default
+$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
+endef
+_ge_attempt = $(or $(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))
+
+# try-cc
+# Usage: option = $(call try-cc, source-to-build, cc-options)
+try-cc = $(shell sh -c                                           \
+       'TMP="$(OUTPUT)$(TMPOUT).$$$$";                           \
+        echo "$(1)" |                                            \
+        $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
+        rm -f "$$TMP"')
index d852cefa20def5ff48665e7ef44bc842093f6f49..23eb22b05d271bf2d317bffde819ceecd790a318 100644 (file)
@@ -12,6 +12,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "util.h"
+#include "debug.h"
 
 #include <sys/mman.h>
 
@@ -165,11 +166,11 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
        return NULL;
 }
 
-union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu)
+union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 {
        /* XXX Move this to perf.c, making it generally available */
        unsigned int page_size = sysconf(_SC_PAGE_SIZE);
-       struct perf_mmap *md = &evlist->mmap[cpu];
+       struct perf_mmap *md = &evlist->mmap[idx];
        unsigned int head = perf_mmap__read_head(md);
        unsigned int old = md->prev;
        unsigned char *data = md->base + page_size;
@@ -234,36 +235,126 @@ union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu)
 
 void perf_evlist__munmap(struct perf_evlist *evlist)
 {
-       int cpu;
+       int i;
 
-       for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
-               if (evlist->mmap[cpu].base != NULL) {
-                       munmap(evlist->mmap[cpu].base, evlist->mmap_len);
-                       evlist->mmap[cpu].base = NULL;
+       for (i = 0; i < evlist->nr_mmaps; i++) {
+               if (evlist->mmap[i].base != NULL) {
+                       munmap(evlist->mmap[i].base, evlist->mmap_len);
+                       evlist->mmap[i].base = NULL;
                }
        }
+
+       free(evlist->mmap);
+       evlist->mmap = NULL;
 }
 
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
 {
-       evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap));
+       evlist->nr_mmaps = evlist->cpus->nr;
+       if (evlist->cpus->map[0] == -1)
+               evlist->nr_mmaps = evlist->threads->nr;
+       evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
        return evlist->mmap != NULL ? 0 : -ENOMEM;
 }
 
-static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
-                              int mask, int fd)
+static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
+                              int idx, int prot, int mask, int fd)
 {
-       evlist->mmap[cpu].prev = 0;
-       evlist->mmap[cpu].mask = mask;
-       evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
+       evlist->mmap[idx].prev = 0;
+       evlist->mmap[idx].mask = mask;
+       evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
                                      MAP_SHARED, fd, 0);
-       if (evlist->mmap[cpu].base == MAP_FAILED)
+       if (evlist->mmap[idx].base == MAP_FAILED) {
+               if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit)
+                       ui__warning("Inherit is not allowed on per-task "
+                                   "events using mmap.\n");
                return -1;
+       }
 
        perf_evlist__add_pollfd(evlist, fd);
        return 0;
 }
 
+static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask)
+{
+       struct perf_evsel *evsel;
+       int cpu, thread;
+
+       for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
+               int output = -1;
+
+               for (thread = 0; thread < evlist->threads->nr; thread++) {
+                       list_for_each_entry(evsel, &evlist->entries, node) {
+                               int fd = FD(evsel, cpu, thread);
+
+                               if (output == -1) {
+                                       output = fd;
+                                       if (__perf_evlist__mmap(evlist, evsel, cpu,
+                                                               prot, mask, output) < 0)
+                                               goto out_unmap;
+                               } else {
+                                       if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
+                                               goto out_unmap;
+                               }
+
+                               if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+                                   perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
+                                       goto out_unmap;
+                       }
+               }
+       }
+
+       return 0;
+
+out_unmap:
+       for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
+               if (evlist->mmap[cpu].base != NULL) {
+                       munmap(evlist->mmap[cpu].base, evlist->mmap_len);
+                       evlist->mmap[cpu].base = NULL;
+               }
+       }
+       return -1;
+}
+
+static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask)
+{
+       struct perf_evsel *evsel;
+       int thread;
+
+       for (thread = 0; thread < evlist->threads->nr; thread++) {
+               int output = -1;
+
+               list_for_each_entry(evsel, &evlist->entries, node) {
+                       int fd = FD(evsel, 0, thread);
+
+                       if (output == -1) {
+                               output = fd;
+                               if (__perf_evlist__mmap(evlist, evsel, thread,
+                                                       prot, mask, output) < 0)
+                                       goto out_unmap;
+                       } else {
+                               if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
+                                       goto out_unmap;
+                       }
+
+                       if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+                           perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
+                               goto out_unmap;
+               }
+       }
+
+       return 0;
+
+out_unmap:
+       for (thread = 0; thread < evlist->threads->nr; thread++) {
+               if (evlist->mmap[thread].base != NULL) {
+                       munmap(evlist->mmap[thread].base, evlist->mmap_len);
+                       evlist->mmap[thread].base = NULL;
+               }
+       }
+       return -1;
+}
+
 /** perf_evlist__mmap - Create per cpu maps to receive events
  *
  * @evlist - list of events
@@ -282,11 +373,11 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
 {
        unsigned int page_size = sysconf(_SC_PAGE_SIZE);
-       int mask = pages * page_size - 1, cpu;
-       struct perf_evsel *first_evsel, *evsel;
+       int mask = pages * page_size - 1;
+       struct perf_evsel *evsel;
        const struct cpu_map *cpus = evlist->cpus;
        const struct thread_map *threads = evlist->threads;
-       int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
+       int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
 
        if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
                return -ENOMEM;
@@ -296,42 +387,18 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
 
        evlist->overwrite = overwrite;
        evlist->mmap_len = (pages + 1) * page_size;
-       first_evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
 
        list_for_each_entry(evsel, &evlist->entries, node) {
                if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
                    evsel->sample_id == NULL &&
                    perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)
                        return -ENOMEM;
-
-               for (cpu = 0; cpu < cpus->nr; cpu++) {
-                       for (thread = 0; thread < threads->nr; thread++) {
-                               int fd = FD(evsel, cpu, thread);
-
-                               if (evsel->idx || thread) {
-                                       if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
-                                                 FD(first_evsel, cpu, 0)) != 0)
-                                               goto out_unmap;
-                               } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0)
-                                       goto out_unmap;
-
-                               if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
-                                   perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
-                                       goto out_unmap;
-                       }
-               }
        }
 
-       return 0;
+       if (evlist->cpus->map[0] == -1)
+               return perf_evlist__mmap_per_thread(evlist, prot, mask);
 
-out_unmap:
-       for (cpu = 0; cpu < cpus->nr; cpu++) {
-               if (evlist->mmap[cpu].base != NULL) {
-                       munmap(evlist->mmap[cpu].base, evlist->mmap_len);
-                       evlist->mmap[cpu].base = NULL;
-               }
-       }
-       return -1;
+       return perf_evlist__mmap_per_cpu(evlist, prot, mask);
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
@@ -342,7 +409,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
        if (evlist->threads == NULL)
                return -1;
 
-       if (target_tid != -1)
+       if (cpu_list == NULL && target_tid != -1)
                evlist->cpus = cpu_map__dummy_new();
        else
                evlist->cpus = cpu_map__new(cpu_list);
index 8b1cb7a4c5f1edbe2d5b3beafce04d2b0606049e..7109d7add14e8ae782e63096b343efd167dfeec4 100644 (file)
@@ -17,6 +17,7 @@ struct perf_evlist {
        struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
        int              nr_entries;
        int              nr_fds;
+       int              nr_mmaps;
        int              mmap_len;
        bool             overwrite;
        union perf_event event_copy;
@@ -46,7 +47,7 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
 
 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
 
-union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu);
+union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
 
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
index 662596afd7f1d49fccaeb8c95ee7c8c64748b8c9..d6fd59beb860739aea40e1b4052f6eda1a741996 100644 (file)
@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel,
 }
 
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                             struct thread_map *threads, bool group, bool inherit)
+                             struct thread_map *threads, bool group)
 {
        int cpu, thread;
        unsigned long flags = 0;
@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 
        for (cpu = 0; cpu < cpus->nr; cpu++) {
                int group_fd = -1;
-               /*
-                * Don't allow mmap() of inherited per-task counters. This
-                * would create a performance issue due to all children writing
-                * to the same buffer.
-                *
-                * FIXME:
-                * Proper fix is not to pass 'inherit' to perf_evsel__open*,
-                * but a 'flags' parameter, with 'group' folded there as well,
-                * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
-                * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
-                * set. Lets go for the minimal fix first tho.
-                */
-               evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
 
                for (thread = 0; thread < threads->nr; thread++) {
 
@@ -253,7 +240,7 @@ static struct {
 };
 
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group, bool inherit)
+                    struct thread_map *threads, bool group)
 {
        if (cpus == NULL) {
                /* Work around old compiler warnings about strict aliasing */
@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
        if (threads == NULL)
                threads = &empty_thread_map.map;
 
-       return __perf_evsel__open(evsel, cpus, threads, group, inherit);
+       return __perf_evsel__open(evsel, cpus, threads, group);
 }
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group, bool inherit)
+                            struct cpu_map *cpus, bool group)
 {
-       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit);
+       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
 }
 
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group, bool inherit)
+                               struct thread_map *threads, bool group)
 {
-       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit);
+       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
 }
 
 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
index 6710ab538342fe1d5970c812423908ddec3ee5a7..f79bb2c09a6cbea510e31d260a1fabb778e13950 100644 (file)
@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group, bool inherit);
+                            struct cpu_map *cpus, bool group);
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group, bool inherit);
+                               struct thread_map *threads, bool group);
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group, bool inherit);
+                    struct thread_map *threads, bool group);
 
 #define perf_evsel__match(evsel, t, c)         \
        (evsel->attr.type == PERF_TYPE_##t &&   \
diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h
new file mode 100644 (file)
index 0000000..6789d78
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _PERF_ASM_ALTERNATIVE_ASM_H
+#define _PERF_ASM_ALTERNATIVE_ASM_H
+
+/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
+
+#define altinstruction_entry #
+
+#endif
index 952b4ae3d954f36c2a85ec9db2d4908e44a91188..41982c373faf2a075f9bbba9bedcd62cc402e0b8 100644 (file)
@@ -31,34 +31,36 @@ char debugfs_path[MAXPATHLEN];
 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
 static struct event_symbol event_symbols[] = {
-  { CHW(CPU_CYCLES),           "cpu-cycles",           "cycles"        },
-  { CHW(INSTRUCTIONS),         "instructions",         ""              },
-  { CHW(CACHE_REFERENCES),     "cache-references",     ""              },
-  { CHW(CACHE_MISSES),         "cache-misses",         ""              },
-  { CHW(BRANCH_INSTRUCTIONS),  "branch-instructions",  "branches"      },
-  { CHW(BRANCH_MISSES),                "branch-misses",        ""              },
-  { CHW(BUS_CYCLES),           "bus-cycles",           ""              },
-
-  { CSW(CPU_CLOCK),            "cpu-clock",            ""              },
-  { CSW(TASK_CLOCK),           "task-clock",           ""              },
-  { CSW(PAGE_FAULTS),          "page-faults",          "faults"        },
-  { CSW(PAGE_FAULTS_MIN),      "minor-faults",         ""              },
-  { CSW(PAGE_FAULTS_MAJ),      "major-faults",         ""              },
-  { CSW(CONTEXT_SWITCHES),     "context-switches",     "cs"            },
-  { CSW(CPU_MIGRATIONS),       "cpu-migrations",       "migrations"    },
-  { CSW(ALIGNMENT_FAULTS),     "alignment-faults",     ""              },
-  { CSW(EMULATION_FAULTS),     "emulation-faults",     ""              },
+  { CHW(CPU_CYCLES),                   "cpu-cycles",                   "cycles"                },
+  { CHW(STALLED_CYCLES_FRONTEND),      "stalled-cycles-frontend",      "idle-cycles-frontend"  },
+  { CHW(STALLED_CYCLES_BACKEND),       "stalled-cycles-backend",       "idle-cycles-backend"   },
+  { CHW(INSTRUCTIONS),                 "instructions",                 ""                      },
+  { CHW(CACHE_REFERENCES),             "cache-references",             ""                      },
+  { CHW(CACHE_MISSES),                 "cache-misses",                 ""                      },
+  { CHW(BRANCH_INSTRUCTIONS),          "branch-instructions",          "branches"              },
+  { CHW(BRANCH_MISSES),                        "branch-misses",                ""                      },
+  { CHW(BUS_CYCLES),                   "bus-cycles",                   ""                      },
+
+  { CSW(CPU_CLOCK),                    "cpu-clock",                    ""                      },
+  { CSW(TASK_CLOCK),                   "task-clock",                   ""                      },
+  { CSW(PAGE_FAULTS),                  "page-faults",                  "faults"                },
+  { CSW(PAGE_FAULTS_MIN),              "minor-faults",                 ""                      },
+  { CSW(PAGE_FAULTS_MAJ),              "major-faults",                 ""                      },
+  { CSW(CONTEXT_SWITCHES),             "context-switches",             "cs"                    },
+  { CSW(CPU_MIGRATIONS),               "cpu-migrations",               "migrations"            },
+  { CSW(ALIGNMENT_FAULTS),             "alignment-faults",             ""                      },
+  { CSW(EMULATION_FAULTS),             "emulation-faults",             ""                      },
 };
 
 #define __PERF_EVENT_FIELD(config, name) \
        ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
 
-#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
+#define PERF_EVENT_RAW(config)         __PERF_EVENT_FIELD(config, RAW)
 #define PERF_EVENT_CONFIG(config)      __PERF_EVENT_FIELD(config, CONFIG)
-#define PERF_EVENT_TYPE(config)        __PERF_EVENT_FIELD(config, TYPE)
+#define PERF_EVENT_TYPE(config)                __PERF_EVENT_FIELD(config, TYPE)
 #define PERF_EVENT_ID(config)          __PERF_EVENT_FIELD(config, EVENT)
 
-static const char *hw_event_names[] = {
+static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
        "cycles",
        "instructions",
        "cache-references",
@@ -66,11 +68,13 @@ static const char *hw_event_names[] = {
        "branches",
        "branch-misses",
        "bus-cycles",
+       "stalled-cycles-frontend",
+       "stalled-cycles-backend",
 };
 
-static const char *sw_event_names[] = {
-       "cpu-clock-msecs",
-       "task-clock-msecs",
+static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
+       "cpu-clock",
+       "task-clock",
        "page-faults",
        "context-switches",
        "CPU-migrations",
@@ -307,7 +311,7 @@ const char *__event_name(int type, u64 config)
 
        switch (type) {
        case PERF_TYPE_HARDWARE:
-               if (config < PERF_COUNT_HW_MAX)
+               if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
                        return hw_event_names[config];
                return "unknown-hardware";
 
@@ -333,7 +337,7 @@ const char *__event_name(int type, u64 config)
        }
 
        case PERF_TYPE_SOFTWARE:
-               if (config < PERF_COUNT_SW_MAX)
+               if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
                        return sw_event_names[config];
                return "unknown-software";
 
@@ -648,13 +652,15 @@ static int check_events(const char *str, unsigned int i)
        int n;
 
        n = strlen(event_symbols[i].symbol);
-       if (!strncmp(str, event_symbols[i].symbol, n))
+       if (!strncasecmp(str, event_symbols[i].symbol, n))
                return n;
 
        n = strlen(event_symbols[i].alias);
-       if (n)
-               if (!strncmp(str, event_symbols[i].alias, n))
+       if (n) {
+               if (!strncasecmp(str, event_symbols[i].alias, n))
                        return n;
+       }
+
        return 0;
 }
 
@@ -718,15 +724,22 @@ parse_numeric_event(const char **strp, struct perf_event_attr *attr)
        return EVT_FAILED;
 }
 
-static enum event_result
+static int
 parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 {
        const char *str = *strp;
        int exclude = 0;
        int eu = 0, ek = 0, eh = 0, precise = 0;
 
-       if (*str++ != ':')
+       if (!*str)
+               return 0;
+
+       if (*str == ',')
                return 0;
+
+       if (*str++ != ':')
+               return -1;
+
        while (*str) {
                if (*str == 'u') {
                        if (!exclude)
@@ -747,14 +760,16 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 
                ++str;
        }
-       if (str >= *strp + 2) {
-               *strp = str;
-               attr->exclude_user   = eu;
-               attr->exclude_kernel = ek;
-               attr->exclude_hv     = eh;
-               attr->precise_ip     = precise;
-               return 1;
-       }
+       if (str < *strp + 2)
+               return -1;
+
+       *strp = str;
+
+       attr->exclude_user   = eu;
+       attr->exclude_kernel = ek;
+       attr->exclude_hv     = eh;
+       attr->precise_ip     = precise;
+
        return 0;
 }
 
@@ -797,7 +812,12 @@ parse_event_symbols(const struct option *opt, const char **str,
        return EVT_FAILED;
 
 modifier:
-       parse_event_modifier(str, attr);
+       if (parse_event_modifier(str, attr) < 0) {
+               fprintf(stderr, "invalid event modifier: '%s'\n", *str);
+               fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n");
+
+               return EVT_FAILED;
+       }
 
        return ret;
 }
@@ -912,7 +932,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
 
                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
                                 sys_dirent.d_name, evt_dirent.d_name);
-                       printf("  %-42s [%s]\n", evt_path,
+                       printf("  %-50s [%s]\n", evt_path,
                                event_type_descriptors[PERF_TYPE_TRACEPOINT]);
                }
                closedir(evt_dir);
@@ -977,7 +997,7 @@ void print_events_type(u8 type)
                else
                        snprintf(name, sizeof(name), "%s", syms->symbol);
 
-               printf("  %-42s [%s]\n", name,
+               printf("  %-50s [%s]\n", name,
                        event_type_descriptors[type]);
        }
 }
@@ -995,11 +1015,10 @@ int print_hwcache_events(const char *event_glob)
                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
                                char *name = event_cache_name(type, op, i);
 
-                               if (event_glob != NULL && 
-                                   !strglobmatch(name, event_glob))
+                               if (event_glob != NULL && !strglobmatch(name, event_glob))
                                        continue;
 
-                               printf("  %-42s [%s]\n", name,
+                               printf("  %-50s [%s]\n", name,
                                        event_type_descriptors[PERF_TYPE_HW_CACHE]);
                                ++printed;
                        }
@@ -1009,14 +1028,16 @@ int print_hwcache_events(const char *event_glob)
        return printed;
 }
 
+#define MAX_NAME_LEN 100
+
 /*
  * Print the help text for the event symbols:
  */
 void print_events(const char *event_glob)
 {
-       struct event_symbol *syms = event_symbols;
        unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
-       char name[40];
+       struct event_symbol *syms = event_symbols;
+       char name[MAX_NAME_LEN];
 
        printf("\n");
        printf("List of pre-defined events (to be used in -e):\n");
@@ -1036,10 +1057,10 @@ void print_events(const char *event_glob)
                        continue;
 
                if (strlen(syms->alias))
-                       sprintf(name, "%s OR %s", syms->symbol, syms->alias);
+                       snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
                else
-                       strcpy(name, syms->symbol);
-               printf("  %-42s [%s]\n", name,
+                       strncpy(name, syms->symbol, MAX_NAME_LEN);
+               printf("  %-50s [%s]\n", name,
                        event_type_descriptors[type]);
 
                prev_type = type;
@@ -1056,12 +1077,12 @@ void print_events(const char *event_glob)
                return;
 
        printf("\n");
-       printf("  %-42s [%s]\n",
+       printf("  %-50s [%s]\n",
                "rNNN (see 'perf list --help' on how to encode it)",
               event_type_descriptors[PERF_TYPE_RAW]);
        printf("\n");
 
-       printf("  %-42s [%s]\n",
+       printf("  %-50s [%s]\n",
                        "mem:<addr>[:access]",
                        event_type_descriptors[PERF_TYPE_BREAKPOINT]);
        printf("\n");
index b7c85ce466a15eb72e1390b0808b3a02ec51d442..3b9d0b800d5c85c332357220f9c5bd1ed8de4ffc 100644 (file)
@@ -1471,6 +1471,38 @@ static int find_probe_point_by_func(struct probe_finder *pf)
        return _param.retval;
 }
 
+struct pubname_callback_param {
+       char *function;
+       char *file;
+       Dwarf_Die *cu_die;
+       Dwarf_Die *sp_die;
+       int found;
+};
+
+static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
+{
+       struct pubname_callback_param *param = data;
+
+       if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
+               if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
+                       return DWARF_CB_OK;
+
+               if (die_compare_name(param->sp_die, param->function)) {
+                       if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
+                               return DWARF_CB_OK;
+
+                       if (param->file &&
+                           strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
+                               return DWARF_CB_OK;
+
+                       param->found = 1;
+                       return DWARF_CB_ABORT;
+               }
+       }
+
+       return DWARF_CB_OK;
+}
+
 /* Find probe points from debuginfo */
 static int find_probes(int fd, struct probe_finder *pf)
 {
@@ -1498,6 +1530,28 @@ static int find_probes(int fd, struct probe_finder *pf)
 
        off = 0;
        line_list__init(&pf->lcache);
+
+       /* Fastpath: lookup by function name from .debug_pubnames section */
+       if (pp->function) {
+               struct pubname_callback_param pubname_param = {
+                       .function = pp->function,
+                       .file     = pp->file,
+                       .cu_die   = &pf->cu_die,
+                       .sp_die   = &pf->sp_die,
+                       .found    = 0,
+               };
+               struct dwarf_callback_param probe_param = {
+                       .data = pf,
+               };
+
+               dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
+               if (pubname_param.found) {
+                       ret = probe_point_search_cb(&pf->sp_die, &probe_param);
+                       if (ret)
+                               goto found;
+               }
+       }
+
        /* Loop on CUs (Compilation Unit) */
        while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
                /* Get the DIE(Debugging Information Entry) of this CU */
@@ -1525,6 +1579,8 @@ static int find_probes(int fd, struct probe_finder *pf)
                }
                off = noff;
        }
+
+found:
        line_list__free(&pf->lcache);
        if (dwfl)
                dwfl_end(dwfl);
@@ -1946,6 +2002,22 @@ int find_line_range(int fd, struct line_range *lr)
                return -EBADF;
        }
 
+       /* Fastpath: lookup by function name from .debug_pubnames section */
+       if (lr->function) {
+               struct pubname_callback_param pubname_param = {
+                       .function = lr->function, .file = lr->file,
+                       .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
+               struct dwarf_callback_param line_range_param = {
+                       .data = (void *)&lf, .retval = 0};
+
+               dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
+               if (pubname_param.found) {
+                       line_range_search_cb(&lf.sp_die, &line_range_param);
+                       if (lf.found)
+                               goto found;
+               }
+       }
+
        /* Loop on CUs (Compilation Unit) */
        while (!lf.found && ret >= 0) {
                if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
@@ -1974,6 +2046,7 @@ int find_line_range(int fd, struct line_range *lr)
                off = noff;
        }
 
+found:
        /* Store comp_dir */
        if (lf.found) {
                comp_dir = cu_get_comp_dir(&lf.cu_die);
index beaefc3c1223df16423cbd084f700b6ee5a5fbf2..605730a366dbc5dc0158ffc32db254420c5045bb 100644 (file)
@@ -49,6 +49,7 @@ struct probe_finder {
        Dwarf_Addr              addr;           /* Address */
        const char              *fname;         /* Real file name */
        Dwarf_Die               cu_die;         /* Current CU */
+       Dwarf_Die               sp_die;
        struct list_head        lcache;         /* Line cache for lazy match */
 
        /* For variable searching */
@@ -83,6 +84,7 @@ struct line_finder {
        int                     lno_s;          /* Start line number */
        int                     lno_e;          /* End line number */
        Dwarf_Die               cu_die;         /* Current CU */
+       Dwarf_Die               sp_die;
        int                     found;
 };
 
index a9f2d7e1204d1655b14b99cafb06d08d5046d8a6..b5c7d818001cc5e984e6f35c693cf6d1dd579cf8 100644 (file)
@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
        struct cpu_map *cpus = NULL;
        struct thread_map *threads = NULL;
        PyObject *pcpus = NULL, *pthreads = NULL;
-       int group = 0, overwrite = 0;
-       static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
+       int group = 0, inherit = 0;
+       static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
-                                        &pcpus, &pthreads, &group, &overwrite))
+                                        &pcpus, &pthreads, &group, &inherit))
                return NULL;
 
        if (pthreads != NULL)
@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
        if (pcpus != NULL)
                cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
 
-       if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
+       evsel->attr.inherit = inherit;
+       if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
        }
@@ -679,7 +680,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
                                         &cpu, &sample_id_all))
                return NULL;
 
-       event = perf_evlist__read_on_cpu(evlist, cpu);
+       event = perf_evlist__mmap_read(evlist, cpu);
        if (event != NULL) {
                struct perf_evsel *first;
                PyObject *pyevent = pyrf_event__new(event);
@@ -809,6 +810,9 @@ static struct {
        { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
        { "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
 
+       { "COUNT_HW_STALLED_CYCLES_FRONTEND",     PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
+       { "COUNT_HW_STALLED_CYCLES_BACKEND",      PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+
        { "COUNT_SW_CPU_CLOCK",        PERF_COUNT_SW_CPU_CLOCK },
        { "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
        { "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
index caa224522fea9b0ff04984595a09e2eccd31e438..fff66741f18d5db2ef85579eef21a5f3ff9ec46b 100644 (file)
@@ -1156,6 +1156,18 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
        return ret;
 }
 
+struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
+                                             unsigned int type)
+{
+       struct perf_evsel *pos;
+
+       list_for_each_entry(pos, &session->evlist->entries, node) {
+               if (pos->attr.type == type)
+                       return pos;
+       }
+       return NULL;
+}
+
 void perf_session__print_symbols(union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_session *session)
index 1ac481fc1100dd1676bcdeaa392b73b15663117d..8daaa2d15396eef76789f4b47fa2701d04c65d3b 100644 (file)
@@ -162,6 +162,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
                                        session->sample_id_all, sample);
 }
 
+struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
+                                           unsigned int type);
+
 void perf_session__print_symbols(union perf_event *event,
                                 struct perf_sample *sample,
                                 struct perf_session *session);
index f06c10f092ba53036a379a3c05983e3e928808aa..516876dfbe5280af9bd52179c07d99b16ed43233 100644 (file)
 #define NT_GNU_BUILD_ID 3
 #endif
 
-static bool dso__build_id_equal(const struct dso *self, u8 *build_id);
+static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
 static int elf_read_build_id(Elf *elf, void *bf, size_t size);
 static void dsos__add(struct list_head *head, struct dso *dso);
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
-static int dso__load_kernel_sym(struct dso *self, struct map *map,
+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 *self, struct map *map,
+static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
                        symbol_filter_t filter);
 static int vmlinux_path__nr_entries;
 static char **vmlinux_path;
@@ -49,27 +49,27 @@ struct symbol_conf symbol_conf = {
        .symfs            = "",
 };
 
-int dso__name_len(const struct dso *self)
+int dso__name_len(const struct dso *dso)
 {
        if (verbose)
-               return self->long_name_len;
+               return dso->long_name_len;
 
-       return self->short_name_len;
+       return dso->short_name_len;
 }
 
-bool dso__loaded(const struct dso *self, enum map_type type)
+bool dso__loaded(const struct dso *dso, enum map_type type)
 {
-       return self->loaded & (1 << type);
+       return dso->loaded & (1 << type);
 }
 
-bool dso__sorted_by_name(const struct dso *self, enum map_type type)
+bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
 {
-       return self->sorted_by_name & (1 << type);
+       return dso->sorted_by_name & (1 << type);
 }
 
-static void dso__set_sorted_by_name(struct dso *self, enum map_type type)
+static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
 {
-       self->sorted_by_name |= (1 << type);
+       dso->sorted_by_name |= (1 << type);
 }
 
 bool symbol_type__is_a(char symbol_type, enum map_type map_type)
@@ -84,9 +84,9 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type)
        }
 }
 
-static void symbols__fixup_end(struct rb_root *self)
+static void symbols__fixup_end(struct rb_root *symbols)
 {
-       struct rb_node *nd, *prevnd = rb_first(self);
+       struct rb_node *nd, *prevnd = rb_first(symbols);
        struct symbol *curr, *prev;
 
        if (prevnd == NULL)
@@ -107,10 +107,10 @@ static void symbols__fixup_end(struct rb_root *self)
                curr->end = roundup(curr->start, 4096);
 }
 
-static void __map_groups__fixup_end(struct map_groups *self, enum map_type type)
+static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
 {
        struct map *prev, *curr;
-       struct rb_node *nd, *prevnd = rb_first(&self->maps[type]);
+       struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]);
 
        if (prevnd == NULL)
                return;
@@ -130,128 +130,128 @@ static void __map_groups__fixup_end(struct map_groups *self, enum map_type type)
        curr->end = ~0ULL;
 }
 
-static void map_groups__fixup_end(struct map_groups *self)
+static void map_groups__fixup_end(struct map_groups *mg)
 {
        int i;
        for (i = 0; i < MAP__NR_TYPES; ++i)
-               __map_groups__fixup_end(self, i);
+               __map_groups__fixup_end(mg, i);
 }
 
 static struct symbol *symbol__new(u64 start, u64 len, u8 binding,
                                  const char *name)
 {
        size_t namelen = strlen(name) + 1;
-       struct symbol *self = calloc(1, (symbol_conf.priv_size +
-                                        sizeof(*self) + namelen));
-       if (self == NULL)
+       struct symbol *sym = calloc(1, (symbol_conf.priv_size +
+                                       sizeof(*sym) + namelen));
+       if (sym == NULL)
                return NULL;
 
        if (symbol_conf.priv_size)
-               self = ((void *)self) + symbol_conf.priv_size;
-
-       self->start   = start;
-       self->end     = len ? start + len - 1 : start;
-       self->binding = binding;
-       self->namelen = namelen - 1;
+               sym = ((void *)sym) + symbol_conf.priv_size;
 
-       pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end);
+       sym->start   = start;
+       sym->end     = len ? start + len - 1 : start;
+       sym->binding = binding;
+       sym->namelen = namelen - 1;
 
-       memcpy(self->name, name, namelen);
+       pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n",
+                 __func__, name, start, sym->end);
+       memcpy(sym->name, name, namelen);
 
-       return self;
+       return sym;
 }
 
-void symbol__delete(struct symbol *self)
+void symbol__delete(struct symbol *sym)
 {
-       free(((void *)self) - symbol_conf.priv_size);
+       free(((void *)sym) - symbol_conf.priv_size);
 }
 
-static size_t symbol__fprintf(struct symbol *self, FILE *fp)
+static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
 {
        return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
-                      self->start, self->end,
-                      self->binding == STB_GLOBAL ? 'g' :
-                      self->binding == STB_LOCAL  ? 'l' : 'w',
-                      self->name);
+                      sym->start, sym->end,
+                      sym->binding == STB_GLOBAL ? 'g' :
+                      sym->binding == STB_LOCAL  ? 'l' : 'w',
+                      sym->name);
 }
 
-void dso__set_long_name(struct dso *self, char *name)
+void dso__set_long_name(struct dso *dso, char *name)
 {
        if (name == NULL)
                return;
-       self->long_name = name;
-       self->long_name_len = strlen(name);
+       dso->long_name = name;
+       dso->long_name_len = strlen(name);
 }
 
-static void dso__set_short_name(struct dso *self, const char *name)
+static void dso__set_short_name(struct dso *dso, const char *name)
 {
        if (name == NULL)
                return;
-       self->short_name = name;
-       self->short_name_len = strlen(name);
+       dso->short_name = name;
+       dso->short_name_len = strlen(name);
 }
 
-static void dso__set_basename(struct dso *self)
+static void dso__set_basename(struct dso *dso)
 {
-       dso__set_short_name(self, basename(self->long_name));
+       dso__set_short_name(dso, basename(dso->long_name));
 }
 
 struct dso *dso__new(const char *name)
 {
-       struct dso *self = calloc(1, sizeof(*self) + strlen(name) + 1);
+       struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
 
-       if (self != NULL) {
+       if (dso != NULL) {
                int i;
-               strcpy(self->name, name);
-               dso__set_long_name(self, self->name);
-               dso__set_short_name(self, self->name);
+               strcpy(dso->name, name);
+               dso__set_long_name(dso, dso->name);
+               dso__set_short_name(dso, dso->name);
                for (i = 0; i < MAP__NR_TYPES; ++i)
-                       self->symbols[i] = self->symbol_names[i] = RB_ROOT;
-               self->symtab_type = SYMTAB__NOT_FOUND;
-               self->loaded = 0;
-               self->sorted_by_name = 0;
-               self->has_build_id = 0;
-               self->kernel = DSO_TYPE_USER;
-               INIT_LIST_HEAD(&self->node);
+                       dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
+               dso->symtab_type = SYMTAB__NOT_FOUND;
+               dso->loaded = 0;
+               dso->sorted_by_name = 0;
+               dso->has_build_id = 0;
+               dso->kernel = DSO_TYPE_USER;
+               INIT_LIST_HEAD(&dso->node);
        }
 
-       return self;
+       return dso;
 }
 
-static void symbols__delete(struct rb_root *self)
+static void symbols__delete(struct rb_root *symbols)
 {
        struct symbol *pos;
-       struct rb_node *next = rb_first(self);
+       struct rb_node *next = rb_first(symbols);
 
        while (next) {
                pos = rb_entry(next, struct symbol, rb_node);
                next = rb_next(&pos->rb_node);
-               rb_erase(&pos->rb_node, self);
+               rb_erase(&pos->rb_node, symbols);
                symbol__delete(pos);
        }
 }
 
-void dso__delete(struct dso *self)
+void dso__delete(struct dso *dso)
 {
        int i;
        for (i = 0; i < MAP__NR_TYPES; ++i)
-               symbols__delete(&self->symbols[i]);
-       if (self->sname_alloc)
-               free((char *)self->short_name);
-       if (self->lname_alloc)
-               free(self->long_name);
-       free(self);
+               symbols__delete(&dso->symbols[i]);
+       if (dso->sname_alloc)
+               free((char *)dso->short_name);
+       if (dso->lname_alloc)
+               free(dso->long_name);
+       free(dso);
 }
 
-void dso__set_build_id(struct dso *self, void *build_id)
+void dso__set_build_id(struct dso *dso, void *build_id)
 {
-       memcpy(self->build_id, build_id, sizeof(self->build_id));
-       self->has_build_id = 1;
+       memcpy(dso->build_id, build_id, sizeof(dso->build_id));
+       dso->has_build_id = 1;
 }
 
-static void symbols__insert(struct rb_root *self, struct symbol *sym)
+static void symbols__insert(struct rb_root *symbols, struct symbol *sym)
 {
-       struct rb_node **p = &self->rb_node;
+       struct rb_node **p = &symbols->rb_node;
        struct rb_node *parent = NULL;
        const u64 ip = sym->start;
        struct symbol *s;
@@ -265,17 +265,17 @@ static void symbols__insert(struct rb_root *self, struct symbol *sym)
                        p = &(*p)->rb_right;
        }
        rb_link_node(&sym->rb_node, parent, p);
-       rb_insert_color(&sym->rb_node, self);
+       rb_insert_color(&sym->rb_node, symbols);
 }
 
-static struct symbol *symbols__find(struct rb_root *self, u64 ip)
+static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 {
        struct rb_node *n;
 
-       if (self == NULL)
+       if (symbols == NULL)
                return NULL;
 
-       n = self->rb_node;
+       n = symbols->rb_node;
 
        while (n) {
                struct symbol *s = rb_entry(n, struct symbol, rb_node);
@@ -296,9 +296,9 @@ struct symbol_name_rb_node {
        struct symbol   sym;
 };
 
-static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
+static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)
 {
-       struct rb_node **p = &self->rb_node;
+       struct rb_node **p = &symbols->rb_node;
        struct rb_node *parent = NULL;
        struct symbol_name_rb_node *symn, *s;
 
@@ -313,27 +313,29 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
                        p = &(*p)->rb_right;
        }
        rb_link_node(&symn->rb_node, parent, p);
-       rb_insert_color(&symn->rb_node, self);
+       rb_insert_color(&symn->rb_node, symbols);
 }
 
-static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source)
+static void symbols__sort_by_name(struct rb_root *symbols,
+                                 struct rb_root *source)
 {
        struct rb_node *nd;
 
        for (nd = rb_first(source); nd; nd = rb_next(nd)) {
                struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
-               symbols__insert_by_name(self, pos);
+               symbols__insert_by_name(symbols, pos);
        }
 }
 
-static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name)
+static struct symbol *symbols__find_by_name(struct rb_root *symbols,
+                                           const char *name)
 {
        struct rb_node *n;
 
-       if (self == NULL)
+       if (symbols == NULL)
                return NULL;
 
-       n = self->rb_node;
+       n = symbols->rb_node;
 
        while (n) {
                struct symbol_name_rb_node *s;
@@ -353,29 +355,29 @@ static struct symbol *symbols__find_by_name(struct rb_root *self, const char *na
        return NULL;
 }
 
-struct symbol *dso__find_symbol(struct dso *self,
+struct symbol *dso__find_symbol(struct dso *dso,
                                enum map_type type, u64 addr)
 {
-       return symbols__find(&self->symbols[type], addr);
+       return symbols__find(&dso->symbols[type], addr);
 }
 
-struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
+struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
                                        const char *name)
 {
-       return symbols__find_by_name(&self->symbol_names[type], name);
+       return symbols__find_by_name(&dso->symbol_names[type], name);
 }
 
-void dso__sort_by_name(struct dso *self, enum map_type type)
+void dso__sort_by_name(struct dso *dso, enum map_type type)
 {
-       dso__set_sorted_by_name(self, type);
-       return symbols__sort_by_name(&self->symbol_names[type],
-                                    &self->symbols[type]);
+       dso__set_sorted_by_name(dso, type);
+       return symbols__sort_by_name(&dso->symbol_names[type],
+                                    &dso->symbols[type]);
 }
 
-int build_id__sprintf(const u8 *self, int len, char *bf)
+int build_id__sprintf(const u8 *build_id, int len, char *bf)
 {
        char *bid = bf;
-       const u8 *raw = self;
+       const u8 *raw = build_id;
        int i;
 
        for (i = 0; i < len; ++i) {
@@ -384,24 +386,25 @@ int build_id__sprintf(const u8 *self, int len, char *bf)
                bid += 2;
        }
 
-       return raw - self;
+       return raw - build_id;
 }
 
-size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
+size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
 {
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 
-       build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
+       build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
        return fprintf(fp, "%s", sbuild_id);
 }
 
-size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp)
+size_t dso__fprintf_symbols_by_name(struct dso *dso,
+                                   enum map_type type, FILE *fp)
 {
        size_t ret = 0;
        struct rb_node *nd;
        struct symbol_name_rb_node *pos;
 
-       for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
                pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
                fprintf(fp, "%s\n", pos->sym.name);
        }
@@ -409,18 +412,18 @@ size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *
        return ret;
 }
 
-size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
+size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
 {
        struct rb_node *nd;
-       size_t ret = fprintf(fp, "dso: %s (", self->short_name);
+       size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
 
-       if (self->short_name != self->long_name)
-               ret += fprintf(fp, "%s, ", self->long_name);
+       if (dso->short_name != dso->long_name)
+               ret += fprintf(fp, "%s, ", dso->long_name);
        ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
-                      self->loaded ? "" : "NOT ");
-       ret += dso__fprintf_buildid(self, fp);
+                      dso->loaded ? "" : "NOT ");
+       ret += dso__fprintf_buildid(dso, fp);
        ret += fprintf(fp, ")\n");
-       for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
                struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
                ret += symbol__fprintf(pos, fp);
        }
@@ -543,10 +546,10 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
  * so that we can in the next step set the symbol ->end address and then
  * call kernel_maps__split_kallsyms.
  */
-static int dso__load_all_kallsyms(struct dso *self, const char *filename,
+static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
                                  struct map *map)
 {
-       struct process_kallsyms_args args = { .map = map, .dso = self, };
+       struct process_kallsyms_args args = { .map = map, .dso = dso, };
        return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
 }
 
@@ -555,7 +558,7 @@ static int dso__load_all_kallsyms(struct dso *self, const char *filename,
  * kernel range is broken in several maps, named [kernel].N, as we don't have
  * the original ELF section names vmlinux have.
  */
-static int dso__split_kallsyms(struct dso *self, struct map *map,
+static int dso__split_kallsyms(struct dso *dso, struct map *map,
                               symbol_filter_t filter)
 {
        struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -563,7 +566,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
        struct map *curr_map = map;
        struct symbol *pos;
        int count = 0, moved = 0;       
-       struct rb_root *root = &self->symbols[map->type];
+       struct rb_root *root = &dso->symbols[map->type];
        struct rb_node *next = rb_first(root);
        int kernel_range = 0;
 
@@ -582,7 +585,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
 
                        if (strcmp(curr_map->dso->short_name, module)) {
                                if (curr_map != map &&
-                                   self->kernel == DSO_TYPE_GUEST_KERNEL &&
+                                   dso->kernel == DSO_TYPE_GUEST_KERNEL &&
                                    machine__is_default_guest(machine)) {
                                        /*
                                         * We assume all symbols of a module are
@@ -618,14 +621,14 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                        pos->end   = curr_map->map_ip(curr_map, pos->end);
                } else if (curr_map != map) {
                        char dso_name[PATH_MAX];
-                       struct dso *dso;
+                       struct dso *ndso;
 
                        if (count == 0) {
                                curr_map = map;
                                goto filter_symbol;
                        }
 
-                       if (self->kernel == DSO_TYPE_GUEST_KERNEL)
+                       if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
                                snprintf(dso_name, sizeof(dso_name),
                                        "[guest.kernel].%d",
                                        kernel_range++);
@@ -634,15 +637,15 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                                        "[kernel].%d",
                                        kernel_range++);
 
-                       dso = dso__new(dso_name);
-                       if (dso == NULL)
+                       ndso = dso__new(dso_name);
+                       if (ndso == NULL)
                                return -1;
 
-                       dso->kernel = self->kernel;
+                       ndso->kernel = dso->kernel;
 
-                       curr_map = map__new2(pos->start, dso, map->type);
+                       curr_map = map__new2(pos->start, ndso, map->type);
                        if (curr_map == NULL) {
-                               dso__delete(dso);
+                               dso__delete(ndso);
                                return -1;
                        }
 
@@ -665,7 +668,7 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
        }
 
        if (curr_map != map &&
-           self->kernel == DSO_TYPE_GUEST_KERNEL &&
+           dso->kernel == DSO_TYPE_GUEST_KERNEL &&
            machine__is_default_guest(kmaps->machine)) {
                dso__set_loaded(curr_map->dso, curr_map->type);
        }
@@ -673,21 +676,21 @@ discard_symbol:           rb_erase(&pos->rb_node, root);
        return count + moved;
 }
 
-int dso__load_kallsyms(struct dso *self, const char *filename,
+int dso__load_kallsyms(struct dso *dso, const char *filename,
                       struct map *map, symbol_filter_t filter)
 {
-       if (dso__load_all_kallsyms(self, filename, map) < 0)
+       if (dso__load_all_kallsyms(dso, filename, map) < 0)
                return -1;
 
-       if (self->kernel == DSO_TYPE_GUEST_KERNEL)
-               self->symtab_type = SYMTAB__GUEST_KALLSYMS;
+       if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
+               dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
        else
-               self->symtab_type = SYMTAB__KALLSYMS;
+               dso->symtab_type = SYMTAB__KALLSYMS;
 
-       return dso__split_kallsyms(self, map, filter);
+       return dso__split_kallsyms(dso, map, filter);
 }
 
-static int dso__load_perf_map(struct dso *self, struct map *map,
+static int dso__load_perf_map(struct dso *dso, struct map *map,
                              symbol_filter_t filter)
 {
        char *line = NULL;
@@ -695,7 +698,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map,
        FILE *file;
        int nr_syms = 0;
 
-       file = fopen(self->long_name, "r");
+       file = fopen(dso->long_name, "r");
        if (file == NULL)
                goto out_failure;
 
@@ -733,7 +736,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map,
                if (filter && filter(map, sym))
                        symbol__delete(sym);
                else {
-                       symbols__insert(&self->symbols[map->type], sym);
+                       symbols__insert(&dso->symbols[map->type], sym);
                        nr_syms++;
                }
        }
@@ -752,7 +755,7 @@ out_failure:
 /**
  * elf_symtab__for_each_symbol - iterate thru all the symbols
  *
- * @self: struct elf_symtab instance to iterate
+ * @syms: struct elf_symtab instance to iterate
  * @idx: uint32_t idx
  * @sym: GElf_Sym iterator
  */
@@ -852,7 +855,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
  * And always look at the original dso, not at debuginfo packages, that
  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
  */
-static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
+static int dso__synthesize_plt_symbols(struct  dso *dso, struct map *map,
                                       symbol_filter_t filter)
 {
        uint32_t nr_rel_entries, idx;
@@ -871,7 +874,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
        char name[PATH_MAX];
 
        snprintf(name, sizeof(name), "%s%s",
-                symbol_conf.symfs, self->long_name);
+                symbol_conf.symfs, dso->long_name);
        fd = open(name, O_RDONLY);
        if (fd < 0)
                goto out;
@@ -947,7 +950,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
                        if (filter && filter(map, f))
                                symbol__delete(f);
                        else {
-                               symbols__insert(&self->symbols[map->type], f);
+                               symbols__insert(&dso->symbols[map->type], f);
                                ++nr;
                        }
                }
@@ -969,7 +972,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
                        if (filter && filter(map, f))
                                symbol__delete(f);
                        else {
-                               symbols__insert(&self->symbols[map->type], f);
+                               symbols__insert(&dso->symbols[map->type], f);
                                ++nr;
                        }
                }
@@ -985,29 +988,30 @@ out_close:
                return nr;
 out:
        pr_debug("%s: problems reading %s PLT info.\n",
-                __func__, self->long_name);
+                __func__, dso->long_name);
        return 0;
 }
 
-static bool elf_sym__is_a(GElf_Sym *self, enum map_type type)
+static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
 {
        switch (type) {
        case MAP__FUNCTION:
-               return elf_sym__is_function(self);
+               return elf_sym__is_function(sym);
        case MAP__VARIABLE:
-               return elf_sym__is_object(self);
+               return elf_sym__is_object(sym);
        default:
                return false;
        }
 }
 
-static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type)
+static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
+                         enum map_type type)
 {
        switch (type) {
        case MAP__FUNCTION:
-               return elf_sec__is_text(self, secstrs);
+               return elf_sec__is_text(shdr, secstrs);
        case MAP__VARIABLE:
-               return elf_sec__is_data(self, secstrs);
+               return elf_sec__is_data(shdr, secstrs);
        default:
                return false;
        }
@@ -1032,13 +1036,13 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
        return -1;
 }
 
-static int dso__load_sym(struct dso *self, struct map *map, const char *name,
+static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
                         int fd, symbol_filter_t filter, int kmodule,
                         int want_symtab)
 {
-       struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
+       struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
        struct map *curr_map = map;
-       struct dso *curr_dso = self;
+       struct dso *curr_dso = dso;
        Elf_Data *symstrs, *secstrs;
        uint32_t nr_syms;
        int err = -1;
@@ -1064,14 +1068,14 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
        }
 
        /* Always reject images with a mismatched build-id: */
-       if (self->has_build_id) {
+       if (dso->has_build_id) {
                u8 build_id[BUILD_ID_SIZE];
 
                if (elf_read_build_id(elf, build_id,
                                      BUILD_ID_SIZE) != BUILD_ID_SIZE)
                        goto out_elf_end;
 
-               if (!dso__build_id_equal(self, build_id))
+               if (!dso__build_id_equal(dso, build_id))
                        goto out_elf_end;
        }
 
@@ -1112,13 +1116,14 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
        nr_syms = shdr.sh_size / shdr.sh_entsize;
 
        memset(&sym, 0, sizeof(sym));
-       if (self->kernel == DSO_TYPE_USER) {
-               self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
+       if (dso->kernel == DSO_TYPE_USER) {
+               dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
                                elf_section_by_name(elf, &ehdr, &shdr,
                                                     ".gnu.prelink_undo",
                                                     NULL) != NULL);
-       } else self->adjust_symbols = 0;
-
+       } else {
+               dso->adjust_symbols = 0;
+       }
        elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
                struct symbol *f;
                const char *elf_name = elf_sym__name(&sym, symstrs);
@@ -1168,22 +1173,22 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                    (sym.st_value & 1))
                        --sym.st_value;
 
-               if (self->kernel != DSO_TYPE_USER || kmodule) {
+               if (dso->kernel != DSO_TYPE_USER || kmodule) {
                        char dso_name[PATH_MAX];
 
                        if (strcmp(section_name,
                                   (curr_dso->short_name +
-                                   self->short_name_len)) == 0)
+                                   dso->short_name_len)) == 0)
                                goto new_symbol;
 
                        if (strcmp(section_name, ".text") == 0) {
                                curr_map = map;
-                               curr_dso = self;
+                               curr_dso = dso;
                                goto new_symbol;
                        }
 
                        snprintf(dso_name, sizeof(dso_name),
-                                "%s%s", self->short_name, section_name);
+                                "%s%s", dso->short_name, section_name);
 
                        curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
                        if (curr_map == NULL) {
@@ -1195,9 +1200,9 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                                curr_dso = dso__new(dso_name);
                                if (curr_dso == NULL)
                                        goto out_elf_end;
-                               curr_dso->kernel = self->kernel;
-                               curr_dso->long_name = self->long_name;
-                               curr_dso->long_name_len = self->long_name_len;
+                               curr_dso->kernel = dso->kernel;
+                               curr_dso->long_name = dso->long_name;
+                               curr_dso->long_name_len = dso->long_name_len;
                                curr_map = map__new2(start, curr_dso,
                                                     map->type);
                                if (curr_map == NULL) {
@@ -1206,9 +1211,9 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                                }
                                curr_map->map_ip = identity__map_ip;
                                curr_map->unmap_ip = identity__map_ip;
-                               curr_dso->symtab_type = self->symtab_type;
+                               curr_dso->symtab_type = dso->symtab_type;
                                map_groups__insert(kmap->kmaps, curr_map);
-                               dsos__add(&self->node, curr_dso);
+                               dsos__add(&dso->node, curr_dso);
                                dso__set_loaded(curr_dso, map->type);
                        } else
                                curr_dso = curr_map->dso;
@@ -1250,7 +1255,7 @@ new_symbol:
         * For misannotated, zeroed, ASM function sizes.
         */
        if (nr > 0) {
-               symbols__fixup_end(&self->symbols[map->type]);
+               symbols__fixup_end(&dso->symbols[map->type]);
                if (kmap) {
                        /*
                         * We need to fixup this here too because we create new
@@ -1266,9 +1271,9 @@ out_close:
        return err;
 }
 
-static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
+static bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
 {
-       return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
+       return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
 }
 
 bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
@@ -1429,7 +1434,7 @@ out:
        return err;
 }
 
-char dso__symtab_origin(const struct dso *self)
+char dso__symtab_origin(const struct dso *dso)
 {
        static const char origin[] = {
                [SYMTAB__KALLSYMS]            = 'k',
@@ -1444,12 +1449,12 @@ char dso__symtab_origin(const struct dso *self)
                [SYMTAB__GUEST_KMODULE]       =  'G',
        };
 
-       if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND)
+       if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND)
                return '!';
-       return origin[self->symtab_type];
+       return origin[dso->symtab_type];
 }
 
-int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
+int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 {
        int size = PATH_MAX;
        char *name;
@@ -1459,12 +1464,12 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
        const char *root_dir;
        int want_symtab;
 
-       dso__set_loaded(self, map->type);
+       dso__set_loaded(dso, map->type);
 
-       if (self->kernel == DSO_TYPE_KERNEL)
-               return dso__load_kernel_sym(self, map, filter);
-       else if (self->kernel == DSO_TYPE_GUEST_KERNEL)
-               return dso__load_guest_kernel_sym(self, map, filter);
+       if (dso->kernel == DSO_TYPE_KERNEL)
+               return dso__load_kernel_sym(dso, map, filter);
+       else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
+               return dso__load_guest_kernel_sym(dso, map, filter);
 
        if (map->groups && map->groups->machine)
                machine = map->groups->machine;
@@ -1475,11 +1480,11 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
        if (!name)
                return -1;
 
-       self->adjust_symbols = 0;
+       dso->adjust_symbols = 0;
 
-       if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
-               ret = dso__load_perf_map(self, map, filter);
-               self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
+       if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
+               ret = dso__load_perf_map(dso, map, filter);
+               dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
                                              SYMTAB__NOT_FOUND;
                return ret;
        }
@@ -1490,33 +1495,33 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
         */
        want_symtab = 1;
 restart:
-       for (self->symtab_type = SYMTAB__BUILD_ID_CACHE;
-            self->symtab_type != SYMTAB__NOT_FOUND;
-            self->symtab_type++) {
-               switch (self->symtab_type) {
+       for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE;
+            dso->symtab_type != SYMTAB__NOT_FOUND;
+            dso->symtab_type++) {
+               switch (dso->symtab_type) {
                case SYMTAB__BUILD_ID_CACHE:
                        /* skip the locally configured cache if a symfs is given */
                        if (symbol_conf.symfs[0] ||
-                           (dso__build_id_filename(self, name, size) == NULL)) {
+                           (dso__build_id_filename(dso, name, size) == NULL)) {
                                continue;
                        }
                        break;
                case SYMTAB__FEDORA_DEBUGINFO:
                        snprintf(name, size, "%s/usr/lib/debug%s.debug",
-                                symbol_conf.symfs, self->long_name);
+                                symbol_conf.symfs, dso->long_name);
                        break;
                case SYMTAB__UBUNTU_DEBUGINFO:
                        snprintf(name, size, "%s/usr/lib/debug%s",
-                                symbol_conf.symfs, self->long_name);
+                                symbol_conf.symfs, dso->long_name);
                        break;
                case SYMTAB__BUILDID_DEBUGINFO: {
                        char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 
-                       if (!self->has_build_id)
+                       if (!dso->has_build_id)
                                continue;
 
-                       build_id__sprintf(self->build_id,
-                                         sizeof(self->build_id),
+                       build_id__sprintf(dso->build_id,
+                                         sizeof(dso->build_id),
                                          build_id_hex);
                        snprintf(name, size,
                                 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
@@ -1525,7 +1530,7 @@ restart:
                        break;
                case SYMTAB__SYSTEM_PATH_DSO:
                        snprintf(name, size, "%s%s",
-                            symbol_conf.symfs, self->long_name);
+                            symbol_conf.symfs, dso->long_name);
                        break;
                case SYMTAB__GUEST_KMODULE:
                        if (map->groups && machine)
@@ -1533,12 +1538,12 @@ restart:
                        else
                                root_dir = "";
                        snprintf(name, size, "%s%s%s", symbol_conf.symfs,
-                                root_dir, self->long_name);
+                                root_dir, dso->long_name);
                        break;
 
                case SYMTAB__SYSTEM_PATH_KMODULE:
                        snprintf(name, size, "%s%s", symbol_conf.symfs,
-                                self->long_name);
+                                dso->long_name);
                        break;
                default:;
                }
@@ -1548,7 +1553,7 @@ restart:
                if (fd < 0)
                        continue;
 
-               ret = dso__load_sym(self, map, name, fd, filter, 0,
+               ret = dso__load_sym(dso, map, name, fd, filter, 0,
                                    want_symtab);
                close(fd);
 
@@ -1560,7 +1565,8 @@ restart:
                        continue;
 
                if (ret > 0) {
-                       int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
+                       int nr_plt = dso__synthesize_plt_symbols(dso, map,
+                                                                filter);
                        if (nr_plt > 0)
                                ret += nr_plt;
                        break;
@@ -1577,17 +1583,17 @@ restart:
        }
 
        free(name);
-       if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
+       if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
                return 0;
        return ret;
 }
 
-struct map *map_groups__find_by_name(struct map_groups *self,
+struct map *map_groups__find_by_name(struct map_groups *mg,
                                     enum map_type type, const char *name)
 {
        struct rb_node *nd;
 
-       for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
                struct map *map = rb_entry(nd, struct map, rb_node);
 
                if (map->dso && strcmp(map->dso->short_name, name) == 0)
@@ -1597,28 +1603,28 @@ struct map *map_groups__find_by_name(struct map_groups *self,
        return NULL;
 }
 
-static int dso__kernel_module_get_build_id(struct dso *self,
-                               const char *root_dir)
+static int dso__kernel_module_get_build_id(struct dso *dso,
+                                          const char *root_dir)
 {
        char filename[PATH_MAX];
        /*
         * kernel module short names are of the form "[module]" and
         * we need just "module" here.
         */
-       const char *name = self->short_name + 1;
+       const char *name = dso->short_name + 1;
 
        snprintf(filename, sizeof(filename),
                 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
                 root_dir, (int)strlen(name) - 1, name);
 
-       if (sysfs__read_build_id(filename, self->build_id,
-                                sizeof(self->build_id)) == 0)
-               self->has_build_id = true;
+       if (sysfs__read_build_id(filename, dso->build_id,
+                                sizeof(dso->build_id)) == 0)
+               dso->has_build_id = true;
 
        return 0;
 }
 
-static int map_groups__set_modules_path_dir(struct map_groups *self,
+static int map_groups__set_modules_path_dir(struct map_groups *mg,
                                const char *dir_name)
 {
        struct dirent *dent;
@@ -1646,7 +1652,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self,
 
                        snprintf(path, sizeof(path), "%s/%s",
                                 dir_name, dent->d_name);
-                       ret = map_groups__set_modules_path_dir(self, path);
+                       ret = map_groups__set_modules_path_dir(mg, path);
                        if (ret < 0)
                                goto out;
                } else {
@@ -1661,7 +1667,8 @@ static int map_groups__set_modules_path_dir(struct map_groups *self,
                                 (int)(dot - dent->d_name), dent->d_name);
 
                        strxfrchar(dso_name, '-', '_');
-                       map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name);
+                       map = map_groups__find_by_name(mg, MAP__FUNCTION,
+                                                      dso_name);
                        if (map == NULL)
                                continue;
 
@@ -1711,20 +1718,20 @@ static char *get_kernel_version(const char *root_dir)
        return strdup(name);
 }
 
-static int machine__set_modules_path(struct machine *self)
+static int machine__set_modules_path(struct machine *machine)
 {
        char *version;
        char modules_path[PATH_MAX];
 
-       version = get_kernel_version(self->root_dir);
+       version = get_kernel_version(machine->root_dir);
        if (!version)
                return -1;
 
        snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
-                self->root_dir, version);
+                machine->root_dir, version);
        free(version);
 
-       return map_groups__set_modules_path_dir(&self->kmaps, modules_path);
+       return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
 }
 
 /*
@@ -1734,23 +1741,23 @@ static int machine__set_modules_path(struct machine *self)
  */
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
 {
-       struct map *self = calloc(1, (sizeof(*self) +
-                                     (dso->kernel ? sizeof(struct kmap) : 0)));
-       if (self != NULL) {
+       struct map *map = calloc(1, (sizeof(*map) +
+                                    (dso->kernel ? sizeof(struct kmap) : 0)));
+       if (map != NULL) {
                /*
                 * ->end will be filled after we load all the symbols
                 */
-               map__init(self, type, start, 0, 0, dso);
+               map__init(map, type, start, 0, 0, dso);
        }
 
-       return self;
+       return map;
 }
 
-struct map *machine__new_module(struct machine *self, u64 start,
+struct map *machine__new_module(struct machine *machine, u64 start,
                                const char *filename)
 {
        struct map *map;
-       struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename);
+       struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
 
        if (dso == NULL)
                return NULL;
@@ -1759,15 +1766,15 @@ struct map *machine__new_module(struct machine *self, u64 start,
        if (map == NULL)
                return NULL;
 
-       if (machine__is_host(self))
+       if (machine__is_host(machine))
                dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE;
        else
                dso->symtab_type = SYMTAB__GUEST_KMODULE;
-       map_groups__insert(&self->kmaps, map);
+       map_groups__insert(&machine->kmaps, map);
        return map;
 }
 
-static int machine__create_modules(struct machine *self)
+static int machine__create_modules(struct machine *machine)
 {
        char *line = NULL;
        size_t n;
@@ -1776,10 +1783,10 @@ static int machine__create_modules(struct machine *self)
        const char *modules;
        char path[PATH_MAX];
 
-       if (machine__is_default_guest(self))
+       if (machine__is_default_guest(machine))
                modules = symbol_conf.default_guest_modules;
        else {
-               sprintf(path, "%s/proc/modules", self->root_dir);
+               sprintf(path, "%s/proc/modules", machine->root_dir);
                modules = path;
        }
 
@@ -1815,16 +1822,16 @@ static int machine__create_modules(struct machine *self)
                *sep = '\0';
 
                snprintf(name, sizeof(name), "[%s]", line);
-               map = machine__new_module(self, start, name);
+               map = machine__new_module(machine, start, name);
                if (map == NULL)
                        goto out_delete_line;
-               dso__kernel_module_get_build_id(map->dso, self->root_dir);
+               dso__kernel_module_get_build_id(map->dso, machine->root_dir);
        }
 
        free(line);
        fclose(file);
 
-       return machine__set_modules_path(self);
+       return machine__set_modules_path(machine);
 
 out_delete_line:
        free(line);
@@ -1832,7 +1839,7 @@ out_failure:
        return -1;
 }
 
-int dso__load_vmlinux(struct dso *self, struct map *map,
+int dso__load_vmlinux(struct dso *dso, struct map *map,
                      const char *vmlinux, symbol_filter_t filter)
 {
        int err = -1, fd;
@@ -1844,9 +1851,9 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
        if (fd < 0)
                return -1;
 
-       dso__set_long_name(self, (char *)vmlinux);
-       dso__set_loaded(self, map->type);
-       err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
+       dso__set_long_name(dso, (char *)vmlinux);
+       dso__set_loaded(dso, map->type);
+       err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0);
        close(fd);
 
        if (err > 0)
@@ -1855,7 +1862,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
        return err;
 }
 
-int dso__load_vmlinux_path(struct dso *self, struct map *map,
+int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                           symbol_filter_t filter)
 {
        int i, err = 0;
@@ -1864,20 +1871,20 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
        pr_debug("Looking at the vmlinux_path (%d entries long)\n",
                 vmlinux_path__nr_entries + 1);
 
-       filename = dso__build_id_filename(self, NULL, 0);
+       filename = dso__build_id_filename(dso, NULL, 0);
        if (filename != NULL) {
-               err = dso__load_vmlinux(self, map, filename, filter);
+               err = dso__load_vmlinux(dso, map, filename, filter);
                if (err > 0) {
-                       dso__set_long_name(self, filename);
+                       dso__set_long_name(dso, filename);
                        goto out;
                }
                free(filename);
        }
 
        for (i = 0; i < vmlinux_path__nr_entries; ++i) {
-               err = dso__load_vmlinux(self, map, vmlinux_path[i], filter);
+               err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
                if (err > 0) {
-                       dso__set_long_name(self, strdup(vmlinux_path[i]));
+                       dso__set_long_name(dso, strdup(vmlinux_path[i]));
                        break;
                }
        }
@@ -1885,7 +1892,7 @@ out:
        return err;
 }
 
-static int dso__load_kernel_sym(struct dso *self, struct map *map,
+static int dso__load_kernel_sym(struct dso *dso, struct map *map,
                                symbol_filter_t filter)
 {
        int err;
@@ -1912,10 +1919,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
        }
 
        if (symbol_conf.vmlinux_name != NULL) {
-               err = dso__load_vmlinux(self, map,
+               err = dso__load_vmlinux(dso, map,
                                        symbol_conf.vmlinux_name, filter);
                if (err > 0) {
-                       dso__set_long_name(self,
+                       dso__set_long_name(dso,
                                           strdup(symbol_conf.vmlinux_name));
                        goto out_fixup;
                }
@@ -1923,7 +1930,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
        }
 
        if (vmlinux_path != NULL) {
-               err = dso__load_vmlinux_path(self, map, filter);
+               err = dso__load_vmlinux_path(dso, map, filter);
                if (err > 0)
                        goto out_fixup;
        }
@@ -1937,13 +1944,13 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
         * we have a build-id, so check if it is the same as the running kernel,
         * using it if it is.
         */
-       if (self->has_build_id) {
+       if (dso->has_build_id) {
                u8 kallsyms_build_id[BUILD_ID_SIZE];
                char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 
                if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
                                         sizeof(kallsyms_build_id)) == 0) {
-                       if (dso__build_id_equal(self, kallsyms_build_id)) {
+                       if (dso__build_id_equal(dso, kallsyms_build_id)) {
                                kallsyms_filename = "/proc/kallsyms";
                                goto do_kallsyms;
                        }
@@ -1952,7 +1959,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
                 * Now look if we have it on the build-id cache in
                 * $HOME/.debug/[kernel.kallsyms].
                 */
-               build_id__sprintf(self->build_id, sizeof(self->build_id),
+               build_id__sprintf(dso->build_id, sizeof(dso->build_id),
                                  sbuild_id);
 
                if (asprintf(&kallsyms_allocated_filename,
@@ -1979,7 +1986,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
        }
 
 do_kallsyms:
-       err = dso__load_kallsyms(self, kallsyms_filename, map, filter);
+       err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
        if (err > 0)
                pr_debug("Using %s for symbols\n", kallsyms_filename);
        free(kallsyms_allocated_filename);
@@ -1987,7 +1994,7 @@ do_kallsyms:
        if (err > 0) {
 out_fixup:
                if (kallsyms_filename != NULL)
-                       dso__set_long_name(self, strdup("[kernel.kallsyms]"));
+                       dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
                map__fixup_start(map);
                map__fixup_end(map);
        }
@@ -1995,8 +2002,8 @@ out_fixup:
        return err;
 }
 
-static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
-                               symbol_filter_t filter)
+static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
+                                     symbol_filter_t filter)
 {
        int err;
        const char *kallsyms_filename = NULL;
@@ -2016,7 +2023,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
                 * Or use file guest_kallsyms inputted by user on commandline
                 */
                if (symbol_conf.default_guest_vmlinux_name != NULL) {
-                       err = dso__load_vmlinux(self, map,
+                       err = dso__load_vmlinux(dso, map,
                                symbol_conf.default_guest_vmlinux_name, filter);
                        goto out_try_fixup;
                }
@@ -2029,7 +2036,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
                kallsyms_filename = path;
        }
 
-       err = dso__load_kallsyms(self, kallsyms_filename, map, filter);
+       err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
        if (err > 0)
                pr_debug("Using %s for symbols\n", kallsyms_filename);
 
@@ -2037,7 +2044,7 @@ out_try_fixup:
        if (err > 0) {
                if (kallsyms_filename != NULL) {
                        machine__mmap_name(machine, path, sizeof(path));
-                       dso__set_long_name(self, strdup(path));
+                       dso__set_long_name(dso, strdup(path));
                }
                map__fixup_start(map);
                map__fixup_end(map);
@@ -2090,12 +2097,12 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
        return ret;
 }
 
-size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp)
+size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
 {
        struct rb_node *nd;
        size_t ret = 0;
 
-       for (nd = rb_first(self); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                ret += __dsos__fprintf(&pos->kernel_dsos, fp);
                ret += __dsos__fprintf(&pos->user_dsos, fp);
@@ -2119,18 +2126,20 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
        return ret;
 }
 
-size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits)
+size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
+                                    bool with_hits)
 {
-       return __dsos__fprintf_buildid(&self->kernel_dsos, fp, with_hits) +
-              __dsos__fprintf_buildid(&self->user_dsos, fp, with_hits);
+       return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) +
+              __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits);
 }
 
-size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits)
+size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
+                                     FILE *fp, bool with_hits)
 {
        struct rb_node *nd;
        size_t ret = 0;
 
-       for (nd = rb_first(self); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
        }
@@ -2139,59 +2148,59 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_
 
 struct dso *dso__new_kernel(const char *name)
 {
-       struct dso *self = dso__new(name ?: "[kernel.kallsyms]");
+       struct dso *dso = dso__new(name ?: "[kernel.kallsyms]");
 
-       if (self != NULL) {
-               dso__set_short_name(self, "[kernel]");
-               self->kernel = DSO_TYPE_KERNEL;
+       if (dso != NULL) {
+               dso__set_short_name(dso, "[kernel]");
+               dso->kernel = DSO_TYPE_KERNEL;
        }
 
-       return self;
+       return dso;
 }
 
 static struct dso *dso__new_guest_kernel(struct machine *machine,
                                        const char *name)
 {
        char bf[PATH_MAX];
-       struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf)));
-
-       if (self != NULL) {
-               dso__set_short_name(self, "[guest.kernel]");
-               self->kernel = DSO_TYPE_GUEST_KERNEL;
+       struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf,
+                                                             sizeof(bf)));
+       if (dso != NULL) {
+               dso__set_short_name(dso, "[guest.kernel]");
+               dso->kernel = DSO_TYPE_GUEST_KERNEL;
        }
 
-       return self;
+       return dso;
 }
 
-void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine)
+void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
 {
        char path[PATH_MAX];
 
        if (machine__is_default_guest(machine))
                return;
        sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
-       if (sysfs__read_build_id(path, self->build_id,
-                                sizeof(self->build_id)) == 0)
-               self->has_build_id = true;
+       if (sysfs__read_build_id(path, dso->build_id,
+                                sizeof(dso->build_id)) == 0)
+               dso->has_build_id = true;
 }
 
-static struct dso *machine__create_kernel(struct machine *self)
+static struct dso *machine__create_kernel(struct machine *machine)
 {
        const char *vmlinux_name = NULL;
        struct dso *kernel;
 
-       if (machine__is_host(self)) {
+       if (machine__is_host(machine)) {
                vmlinux_name = symbol_conf.vmlinux_name;
                kernel = dso__new_kernel(vmlinux_name);
        } else {
-               if (machine__is_default_guest(self))
+               if (machine__is_default_guest(machine))
                        vmlinux_name = symbol_conf.default_guest_vmlinux_name;
-               kernel = dso__new_guest_kernel(self, vmlinux_name);
+               kernel = dso__new_guest_kernel(machine, vmlinux_name);
        }
 
        if (kernel != NULL) {
-               dso__read_running_kernel_build_id(kernel, self);
-               dsos__add(&self->kernel_dsos, kernel);
+               dso__read_running_kernel_build_id(kernel, machine);
+               dsos__add(&machine->kernel_dsos, kernel);
        }
        return kernel;
 }
@@ -2236,41 +2245,43 @@ static u64 machine__get_kernel_start_addr(struct machine *machine)
        return args.start;
 }
 
-int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
+int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
 {
        enum map_type type;
-       u64 start = machine__get_kernel_start_addr(self);
+       u64 start = machine__get_kernel_start_addr(machine);
 
        for (type = 0; type < MAP__NR_TYPES; ++type) {
                struct kmap *kmap;
 
-               self->vmlinux_maps[type] = map__new2(start, kernel, type);
-               if (self->vmlinux_maps[type] == NULL)
+               machine->vmlinux_maps[type] = map__new2(start, kernel, type);
+               if (machine->vmlinux_maps[type] == NULL)
                        return -1;
 
-               self->vmlinux_maps[type]->map_ip =
-                       self->vmlinux_maps[type]->unmap_ip = identity__map_ip;
-
-               kmap = map__kmap(self->vmlinux_maps[type]);
-               kmap->kmaps = &self->kmaps;
-               map_groups__insert(&self->kmaps, self->vmlinux_maps[type]);
+               machine->vmlinux_maps[type]->map_ip =
+                       machine->vmlinux_maps[type]->unmap_ip =
+                               identity__map_ip;
+               kmap = map__kmap(machine->vmlinux_maps[type]);
+               kmap->kmaps = &machine->kmaps;
+               map_groups__insert(&machine->kmaps,
+                                  machine->vmlinux_maps[type]);
        }
 
        return 0;
 }
 
-void machine__destroy_kernel_maps(struct machine *self)
+void machine__destroy_kernel_maps(struct machine *machine)
 {
        enum map_type type;
 
        for (type = 0; type < MAP__NR_TYPES; ++type) {
                struct kmap *kmap;
 
-               if (self->vmlinux_maps[type] == NULL)
+               if (machine->vmlinux_maps[type] == NULL)
                        continue;
 
-               kmap = map__kmap(self->vmlinux_maps[type]);
-               map_groups__remove(&self->kmaps, self->vmlinux_maps[type]);
+               kmap = map__kmap(machine->vmlinux_maps[type]);
+               map_groups__remove(&machine->kmaps,
+                                  machine->vmlinux_maps[type]);
                if (kmap->ref_reloc_sym) {
                        /*
                         * ref_reloc_sym is shared among all maps, so free just
@@ -2284,25 +2295,25 @@ void machine__destroy_kernel_maps(struct machine *self)
                        kmap->ref_reloc_sym = NULL;
                }
 
-               map__delete(self->vmlinux_maps[type]);
-               self->vmlinux_maps[type] = NULL;
+               map__delete(machine->vmlinux_maps[type]);
+               machine->vmlinux_maps[type] = NULL;
        }
 }
 
-int machine__create_kernel_maps(struct machine *self)
+int machine__create_kernel_maps(struct machine *machine)
 {
-       struct dso *kernel = machine__create_kernel(self);
+       struct dso *kernel = machine__create_kernel(machine);
 
        if (kernel == NULL ||
-           __machine__create_kernel_maps(self, kernel) < 0)
+           __machine__create_kernel_maps(machine, kernel) < 0)
                return -1;
 
-       if (symbol_conf.use_modules && machine__create_modules(self) < 0)
+       if (symbol_conf.use_modules && machine__create_modules(machine) < 0)
                pr_debug("Problems creating module maps, continuing anyway...\n");
        /*
         * Now that we have all the maps created, just set the ->end of them:
         */
-       map_groups__fixup_end(&self->kmaps);
+       map_groups__fixup_end(&machine->kmaps);
        return 0;
 }
 
@@ -2366,11 +2377,11 @@ out_fail:
        return -1;
 }
 
-size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp)
+size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
 {
        int i;
        size_t printed = 0;
-       struct dso *kdso = self->vmlinux_maps[MAP__FUNCTION]->dso;
+       struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
 
        if (kdso->has_build_id) {
                char filename[PATH_MAX];
@@ -2467,9 +2478,9 @@ void symbol__exit(void)
        symbol_conf.initialized = false;
 }
 
-int machines__create_kernel_maps(struct rb_root *self, pid_t pid)
+int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
 {
-       struct machine *machine = machines__findnew(self, pid);
+       struct machine *machine = machines__findnew(machines, pid);
 
        if (machine == NULL)
                return -1;
@@ -2520,7 +2531,7 @@ char *strxfrchar(char *s, char from, char to)
        return s;
 }
 
-int machines__create_guest_kernel_maps(struct rb_root *self)
+int machines__create_guest_kernel_maps(struct rb_root *machines)
 {
        int ret = 0;
        struct dirent **namelist = NULL;
@@ -2531,7 +2542,7 @@ int machines__create_guest_kernel_maps(struct rb_root *self)
        if (symbol_conf.default_guest_vmlinux_name ||
            symbol_conf.default_guest_modules ||
            symbol_conf.default_guest_kallsyms) {
-               machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID);
+               machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
        }
 
        if (symbol_conf.guestmount) {
@@ -2552,7 +2563,7 @@ int machines__create_guest_kernel_maps(struct rb_root *self)
                                pr_debug("Can't access file %s\n", path);
                                goto failure;
                        }
-                       machines__create_kernel_maps(self, pid);
+                       machines__create_kernel_maps(machines, pid);
                }
 failure:
                free(namelist);
@@ -2561,23 +2572,23 @@ failure:
        return ret;
 }
 
-void machines__destroy_guest_kernel_maps(struct rb_root *self)
+void machines__destroy_guest_kernel_maps(struct rb_root *machines)
 {
-       struct rb_node *next = rb_first(self);
+       struct rb_node *next = rb_first(machines);
 
        while (next) {
                struct machine *pos = rb_entry(next, struct machine, rb_node);
 
                next = rb_next(&pos->rb_node);
-               rb_erase(&pos->rb_node, self);
+               rb_erase(&pos->rb_node, machines);
                machine__delete(pos);
        }
 }
 
-int machine__load_kallsyms(struct machine *self, const char *filename,
+int machine__load_kallsyms(struct machine *machine, const char *filename,
                           enum map_type type, symbol_filter_t filter)
 {
-       struct map *map = self->vmlinux_maps[type];
+       struct map *map = machine->vmlinux_maps[type];
        int ret = dso__load_kallsyms(map->dso, filename, map, filter);
 
        if (ret > 0) {
@@ -2587,16 +2598,16 @@ int machine__load_kallsyms(struct machine *self, const char *filename,
                 * kernel, with modules between them, fixup the end of all
                 * sections.
                 */
-               __map_groups__fixup_end(&self->kmaps, type);
+               __map_groups__fixup_end(&machine->kmaps, type);
        }
 
        return ret;
 }
 
-int machine__load_vmlinux_path(struct machine *self, enum map_type type,
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
                               symbol_filter_t filter)
 {
-       struct map *map = self->vmlinux_maps[type];
+       struct map *map = machine->vmlinux_maps[type];
        int ret = dso__load_vmlinux_path(map->dso, map, filter);
 
        if (ret > 0) {
index 713b0b40cc4acbb6f01ff6b7b366dc845d9d1852..242de0101a868f99d38c0fbf7348590556f8187f 100644 (file)
@@ -62,7 +62,7 @@ struct symbol {
        char            name[0];
 };
 
-void symbol__delete(struct symbol *self);
+void symbol__delete(struct symbol *sym);
 
 struct strlist;
 
@@ -96,9 +96,9 @@ struct symbol_conf {
 
 extern struct symbol_conf symbol_conf;
 
-static inline void *symbol__priv(struct symbol *self)
+static inline void *symbol__priv(struct symbol *sym)
 {
-       return ((void *)self) - symbol_conf.priv_size;
+       return ((void *)sym) - symbol_conf.priv_size;
 }
 
 struct ref_reloc_sym {
@@ -155,43 +155,45 @@ struct dso {
 
 struct dso *dso__new(const char *name);
 struct dso *dso__new_kernel(const char *name);
-void dso__delete(struct dso *self);
+void dso__delete(struct dso *dso);
 
-int dso__name_len(const struct dso *self);
+int dso__name_len(const struct dso *dso);
 
-bool dso__loaded(const struct dso *self, enum map_type type);
-bool dso__sorted_by_name(const struct dso *self, enum map_type type);
+bool dso__loaded(const struct dso *dso, enum map_type type);
+bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
 
-static inline void dso__set_loaded(struct dso *self, enum map_type type)
+static inline void dso__set_loaded(struct dso *dso, enum map_type type)
 {
-       self->loaded |= (1 << type);
+       dso->loaded |= (1 << type);
 }
 
-void dso__sort_by_name(struct dso *self, enum map_type type);
+void dso__sort_by_name(struct dso *dso, enum map_type type);
 
 struct dso *__dsos__findnew(struct list_head *head, const char *name);
 
-int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
-int dso__load_vmlinux(struct dso *self, struct map *map,
+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);
-int dso__load_vmlinux_path(struct dso *self, struct map *map,
+int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                           symbol_filter_t filter);
-int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
+int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
                       symbol_filter_t filter);
-int machine__load_kallsyms(struct machine *self, const char *filename,
+int machine__load_kallsyms(struct machine *machine, const char *filename,
                           enum map_type type, symbol_filter_t filter);
-int machine__load_vmlinux_path(struct machine *self, enum map_type type,
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
                               symbol_filter_t filter);
 
 size_t __dsos__fprintf(struct list_head *head, FILE *fp);
 
-size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits);
-size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp);
-size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
-
-size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
-size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp);
-size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
+size_t machine__fprintf_dsos_buildid(struct machine *machine,
+                                    FILE *fp, bool with_hits);
+size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
+size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
+                                     FILE *fp, bool with_hits);
+size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
+size_t dso__fprintf_symbols_by_name(struct dso *dso,
+                                   enum map_type type, FILE *fp);
+size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
 
 enum symtab_type {
        SYMTAB__KALLSYMS = 0,
@@ -207,34 +209,36 @@ enum symtab_type {
        SYMTAB__NOT_FOUND,
 };
 
-char dso__symtab_origin(const struct dso *self);
-void dso__set_long_name(struct dso *self, char *name);
-void dso__set_build_id(struct dso *self, void *build_id);
-void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine);
-struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
-struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
+char dso__symtab_origin(const struct dso *dso);
+void dso__set_long_name(struct dso *dso, char *name);
+void dso__set_build_id(struct dso *dso, void *build_id);
+void dso__read_running_kernel_build_id(struct dso *dso,
+                                      struct machine *machine);
+struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
+                               u64 addr);
+struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
                                        const char *name);
 
 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);
 bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
-int build_id__sprintf(const u8 *self, int len, char *bf);
+int build_id__sprintf(const u8 *build_id, int len, char *bf);
 int kallsyms__parse(const char *filename, void *arg,
                    int (*process_symbol)(void *arg, const char *name,
                                          char type, u64 start, u64 end));
 
-void machine__destroy_kernel_maps(struct machine *self);
-int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
-int machine__create_kernel_maps(struct machine *self);
+void machine__destroy_kernel_maps(struct machine *machine);
+int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
+int machine__create_kernel_maps(struct machine *machine);
 
-int machines__create_kernel_maps(struct rb_root *self, pid_t pid);
-int machines__create_guest_kernel_maps(struct rb_root *self);
-void machines__destroy_guest_kernel_maps(struct rb_root *self);
+int machines__create_kernel_maps(struct rb_root *machines, pid_t pid);
+int machines__create_guest_kernel_maps(struct rb_root *machines);
+void machines__destroy_guest_kernel_maps(struct rb_root *machines);
 
 int symbol__init(void);
 void symbol__exit(void);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
-size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp);
+size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
 
 #endif /* __PERF_SYMBOL */
index 0a7ed5b5e281c88b321de87ced66a3d29ebb003d..1e88485c16a04b755e68bb14510c3fd5cf368769 100644 (file)
@@ -2187,7 +2187,6 @@ static const struct flag flags[] = {
        { "TASKLET_SOFTIRQ", 6 },
        { "SCHED_SOFTIRQ", 7 },
        { "HRTIMER_SOFTIRQ", 8 },
-       { "RCU_SOFTIRQ", 9 },
 
        { "HRTIMER_NORESTART", 0 },
        { "HRTIMER_RESTART", 1 },
index 8c17a8730e4a36a9923537f79466c3793fd06559..15633d6081332f0204acc978974ff6deec8d2375 100644 (file)
@@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
                         int refresh)
 {
        struct objdump_line *pos, *n;
-       struct annotation *notes = symbol__annotation(sym);
+       struct annotation *notes;
        struct annotate_browser browser = {
                .b = {
-                       .entries = &notes->src->source,
                        .refresh = ui_browser__list_head_refresh,
                        .seek    = ui_browser__list_head_seek,
                        .write   = annotate_browser__write,
@@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 
        ui_helpline__push("Press <- or ESC to exit");
 
+       notes = symbol__annotation(sym);
+
        list_for_each_entry(pos, &notes->src->source, node) {
                struct objdump_line_rb_node *rbpos;
                size_t line_len = strlen(pos->line);
@@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
                rbpos->idx = browser.b.nr_entries++;
        }
 
+       browser.b.entries = &notes->src->source,
        browser.b.width += 18; /* Percentage */
        ret = annotate_browser__run(&browser, evidx, refresh);
        list_for_each_entry_safe(pos, n, &notes->src->source, node) {
index 798efdca3eadd9fe89b84157ceba5c56a8d5dcb2..5d767c622dfc1f862fb747ababa610e9031944c8 100644 (file)
@@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
                        goto out_free_stack;
                case 'a':
                        if (browser->selection == NULL ||
-                           browser->selection->map == NULL ||
+                           browser->selection->sym == NULL ||
                            browser->selection->map->dso->annotate_warned)
                                continue;
                        goto do_annotate;