Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 00:36:08 +0000 (17:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 00:36:08 +0000 (17:36 -0700)
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (107 commits)
  perf stat: Add more cache-miss percentage printouts
  perf stat: Add -d -d and -d -d -d options to show more CPU events
  ftrace/kbuild: Add recordmcount files to force full build
  ftrace: Add self-tests for multiple function trace users
  ftrace: Modify ftrace_set_filter/notrace to take ops
  ftrace: Allow dynamically allocated function tracers
  ftrace: Implement separate user function filtering
  ftrace: Free hash with call_rcu_sched()
  ftrace: Have global_ops store the functions that are to be traced
  ftrace: Add ops parameter to ftrace_startup/shutdown functions
  ftrace: Add enabled_functions file
  ftrace: Use counters to enable functions to trace
  ftrace: Separate hash allocation and assignment
  ftrace: Create a global_ops to hold the filter and notrace hashes
  ftrace: Use hash instead for FTRACE_FL_FILTER
  ftrace: Replace FTRACE_FL_NOTRACE flag with a hash of ignored functions
  perf bench, x86: Add alternatives-asm.h wrapper
  x86, 64-bit: Fix copy_[to/from]_user() checks for the userspace address limit
  x86, mem: memset_64.S: Optimize memset by enhanced REP MOVSB/STOSB
  x86, mem: memmove_64.S: Optimize memmove by enhanced REP MOVSB/STOSB
  ...

701 files changed:
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-power
Documentation/DocBook/genericirq.tmpl
Documentation/feature-removal-schedule.txt
Documentation/kernel-parameters.txt
Documentation/power/devices.txt
Documentation/power/notifiers.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/x86/x86_64/boot-options.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/unistd.h
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/include/asm/mach/time.h
arch/arm/include/asm/system.h
arch/arm/kernel/leds.c
arch/arm/kernel/signal.c
arch/arm/kernel/time.c
arch/arm/mach-davinci/cpufreq.c
arch/arm/mach-exynos4/pm.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-omap1/pm_bus.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/pm_bus.c [deleted file]
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/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.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-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/mm/init.c
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/mach-common/dpmc.c
arch/ia64/kernel/cpufreq/acpi-cpufreq.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/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/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/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/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/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/cpu-probe.c
arch/mips/kernel/entry.S
arch/mips/kernel/ftrace.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/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/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/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-klnuma.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sni/time.c
arch/powerpc/include/asm/mpic.h
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/include/asm/cacheflush.h
arch/s390/include/asm/diag.h
arch/s390/include/asm/mmu_context.h
arch/s390/kernel/diag.c
arch/s390/kernel/dis.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/mm/cmm.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/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/time_32.c
arch/sparc/lib/checksum_32.S
arch/um/os-Linux/util.c
arch/unicore32/kernel/irq.c
arch/x86/Kconfig
arch/x86/include/asm/amd_iommu_proto.h
arch/x86/include/asm/amd_iommu_types.h
arch/x86/include/asm/apicdef.h
arch/x86/include/asm/pgtable_types.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/amd_gart_64.c [moved from arch/x86/kernel/pci-gart_64.c with 100% similarity]
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.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/cpufreq/Makefile [deleted file]
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/kprobes.c
arch/x86/kernel/pci-iommu_table.c
arch/x86/kernel/x86_init.c
arch/x86/lguest/boot.c
arch/x86/mm/init.c
arch/x86/pci/xen.c
arch/x86/platform/uv/tlb_uv.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
block/blk-cgroup.c
block/blk-cgroup.h
block/blk-core.c
block/blk-throttle.c
block/cfq-iosched.c
drivers/acpi/processor_perflib.c
drivers/ata/libahci.c
drivers/ata/libata-eh.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/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/hw_random/n2-drv.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/xilinx_hwicap/xilinx_hwicap.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/ppc4xx_edac.c
drivers/firmware/iscsi_ibft_find.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/vga/vga_switcheroo.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-pnx.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_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/leds/leds-lm3530.c
drivers/lguest/Kconfig
drivers/lguest/Makefile
drivers/media/video/cx88/cx88-input.c
drivers/media/video/soc_camera.c
drivers/media/video/v4l2-device.c
drivers/media/video/v4l2-subdev.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/host.c
drivers/mmc/host/sdhci-of-core.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/net/Kconfig
drivers/net/Makefile
drivers/net/arm/etherh.c
drivers/net/atarilance.c
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/bonding/bond_3ad.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/mii-fec.c
drivers/net/hydra.c
drivers/net/lantiq_etop.c [new file with mode: 0644]
drivers/net/ne-h8300.c
drivers/net/pch_gbe/pch_gbe_main.c
drivers/net/sfc/mcdi.c
drivers/net/sfc/nic.c
drivers/net/sfc/nic.h
drivers/net/sfc/siena.c
drivers/net/slip.c
drivers/net/sunhme.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/ipheth.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlegacy/iwl-core.c
drivers/net/wireless/iwlegacy/iwl-dev.h
drivers/net/wireless/libertas/cmd.c
drivers/net/zorro8390.c
drivers/pci/intel-iommu.c
drivers/pci/iov.c
drivers/pci/pci.h
drivers/pci/setup-bus.c
drivers/rapidio/switches/idt_gen2.c
drivers/rapidio/switches/idtcps.c
drivers/rapidio/switches/tsi57x.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-pcap.c
drivers/rtc/rtc-rp5c01.c
drivers/rtc/rtc-s3c.c
drivers/s390/block/dasd.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/tape_block.c
drivers/scsi/qlogicpti.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/ssb/pci.c
drivers/ssb/sprom.c
drivers/ssb/ssb_private.h
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/lantiq.c [new file with mode: 0644]
drivers/tty/serial/of_serial.c
drivers/usb/gadget/fsl_qe_udc.c
drivers/vhost/vhost.c
drivers/video/acornfb.c
drivers/video/atafb.c
drivers/video/fbmem.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
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/extent-tree.c
fs/btrfs/ioctl.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h
fs/cifs/cifs_unicode.c
fs/cifs/connect.c
fs/configfs/dir.c
fs/debugfs/file.c
fs/fuse/dir.c
fs/namei.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/read.c
fs/nfs/write.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/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/linux/bootmem.h
include/linux/bsearch.h [new file with mode: 0644]
include/linux/capability.h
include/linux/cpufreq.h
include/linux/cred.h
include/linux/device.h
include/linux/fb.h
include/linux/fs.h
include/linux/gfp.h
include/linux/irq.h
include/linux/irqdesc.h
include/linux/kmod.h
include/linux/list.h
include/linux/mmc/host.h
include/linux/module.h
include/linux/moduleparam.h
include/linux/nfs_xdr.h
include/linux/of_device.h
include/linux/pci-ats.h [new file with mode: 0644]
include/linux/platform_device.h
include/linux/pm.h
include/linux/pm_runtime.h
include/linux/proc_fs.h
include/linux/rculist.h
include/linux/seqlock.h
include/linux/ssb/ssb.h
include/linux/string.h
include/linux/sysdev.h
include/net/inet_ecn.h
include/net/ip_vs.h
include/net/llc_pdu.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/xen/events.h
init/Kconfig
init/main.c
kernel/capability.c
kernel/cred.c
kernel/freezer.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/settings.h
kernel/kexec.c
kernel/kmod.c
kernel/lockdep.c
kernel/module.c
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/sys.c
kernel/time/clocksource.c
kernel/time/tick-broadcast.c
lib/Kconfig.debug
lib/Makefile
lib/bsearch.c [new file with mode: 0644]
lib/dma-debug.c
lib/string.c
lib/vsprintf.c
mm/kmemleak.c
mm/page_alloc.c
mm/page_cgroup.c
mm/shmem.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/bluetooth/sco.c
net/bridge/br_netfilter.c
net/bridge/netfilter/ebtables.c
net/core/dev.c
net/dccp/options.c
net/ipv4/ip_fragment.c
net/ipv4/tcp_cubic.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_state.c
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_state.c
net/mac80211/tx.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_netlink.c
net/netfilter/x_tables.c
net/netfilter/xt_DSCP.c
net/netfilter/xt_conntrack.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/module-common.lds
security/selinux/ss/policydb.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/wm8903.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/mid-x86/sst_platform.c
sound/soc/soc-core.c
tools/perf/builtin-record.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/python.c

index c17cd4b..1b777b9 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 194ca44..b464d12 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 fb10fd0..b342234 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 492e81d..f6a24e8 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 cc85a92..259037b 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
index 1971bcf..8888083 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 cf98070..c2a4a34 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,
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 730475a..a850986 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 dad9997..bff0c55 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 092e596..c54b4f5 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 16a5c5f..8df8d2d 100644 (file)
@@ -405,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/
 
@@ -2813,38 +2813,19 @@ 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
@@ -2895,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>
@@ -2945,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/
 
@@ -3478,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
@@ -3807,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
@@ -3994,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
@@ -4989,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
@@ -6618,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/
@@ -7024,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 e7d01ad..a0344a8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 39
-EXTRAVERSION = -rc7
+EXTRAVERSION =
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index 058937b..b183416 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 a6a1de9..15f999d 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 918e8e0..818e74e 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 8ebbb51..0c6852d 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 adf583c..49f5b2e 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 5309909..ea80abe 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 113085a..7aa4262 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;
 }
index 883f6be..d5adaae 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 885be09..832888d 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 31a316c..0f107dc 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 cb83983..0340224 100644 (file)
@@ -597,19 +597,13 @@ 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;
@@ -617,26 +611,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        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
         */
        if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
@@ -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 1ff46ca..cb634c3 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 0a95be1..41669ec 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 10d917d..8755ca8 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 980803f..d3e9645 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 6588c22..fe31d93 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 512b152..66dfbcc 100644 (file)
@@ -59,10 +59,10 @@ 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
index b2b1e37..d6e34dd 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;
 }
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 bfbecec..810a982 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 1ce0904..1d5859d 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 3f864cd..2a37a9a 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 f9f349a..1f2fb9c 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 b88d601..13518a7 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 8225e2e..a109967 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 81c3c43..d28e802 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 44c1b77..80538b8 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 6fc5d32..7545a48 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 a079d8b..e6c9344 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 6251e3f..32ed551 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 f5de541..6cf8180 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 3ede978..e10ddb8 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 95163ba..3479e2b 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 1d1419b..87ae312 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 7a270ee..89863a0 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 23925db..e347013 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 a6f898c..4061ecd 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 8aadad5..20d1b18 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 3b8a4f3..65f24f0 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 a4af8c5..fed363c 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 909756e..2fecbec 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 8dd1073..8521d7d 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 23b229b..ecc82a3 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 cd18613..d130f77 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 232b731..7992305 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 b9cfbeb..687417a 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 b523f11..903218e 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 f71d377..67bd414 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 0c5d749..9a73219 100644 (file)
@@ -4,5 +4,5 @@
  * operation to deadlock the system.
  */
 #define mb()           dsb()
-#define rmb()          dmb()
+#define rmb()          dsb()
 #define wmb()          mb()
index 5e2f353..2854129 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 2970ea9..1e2d536 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 725636f..4728f9a 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 adc90a3..f1d3bd8 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 f3355d2..1a1aa22 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 923e01b..85dcaeb 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 a7417c4..752b13a 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 4c6df51..ef0958d 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 77b38f2..28ad20d 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 4a04205..41db2b2 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 ba7fd87..494ce91 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 14dc678..d885363 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 f7663f7..ce99ff7 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 ecf8135..6224bad 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 de07c2f..c63e8f2 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 90c1707..7e8a23d 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 da1bec6..8bec61e 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 549d792..24febae 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 423ddb3..dfbf824 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 94912d3..2d1b67a 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 cc11517..425b42e 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 e5f6fc4..e591513 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 d2adcdd..bd9e321 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 8a51fd5..34fc31e 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 9bbda9a..a37b8eb 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 dce088f..48ebb94 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 a9aa5ad..be12ead 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 27ea852..c10d10c 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 c3624d8..0efb2e2 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 5259ad4..327acb3 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 cedfff5..3aedac0 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 937cc2a..7fb6f6b 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 f746950..f25e7ec 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 21ce35f..3e36461 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 0b5f72f..401eb1d 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 382099f..5e4112e 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 22f6152..f09b174 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 b995513..95022b0 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 604329f..ddbf43c 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 546e7da..68f3622 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 9d69f6e..e9020f8 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 29e1790..f3b649d 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 55d5d6b..aced678 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 1359ee6..bd0ec05 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 9b8393d..5909e39 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 7ff9b54..aef6c91 100644 (file)
@@ -11,6 +11,7 @@ platforms += dec
 platforms += emma
 platforms += jazz
 platforms += jz4740
+platforms += lantiq
 platforms += lasat
 platforms += loongson
 platforms += mipssim
index 8e256cc..2d1cf97 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
index 53e3514..884819c 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 ca0506a..3a5abb5 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 d527887..347980e 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 55dd7c8..8b60ba0 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 9e7814d..3b2c18b 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 561e5da..1b887c8 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 4a89800..1dac4f2 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 05f120f..5c956fe 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 2d85c4b..e64fdcb 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 83f4621..3b4fa32 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 baeb213..e5306b5 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 ad2e3f1..5f8f069 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 f044f4c..229aafa 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 cf436ab..3ae984c 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 f8d2557..2e81cc7 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 956f946..55628e3 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 febfb0f..81e57fa 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 15125c2..0ee02cf 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 425dfa5..bb571bc 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 e5b6615..54db815 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 c95f90b..73b529b 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 8dba8cf..40b223b 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 88c9d96..9a62436 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 1bff22f..eb063e6 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 caae228..cad555e 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 0707fae..2d9028f 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 ba78b21..716fae6 100644 (file)
@@ -37,7 +37,7 @@ 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);
@@ -200,16 +200,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 167c1d0..b6acd2f 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 7270f31..5527abb 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 a97a42c..37862b2 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 650ac9b..b4db69f 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 fa4328f..65f9bdd 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 8687753..34c0d3c 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 655f849..7aa37dd 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 f5e8560..c565b7c 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 a697661..f260ebe 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 c333b4e..59f5b55 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 c8a553a..2fdacfe 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 62d2f13..1f41a52 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 9759588..184d5ec 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 32978d3..ed72e6a 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 0b2b5eb..dedef7d 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 d94085a..bc01a02 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 9f1b8db..de39b1f 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 d71160d..97f8bf6 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 9ce9f64..2d8e447 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 5ebe75a..d7feb89 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 6a9e14d..d97cfbf 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 fe01678..eaa853a 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,
index b2c0151..654d5c3 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 cedee2b..83bba33 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 f65d4c8..bb133d1 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 ffa3310..37acfa0 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 94ca2b0..feb8021 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 d21c388..4e6ea1f 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 7f5468b..7a8e1dd 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 a2e1fcb..2d31c83 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 b2c7624..38a0503 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 049a9c8..91ea5e4 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 58beabf..d027657 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 71350f7..e9b3af2 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 832afbb..cd2ca54 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 2adead5..b2cad4f 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 11b193f..d93830a 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 d679c77..4d8c162 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 b4923a7..d9bc5d3 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 5ef294f..424ed4b 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 414f0c9..31180c3 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 9027061..e85c977 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);
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 c9209ca..4df8799 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 f9b9dcd..98fd009 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 dbb5c7b..f8a751c 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 37de05d..6c47dfe 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 deddbf0..698904d 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 603fc91..1a94c98 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 a1fa4ab..cd0d5b0 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 c3d30a8..1d1919a 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 a152538..3f810c9 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;
index c76151b..0904d4d 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 7005ee0..49baddc 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 1882729..104faa8 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 acfacce..3675da7 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 023f240..7c18a16 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 d5679dc..01cd2f0 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 fa438be..596554a 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 f91c065..7e5dc8f 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 43a5c78..3e20383 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 72b2e2f..7e91c58 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 a6f0e7c..8c277ca 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 c032d11..8237fc0 100644 (file)
@@ -9,27 +9,6 @@
 #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
  */
 int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
index c83726c..3d4a78f 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 648f642..1b67fc6 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 9d3603d..9fd8645 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
index c66ffd8..1f1dba9 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 0607e4b..f05edcc 100644 (file)
@@ -54,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 4952872..33cbd37 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 8c72b59..1912f3b 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 c63d7e5..5995e9b 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 4b89da2..bc439de 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 e71a531..77ec0e7 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 dc4a2eb..c416505 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 6dcb816..22db127 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 f679c57..1e34f29 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 948068a..d1840db 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 fecfcb2..283fbc3 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 93d7b44..6a585d3 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 91c10fb..850a136 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)
index 4e23639..96046a4 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 3632cb3..0084c33 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 6ea7797..42827ca 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 2aa30a3..d4efa7d 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 cc6c53a..650bb8c 100644 (file)
@@ -71,7 +71,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)
@@ -690,6 +689,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
@@ -1848,7 +1848,7 @@ config APM_ALLOW_INTS
 
 endif # APM
 
-source "arch/x86/kernel/cpu/cpufreq/Kconfig"
+source "drivers/cpufreq/Kconfig"
 
 source "drivers/cpuidle/Kconfig"
 
index 916bc81..55d95eb 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 e3509fc..4c99829 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 d87988b..34595d5 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 7db7723..d56187c 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);
index 3e094af..130f1ee 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 a501741..4298002 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 20cafea..f5bb64a 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 643ebf2..d3d8590 100644 (file)
@@ -68,6 +68,17 @@ struct x86_init_oem {
 };
 
 /**
+ * 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
  * @pagetable_setup_done:      platform specific post 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 c61934f..64a619d 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 aa86209..4fbda9a 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 7338ef2..97ebf82 100644 (file)
@@ -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 ff93bc1..18a857b 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 57ca777..873e7e1 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 246d727..9179c21 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 33b10a0..7acd2d2 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 adee12e..3bfa022 100644 (file)
@@ -1238,7 +1238,6 @@ static int suspend(int vetoable)
        dpm_suspend_noirq(PMSG_SUSPEND);
 
        local_irq_disable();
-       sysdev_suspend(PMSG_SUSPEND);
        syscore_suspend();
 
        local_irq_enable();
@@ -1258,7 +1257,6 @@ static int suspend(int vetoable)
        err = (err == APM_SUCCESS) ? 0 : -EIO;
 
        syscore_resume();
-       sysdev_resume();
        local_irq_enable();
 
        dpm_resume_noirq(PMSG_RESUME);
@@ -1282,7 +1280,6 @@ static void standby(void)
        dpm_suspend_noirq(PMSG_SUSPEND);
 
        local_irq_disable();
-       sysdev_suspend(PMSG_SUSPEND);
        syscore_suspend();
        local_irq_enable();
 
@@ -1292,7 +1289,6 @@ static void standby(void)
 
        local_irq_disable();
        syscore_resume();
-       sysdev_resume();
        local_irq_enable();
 
        dpm_resume_noirq(PMSG_RESUME);
index 3f0ebe4..6042981 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 bb9eb29..6f9d1f6 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);
 
        /*
@@ -698,7 +698,7 @@ cpu_dev_register(amd_cpu_dev);
  */
 
 const int amd_erratum_400[] =
-       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf),
+       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
                            AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
 EXPORT_SYMBOL_GPL(amd_erratum_400);
 
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 167f97b..bb0adad 100644 (file)
@@ -509,6 +509,7 @@ recurse:
 out_free:
        if (b) {
                kobject_put(&b->kobj);
+               list_del(&b->miscj);
                kfree(b);
        }
        return err;
index 6f8c5e9..0f03446 100644 (file)
@@ -446,18 +446,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 c969fd9..f1a6244 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 55d745e..35ccf75 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);
                }
        }
 }
index c11514e..75ef4b1 100644 (file)
@@ -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 1cd6089..395bf01 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
index 286d289..37b8b0f 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 e37b407..8214724 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 7cb6424..c58e0ea 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 e3c6a06..dd7b88f 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 6a6fe89..8bbb465 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 55c965b..02d7524 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();
@@ -1463,119 +1477,6 @@ static int xen_pgd_alloc(struct mm_struct *mm)
        return ret;
 }
 
-#ifdef CONFIG_X86_64
-static __initdata u64 __last_pgt_set_rw = 0;
-static __initdata u64 __pgt_buf_start = 0;
-static __initdata u64 __pgt_buf_end = 0;
-static __initdata u64 __pgt_buf_top = 0;
-/*
- * As a consequence of the commit:
- * 
- * commit 4b239f458c229de044d6905c2b0f9fe16ed9e01e
- * Author: Yinghai Lu <yinghai@kernel.org>
- * Date:   Fri Dec 17 16:58:28 2010 -0800
- * 
- *     x86-64, mm: Put early page table high
- * 
- * at some point init_memory_mapping is going to reach the pagetable pages
- * area and map those pages too (mapping them as normal memory that falls
- * in the range of addresses passed to init_memory_mapping as argument).
- * Some of those pages are already pagetable pages (they are in the range
- * pgt_buf_start-pgt_buf_end) therefore they are going to be mapped RO and
- * everything is fine.
- * Some of these pages are not pagetable pages yet (they fall in the range
- * pgt_buf_end-pgt_buf_top; for example the page at pgt_buf_end) so they
- * are going to be mapped RW.  When these pages become pagetable pages and
- * are hooked into the pagetable, xen will find that the guest has already
- * a RW mapping of them somewhere and fail the operation.
- * The reason Xen requires pagetables to be RO is that the hypervisor needs
- * to verify that the pagetables are valid before using them. The validation
- * operations are called "pinning".
- * 
- * In order to fix the issue we mark all the pages in the entire range
- * pgt_buf_start-pgt_buf_top as RO, however when the pagetable allocation
- * is completed only the range pgt_buf_start-pgt_buf_end is reserved by
- * init_memory_mapping. Hence the kernel is going to crash as soon as one
- * of the pages in the range pgt_buf_end-pgt_buf_top is reused (b/c those
- * ranges are RO).
- * 
- * For this reason, 'mark_rw_past_pgt' is introduced which is called _after_
- * the init_memory_mapping has completed (in a perfect world we would
- * call this function from init_memory_mapping, but lets ignore that).
- * 
- * Because we are called _after_ init_memory_mapping the pgt_buf_[start,
- * end,top] have all changed to new values (b/c init_memory_mapping
- * is called and setting up another new page-table). Hence, the first time
- * we enter this function, we save away the pgt_buf_start value and update
- * the pgt_buf_[end,top].
- * 
- * When we detect that the "old" pgt_buf_start through pgt_buf_end
- * PFNs have been reserved (so memblock_x86_reserve_range has been called),
- * we immediately set out to RW the "old" pgt_buf_end through pgt_buf_top.
- * 
- * And then we update those "old" pgt_buf_[end|top] with the new ones
- * so that we can redo this on the next pagetable.
- */
-static __init void mark_rw_past_pgt(void) {
-
-       if (pgt_buf_end > pgt_buf_start) {
-               u64 addr, size;
-
-               /* Save it away. */
-               if (!__pgt_buf_start) {
-                       __pgt_buf_start = pgt_buf_start;
-                       __pgt_buf_end = pgt_buf_end;
-                       __pgt_buf_top = pgt_buf_top;
-                       return;
-               }
-               /* If we get the range that starts at __pgt_buf_end that means
-                * the range is reserved, and that in 'init_memory_mapping'
-                * the 'memblock_x86_reserve_range' has been called with the
-                * outdated __pgt_buf_start, __pgt_buf_end (the "new"
-                * pgt_buf_[start|end|top] refer now to a new pagetable.
-                * Note: we are called _after_ the pgt_buf_[..] have been
-                * updated.*/
-
-               addr = memblock_x86_find_in_range_size(PFN_PHYS(__pgt_buf_start),
-                                                      &size, PAGE_SIZE);
-
-               /* Still not reserved, meaning 'memblock_x86_reserve_range'
-                * hasn't been called yet. Update the _end and _top.*/
-               if (addr == PFN_PHYS(__pgt_buf_start)) {
-                       __pgt_buf_end = pgt_buf_end;
-                       __pgt_buf_top = pgt_buf_top;
-                       return;
-               }
-
-               /* OK, the area is reserved, meaning it is time for us to
-                * set RW for the old end->top PFNs. */
-
-               /* ..unless we had already done this. */
-               if (__pgt_buf_end == __last_pgt_set_rw)
-                       return;
-
-               addr = PFN_PHYS(__pgt_buf_end);
-               
-               /* set as RW the rest */
-               printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n",
-                       PFN_PHYS(__pgt_buf_end), PFN_PHYS(__pgt_buf_top));
-               
-               while (addr < PFN_PHYS(__pgt_buf_top)) {
-                       make_lowmem_page_readwrite(__va(addr));
-                       addr += PAGE_SIZE;
-               }
-               /* And update everything so that we are ready for the next
-                * pagetable (the one created for regions past 4GB) */
-               __last_pgt_set_rw = __pgt_buf_end;
-               __pgt_buf_start = pgt_buf_start;
-               __pgt_buf_end = pgt_buf_end;
-               __pgt_buf_top = pgt_buf_top;
-       }
-       return;
-}
-#else
-static __init void mark_rw_past_pgt(void) { }
-#endif
 static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
 #ifdef CONFIG_X86_64
@@ -1587,7 +1488,7 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 }
 
 #ifdef CONFIG_X86_32
-static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
+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)
@@ -1597,19 +1498,11 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
        return pte;
 }
 #else /* CONFIG_X86_64 */
-static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
+static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
 {
        unsigned long pfn = pte_pfn(pte);
 
        /*
-        * A bit of optimization. We do not need to call the workaround
-        * when xen_set_pte_init is called with a PTE with 0 as PFN.
-        * That is b/c the pagetable at that point are just being populated
-        * with empty values and we can save some cycles by not calling
-        * the 'memblock' code.*/
-       if (pfn)
-               mark_rw_past_pgt();
-       /*
         * If the new pfn is within the range of the newly allocated
         * kernel pagetable, and it isn't being mapped into an
         * early_ioremap fixmap slot as a freshly allocated page, make sure
@@ -1626,7 +1519,7 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 
 /* 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);
 
@@ -1644,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 */
@@ -1654,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 */
@@ -1664,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)));
 }
@@ -1796,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;
@@ -1879,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;
@@ -1950,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));
 
@@ -1987,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;
@@ -2093,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;
 
@@ -2116,10 +2009,8 @@ __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)
 {
-       mark_rw_past_pgt();
-
 #ifdef CONFIG_XEN_DEBUG
        pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
 #endif
@@ -2155,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,
 
@@ -2228,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 141eb0d..58efeb9 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 90bac0a..be1a464 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 3061244..194a3ed 100644 (file)
@@ -57,7 +57,7 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static __cpuinit void cpu_bringup(void)
+static void __cpuinit cpu_bringup(void)
 {
        int cpu = smp_processor_id();
 
@@ -85,7 +85,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 +242,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 +486,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 2e2d370..bd4ffd7 100644 (file)
@@ -439,11 +439,11 @@ 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;
@@ -468,7 +468,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 +490,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 3112f55..97dfdc8 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 f0605ab..471fdcc 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 10919fa..c774930 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 a2e58ee..3fe00a1 100644 (file)
@@ -316,8 +316,10 @@ 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);
 
index 0475a22..252a81a 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 5b52011..ab7a9e6 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();
index 3a73a93..85b3237 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 ff9d832..d38c40f 100644 (file)
@@ -561,27 +561,6 @@ void ahci_start_engine(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
-       u8 status;
-
-       status = readl(port_mmio + PORT_TFDATA) & 0xFF;
-
-       /*
-        * At end of section 10.1 of AHCI spec (rev 1.3), it states
-        * Software shall not set PxCMD.ST to 1 until it is determined
-        * that a functoinal device is present on the port as determined by
-        * PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h
-        *
-        * Even though most AHCI host controllers work without this check,
-        * specific controller will fail under this condition
-        */
-       if (status & (ATA_BUSY | ATA_DRQ))
-               return;
-       else {
-               ahci_scr_read(&ap->link, SCR_STATUS, &tmp);
-
-               if ((tmp & 0xf) != 0x3)
-                       return;
-       }
 
        /* start DMA */
        tmp = readl(port_mmio + PORT_CMD);
index f26f2fe..dad9fd6 100644 (file)
@@ -3316,7 +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 = ap->flags & ATA_FLAG_NO_DIPM;
+       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;
index bdd2719..bc9e702 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 e9e5238..d57e8d0 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 19f49e4..a34dca0 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 da57ee9..29917c7 100644 (file)
@@ -316,8 +316,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);
 
@@ -326,6 +325,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)
@@ -338,7 +339,6 @@ static void __device_release_driver(struct device *dev)
                                                     BUS_NOTIFY_UNBOUND_DRIVER,
                                                     dev);
 
-               pm_runtime_put_sync(dev);
        }
 }
 
index 8c798ef..bbb03e6 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 9e0e4fc..48425f1 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 118c1b9..3647e11 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 42f97f9..cb3bb36 100644 (file)
@@ -74,6 +74,23 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
 
 #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.
  * @event: PM transition of the system under way.
@@ -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 abe3ab7..aa63202 100644 (file)
@@ -426,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) {
@@ -517,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) {
@@ -580,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;
@@ -629,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);
@@ -658,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)) {
@@ -690,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);
 }
@@ -732,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)
@@ -749,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;
 }
 
@@ -841,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;
                }
        }
 
@@ -869,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);
@@ -914,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;
@@ -965,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);
@@ -984,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:
@@ -1005,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);
@@ -1057,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 3172c60..0d4587b 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 fff49be..a9f5b89 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 abbbd33..84f7c7d 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);
 
index acde9b5..9dff77b 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 8066d08..e086fbb 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 456c0cc..8eba86b 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 c871eae..ede16c6 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 301d7a9..db8f885 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 2f2ccf6..8690e31 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 21dfdb7..869e767 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 7adeb1e..f21b520 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 3e90471..9712fad 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);
 
@@ -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 24a482f..fd5adcd 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 4c10f56..773bfa7 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 68b9430..0e376d4 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 645ff76..6c7fd7d 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 514dd8e..75fb965 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 b2b034f..3ceaf00 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 4e874c5..e427fbe 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 43ac619..ac6739e 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 cc6c9b2..64c6b85 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 d6412c1..39ccdea 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 ca8ee80..9fb8485 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 870e6cc..343f847 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
@@ -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 71fc3b4..c7f1a6f 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 a2baafb..4e04e12 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 141abeb..7bac808 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 2dafc5c..0a5bea9 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
@@ -181,93 +178,6 @@ 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 7e2e515..f13a8a9 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 e6db5fa..4c2eb51 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 00d73fc..b60a4c2 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 66d2d1d..f231015 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 0543221..90431cb 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 32974cf..ffe1f2c 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 cf48cdd..f47d26e 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 d9f5136..34ea359 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 52c9364..6be3e07 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 755a31e..7b0603e 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 4a45fd6..d71d9f3 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 2368e38..83479b6 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 df3529b..3744d26 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 435a996..1e205e6 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 9b1ff37..6ea3455 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 561758e..a748ce7 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 a94ec6b..8af2d2f 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 91bc25b..c76ead3 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 c1f0045..af8e7b1 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 2192456..f032e44 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 11d7a72..140b952 100644 (file)
@@ -1516,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)
@@ -1535,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");
 
@@ -1546,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 c34a8dd..32d1b3e 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 373c2a0..2166ee0 100644 (file)
@@ -5154,6 +5154,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
+       if (!HAS_PCH_SPLIT(dev))
+               intel_enable_plane(dev_priv, plane, pipe);
 
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
index 4bce801..c77111e 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;
index c20eac3..9073e3b 100644 (file)
@@ -1780,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:
index 9453384..fc40e0c 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
index 7aade20..3d8a763 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 dd881d0..90dfb2b 100644 (file)
@@ -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:
index 8a955bb..a533f52 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 6334f8a..0aa8e85 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 7e16371..0e28cae 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 e01cacb..498b284 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 75b984c..107397a 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 a97e3fe..04be9f8 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 5ed9d25..99dde87 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 2a1e9ae..a9c0423 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 ec1e9da..b3fa798 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 9d8dcfa..d7ee70f 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 e29172c..40a13cc 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 9f6166f..35d2a5d 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 f66dd8b..5b9e422 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 70a5a3c..3b773b0 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 58c0e41..be24ac7 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 33c7eed..e74cdf9 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 26d8018..95ca93c 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 6bab3ea..9f53e68 100644 (file)
@@ -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 48b6674..891cc2f 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 1839194..10bcd4a 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 adf45b3..5c4a692 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 c24946f..1de1c19 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 e7089a1..b37e618 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 0aaa059..34ae49d 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 7d463c2..8ac947c 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 c820e2f..3f44200 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 3973f9a..ddb4c09 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;
 
index 5aeaf87..4aae501 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 0b80644..812729e 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 643ad52..4796bbf 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 d4a851c..0b4d5b2 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 2e16511..3ab9ffa 100644 (file)
@@ -717,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 */
@@ -904,11 +904,11 @@ 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:
index 16422de..2c0d4d1 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 2b200c1..461e6a1 100644 (file)
@@ -94,7 +94,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
                spin_unlock_irqrestore(&host->clk_lock, flags);
                return;
        }
-       mmc_claim_host(host);
+       mutex_lock(&host->clk_gate_mutex);
        spin_lock_irqsave(&host->clk_lock, flags);
        if (!host->clk_requests) {
                spin_unlock_irqrestore(&host->clk_lock, flags);
@@ -104,7 +104,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
                pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
        }
        spin_unlock_irqrestore(&host->clk_lock, flags);
-       mmc_release_host(host);
+       mutex_unlock(&host->clk_gate_mutex);
 }
 
 /*
@@ -130,7 +130,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
 {
        unsigned long flags;
 
-       mmc_claim_host(host);
+       mutex_lock(&host->clk_gate_mutex);
        spin_lock_irqsave(&host->clk_lock, flags);
        if (host->clk_gated) {
                spin_unlock_irqrestore(&host->clk_lock, flags);
@@ -140,7 +140,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
        }
        host->clk_requests++;
        spin_unlock_irqrestore(&host->clk_lock, flags);
-       mmc_release_host(host);
+       mutex_unlock(&host->clk_gate_mutex);
 }
 
 /**
@@ -215,6 +215,7 @@ static inline void mmc_host_clk_init(struct mmc_host *host)
        host->clk_gated = false;
        INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
        spin_lock_init(&host->clk_lock);
+       mutex_init(&host->clk_gate_mutex);
 }
 
 /**
index f9b611f..60e4186 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 44b1f46..5069111 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 08533bd..6adf4c9 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 bd483f0..c1d3346 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 3ffe05d..5d513b5 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 dc280bc..19f04a3 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 01b604a..209fbb7 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 4af235d..fbfb5b4 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 ce0091e..1264d78 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 66823ed..2353eca 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 1e2d825..9dc9394 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 02a0443..9187fb4 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 */
index b28baff..01b8a6a 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 bd1d811..5fedc33 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 *)ofdev->dev.of_match->data;
+       data = match->data;
 
        base = of_iomap(np, 0);
        if (!base) {
index a358ea9..f501bba 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 b423965..1b49df6 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 3e2e734..f3bbdce 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 53c0f04..cf79cf7 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;
@@ -3276,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 24cb953..5131e61 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 7e840d3..6a2e150 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 c5ef62c..1cd481c 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;
 
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 30be8c6..7298a34 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 2ef2f9c..56d049a 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 d984790..3dd45ed 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 10f1cb7..9b29a8d 100644 (file)
@@ -1937,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 a42db6e..d91701a 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;
 };
 
index e4dd898..837869b 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 86cbb9e..8ec1a9a 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 eb4f59f..bff2f79 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 a301479..c924ea2 100644 (file)
@@ -567,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,
 },
 
 /*
index 7d42f9a..81126ff 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 009bba3..9ab439d 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,
@@ -1524,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 0d47c3a..c16ed96 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 51f2ef1..9764672 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 17d04ff..1482fa6 100644 (file)
@@ -2141,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;
 
@@ -2149,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 c1511b1..42db0fc 100644 (file)
@@ -2155,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 9ee849d..f43ac1e 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 7e8a658..f3ac624 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 b78a38d..8c7c522 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 d552d2c..6af6b62 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"
index 553d8ee..42fae47 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 a6ec200..4020025 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 ebf51ad..a806cb3 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 ac2701b..043ee31 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 3a97107..d06ee2d 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 1a62934..db8b802 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 8d46838..755e1fe 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 60ce696..47e681d 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 11ae64d..335551d 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 69fe664..eda128f 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 20494b5..3bc046f 100644 (file)
@@ -258,6 +258,8 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
        }
 
        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);
@@ -267,10 +269,9 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
                goto out_rtc;
        }
 
-       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 3f7bc6b..2e48aa6 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 c5ac037..a1a278b 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 6782062..fcb113c 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 826ab64..d814417 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 a633abc..cd4f198 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 694da39..359da6d 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 b3466c4..16512ec 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 475e603..86b6f1c 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)
index 4b60ede..be55fb2 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 83cea9a..1b3924c 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 e2d45c9..9689d41 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 0bac91e..ec1803a 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;
 }
@@ -438,7 +436,11 @@ static void scsi_run_queue(struct request_queue *q)
                        continue;
                }
 
-               blk_run_queue_async(sdev->request_queue);
+               spin_unlock(shost->host_lock);
+               spin_lock(sdev->request_queue->queue_lock);
+               __blk_run_queue(sdev->request_queue);
+               spin_unlock(sdev->request_queue->queue_lock);
+               spin_lock(shost->host_lock);
        }
        /* put any unprocessed entries back */
        list_splice(&starved_list, &shost->starved_list);
@@ -447,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 087821f..58584dc 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 6f34963..7ad4858 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 5f34d7a..45ff0e3 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 0331139..7765301 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 80484af..b1f0f83 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 fee0690..3527604 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
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 0e8eec5..c911b24 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 36613b3..3a68e09 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 2ab2912..7aa4eea 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 82acb8d..6183a57 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 5b2b5ef..64e41f5 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 e0c2284..5aac00e 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 1b0f98b..022f9eb 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 3f8608b..ed26f70 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
 
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 528bceb..eed5436 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 5ec5ac1..1479dc4 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 f420f1f..4781f80 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 043af8a..f54290b 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 33167b4..3ff822b 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 a7ffdfe..f6832f4 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 b0f9e8f..f914b26 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 3745a31..fd725cd 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 a2eee57..0b5366b 100644 (file)
@@ -70,12 +70,7 @@ static int xen_suspend(void *data)
 
        BUG_ON(!irqs_disabled());
 
-       err = sysdev_suspend(PMSG_FREEZE);
-       if (!err) {
-               err = syscore_suspend();
-               if (err)
-                       sysdev_resume();
-       }
+       err = syscore_suspend();
        if (err) {
                printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
                        err);
@@ -102,7 +97,6 @@ static int xen_suspend(void *data)
        }
 
        syscore_resume();
-       sysdev_resume();
 
        return 0;
 }
index 60f1827..1e0fe01 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 5147bdd..257b00e 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 5d505aa..44ea5b9 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 cd52f7f..9ee6bd5 100644 (file)
@@ -8856,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 ffb48d6..2616f7e 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 9fa0866..2a5404c 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;
 }
@@ -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)
+               if (ci->i_wb_ref == 0)
                        ihold(&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);
+               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 03d6daf..70b6a48 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;
index f60b07b..d0fae4c 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 e86ec11..24067d6 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 b1f1b8b..f5cabef 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. */
index 23d43cd..1b2e180 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 05f1dcf..277262a 100644 (file)
@@ -2673,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 3313dd1..9a37a9b 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 89d394d..568304d 100644 (file)
@@ -429,25 +429,16 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
 {
        char buf[32];
        int buf_size;
+       bool bv;
        u32 *val = file->private_data;
 
        buf_size = min(count, (sizeof(buf)-1));
        if (copy_from_user(buf, user_buf, buf_size))
                return -EFAULT;
 
-       switch (buf[0]) {
-       case 'y':
-       case 'Y':
-       case '1':
-               *val = 1;
-               break;
-       case 'n':
-       case 'N':
-       case '0':
-               *val = 0;
-               break;
-       }
-       
+       if (strtobool(buf, &bv) == 0)
+               *val = bv;
+
        return count;
 }
 
index c6ba49b..b32eb29 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 54fc993..e3c4f11 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 6f8192f..be79dc9 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 7c44579..2b461d7 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 de5350f..db07c7a 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 69c0f3c..cf1b339 100644 (file)
@@ -300,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;
@@ -3695,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;
@@ -4844,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;
        }
@@ -5479,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 ff681ab..f57f528 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);
 }
index bc48272..0c015ba 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 7cded2b..2bcf0dc 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 3bd5d7e..49c715b 100644 (file)
@@ -939,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;
@@ -1013,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))
index 0a0a66d..f768448 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 6437202..9a3e6bb 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 9fe5b8f..8582e3f 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 7540a49..3b179d6 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 fede57e..84d1663 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 41565ae..89659d6 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 b141a44..295d564 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 e4f9c1b..3e898a4 100644 (file)
@@ -926,6 +926,7 @@ restart:
                                        XFS_LOOKUP_BATCH,
                                        XFS_ICI_RECLAIM_TAG);
                        if (!nr_found) {
+                               done = 1;
                                rcu_read_unlock();
                                break;
                        }
index acdb92f..5fc2380 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 75a8692..077c00d 100644 (file)
        /* 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) = .;        \
        }                                                               \
                                                                        \
index ade09d7..c99c3d3 100644 (file)
@@ -127,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 b8613e8..01eca17 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 16ee8b4..d4675af 100644 (file)
@@ -546,18 +546,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 9343dd3..11be48e 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 9aeeb0b..be16b61 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 ab8dfc0..0d75350 100644 (file)
@@ -442,7 +442,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" */
 
@@ -633,13 +632,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 df728c1..6a82748 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 dbd860a..cdf9495 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 bfb8f93..56d8fc8 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 09a3080..8b45384 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 a082905..2d921b3 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 6efd7a7..3102318 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 3a54266..cc6d2aa 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 eb792cb..bcb793e 100644 (file)
@@ -183,6 +183,7 @@ struct mmc_host {
        struct work_struct      clk_gate_work; /* delayed clock gate */
        unsigned int            clk_old;        /* old clock value cache */
        spinlock_t              clk_lock;       /* lock for clk fields */
+       struct mutex            clk_gate_mutex; /* mutex for clock gating */
 #endif
 
        /* host specific block data */
index 5de4204..d9ca2d5 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 07b4195..ddaae98 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 890dce2..7e371f7 100644 (file)
@@ -233,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 8bfe6c1..ae56384 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 744942c..ede1a80 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 512e091..3160648 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 8de9aa6..878cf84 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 838c114..eaf4350 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 2dea94f..e3beb31 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 e98cd2e..06d6964 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 9659eff..045f72a 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 a716ee2..a176db2 100644 (file)
@@ -123,6 +123,7 @@ extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
 extern void argv_free(char **argv);
 
 extern bool sysfs_streq(const char *s1, const char *s2);
+extern int strtobool(const char *s, bool *res);
 
 #ifdef CONFIG_BINARY_PRINTF
 int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
index dfb078d..d35e783 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 88bdd01..2fa8d13 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 d516f00..86aefed 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 75b8e29..f57e7d4 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 6ae4bc5..20afeaa 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 cbb822e..2d0191c 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 4fae903..169f7a5 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 1d16502..fc82c18 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 2d3ec50..dd82e02 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 e3615c0..9fe3a36 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 f1b87ad..9af21e1 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 d886b1e..7a71e0a 100644 (file)
@@ -1226,7 +1226,6 @@ config SLAB
          per cpu and per node queues.
 
 config SLUB
-       depends on BROKEN || NUMA || !DISCONTIGMEM
        bool "SLUB (Unqueued Allocator)"
        help
           SLUB is a slab allocator that minimizes cache line usage
index 4a9479e..48df882 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 bf0c734..32a80e0 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 5557b55..8093c16 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)
index 66ecd2e..7b01de9 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 53ead17..ea64012 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 c574f9a..d1d051b 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 54329cd..7329005 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 4af1e2b..d5a3009 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 306cba3..97a8bfa 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 2c039c9..886e803 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 07c1611..f7ce002 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 0d91730..f166783 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 87b77de..8d814cb 100644 (file)
@@ -1531,13 +1531,7 @@ int kernel_kexec(void)
                if (error)
                        goto Enable_cpus;
                local_irq_disable();
-               /* Suspend system devices */
-               error = sysdev_suspend(PMSG_FREEZE);
-               if (!error) {
-                       error = syscore_suspend();
-                       if (error)
-                               sysdev_resume();
-               }
+               error = syscore_suspend();
                if (error)
                        goto Enable_irqs;
        } else
@@ -1553,7 +1547,6 @@ int kernel_kexec(void)
 #ifdef CONFIG_KEXEC_JUMP
        if (kexec_image->preserve_context) {
                syscore_resume();
-               sysdev_resume();
  Enable_irqs:
                local_irq_enable();
  Enable_cpus:
index 9cd0591..5ae0ff3 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 53a6895..63437d0 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 d5938a5..2287972 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 7ab388a..ed72e13 100644 (file)
@@ -297,21 +297,15 @@ EXPORT_SYMBOL(param_ops_charp);
 int param_set_bool(const char *val, const struct kernel_param *kp)
 {
        bool v;
+       int ret;
 
        /* No equals means "set"... */
        if (!val) val = "1";
 
        /* One of =[yYnN01] */
-       switch (val[0]) {
-       case 'y': case 'Y': case '1':
-               v = true;
-               break;
-       case 'n': case 'N': case '0':
-               v = false;
-               break;
-       default:
-               return -EINVAL;
-       }
+       ret = strtobool(val, &v);
+       if (ret)
+               return ret;
 
        if (kp->flags & KPARAM_ISBOOL)
                *(bool *)kp->arg = v;
@@ -821,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 6de9a8f..87f4d24 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 50aae66..f9bec56 100644 (file)
@@ -272,12 +272,7 @@ static int create_image(int platform_mode)
 
        local_irq_disable();
 
-       error = sysdev_suspend(PMSG_FREEZE);
-       if (!error) {
-               error = syscore_suspend();
-               if (error)
-                       sysdev_resume();
-       }
+       error = syscore_suspend();
        if (error) {
                printk(KERN_ERR "PM: Some system devices failed to power down, "
                        "aborting hibernation\n");
@@ -302,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.
         */
@@ -333,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;
 
@@ -364,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;
@@ -409,12 +412,7 @@ static int resume_target_kernel(bool platform_mode)
 
        local_irq_disable();
 
-       error = sysdev_suspend(PMSG_QUIESCE);
-       if (!error) {
-               error = syscore_suspend();
-               if (error)
-                       sysdev_resume();
-       }
+       error = syscore_suspend();
        if (error)
                goto Enable_irqs;
 
@@ -442,7 +440,6 @@ static int resume_target_kernel(bool platform_mode)
        touch_softlockup_watchdog();
 
        syscore_resume();
-       sysdev_resume();
 
  Enable_irqs:
        local_irq_enable();
@@ -528,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;
@@ -541,7 +537,6 @@ int hibernation_platform_enter(void)
 
  Power_up:
        syscore_resume();
-       sysdev_resume();
        local_irq_enable();
        enable_nonboot_cpus();
 
@@ -982,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 de9aef8..2981af4 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 03634be..9a00a0a 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 ca0aacc..ace5588 100644 (file)
@@ -41,16 +41,28 @@ 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 8935369..1c41ba2 100644 (file)
@@ -163,19 +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();
-               if (error)
-                       sysdev_resume();
-       }
+       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();
@@ -216,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) {
@@ -227,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)
@@ -294,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 c36c3b9..7d02d33 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 af468ed..f0c1038 100644 (file)
@@ -315,7 +315,6 @@ void kernel_restart_prepare(char *cmd)
        blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
        system_state = SYSTEM_RESTART;
        device_shutdown();
-       sysdev_shutdown();
        syscore_shutdown();
 }
 
@@ -354,7 +353,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);
@@ -374,7 +372,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 6519cf6..0e17c10 100644 (file)
@@ -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 da800ff..723c763 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 c768bcd..9b1707b 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
@@ -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
index ef0f285..4b49a24 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 4bfb047..db07bfd 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 f71bead..01fad9b 100644 (file)
@@ -535,6 +535,35 @@ bool sysfs_streq(const char *s1, const char *s2)
 }
 EXPORT_SYMBOL(sysfs_streq);
 
+/**
+ * strtobool - convert common user inputs into boolean values
+ * @s: input string
+ * @res: result
+ *
+ * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
+ * Otherwise it will return -EINVAL.  Value pointed to by res is
+ * updated upon finding a match.
+ */
+int strtobool(const char *s, bool *res)
+{
+       switch (s[0]) {
+       case 'y':
+       case 'Y':
+       case '1':
+               *res = true;
+               break;
+       case 'n':
+       case 'N':
+       case '0':
+               *res = false;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(strtobool);
+
 #ifndef __HAVE_ARCH_MEMSET
 /**
  * memset - Fill a region of memory with the given value
index bc0ac6b..dfd6019 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 c1d5867..aacee45 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 9f8a97b..3f8bce2 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,22 +2351,33 @@ 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.
  * @size: size of allocation, same value as passed to 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 9905501..2daadc3 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 8fa27e4..dfc7069 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 a448db3..5602f1a 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 f6b435c..8bfd450 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 7850412..0eb1a88 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 e34ea9e..b2ff6c8 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 7736774..a9aa2dd 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 b58a501..a873277 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 e883172..9a70ebd 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 94954c7..42fdffd 100644 (file)
@@ -369,15 +369,6 @@ static void __sco_sock_close(struct sock *sk)
 
        case BT_CONNECTED:
        case BT_CONFIG:
-               if (sco_pi(sk)->conn) {
-                       sk->sk_state = BT_DISCONN;
-                       sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
-                       hci_conn_put(sco_pi(sk)->conn->hcon);
-                       sco_pi(sk)->conn = NULL;
-               } else
-                       sco_chan_del(sk, ECONNRESET);
-               break;
-
        case BT_CONNECT:
        case BT_DISCONN:
                sco_chan_del(sk, ECONNRESET);
index f3bc322..74ef4d4 100644 (file)
@@ -737,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 893669c..1a92b36 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 856b6ee..b624fe4 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);
@@ -5184,27 +5186,27 @@ 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_ALL_TSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping TSO features since no SG feature.\n");
+               netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
                features &= ~NETIF_F_ALL_TSO;
        }
 
@@ -5214,7 +5216,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 
        /* 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;
        }
 
@@ -5224,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;
                }
@@ -5412,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 f06ffcf..4b2ab65 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 a1151b8..b1d282f 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 34340c9..f376b05 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 571aa96..2d51840 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 1717c64..805d63e 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 28e7448..a5a4c5d 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 8e688b3..49a91c5 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 afe941e..248f0b2 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 ce4596e..bd1224f 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 2dc6de1..059af31 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 c97bd45..bf28ac2 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 07accf6..a74dae6 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 ae47090..37890f2 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 8c8766c..508cce9 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 17484a4..eb86028 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 3e7961e..e292e5b 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 30bf8a1..482e90c 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 a9adf4c..8a025a5 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 0a22919..ae82716 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 481a86f..61805d7 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 15792d8..b4d745e 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 e8a7814..47f1b86 100644 (file)
@@ -535,6 +535,9 @@ int xfrm_init_replay(struct xfrm_state *x)
                    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 cd104af..413c536 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 0388cfc..2031119 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 47a1f9a..0865b3e 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 e6e7ce0..7102457 100644 (file)
@@ -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;
index 2727bef..b04d280 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 48ffd40..a7b8f30 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 f52b623..824d1c8 100644 (file)
@@ -692,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),
 
index 419bf4f..cd22a54 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 d567c32..6b1f9d3 100644 (file)
@@ -376,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,
@@ -384,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 d8562ce..dd55d10 100644 (file)
@@ -3291,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 4165382..0974f95 100644 (file)
@@ -427,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 11e3c84..2f9a337 100644 (file)
@@ -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 7e3d6e3..ebfc7cf 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)
index 45da8d1..23eb22b 100644 (file)
@@ -166,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;
@@ -235,31 +235,37 @@ 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, struct perf_evsel *evsel,
-                              int cpu, int prot, int mask, int fd)
+                              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->cpus->map[cpu] == -1 && evsel->attr.inherit)
+       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;
@@ -269,6 +275,86 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *ev
        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
@@ -287,11 +373,11 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *ev
 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;
@@ -301,43 +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, evsel, 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,
@@ -348,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 8b1cb7a..7109d7a 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 8b0eff8..b5c7d81 100644 (file)
@@ -680,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);