]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 19 Feb 2007 21:36:16 +0000 (13:36 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 19 Feb 2007 21:36:16 +0000 (13:36 -0800)
* 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  hwmon/vt1211: Add probing of alternate config index port
  hwmon/f71805f: Fix a race condition
  hwmon/abituguru: Fix unchecked return status
  hwmon: New driver for the Analog Devices ADM1029
  hwmon/w83627ehf: Add support for the W83627DHG chip
  hwmon: Use subsys_initcall
  hwmon/lm70: Make lm70_remove a __devexit function
  hwmon: Cleanup a bogus legacy comment
  hwmon: Simplify the locking model of two drivers
  hwmon: Drop unused mutexes in two drivers
  hwmon/it87: Add PWM base frequency control

1986 files changed:
.mailmap [new file with mode: 0644]
Documentation/acpi-hotkey.txt [deleted file]
Documentation/arm/Samsung-S3C24XX/DMA.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/Overview.txt
Documentation/driver-model/platform.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/00-INDEX
Documentation/filesystems/9p.txt
Documentation/filesystems/sysfs-pci.txt
Documentation/gpio.txt
Documentation/hrtimer/timer_stats.txt [new file with mode: 0644]
Documentation/hrtimers/highres.txt [new file with mode: 0644]
Documentation/hrtimers/hrtimers.txt [moved from Documentation/hrtimers.txt with 100% similarity]
Documentation/kbuild/makefiles.txt
Documentation/kernel-docs.txt
Documentation/kernel-parameters.txt
Documentation/pci.txt
Documentation/powerpc/booting-without-of.txt
Documentation/sh/new-machine.txt
Documentation/sony-laptop.txt [new file with mode: 0644]
Documentation/video4linux/bttv/Insmod-options
Documentation/x86_64/boot-options.txt
Documentation/x86_64/cpu-hotplug-spec
Documentation/x86_64/kernel-stacks
Documentation/x86_64/machinecheck [new file with mode: 0644]
Documentation/x86_64/mm.txt
MAINTAINERS
Makefile
README
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/.gitignore [new file with mode: 0644]
arch/arm/boot/compressed/.gitignore [new file with mode: 0644]
arch/arm/common/dmabounce.c
arch/arm/common/gic.c
arch/arm/configs/at91sam9263ek_defconfig [new file with mode: 0644]
arch/arm/configs/ateb9200_defconfig
arch/arm/configs/csb337_defconfig
arch/arm/configs/csb637_defconfig
arch/arm/configs/kafa_defconfig
arch/arm/configs/ns9xxx_defconfig [new file with mode: 0644]
arch/arm/configs/s3c2410_defconfig
arch/arm/kernel/Makefile
arch/arm/kernel/calls.S
arch/arm/kernel/crunch.c
arch/arm/kernel/ecard.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/irq.c
arch/arm/kernel/isa.c
arch/arm/kernel/machine_kexec.c [new file with mode: 0644]
arch/arm/kernel/process.c
arch/arm/kernel/relocate_kernel.S [new file with mode: 0644]
arch/arm/kernel/setup.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/mach-at91/Kconfig [moved from arch/arm/mach-at91rm9200/Kconfig with 76% similarity]
arch/arm/mach-at91/Makefile [moved from arch/arm/mach-at91rm9200/Makefile with 88% similarity]
arch/arm/mach-at91/Makefile.boot [moved from arch/arm/mach-at91rm9200/Makefile.boot with 100% similarity]
arch/arm/mach-at91/at91rm9200.c [moved from arch/arm/mach-at91rm9200/at91rm9200.c with 89% similarity]
arch/arm/mach-at91/at91rm9200_devices.c [moved from arch/arm/mach-at91rm9200/at91rm9200_devices.c with 98% similarity]
arch/arm/mach-at91/at91rm9200_time.c [moved from arch/arm/mach-at91rm9200/at91rm9200_time.c with 98% similarity]
arch/arm/mach-at91/at91sam9260.c [moved from arch/arm/mach-at91rm9200/at91sam9260.c with 79% similarity]
arch/arm/mach-at91/at91sam9260_devices.c [moved from arch/arm/mach-at91rm9200/at91sam9260_devices.c with 97% similarity]
arch/arm/mach-at91/at91sam9261.c [moved from arch/arm/mach-at91rm9200/at91sam9261.c with 92% similarity]
arch/arm/mach-at91/at91sam9261_devices.c [moved from arch/arm/mach-at91rm9200/at91sam9261_devices.c with 98% similarity]
arch/arm/mach-at91/at91sam9263.c [new file with mode: 0644]
arch/arm/mach-at91/at91sam9263_devices.c [new file with mode: 0644]
arch/arm/mach-at91/at91sam926x_time.c [moved from arch/arm/mach-at91rm9200/at91sam926x_time.c with 94% similarity]
arch/arm/mach-at91/board-1arm.c [moved from arch/arm/mach-at91rm9200/board-1arm.c with 98% similarity]
arch/arm/mach-at91/board-carmeva.c [moved from arch/arm/mach-at91rm9200/board-carmeva.c with 97% similarity]
arch/arm/mach-at91/board-csb337.c [moved from arch/arm/mach-at91rm9200/board-csb337.c with 78% similarity]
arch/arm/mach-at91/board-csb637.c [moved from arch/arm/mach-at91rm9200/board-csb637.c with 75% similarity]
arch/arm/mach-at91/board-dk.c [moved from arch/arm/mach-at91rm9200/board-dk.c with 98% similarity]
arch/arm/mach-at91/board-eb9200.c [moved from arch/arm/mach-at91rm9200/board-eb9200.c with 97% similarity]
arch/arm/mach-at91/board-ek.c [moved from arch/arm/mach-at91rm9200/board-ek.c with 98% similarity]
arch/arm/mach-at91/board-kafa.c [moved from arch/arm/mach-at91rm9200/board-kafa.c with 98% similarity]
arch/arm/mach-at91/board-kb9202.c [moved from arch/arm/mach-at91rm9200/board-kb9202.c with 97% similarity]
arch/arm/mach-at91/board-sam9260ek.c [moved from arch/arm/mach-at91rm9200/board-sam9260ek.c with 96% similarity]
arch/arm/mach-at91/board-sam9261ek.c [moved from arch/arm/mach-at91rm9200/board-sam9261ek.c with 98% similarity]
arch/arm/mach-at91/board-sam9263ek.c [new file with mode: 0644]
arch/arm/mach-at91/clock.c [moved from arch/arm/mach-at91rm9200/clock.c with 94% similarity]
arch/arm/mach-at91/clock.h [moved from arch/arm/mach-at91rm9200/clock.h with 94% similarity]
arch/arm/mach-at91/generic.h [moved from arch/arm/mach-at91rm9200/generic.h with 90% similarity]
arch/arm/mach-at91/gpio.c [moved from arch/arm/mach-at91rm9200/gpio.c with 99% similarity]
arch/arm/mach-at91/irq.c [moved from arch/arm/mach-at91rm9200/irq.c with 99% similarity]
arch/arm/mach-at91/leds.c [moved from arch/arm/mach-at91rm9200/leds.c with 93% similarity]
arch/arm/mach-at91/pm.c [moved from arch/arm/mach-at91rm9200/pm.c with 98% similarity]
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/Makefile
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/micro9.c [new file with mode: 0644]
arch/arm/mach-imx/time.c
arch/arm/mach-iop13xx/irq.c
arch/arm/mach-iop32x/irq.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/irq.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/avila-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/avila-setup.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-netx/time.c
arch/arm/mach-ns9xxx/Kconfig [new file with mode: 0644]
arch/arm/mach-ns9xxx/Makefile [new file with mode: 0644]
arch/arm/mach-ns9xxx/Makefile.boot [new file with mode: 0644]
arch/arm/mach-ns9xxx/board-a9m9750dev.c [new file with mode: 0644]
arch/arm/mach-ns9xxx/board-a9m9750dev.h [new file with mode: 0644]
arch/arm/mach-ns9xxx/generic.c [new file with mode: 0644]
arch/arm/mach-ns9xxx/generic.h [new file with mode: 0644]
arch/arm/mach-ns9xxx/irq.c [new file with mode: 0644]
arch/arm/mach-ns9xxx/mach-cc9p9360dev.c [new file with mode: 0644]
arch/arm/mach-ns9xxx/time.c [new file with mode: 0644]
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/time.c
arch/arm/mach-realview/Kconfig
arch/arm/mach-realview/platsmp.c
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-s3c2400/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2400/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2400/gpio.c [moved from arch/arm/mach-s3c2410/s3c2400-gpio.c with 96% similarity]
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/bast.h
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-amlm5900.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-qt2410.c [new file with mode: 0644]
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/s3c2410-clock.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-dma.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-gpio.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-irq.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-pm.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-sleep.S [deleted file]
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-s3c2412/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2412/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2412/clock.c [moved from arch/arm/mach-s3c2410/s3c2412-clock.c with 99% similarity]
arch/arm/mach-s3c2412/dma.c [moved from arch/arm/mach-s3c2410/s3c2412-dma.c with 97% similarity]
arch/arm/mach-s3c2412/irq.c [moved from arch/arm/mach-s3c2410/s3c2412-irq.c with 96% similarity]
arch/arm/mach-s3c2412/mach-smdk2413.c [moved from arch/arm/mach-s3c2410/mach-smdk2413.c with 67% similarity]
arch/arm/mach-s3c2412/mach-vstms.c [moved from arch/arm/mach-s3c2410/mach-vstms.c with 93% similarity]
arch/arm/mach-s3c2412/pm.c [moved from arch/arm/mach-s3c2410/s3c2412-pm.c with 95% similarity]
arch/arm/mach-s3c2412/s3c2412.c [moved from arch/arm/mach-s3c2410/s3c2412.c with 95% similarity]
arch/arm/mach-s3c2440/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2440/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2440/clock.c [moved from arch/arm/mach-s3c2410/s3c2440-clock.c with 97% similarity]
arch/arm/mach-s3c2440/dma.c [moved from arch/arm/mach-s3c2410/s3c2440-dma.c with 83% similarity]
arch/arm/mach-s3c2440/dsc.c [moved from arch/arm/mach-s3c2410/s3c2440-dsc.c with 91% similarity]
arch/arm/mach-s3c2440/irq.c [moved from arch/arm/mach-s3c2410/s3c2440-irq.c with 95% similarity]
arch/arm/mach-s3c2440/mach-anubis.c [moved from arch/arm/mach-s3c2410/mach-anubis.c with 98% similarity]
arch/arm/mach-s3c2440/mach-nexcoder.c [moved from arch/arm/mach-s3c2410/mach-nexcoder.c with 94% similarity]
arch/arm/mach-s3c2440/mach-osiris.c [moved from arch/arm/mach-s3c2410/mach-osiris.c with 97% similarity]
arch/arm/mach-s3c2440/mach-rx3715.c [moved from arch/arm/mach-s3c2410/mach-rx3715.c with 96% similarity]
arch/arm/mach-s3c2440/mach-smdk2440.c [moved from arch/arm/mach-s3c2410/mach-smdk2440.c with 93% similarity]
arch/arm/mach-s3c2440/s3c2440.c [moved from arch/arm/mach-s3c2410/s3c2440.c with 88% similarity]
arch/arm/mach-s3c2442/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2442/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2442/clock.c [moved from arch/arm/mach-s3c2410/s3c2442-clock.c with 97% similarity]
arch/arm/mach-s3c2442/s3c2442.c [moved from arch/arm/mach-s3c2410/s3c2442.c with 86% similarity]
arch/arm/mach-s3c2443/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2443/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2443/clock.c [new file with mode: 0644]
arch/arm/mach-s3c2443/dma.c [new file with mode: 0644]
arch/arm/mach-s3c2443/irq.c [new file with mode: 0644]
arch/arm/mach-s3c2443/mach-smdk2443.c [new file with mode: 0644]
arch/arm/mach-s3c2443/s3c2443.c [new file with mode: 0644]
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/cache-l2x0.c [new file with mode: 0644]
arch/arm/mm/consistent.c
arch/arm/mm/context.c
arch/arm/mm/fault-armv.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/tlb-v6.S
arch/arm/oprofile/Kconfig
arch/arm/oprofile/Makefile
arch/arm/oprofile/common.c
arch/arm/oprofile/op_arm_model.h
arch/arm/oprofile/op_model_arm11_core.c [new file with mode: 0644]
arch/arm/oprofile/op_model_arm11_core.h [new file with mode: 0644]
arch/arm/oprofile/op_model_mpcore.c [new file with mode: 0644]
arch/arm/oprofile/op_model_mpcore.h [new file with mode: 0644]
arch/arm/oprofile/op_model_v6.c [new file with mode: 0644]
arch/arm/plat-iop/Makefile
arch/arm/plat-iop/cp6.c [new file with mode: 0644]
arch/arm/plat-iop/io.c [new file with mode: 0644]
arch/arm/plat-iop/pci.c
arch/arm/plat-s3c24xx/Kconfig [new file with mode: 0644]
arch/arm/plat-s3c24xx/Makefile [new file with mode: 0644]
arch/arm/plat-s3c24xx/clock.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/common-smdk.c [moved from arch/arm/mach-s3c2410/common-smdk.c with 96% similarity]
arch/arm/plat-s3c24xx/cpu.c [moved from arch/arm/mach-s3c2410/cpu.c with 92% similarity]
arch/arm/plat-s3c24xx/devs.c [moved from arch/arm/mach-s3c2410/devs.c with 96% similarity]
arch/arm/plat-s3c24xx/dma.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/gpio.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/irq.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/pm-simtec.c [moved from arch/arm/mach-s3c2410/pm-simtec.c with 95% similarity]
arch/arm/plat-s3c24xx/pm.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/s3c244x-irq.c [moved from arch/arm/mach-s3c2410/s3c244x-irq.c with 95% similarity]
arch/arm/plat-s3c24xx/s3c244x.c [moved from arch/arm/mach-s3c2410/s3c244x.c with 93% similarity]
arch/arm/plat-s3c24xx/s3c244x.h [moved from arch/arm/mach-s3c2410/s3c244x.h with 94% similarity]
arch/arm/plat-s3c24xx/sleep.S [new file with mode: 0644]
arch/arm/plat-s3c24xx/time.c [moved from arch/arm/mach-s3c2410/time.c with 98% similarity]
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/kernel/syscall_table.S
arch/avr32/kernel/time.c
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mach-at32ap/clock.c
arch/avr32/mach-at32ap/clock.h
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v32/drivers/pcf8563.c
arch/frv/kernel/pm.c
arch/frv/kernel/sysctl.c
arch/i386/Kconfig
arch/i386/Kconfig.cpu
arch/i386/Kconfig.debug
arch/i386/boot/compressed/relocs.c
arch/i386/defconfig
arch/i386/kernel/Makefile
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/apic.c
arch/i386/kernel/apm.c
arch/i386/kernel/asm-offsets.c
arch/i386/kernel/cpu/common.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/Makefile
arch/i386/kernel/cpu/cpufreq/e_powersaver.c [new file with mode: 0644]
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cyrix.c
arch/i386/kernel/cpu/mcheck/mce.c
arch/i386/kernel/cpu/mcheck/mce.h
arch/i386/kernel/cpu/mcheck/p4.c
arch/i386/kernel/cpu/mtrr/if.c
arch/i386/kernel/cpu/mtrr/main.c
arch/i386/kernel/cpu/mtrr/mtrr.h
arch/i386/kernel/cpu/proc.c
arch/i386/kernel/cpu/transmeta.c
arch/i386/kernel/cpuid.c
arch/i386/kernel/e820.c
arch/i386/kernel/entry.S
arch/i386/kernel/head.S
arch/i386/kernel/hpet.c
arch/i386/kernel/i8253.c
arch/i386/kernel/i8259.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/irq.c
arch/i386/kernel/kprobes.c
arch/i386/kernel/microcode.c
arch/i386/kernel/msr.c
arch/i386/kernel/nmi.c
arch/i386/kernel/paravirt.c
arch/i386/kernel/pcspeaker.c [new file with mode: 0644]
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/sysenter.c
arch/i386/kernel/time.c
arch/i386/kernel/topology.c
arch/i386/kernel/traps.c
arch/i386/kernel/tsc.c
arch/i386/kernel/tsc_sync.c [new file with mode: 0644]
arch/i386/kernel/vm86.c
arch/i386/kernel/vmi.c [new file with mode: 0644]
arch/i386/kernel/vmitime.c [new file with mode: 0644]
arch/i386/kernel/vmlinux.lds.S
arch/i386/mach-default/setup.c
arch/i386/math-emu/get_address.c
arch/i386/math-emu/status_w.h
arch/i386/mm/discontig.c
arch/i386/mm/fault.c
arch/i386/mm/init.c
arch/i386/mm/pageattr.c
arch/i386/mm/pgtable.c
arch/i386/oprofile/nmi_int.c
arch/i386/oprofile/op_model_ppro.c
arch/i386/pci/Makefile
arch/i386/pci/common.c
arch/i386/pci/mmconfig-shared.c [new file with mode: 0644]
arch/i386/pci/mmconfig.c
arch/i386/pci/pci.h
arch/ia64/Kconfig
arch/ia64/kernel/acpi.c
arch/ia64/kernel/crash.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/perfmon.c
arch/ia64/sn/kernel/xpc_main.c
arch/m32r/lib/usercopy.c
arch/m68k/atari/stdma.c
arch/m68knommu/platform/5307/timers.c
arch/mips/au1000/common/power.c
arch/mips/kernel/machine_kexec.c
arch/mips/kernel/time.c
arch/mips/lasat/sysctl.c
arch/parisc/kernel/topology.c
arch/powerpc/Kconfig
arch/powerpc/boot/dts/kuroboxHD.dts
arch/powerpc/boot/dts/kuroboxHG.dts
arch/powerpc/boot/dts/mpc7448hpc2.dts
arch/powerpc/boot/dts/mpc8272ads.dts
arch/powerpc/boot/dts/mpc8313erdb.dts
arch/powerpc/boot/dts/mpc832x_mds.dts [moved from arch/powerpc/boot/dts/mpc8323emds.dts with 77% similarity]
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/mpc8349emitxgp.dts
arch/powerpc/boot/dts/mpc834x_mds.dts
arch/powerpc/boot/dts/mpc836x_mds.dts [moved from arch/powerpc/boot/dts/mpc8360emds.dts with 79% similarity]
arch/powerpc/boot/dts/mpc8540ads.dts
arch/powerpc/boot/dts/mpc8541cds.dts
arch/powerpc/boot/dts/mpc8548cds.dts
arch/powerpc/boot/dts/mpc8555cds.dts
arch/powerpc/boot/dts/mpc8560ads.dts
arch/powerpc/boot/dts/mpc8568mds.dts
arch/powerpc/boot/dts/mpc8641_hpcn.dts
arch/powerpc/boot/dts/mpc866ads.dts
arch/powerpc/boot/dts/mpc885ads.dts
arch/powerpc/configs/cell_defconfig
arch/powerpc/configs/mpc832x_mds_defconfig [moved from arch/powerpc/configs/mpc832xemds_defconfig with 100% similarity]
arch/powerpc/configs/mpc836x_mds_defconfig [moved from arch/powerpc/configs/mpc8360emds_defconfig with 97% similarity]
arch/powerpc/configs/mpc8568mds_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/rtas.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/Makefile
arch/powerpc/platforms/83xx/mpc8313_rdb.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc834x_itx.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c [moved from arch/powerpc/platforms/83xx/mpc8360e_pb.c with 67% similarity]
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c [moved from arch/powerpc/platforms/85xx/mpc8568_mds.c with 84% similarity]
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/celleb/Makefile
arch/powerpc/platforms/celleb/setup.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/power.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/pmi.c [new file with mode: 0644]
arch/powerpc/sysdev/qe_lib/ucc_fast.c
arch/powerpc/sysdev/qe_lib/ucc_slow.c
arch/ppc/kernel/ppc_htab.c
arch/ppc/syslib/i8259.c
arch/s390/appldata/appldata.h
arch/s390/appldata/appldata_base.c
arch/s390/kernel/debug.c
arch/s390/kernel/time.c
arch/s390/mm/cmm.c
arch/sh/Kconfig
arch/sh/Makefile
arch/sh/boards/bigsur/Makefile [deleted file]
arch/sh/boards/bigsur/io.c [deleted file]
arch/sh/boards/bigsur/irq.c [deleted file]
arch/sh/boards/bigsur/led.c [deleted file]
arch/sh/boards/bigsur/setup.c [deleted file]
arch/sh/boards/ec3104/Makefile [deleted file]
arch/sh/boards/ec3104/io.c [deleted file]
arch/sh/boards/ec3104/irq.c [deleted file]
arch/sh/boards/ec3104/setup.c [deleted file]
arch/sh/boards/mpc1211/Makefile
arch/sh/boards/mpc1211/led.c [deleted file]
arch/sh/boards/mpc1211/setup.c
arch/sh/boards/renesas/r7780rp/Makefile
arch/sh/boards/renesas/r7780rp/io.c
arch/sh/boards/renesas/r7780rp/led.c [deleted file]
arch/sh/boards/renesas/r7780rp/setup.c
arch/sh/boards/renesas/rts7751r2d/Makefile
arch/sh/boards/renesas/rts7751r2d/io.c [deleted file]
arch/sh/boards/renesas/rts7751r2d/irq.c
arch/sh/boards/renesas/rts7751r2d/led.c [deleted file]
arch/sh/boards/renesas/rts7751r2d/setup.c
arch/sh/boards/se/7206/Makefile
arch/sh/boards/se/7206/led.c [deleted file]
arch/sh/boards/se/7206/setup.c
arch/sh/boards/se/7300/Makefile
arch/sh/boards/se/7300/led.c [deleted file]
arch/sh/boards/se/7300/setup.c
arch/sh/boards/se/73180/Makefile
arch/sh/boards/se/73180/led.c [deleted file]
arch/sh/boards/se/73180/setup.c
arch/sh/boards/se/7343/Makefile
arch/sh/boards/se/7343/led.c [deleted file]
arch/sh/boards/se/7343/setup.c
arch/sh/boards/se/770x/Makefile
arch/sh/boards/se/770x/irq.c
arch/sh/boards/se/770x/led.c [deleted file]
arch/sh/boards/se/770x/setup.c
arch/sh/boards/se/7751/Makefile
arch/sh/boards/se/7751/led.c [deleted file]
arch/sh/boards/se/7751/setup.c
arch/sh/boards/sh03/Makefile
arch/sh/boards/sh03/led.c [deleted file]
arch/sh/boards/sh03/setup.c
arch/sh/boards/shmin/setup.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/cchips/voyagergx/setup.c
arch/sh/configs/rts7751r2d_defconfig
arch/sh/configs/se7750_defconfig
arch/sh/drivers/Makefile
arch/sh/drivers/dma/dma-sh.c
arch/sh/drivers/heartbeat.c [new file with mode: 0644]
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/ops-bigsur.c [deleted file]
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/sh2/clock-sh7619.c
arch/sh/kernel/cpu/sh2/entry.S
arch/sh/kernel/cpu/sh2/probe.c
arch/sh/kernel/cpu/sh2/setup-sh7619.c
arch/sh/kernel/cpu/sh2a/clock-sh7206.c
arch/sh/kernel/cpu/sh2a/probe.c
arch/sh/kernel/cpu/sh2a/setup-sh7206.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh3/setup-sh7709.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/debugtraps.S [new file with mode: 0644]
arch/sh/kernel/early_printk.c
arch/sh/kernel/entry-common.S
arch/sh/kernel/io_generic.c
arch/sh/kernel/kgdb_stub.c
arch/sh/kernel/process.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/syscalls.S
arch/sh/kernel/traps.c
arch/sh/mm/Kconfig
arch/sh/mm/cache-debugfs.c
arch/sh/mm/cache-sh3.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/fault.c
arch/sh/mm/init.c
arch/sh/mm/ioremap.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pg-sh7705.c
arch/sh/mm/tlb-flush.c
arch/sh/mm/tlb-nommu.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sh/oprofile/op_model_sh7750.c
arch/sh/tools/mach-types
arch/sh64/kernel/traps.c
arch/um/os-Linux/sigio.c
arch/v850/Kconfig
arch/x86_64/Kconfig
arch/x86_64/defconfig
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/ia32/ia32_signal.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/acpi/sleep.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/early-quirks.c
arch/x86_64/kernel/head.S
arch/x86_64/kernel/hpet.c [moved from arch/i386/kernel/time_hpet.c with 57% similarity]
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/ioport.c
arch/x86_64/kernel/irq.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mce_amd.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-calgary.c
arch/x86_64/kernel/pci-dma.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/pmtimer.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/stacktrace.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/tsc.c [new file with mode: 0644]
arch/x86_64/kernel/tsc_sync.c [new file with mode: 0644]
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsyscall.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/lib/Makefile
arch/x86_64/lib/copy_user_nocache.S [new file with mode: 0644]
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/pageattr.c
arch/x86_64/pci/Makefile
arch/x86_64/pci/mmconfig.c
block/Kconfig.iosched
drivers/acorn/block/mfmhd.c
drivers/acorn/char/i2c.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/asus_acpi.c
drivers/acpi/battery.c
drivers/acpi/bay.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/cm_sbs.c
drivers/acpi/container.c
drivers/acpi/debug.c
drivers/acpi/dispatcher/dsmethod.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/events/evgpe.c
drivers/acpi/events/evmisc.c
drivers/acpi/executer/exdump.c
drivers/acpi/executer/exmutex.c
drivers/acpi/fan.c
drivers/acpi/glue.c
drivers/acpi/hardware/hwsleep.c
drivers/acpi/hotkey.c [deleted file]
drivers/acpi/i2c_ec.c
drivers/acpi/ibm_acpi.c
drivers/acpi/namespace/nsinit.c
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/pci_bind.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep/main.c
drivers/acpi/sleep/poweroff.c
drivers/acpi/system.c
drivers/acpi/tables.c
drivers/acpi/tables/tbxface.c
drivers/acpi/thermal.c
drivers/acpi/toshiba_acpi.c
drivers/acpi/utilities/utdelete.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/libata-acpi.c [new file with mode: 0644]
drivers/ata/libata-core.c
drivers/ata/libata.h
drivers/ata/pata_legacy.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_qdi.c
drivers/ata/pata_sl82c105.c
drivers/ata/pdc_adma.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sx4.c
drivers/ata/sata_vsc.c
drivers/atm/adummy.c
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/idt77105.c
drivers/atm/idt77252.c
drivers/atm/nicstarmac.c
drivers/atm/uPD98402.c
drivers/atm/zatm.c
drivers/base/bus.c
drivers/base/class.c
drivers/base/cpu.c
drivers/base/node.c
drivers/block/acsi.c
drivers/block/paride/pd.c
drivers/block/umem.c
drivers/bluetooth/bfusb.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/bluetooth/hci_bcsp.c
drivers/bluetooth/hci_h4.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_usb.c
drivers/cdrom/aztcd.c
drivers/cdrom/cdrom.c
drivers/cdrom/cm206.c
drivers/cdrom/gscd.c
drivers/cdrom/sjcd.c
drivers/char/agp/Makefile
drivers/char/agp/agp.h
drivers/char/agp/ali-agp.c
drivers/char/agp/alpha-agp.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/backend.c
drivers/char/agp/compat_ioctl.c [new file with mode: 0644]
drivers/char/agp/compat_ioctl.h [new file with mode: 0644]
drivers/char/agp/efficeon-agp.c
drivers/char/agp/frontend.c
drivers/char/agp/generic.c
drivers/char/agp/hp-agp.c
drivers/char/agp/i460-agp.c
drivers/char/agp/intel-agp.c
drivers/char/agp/nvidia-agp.c
drivers/char/agp/parisc-agp.c
drivers/char/agp/sgi-agp.c
drivers/char/agp/sis-agp.c
drivers/char/agp/sworks-agp.c
drivers/char/agp/uninorth-agp.c
drivers/char/agp/via-agp.c
drivers/char/briq_panel.c
drivers/char/drm/ffb_context.c
drivers/char/drm/ffb_drv.c
drivers/char/ds1620.c
drivers/char/dsp56k.c
drivers/char/hangcheck-timer.c
drivers/char/hpet.c
drivers/char/hvsi.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/nvram.c
drivers/char/nwflash.c
drivers/char/pty.c
drivers/char/rio/rio_linux.c
drivers/char/rtc.c
drivers/char/ser_a2232.c
drivers/char/sonypi.c
drivers/char/sysrq.c
drivers/char/tlclk.c
drivers/char/toshiba.c
drivers/char/tpm/tpm.c
drivers/char/vc_screen.c
drivers/char/vme_scc.c
drivers/char/watchdog/rm9k_wdt.c
drivers/clocksource/acpi_pm.c
drivers/clocksource/cyclone.c
drivers/clocksource/scx200_hrt.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_userspace.c
drivers/crypto/geode-aes.c
drivers/fc4/fc_syms.c
drivers/fc4/soc.c
drivers/fc4/socal.c
drivers/hid/hid-core.c
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/chips/eeprom.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/arm/icside.c
drivers/ide/arm/rapide.c
drivers/ide/cris/ide-cris.c
drivers/ide/h8300/ide-h8300.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-io.c
drivers/ide/ide-iops.c
drivers/ide/ide-lib.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide.c
drivers/ide/legacy/buddha.c
drivers/ide/legacy/gayle.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/macide.c
drivers/ide/legacy/q40ide.c
drivers/ide/mips/au1xxx-ide.c
drivers/ide/mips/swarm.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5520.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5535.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/hpt34x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it8213.c
drivers/ide/pci/it821x.c
drivers/ide/pci/jmicron.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/opti621.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/pdc202xx_old.c
drivers/ide/pci/piix.c
drivers/ide/pci/sc1200.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sgiioc4.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/slc90e66.c
drivers/ide/pci/tc86c001.c
drivers/ide/pci/triflex.c
drivers/ide/pci/trm290.c
drivers/ide/pci/via82cxxx.c
drivers/ide/ppc/mpc8xx.c
drivers/ide/ppc/pmac.c
drivers/ide/ppc/scc_pata.c [new file with mode: 0644]
drivers/ieee1394/eth1394.c
drivers/ieee1394/ieee1394-ioctl.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/iso.c
drivers/ieee1394/nodemgr.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/raw1394.h
drivers/infiniband/core/Makefile
drivers/infiniband/core/cache.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/fmr_pool.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/multicast.c [new file with mode: 0644]
drivers/infiniband/core/sa.h [new file with mode: 0644]
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/amso1100/c2.c
drivers/infiniband/hw/cxgb3/cxio_dbg.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_resource.c
drivers/infiniband/hw/cxgb3/cxio_resource.h
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch.c
drivers/infiniband/hw/cxgb3/iwch.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_cm.h
drivers/infiniband/hw/cxgb3/iwch_cq.c
drivers/infiniband/hw/cxgb3/iwch_ev.c
drivers/infiniband/hw/cxgb3/iwch_mem.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_provider.h
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/cxgb3/iwch_user.h
drivers/infiniband/hw/ehca/Kconfig
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_eq.c
drivers/infiniband/hw/ehca/ehca_hca.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_irq.h
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ipz_pt_fn.h
drivers/infiniband/hw/ipath/ipath_dma.c
drivers/infiniband/hw/ipath/ipath_iba6110.c
drivers/infiniband/hw/ipath/ipath_iba6120.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/ff-memless.c
drivers/input/input.c
drivers/input/joystick/amijoy.c
drivers/input/joystick/analog.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/turbografx.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/hilkbd.c
drivers/input/mouse/inport.c
drivers/input/mouse/logibm.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/rpcmouse.c
drivers/input/mouse/synaptics.c
drivers/input/serio/hil_mlc.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/i8042.c
drivers/input/serio/libps2.c
drivers/input/serio/serio.c
drivers/input/touchscreen/ads7846.c
drivers/isdn/capi/capidrv.c
drivers/isdn/gigaset/Makefile
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hardware/eicon/divamnt.c
drivers/isdn/hardware/eicon/divasmain.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/hysdn/boardergo.c
drivers/isdn/hysdn/hysdn_sched.c
drivers/isdn/i4l/isdn_bsdcomp.c
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/pcbit/callbacks.c
drivers/isdn/pcbit/capi.c
drivers/isdn/pcbit/drv.c
drivers/isdn/pcbit/edss1.c
drivers/isdn/pcbit/layer2.c
drivers/isdn/pcbit/module.c
drivers/kvm/vmx.c
drivers/macintosh/mac_hid.c
drivers/macintosh/macio-adb.c
drivers/macintosh/via-cuda.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-maciisi.c
drivers/macintosh/via-pmu68k.c
drivers/md/md.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/radio/miropcm20-rds.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/bt819.c
drivers/media/video/bt856.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/indycam.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/meye.c
drivers/media/video/pms.c
drivers/media/video/pvrusb2/pvrusb2-audio.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pvrusb2/pvrusb2-tuner.c
drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
drivers/media/video/pvrusb2/pvrusb2-wm8775.c
drivers/media/video/saa5246a.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa711x.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7185.c
drivers/media/video/saa7191.c
drivers/media/video/tda7432.c
drivers/media/video/tda9875.c
drivers/media/video/tuner-core.c
drivers/media/video/tvmixer.c
drivers/media/video/usbvideo/ibmcam.c
drivers/media/video/usbvideo/ultracam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/asus-laptop.c
drivers/misc/sony-laptop.c [new file with mode: 0644]
drivers/misc/tifm_7xx1.c
drivers/mmc/at91_mci.c
drivers/mmc/mmc_block.c
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/cfi_util.c
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docecc.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/slram.c
drivers/mtd/ftl.c
drivers/mtd/inftlmount.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/amd76xrom.c
drivers/mtd/maps/ck804xrom.c
drivers/mtd/maps/esb2rom.c
drivers/mtd/maps/ichxrom.c
drivers/mtd/maps/netsc520.c
drivers/mtd/maps/sc520cdp.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/cafe.c
drivers/mtd/nand/cafe_ecc.c
drivers/mtd/nand/excite_nandflash.c [new file with mode: 0644]
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nftlcore.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_bbt.c
drivers/mtd/redboot.c
drivers/net/7990.c
drivers/net/Kconfig
drivers/net/arcnet/arc-rawmode.c
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/com20020-pci.c
drivers/net/arcnet/com20020.c
drivers/net/arm/ether1.c
drivers/net/arm/ether3.c
drivers/net/arm/etherh.c
drivers/net/atl1/atl1_hw.c
drivers/net/atl1/atl1_main.c
drivers/net/au1000_eth.c
drivers/net/b44.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/cris/eth_v10.c
drivers/net/cxgb3/cxgb3_defs.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/cxgb3_offload.h
drivers/net/cxgb3/l2t.c
drivers/net/cxgb3/l2t.h
drivers/net/cxgb3/t3cdev.h
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/eexpress.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/ehea/ehea_phyp.c
drivers/net/ehea/ehea_phyp.h
drivers/net/ehea/ehea_qmr.c
drivers/net/ehea/ehea_qmr.h
drivers/net/fec_8xx/fec_8xx-netta.c
drivers/net/fec_8xx/fec_main.c
drivers/net/fec_8xx/fec_mii.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/fs_enet/mac-fec.c
drivers/net/fs_enet/mac-scc.c
drivers/net/fs_enet/mii-bitbang.c
drivers/net/fs_enet/mii-fec.c
drivers/net/gianfar.c
drivers/net/gianfar_ethtool.c
drivers/net/gianfar_mii.c
drivers/net/gianfar_sysfs.c
drivers/net/hamradio/Kconfig
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ioc3-eth.c
drivers/net/irda/ma600-sir.c
drivers/net/macb.c
drivers/net/meth.c
drivers/net/mipsnet.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_niu.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/phy/cicada.c
drivers/net/phy/davicom.c
drivers/net/phy/fixed.c
drivers/net/phy/lxt.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/qsemi.c
drivers/net/qla3xxx.c
drivers/net/s2io.c
drivers/net/sc92031.c
drivers/net/sk98lin/skge.c
drivers/net/sky2.c
drivers/net/sky2.h
drivers/net/sungem_phy.c
drivers/net/tsi108_eth.c
drivers/net/ucc_geth.c
drivers/net/ucc_geth_phy.c
drivers/net/wan/Kconfig
drivers/net/wan/cycx_drv.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wireless/arlan-proc.c
drivers/net/wireless/atmel.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_dma.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/parisc/eisa.c
drivers/parport/parport_cs.c
drivers/parport/parport_gsc.c
drivers/parport/procfs.c
drivers/pci/hotplug/ibmphp_ebda.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/setup-bus.c
drivers/pci/setup-irq.c
drivers/pci/syscall.c
drivers/pcmcia/at91_cf.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/omap_cf.c
drivers/pcmcia/pxa2xx_lubbock.c
drivers/pcmcia/sa1100_badge4.c
drivers/pcmcia/sa1100_cerf.c
drivers/pcmcia/sa1100_h3600.c
drivers/pcmcia/sa1100_jornada720.c
drivers/pcmcia/sa1100_neponset.c
drivers/pcmcia/sa1100_shannon.c
drivers/pcmcia/sa1100_simpad.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/yenta_socket.c
drivers/pnp/pnpacpi/Kconfig
drivers/ps3/Makefile
drivers/ps3/sys-manager.c [new file with mode: 0644]
drivers/ps3/vuart.c
drivers/ps3/vuart.h
drivers/rapidio/rio-sysfs.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-s3c.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_vt220.c
drivers/s390/net/ctcmain.c
drivers/s390/net/netiucv.c
drivers/sbus/char/cpwatchdog.c
drivers/sbus/char/openprom.c
drivers/sbus/char/uctrl.c
drivers/sbus/char/vfc_dev.c
drivers/sbus/char/vfc_i2c.c
drivers/scsi/53c700.c
drivers/scsi/Kconfig
drivers/scsi/NCR53c406a.c
drivers/scsi/a100u2w.c
drivers/scsi/a2091.c
drivers/scsi/a3000.c
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/dpcsup.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/aha152x.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx_old.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_seq.c
drivers/scsi/aic94xx/aic94xx_seq.h
drivers/scsi/amiga7xx.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/arxescsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/cumana_2.c
drivers/scsi/arm/ecoscsi.c
drivers/scsi/arm/eesox.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/oak.c
drivers/scsi/arm/powertec.c
drivers/scsi/atari_scsi.c
drivers/scsi/bvme6000.c
drivers/scsi/ch.c
drivers/scsi/dtc.c
drivers/scsi/eata_pio.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/gvp11.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ide-scsi.c
drivers/scsi/initio.c
drivers/scsi/lasi700.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/mac_scsi.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/mvme147.c
drivers/scsi/mvme16x.c
drivers/scsi/nsp32.c
drivers/scsi/osst.c
drivers/scsi/pas16.c
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/scsi/qla1280.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysctl.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_if.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sd.c
drivers/scsi/sgiwd93.c
drivers/scsi/sr.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/scsi/stex.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi_vme.c
drivers/scsi/sym53c416.c
drivers/scsi/sym53c8xx_2/sym_fw1.h
drivers/scsi/sym53c8xx_2/sym_fw2.h
drivers/scsi/t128.c
drivers/scsi/tmscsim.c
drivers/scsi/wd33c93.c
drivers/scsi/wd33c93.h
drivers/serial/8250.c
drivers/serial/8250_acorn.c
drivers/serial/8250_pci.c
drivers/serial/8250_pnp.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/atmel_serial.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c
drivers/serial/icom.c
drivers/serial/imx.c
drivers/serial/ioc3_serial.c
drivers/serial/ioc4_serial.c
drivers/serial/ip22zilog.c
drivers/serial/jsm/jsm_driver.c
drivers/serial/jsm/jsm_tty.c
drivers/serial/mpc52xx_uart.c
drivers/serial/pnx8xxx_uart.c [new file with mode: 0644]
drivers/serial/serial_core.c
drivers/serial/serial_cs.c
drivers/serial/sunsab.c
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/atmel_spi.c [new file with mode: 0644]
drivers/spi/atmel_spi.h [new file with mode: 0644]
drivers/tc/lk201.c
drivers/telephony/ixj_pcmcia.c
drivers/usb/Makefile
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/generic.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/otg_whitelist.h
drivers/usb/core/sysfs.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/hc_crisv10.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/ohci-pnx8550.c
drivers/usb/host/sl811_cs.c
drivers/usb/host/uhci-hcd.c
drivers/usb/image/microtek.c
drivers/usb/input/Kconfig
drivers/usb/input/aiptek.c
drivers/usb/input/hid-core.c
drivers/usb/input/hid-ff.c
drivers/usb/input/hid-lgff.c
drivers/usb/input/hid-pidff.c
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/appledisplay.c
drivers/usb/misc/berry_charge.c [new file with mode: 0644]
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb_con.c
drivers/usb/net/Kconfig
drivers/usb/net/asix.c
drivers/usb/net/cdc_ether.c
drivers/usb/net/cdc_subset.c
drivers/usb/net/gl620a.c
drivers/usb/net/kaweth.c
drivers/usb/net/net1080.c
drivers/usb/net/plusb.c
drivers/usb/net/rndis_host.c
drivers/usb/net/rtl8150.c
drivers/usb/net/usbnet.c
drivers/usb/net/zaurus.c
drivers/usb/serial/airprime.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/generic.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/datafab.c
drivers/usb/storage/initializers.c
drivers/usb/storage/jumpshot.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/sddr09.c
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/unusual_devs.h
drivers/usb/usb-skeleton.c
drivers/video/atafb.c
drivers/video/aty/mach64_accel.c
drivers/video/aty/mach64_gx.c
drivers/video/aty/radeon_i2c.c
drivers/video/console/fbcon.c
drivers/video/console/mdacon.c
drivers/video/console/vgacon.c
drivers/video/fbmem.c
drivers/video/g364fb.c
drivers/video/hitfb.c
drivers/video/hpfb.c
drivers/video/i810/i810-i2c.c
drivers/video/imxfb.c
drivers/video/intelfb/intelfb_i2c.c
drivers/video/intelfb/intelfbhw.c
drivers/video/kyro/fbdev.c
drivers/video/macfb.c
drivers/video/maxinefb.c
drivers/video/modedb.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nv_of.c
drivers/video/pmag-aa-fb.c
drivers/video/riva/rivafb-i2c.c
drivers/video/s3c2410fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/tgafb.c
fs/9p/fid.c
fs/9p/mux.c
fs/9p/v9fs.c
fs/9p/v9fs.h
fs/9p/v9fs_vfs.h
fs/9p/vfs_addr.c
fs/9p/vfs_dentry.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/Kconfig
fs/Makefile
fs/afs/cell.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/inode.c
fs/afs/main.c
fs/afs/mntpt.c
fs/afs/proc.c
fs/binfmt_elf.c
fs/cifs/README
fs/cifs/cifssmb.c
fs/coda/sysctl.c
fs/debugfs/file.c
fs/debugfs/inode.c
fs/dquot.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/ext3/hash.c
fs/ext3/resize.c
fs/ext4/extents.c
fs/ext4/hash.c
fs/ext4/resize.c
fs/filesystems.c
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/eaops.c
fs/gfs2/eattr.c
fs/gfs2/glops.c
fs/gfs2/lm.c
fs/gfs2/main.c
fs/gfs2/mount.c
fs/gfs2/ondisk.c
fs/gfs2/ops_dentry.c
fs/gfs2/ops_export.c
fs/gfs2/ops_file.c
fs/gfs2/ops_inode.c
fs/gfs2/ops_vm.c
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/util.c
fs/hfsplus/catalog.c
fs/hfsplus/dir.c
fs/hfsplus/super.c
fs/jffs/Makefile [deleted file]
fs/jffs/inode-v23.c [deleted file]
fs/jffs/intrep.c [deleted file]
fs/jffs/intrep.h [deleted file]
fs/jffs/jffs_fm.c [deleted file]
fs/jffs/jffs_fm.h [deleted file]
fs/jffs/jffs_proc.c [deleted file]
fs/jffs/jffs_proc.h [deleted file]
fs/jffs2/build.c
fs/jffs2/compr_zlib.c
fs/jffs2/dir.c
fs/jffs2/jffs2_fs_sb.h
fs/jffs2/scan.c
fs/jffs2/summary.c
fs/jffs2/wbuf.c
fs/lockd/host.c
fs/lockd/svc.c
fs/namei.c
fs/nfs/nfs4renewd.c
fs/nfs/sysctl.c
fs/nfsd/export.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
fs/ntfs/sysctl.c
fs/ocfs2/cluster/nodemanager.c
fs/ocfs2/cluster/nodemanager.h
fs/ocfs2/namei.c
fs/partitions/check.c
fs/pipe.c
fs/proc/Makefile
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/proc_sysctl.c [new file with mode: 0644]
fs/proc/root.c
fs/smbfs/symlink.c
fs/sysfs/file.c
fs/ufs/balloc.c
fs/ufs/dir.c
fs/xattr_acl.c
fs/xfs/linux-2.6/kmem.c
fs/xfs/linux-2.6/xfs_sysctl.c
include/acpi/acinterp.h
include/acpi/acobject.h
include/acpi/acpi_drivers.h
include/acpi/acpiosxf.h
include/acpi/processor.h
include/asm-arm/.gitignore [new file with mode: 0644]
include/asm-arm/arch-at91/at91_aic.h [moved from include/asm-arm/arch-at91rm9200/at91_aic.h with 98% similarity]
include/asm-arm/arch-at91/at91_dbgu.h [moved from include/asm-arm/arch-at91rm9200/at91_dbgu.h with 76% similarity]
include/asm-arm/arch-at91/at91_ecc.h [moved from include/asm-arm/arch-at91rm9200/at91_ecc.h with 96% similarity]
include/asm-arm/arch-at91/at91_lcdc.h [moved from include/asm-arm/arch-at91rm9200/at91_lcdc.h with 99% similarity]
include/asm-arm/arch-at91/at91_mci.h [moved from include/asm-arm/arch-at91rm9200/at91_mci.h with 99% similarity]
include/asm-arm/arch-at91/at91_pio.h [moved from include/asm-arm/arch-at91rm9200/at91_pio.h with 97% similarity]
include/asm-arm/arch-at91/at91_pit.h [moved from include/asm-arm/arch-at91rm9200/at91_pit.h with 95% similarity]
include/asm-arm/arch-at91/at91_pmc.h [moved from include/asm-arm/arch-at91rm9200/at91_pmc.h with 98% similarity]
include/asm-arm/arch-at91/at91_rstc.h [moved from include/asm-arm/arch-at91rm9200/at91_rstc.h with 90% similarity]
include/asm-arm/arch-at91/at91_rtc.h [moved from include/asm-arm/arch-at91rm9200/at91_rtc.h with 98% similarity]
include/asm-arm/arch-at91/at91_rtt.h [moved from include/asm-arm/arch-at91rm9200/at91_rtt.h with 96% similarity]
include/asm-arm/arch-at91/at91_shdwc.h [moved from include/asm-arm/arch-at91rm9200/at91_shdwc.h with 96% similarity]
include/asm-arm/arch-at91/at91_spi.h [moved from include/asm-arm/arch-at91rm9200/at91_spi.h with 98% similarity]
include/asm-arm/arch-at91/at91_ssc.h [moved from include/asm-arm/arch-at91rm9200/at91_ssc.h with 99% similarity]
include/asm-arm/arch-at91/at91_st.h [moved from include/asm-arm/arch-at91rm9200/at91_st.h with 97% similarity]
include/asm-arm/arch-at91/at91_tc.h [moved from include/asm-arm/arch-at91rm9200/at91_tc.h with 99% similarity]
include/asm-arm/arch-at91/at91_twi.h [moved from include/asm-arm/arch-at91rm9200/at91_twi.h with 98% similarity]
include/asm-arm/arch-at91/at91_wdt.h [moved from include/asm-arm/arch-at91rm9200/at91_wdt.h with 96% similarity]
include/asm-arm/arch-at91/at91rm9200.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200.h with 99% similarity]
include/asm-arm/arch-at91/at91rm9200_emac.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_emac.h with 99% similarity]
include/asm-arm/arch-at91/at91rm9200_mc.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_mc.h with 99% similarity]
include/asm-arm/arch-at91/at91sam9260.h [moved from include/asm-arm/arch-at91rm9200/at91sam9260.h with 96% similarity]
include/asm-arm/arch-at91/at91sam9260_matrix.h [moved from include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h with 97% similarity]
include/asm-arm/arch-at91/at91sam9261.h [moved from include/asm-arm/arch-at91rm9200/at91sam9261.h with 99% similarity]
include/asm-arm/arch-at91/at91sam9261_matrix.h [moved from include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h with 98% similarity]
include/asm-arm/arch-at91/at91sam9263.h [new file with mode: 0644]
include/asm-arm/arch-at91/at91sam9263_matrix.h [new file with mode: 0644]
include/asm-arm/arch-at91/at91sam926x_mc.h [moved from include/asm-arm/arch-at91rm9200/at91sam926x_mc.h with 92% similarity]
include/asm-arm/arch-at91/board.h [moved from include/asm-arm/arch-at91rm9200/board.h with 92% similarity]
include/asm-arm/arch-at91/cpu.h [moved from include/asm-arm/arch-at91rm9200/cpu.h with 56% similarity]
include/asm-arm/arch-at91/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-at91/dma.h [moved from include/asm-arm/arch-at91rm9200/dma.h with 94% similarity]
include/asm-arm/arch-at91/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-at91/gpio.h [moved from include/asm-arm/arch-at91rm9200/gpio.h with 84% similarity]
include/asm-arm/arch-at91/hardware.h [moved from include/asm-arm/arch-at91rm9200/hardware.h with 86% similarity]
include/asm-arm/arch-at91/io.h [moved from include/asm-arm/arch-at91rm9200/io.h with 95% similarity]
include/asm-arm/arch-at91/irqs.h [moved from include/asm-arm/arch-at91rm9200/irqs.h with 90% similarity]
include/asm-arm/arch-at91/memory.h [moved from include/asm-arm/arch-at91rm9200/memory.h with 96% similarity]
include/asm-arm/arch-at91/system.h [moved from include/asm-arm/arch-at91rm9200/system.h with 97% similarity]
include/asm-arm/arch-at91/timex.h [moved from include/asm-arm/arch-at91rm9200/timex.h with 86% similarity]
include/asm-arm/arch-at91/uncompress.h [moved from include/asm-arm/arch-at91rm9200/uncompress.h with 97% similarity]
include/asm-arm/arch-at91/vmalloc.h [moved from include/asm-arm/arch-at91rm9200/vmalloc.h with 95% similarity]
include/asm-arm/arch-at91rm9200/at91_pdc.h [deleted file]
include/asm-arm/arch-at91rm9200/debug-macro.S [deleted file]
include/asm-arm/arch-at91rm9200/entry-macro.S [deleted file]
include/asm-arm/arch-ep93xx/ep93xx-regs.h
include/asm-arm/arch-ep93xx/irqs.h
include/asm-arm/arch-ep93xx/platform.h
include/asm-arm/arch-imx/entry-macro.S
include/asm-arm/arch-iop32x/io.h
include/asm-arm/arch-iop33x/io.h
include/asm-arm/arch-ixp4xx/avila.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/hardware.h
include/asm-arm/arch-ixp4xx/irqs.h
include/asm-arm/arch-ixp4xx/udc.h
include/asm-arm/arch-ns9xxx/board.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/clock.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/dma.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/hardware.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/io.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/irqs.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/memory.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/processor.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/regs-bbu.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/regs-mem.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/regs-sys.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/system.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/timex.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-ns9xxx/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/udc.h
include/asm-arm/arch-realview/hardware.h
include/asm-arm/arch-realview/irqs.h
include/asm-arm/arch-realview/platform.h
include/asm-arm/arch-realview/scu.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/dma.h
include/asm-arm/arch-s3c2410/irqs.h
include/asm-arm/arch-s3c2410/regs-adc.h
include/asm-arm/arch-s3c2410/regs-gpio.h
include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-serial.h
include/asm-arm/arch-s3c2410/reset.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/system.h
include/asm-arm/arch-s3c2410/udc.h [new file with mode: 0644]
include/asm-arm/cacheflush.h
include/asm-arm/checksum.h
include/asm-arm/device.h
include/asm-arm/dma-mapping.h
include/asm-arm/domain.h
include/asm-arm/hardware/arm_scu.h
include/asm-arm/hardware/cache-l2x0.h [new file with mode: 0644]
include/asm-arm/hardware/gic.h
include/asm-arm/hardware/iop3xx.h
include/asm-arm/hardware/sa1111.h
include/asm-arm/kexec.h [new file with mode: 0644]
include/asm-arm/pgtable.h
include/asm-arm/plat-s3c24xx/clock.h [moved from arch/arm/mach-s3c2410/clock.h with 97% similarity]
include/asm-arm/plat-s3c24xx/common-smdk.h [moved from arch/arm/mach-s3c2410/common-smdk.h with 88% similarity]
include/asm-arm/plat-s3c24xx/cpu.h [moved from arch/arm/mach-s3c2410/cpu.h with 95% similarity]
include/asm-arm/plat-s3c24xx/devs.h [moved from arch/arm/mach-s3c2410/devs.h with 97% similarity]
include/asm-arm/plat-s3c24xx/dma.h [moved from arch/arm/mach-s3c2410/dma.h with 53% similarity]
include/asm-arm/plat-s3c24xx/irq.h [moved from arch/arm/mach-s3c2410/irq.h with 98% similarity]
include/asm-arm/plat-s3c24xx/pm.h [moved from arch/arm/mach-s3c2410/pm.h with 97% similarity]
include/asm-arm/plat-s3c24xx/s3c2400.h [moved from arch/arm/mach-s3c2410/s3c2400.h with 94% similarity]
include/asm-arm/plat-s3c24xx/s3c2410.h [moved from arch/arm/mach-s3c2410/s3c2410.h with 93% similarity]
include/asm-arm/plat-s3c24xx/s3c2412.h [moved from arch/arm/mach-s3c2410/s3c2412.h with 93% similarity]
include/asm-arm/plat-s3c24xx/s3c2440.h [moved from arch/arm/mach-s3c2410/s3c2440.h with 89% similarity]
include/asm-arm/plat-s3c24xx/s3c2442.h [moved from arch/arm/mach-s3c2410/s3c2442.h with 89% similarity]
include/asm-arm/plat-s3c24xx/s3c2443.h [new file with mode: 0644]
include/asm-arm/system.h
include/asm-arm/tlbflush.h
include/asm-arm/uaccess.h
include/asm-arm/unistd.h
include/asm-arm26/uaccess.h
include/asm-avr32/arch-at32ap/at91_pdc.h [deleted file]
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/io.h
include/asm-avr32/unistd.h
include/asm-generic/pgtable.h
include/asm-i386/acpi.h
include/asm-i386/apic.h
include/asm-i386/bugs.h
include/asm-i386/desc.h
include/asm-i386/elf.h
include/asm-i386/hpet.h
include/asm-i386/i8253.h
include/asm-i386/idle.h [new file with mode: 0644]
include/asm-i386/mach-default/do_timer.h
include/asm-i386/mach-voyager/do_timer.h
include/asm-i386/mce.h
include/asm-i386/mmu_context.h
include/asm-i386/mpspec.h
include/asm-i386/msr.h
include/asm-i386/paravirt.h
include/asm-i386/pda.h
include/asm-i386/pgalloc.h
include/asm-i386/processor.h
include/asm-i386/ptrace.h
include/asm-i386/segment.h
include/asm-i386/setup.h
include/asm-i386/smp.h
include/asm-i386/time.h
include/asm-i386/timer.h
include/asm-i386/tsc.h
include/asm-i386/vmi.h [new file with mode: 0644]
include/asm-i386/vmi_time.h [new file with mode: 0644]
include/asm-ia64/dma-mapping.h
include/asm-ia64/kexec.h
include/asm-ia64/libata-portmap.h [new file with mode: 0644]
include/asm-ia64/pal.h
include/asm-powerpc/atomic.h
include/asm-powerpc/dcr-native.h
include/asm-powerpc/pmi.h [new file with mode: 0644]
include/asm-powerpc/prom.h
include/asm-powerpc/ps3.h
include/asm-powerpc/ucc_slow.h
include/asm-sh/Kbuild
include/asm-sh/bigsur/bigsur.h [deleted file]
include/asm-sh/bigsur/io.h [deleted file]
include/asm-sh/bigsur/serial.h [deleted file]
include/asm-sh/bugs.h
include/asm-sh/cacheflush.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh/cpu-sh4/dma.h
include/asm-sh/dma-mapping.h
include/asm-sh/ec3104/ec3104.h [deleted file]
include/asm-sh/ec3104/io.h [deleted file]
include/asm-sh/ec3104/keyboard.h [deleted file]
include/asm-sh/ec3104/serial.h [deleted file]
include/asm-sh/irq.h
include/asm-sh/kgdb.h
include/asm-sh/mmu.h
include/asm-sh/mmu_context.h
include/asm-sh/page.h
include/asm-sh/pgtable.h
include/asm-sh/processor.h
include/asm-sh/rts7751r2d.h
include/asm-sh/serial.h
include/asm-sh/thread_info.h
include/asm-sh/tlbflush.h
include/asm-sh/ubc.h
include/asm-sh/unistd.h
include/asm-sh/voyagergx.h
include/asm-x86_64/bitops.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/e820.h
include/asm-x86_64/hpet.h
include/asm-x86_64/hw_irq.h
include/asm-x86_64/io.h
include/asm-x86_64/io_apic.h
include/asm-x86_64/mce.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/mutex.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/proto.h
include/asm-x86_64/timex.h
include/asm-x86_64/tsc.h [new file with mode: 0644]
include/asm-x86_64/uaccess.h
include/asm-x86_64/vsyscall.h
include/linux/acpi.h
include/linux/acpi_pmtmr.h [new file with mode: 0644]
include/linux/agp_backend.h
include/linux/ata.h
include/linux/atmel_pdc.h [new file with mode: 0644]
include/linux/audit.h
include/linux/binfmts.h
include/linux/clockchips.h [new file with mode: 0644]
include/linux/clocksource.h
include/linux/cpufreq.h
include/linux/debugfs.h
include/linux/device.h
include/linux/ext4_fs_extents.h
include/linux/hardirq.h
include/linux/hrtimer.h
include/linux/ide.h
include/linux/interrupt.h
include/linux/irq.h
include/linux/jffs.h [deleted file]
include/linux/jiffies.h
include/linux/kexec.h
include/linux/kmod.h
include/linux/ktime.h
include/linux/libata.h
include/linux/log2.h
include/linux/module.h
include/linux/moduleparam.h
include/linux/mtd/bbm.h
include/linux/mtd/map.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/onenand.h
include/linux/mtd/onenand_regs.h
include/linux/mtd/physmap.h
include/linux/nfs4.h
include/linux/nfs4_acl.h
include/linux/nfsd/export.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/nfsfh.h
include/linux/nmi.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/proc_fs.h
include/linux/seqlock.h
include/linux/serial_core.h
include/linux/serial_ip3106.h [deleted file]
include/linux/serial_pnx8xxx.h [new file with mode: 0644]
include/linux/serio.h
include/linux/sunrpc/debug.h
include/linux/sysctl.h
include/linux/tick.h [new file with mode: 0644]
include/linux/time.h
include/linux/timer.h
include/linux/timex.h
include/linux/usb.h
include/linux/usb/cdc.h
include/linux/usb/ch9.h
include/linux/usb/serial.h
include/linux/usb_usual.h
include/linux/usbdevice_fs.h
include/mtd/mtd-abi.h
include/pcmcia/ciscode.h
include/rdma/ib_addr.h
include/rdma/ib_sa.h
include/rdma/rdma_cm.h
include/rdma/rdma_cm_ib.h
include/rdma/rdma_user_cm.h
include/scsi/scsi_device.h
include/scsi/scsi_tgt_if.h
include/scsi/scsi_transport.h
include/sound/emu10k1.h
include/sound/version.h
init/Kconfig
init/calibrate.c
init/main.c
init/version.c
ipc/Makefile
ipc/ipc_sysctl.c [new file with mode: 0644]
ipc/mqueue.c
kernel/Makefile
kernel/audit.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/itimer.c
kernel/kmod.c
kernel/lockdep_proc.c
kernel/module.c
kernel/mutex-debug.c
kernel/params.c
kernel/posix-cpu-timers.c
kernel/posix-timers.c
kernel/printk.c
kernel/resource.c
kernel/rtmutex.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/sysctl.c
kernel/time.c
kernel/time/Kconfig [new file with mode: 0644]
kernel/time/Makefile
kernel/time/clockevents.c [new file with mode: 0644]
kernel/time/clocksource.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c [new file with mode: 0644]
kernel/time/tick-common.c [new file with mode: 0644]
kernel/time/tick-internal.h [new file with mode: 0644]
kernel/time/tick-oneshot.c [new file with mode: 0644]
kernel/time/tick-sched.c [new file with mode: 0644]
kernel/time/timer_list.c [new file with mode: 0644]
kernel/time/timer_stats.c [new file with mode: 0644]
kernel/timer.c
kernel/tsacct.c
kernel/utsname_sysctl.c [new file with mode: 0644]
kernel/workqueue.c
lib/Kconfig.debug
lib/devres.c
lib/kobject.c
lib/textsearch.c
mm/filemap.c
mm/mincore.c
net/802/fc.c
net/802/fddi.c
net/802/hippi.c
net/appletalk/sysctl_net_atalk.c
net/atm/addr.c
net/atm/lec.c
net/atm/raw.c
net/ax25/ax25_addr.c
net/ax25/ax25_dev.c
net/ax25/ax25_ds_in.c
net/ax25/ax25_ds_subr.c
net/ax25/ax25_iface.c
net/ax25/ax25_in.c
net/ax25/ax25_ip.c
net/ax25/ax25_out.c
net/ax25/ax25_std_in.c
net/ax25/ax25_std_subr.c
net/ax25/ax25_std_timer.c
net/ax25/ax25_subr.c
net/ax25/ax25_uid.c
net/ax25/sysctl_net_ax25.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/sock.c
net/bridge/br_netfilter.c
net/bridge/netfilter/ebtables.c
net/compat.c
net/core/dev_mcast.c
net/core/dst.c
net/core/filter.c
net/core/iovec.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/core/skbuff.c
net/dccp/sysctl.c
net/decnet/dn_dev.c
net/decnet/dn_nsp_in.c
net/decnet/dn_nsp_out.c
net/decnet/sysctl_net_decnet.c
net/econet/af_econet.c
net/ethernet/eth.c
net/ieee80211/ieee80211_tx.c
net/ipv4/Kconfig
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_hash.c
net/ipv4/fib_trie.c
net/ipv4/inetpeer.c
net/ipv4/ip_forward.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_lblc.c
net/ipv4/ipvs/ip_vs_lblcr.c
net/ipv4/ipvs/ip_vs_sched.c
net/ipv4/multipath_drr.c
net/ipv4/multipath_random.c
net/ipv4/multipath_rr.c
net/ipv4/multipath_wrandom.c
net/ipv4/netfilter/ip_conntrack_proto_generic.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_sctp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
net/ipv4/protocol.c
net/ipv4/route.c
net/ipv4/tcp_cong.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/anycast.c
net/ipv6/datagram.c
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/ip6_input.c
net/ipv6/ipv6_sockglue.c
net/ipv6/netfilter/ip6_queue.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/proc.c
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/sysctl_net_ipv6.c
net/ipv6/udp.c
net/ipx/sysctl_net_ipx.c
net/irda/ircomm/ircomm_core.c
net/irda/ircomm/ircomm_event.c
net/irda/ircomm/ircomm_lmp.c
net/irda/ircomm/ircomm_param.c
net/irda/ircomm/ircomm_ttp.c
net/irda/ircomm/ircomm_tty_attach.c
net/irda/ircomm/ircomm_tty_ioctl.c
net/irda/irsysctl.c
net/lapb/lapb_in.c
net/lapb/lapb_out.c
net/lapb/lapb_subr.c
net/llc/sysctl_net_llc.c
net/netfilter/nf_conntrack_proto_generic.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_sysctl.c
net/netfilter/nfnetlink.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/sysctl_net_netrom.c
net/packet/af_packet.c
net/rose/rose_dev.c
net/rose/rose_in.c
net/rose/rose_out.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/rose/sysctl_net_rose.c
net/rxrpc/sysctl.c
net/rxrpc/transport.c
net/sched/act_api.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/cls_api.c
net/sched/cls_basic.c
net/sched/cls_fw.c
net/sched/cls_route.c
net/sched/cls_rsvp.c
net/sched/cls_rsvp6.c
net/sched/cls_u32.c
net/sched/em_nbyte.c
net/sched/em_text.c
net/sched/ematch.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_htb.c
net/sched/sch_prio.c
net/sched/sch_teql.c
net/sctp/associola.c
net/sctp/bind_addr.c
net/sctp/endpointola.c
net/sctp/ipv6.c
net/sctp/sysctl.c
net/socket.c
net/sunrpc/auth_null.c
net/sunrpc/stats.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
net/sunrpc/sysctl.c
net/sunrpc/xprtsock.c
net/unix/garbage.c
net/unix/sysctl_net_unix.c
net/x25/sysctl_net_x25.c
scripts/kconfig/qconf.cc
scripts/mkcompile_h
scripts/mkuboot.sh
scripts/mod/modpost.c
security/keys/compat.c
security/keys/user_defined.c
security/security.c
security/selinux/hooks.c
security/selinux/ss/sidtab.c
sound/arm/aaci.c
sound/arm/aaci.h
sound/arm/pxa2xx-ac97.c
sound/core/misc.c
sound/core/seq/instr/ainstr_fm.c
sound/core/seq/instr/ainstr_gf1.c
sound/core/seq/instr/ainstr_iw.c
sound/core/seq/instr/ainstr_simple.c
sound/core/seq/seq_virmidi.c
sound/drivers/dummy.c
sound/drivers/mtpav.c
sound/drivers/mts64.c
sound/drivers/portman2x4.c
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/isa/ad1848/ad1848.c
sound/isa/cmi8330.c
sound/isa/dt019x.c
sound/isa/es1688/es1688.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/opl3sa2.c
sound/isa/sb/sb8.c
sound/oss/ac97_codec.c
sound/oss/ad1889.c
sound/oss/btaudio.c
sound/oss/cs46xx.c
sound/oss/dmasound/dac3550a.c
sound/oss/dmasound/tas3001c.c
sound/oss/dmasound/tas3004.c
sound/oss/dmasound/tas_common.c
sound/oss/emu10k1/main.c
sound/oss/es1371.c
sound/oss/hal2.c
sound/oss/i810_audio.c
sound/oss/kahlua.c
sound/oss/nec_vrc5477.c
sound/oss/opl3.c
sound/oss/sb_card.c
sound/oss/swarm_cs4297a.c
sound/oss/trident.c
sound/oss/waveartist.c
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_patch.h
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_sigmatel.c
sound/soc/at91/at91-i2s.c
sound/soc/at91/at91-pcm.c
sound/soc/codecs/Kconfig
sound/synth/emux/emux.c
sound/synth/emux/emux_proc.c
sound/usb/usbaudio.c
sound/usb/usbquirks.h

diff --git a/.mailmap b/.mailmap
new file mode 100644 (file)
index 0000000..bf62dbe
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,96 @@
+#
+# This list is used by git-shortlog to fix a few botched name translations
+# in the git archive, either because the author's full name was messed up
+# and/or not always written the same way, making contributions from the
+# same person appearing not to be so or badly displayed.
+#
+# repo-abbrev: /pub/scm/linux/kernel/git/
+#
+
+Aaron Durbin <adurbin@google.com>
+Adam Oldham <oldhamca@gmail.com>
+Adam Radford <aradford@gmail.com>
+Adrian Bunk <bunk@stusta.de>
+Alan Cox <alan@lxorguk.ukuu.org.uk>
+Alan Cox <root@hraefn.swansea.linux.org.uk>
+Aleksey Gorelov <aleksey_gorelov@phoenix.com>
+Al Viro <viro@ftp.linux.org.uk>
+Al Viro <viro@zenIV.linux.org.uk>
+Andreas Herrmann <aherrman@de.ibm.com>
+Andrew Morton <akpm@osdl.org>
+Andrew Vasquez <andrew.vasquez@qlogic.com>
+Andy Adamson <andros@citi.umich.edu>
+Arnaud Patard <arnaud.patard@rtp-net.org>
+Arnd Bergmann <arnd@arndb.de>
+Axel Dyks <xl@xlsigned.net>
+Ben Gardner <bgardner@wabtec.com>
+Ben M Cahill <ben.m.cahill@intel.com>
+Björn Steinbrink <B.Steinbrink@gmx.de>
+Brian Avery <b.avery@hp.com>
+Brian King <brking@us.ibm.com>
+Christoph Hellwig <hch@lst.de>
+Corey Minyard <minyard@acm.org>
+David Brownell <david-b@pacbell.net>
+David Woodhouse <dwmw2@shinybook.infradead.org>
+Domen Puncer <domen@coderock.org>
+Douglas Gilbert <dougg@torque.net>
+Ed L. Cashin <ecashin@coraid.com>
+Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Felipe W Damasio <felipewd@terra.com.br>
+Felix Kuhling <fxkuehl@gmx.de>
+Felix Moeller <felix@derklecks.de>
+Filipe Lautert <filipe@icewall.org>
+Franck Bui-Huu <vagabon.xyz@gmail.com>
+Frank Zago <fzago@systemfabricworks.com>
+Greg Kroah-Hartman <greg@echidna.(none)>
+Greg Kroah-Hartman <gregkh@suse.de>
+Greg Kroah-Hartman <greg@kroah.com>
+Henk Vergonet <Henk.Vergonet@gmail.com>
+Henrik Kretzschmar <henne@nachtwindheim.de>
+Herbert Xu <herbert@gondor.apana.org.au>
+Jacob Shin <Jacob.Shin@amd.com>
+James Bottomley <jejb@mulgrave.(none)>
+James Bottomley <jejb@titanic.il.steeleye.com>
+James E Wilson <wilson@specifix.com>
+James Ketrenos <jketreno@io.(none)>
+Jean Tourrilhes <jt@hpl.hp.com>
+Jeff Garzik <jgarzik@pretzel.yyz.us>
+Jens Axboe <axboe@suse.de>
+Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+John Stultz <johnstul@us.ibm.com>
+Juha Yrjola <at solidboot.com>
+Juha Yrjola <juha.yrjola@nokia.com>
+Juha Yrjola <juha.yrjola@solidboot.com>
+Kay Sievers <kay.sievers@vrfy.org>
+Kenneth W Chen <kenneth.w.chen@intel.com>
+Koushik <raghavendra.koushik@neterion.com>
+Leonid I Ananiev <leonid.i.ananiev@intel.com>
+Linas Vepstas <linas@austin.ibm.com>
+Matthieu CASTET <castet.matthieu@free.fr>
+Michel Dänzer <michel@tungstengraphics.com>
+Mitesh shah <mshah@teja.com>
+Morten Welinder <terra@gnome.org>
+Morten Welinder <welinder@anemone.rentec.com>
+Morten Welinder <welinder@darter.rentec.com>
+Morten Welinder <welinder@troll.com>
+Nguyen Anh Quynh <aquynh@gmail.com>
+Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+Patrick Mochel <mochel@digitalimplant.org>
+Peter A Jonsson <pj@ludd.ltu.se>
+Praveen BP <praveenbp@ti.com>
+Rajesh Shah <rajesh.shah@intel.com>
+Ralf Baechle <ralf@linux-mips.org>
+Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+Rémi Denis-Courmont <rdenis@simphalempin.com>
+Rudolf Marek <R.Marek@sh.cvut.cz>
+Rui Saraiva <rmps@joel.ist.utl.pt>
+Sachin P Sant <ssant@in.ibm.com>
+Sam Ravnborg <sam@mars.ravnborg.org>
+Simon Kelley <simon@thekelleys.org.uk>
+Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
+Stephen Hemminger <shemminger@osdl.org>
+Tejun Heo <htejun@gmail.com>
+Thomas Graf <tgraf@suug.ch>
+Tony Luck <tony.luck@intel.com>
+Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
+Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
deleted file mode 100644 (file)
index 38040fa..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-driver/acpi/hotkey.c implement:
-1. /proc/acpi/hotkey/event_config 
-(event based hotkey or event config interface):
-a. add a  event based hotkey(event) : 
-echo "0:bus::action:method:num:num" > event_config
-
-b. delete a event based hotkey(event): 
-echo "1:::::num:num" > event_config
-
-c.  modify a event based hotkey(event):    
-echo "2:bus::action:method:num:num" > event_config
-
-2. /proc/acpi/hotkey/poll_config 
-(polling based hotkey or event config interface):
-a.add a polling based hotkey(event) :  
-echo "0:bus:method:action:method:num" > poll_config
-this adding command will create a proc file 
-/proc/acpi/hotkey/method, which is used to get 
-result of polling.
-
-b.delete a polling based hotkey(event):        
-echo "1:::::num" > event_config
-
-c.modify a polling based hotkey(event):    
-echo "2:bus:method:action:method:num" > poll_config
-
-3./proc/acpi/hotkey/action 
-(interface to call aml method associated with a 
-specific hotkey(event))
-echo "event_num:event_type:event_argument" > 
-       /proc/acpi/hotkey/action.
-The result of the execution of this aml method is 
-attached to /proc/acpi/hotkey/poll_method, which is dynamically
-created.  Please use command "cat /proc/acpi/hotkey/polling_method" 
-to retrieve it.
-
-Note: Use cmdline "acpi_generic_hotkey" to over-ride
-platform-specific with generic driver.
diff --git a/Documentation/arm/Samsung-S3C24XX/DMA.txt b/Documentation/arm/Samsung-S3C24XX/DMA.txt
new file mode 100644 (file)
index 0000000..37f4edc
--- /dev/null
@@ -0,0 +1,46 @@
+                       S3C2410 DMA
+                       ===========
+
+Introduction
+------------
+
+   The kernel provides an interface to manage DMA transfers
+   using the DMA channels in the cpu, so that the central
+   duty of managing channel mappings, and programming the
+   channel generators is in one place.
+
+
+DMA Channel Ordering
+--------------------
+
+   Many of the range do not have connections for the DMA
+   channels to all sources, which means that some devices
+   have a restricted number of channels that can be used.
+
+   To allow flexibilty for each cpu type and board, the
+   dma code can be given an dma ordering structure which
+   allows the order of channel search to be specified, as
+   well as allowing the prohibition of certain claims.
+
+   struct s3c24xx_dma_order has a list of channels, and
+   each channel within has a slot for a list of dma
+   channel numbers. The slots are searched in order, for
+   the presence of a dma channel number with DMA_CH_VALID
+   orred in.
+
+   If the order has the flag DMA_CH_NEVER set, then after
+   checking the channel list, the system will return no
+   found channel, thus denying the request.
+
+   A board support file can call s3c24xx_dma_order_set()
+   to register an complete ordering set. The routine will
+   copy the data, so the original can be discared with
+   __initdata.
+
+
+Authour
+-------
+
+Ben Dooks,
+Copyright (c) 2007 Ben Dooks, Simtec Electronics
+Licensed under the GPL v2
index 28d014714ab8930fbfb9c3c65fb0f85644b807b4..c31b76fa66c462601a92054221baea08643057da 100644 (file)
@@ -8,13 +8,10 @@ Introduction
 
   The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
   by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
-  S3C2440 and S3C2442 devices are supported.
+  S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.
 
   Support for the S3C2400 series is in progress.
 
-  Support for the S3C2412 and S3C2413 CPUs is being merged.
-
-
 Configuration
 -------------
 
@@ -26,6 +23,22 @@ Configuration
   please check the machine specific documentation.
 
 
+Layout
+------
+
+  The core support files are located in the platform code contained in
+  arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
+  This directory should be kept to items shared between the platform
+  code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
+
+  Each cpu has a directory with the support files for it, and the
+  machines that carry the device. For example S3C2410 is contained
+  in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
+
+  Register, kernel and platform data definitions are held in the
+  include/asm-arm/arch-s3c2410 directory.
+
+
 Machines
 --------
 
index 9f0bc3bfd776b4b3f50523604a320ffe5d8eba8e..f7c9262b2dc8543aa2808931e2cb5c316efacb06 100644 (file)
@@ -66,7 +66,7 @@ runtime memory footprint:
 
 Device Enumeration
 ~~~~~~~~~~~~~~~~~~
-As a rule, platform specific (and often board-specific) setup code wil
+As a rule, platform specific (and often board-specific) setup code will
 register platform devices:
 
        int platform_device_register(struct platform_device *pdev);
@@ -106,7 +106,7 @@ It's built from two components:
     * platform_device.id ... the device instance number, or else "-1"
       to indicate there's only one.
 
-These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and
+These are concatenated, so name/id "serial"/0 indicates bus_id "serial.0", and
 "serial/3" indicates bus_id "serial.3"; both would use the platform_driver
 named "serial".  While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
 and use the platform_driver called "my_rtc".
index c585aa8d62b430fc4c052253f8db7fd38bd0e2cc..6a451f47d40f3ede1ee6b726b5782d13ed145d6b 100644 (file)
@@ -253,29 +253,6 @@ Who:       Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
 
 ---------------------------
 
-<<<<<<< test:Documentation/feature-removal-schedule.txt
-What:  ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
-When:  2.6.21
-Why:   hotkey.c was an attempt to consolidate multiple drivers that use
-       ACPI to implement hotkeys.  However, hotkeys are not documented
-       in the ACPI specification, so the drivers used undocumented
-       vendor-specific hooks and turned out to be more different than
-       the same.
-
-       Further, the keys and the features supplied by each platform
-       are different, so there will always be a need for
-       platform-specific drivers.
-
-       So the new plan is to delete hotkey.c and instead, work on the
-       platform specific drivers to try to make them look the same
-       to the user when they supply the same features.
-
-       hotkey.c has always depended on CONFIG_EXPERIMENTAL
-
-Who:   Len Brown <len.brown@intel.com>
-
----------------------------
-
 What:  /sys/firmware/acpi/namespace
 When:  2.6.21
 Why:   The ACPI namespace is effectively the symbol list for
@@ -306,13 +283,6 @@ Who:       Len Brown <len.brown@intel.com>
 
 ---------------------------
 
-What:  JFFS (version 1)
-When:  2.6.21
-Why:   Unmaintained for years, superceded by JFFS2 for years.
-Who:   Jeff Garzik <jeff@garzik.org>
-
----------------------------
-
 What:   sk98lin network driver
 When:   July 2007
 Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
index 4dc28cc935037c3b9c8f7cdc4dbb26854fbc2ea8..571785887a4f46e2341051388cc51d8dbb5cc8d7 100644 (file)
@@ -4,6 +4,8 @@ Exporting
        - explanation of how to make filesystems exportable.
 Locking
        - info on locking rules as they pertain to Linux VFS.
+9p.txt
+       - 9p (v9fs) is an implementation of the Plan 9 remote fs protocol.
 adfs.txt
        - info and mount options for the Acorn Advanced Disc Filing System.
 afs.txt
@@ -82,8 +84,6 @@ udf.txt
        - info and mount options for the UDF filesystem.
 ufs.txt
        - info on the ufs filesystem.
-v9fs.txt
-       - v9fs is a Unix implementation of the Plan 9 9p remote fs protocol.
 vfat.txt
        - info on using the VFAT filesystem used in Windows NT and Windows 95
 vfs.txt
index 4d075a4558f9d8ad61799cfcf6028edd497a59b3..bbd8b28c13de917dc3bdc6d04b1bc38e9aea2768 100644 (file)
@@ -40,6 +40,10 @@ OPTIONS
   aname=name   aname specifies the file tree to access when the server is
                offering several exported file systems.
 
+  cache=mode   specifies a cacheing policy.  By default, no caches are used.
+                       loose = no attempts are made at consistency,
+                                intended for exclusive, read-only mounts
+
   debug=n      specifies debug level.  The debug level is a bitmask.
                        0x01 = display verbose error messages
                        0x02 = developer debug (DEBUG_CURRENT)
index 7ba2baa165ffdc547b292708a4578a2c7800abf8..5daa2aaec2c529d7cfa757fb68b5e3499ff32ed6 100644 (file)
@@ -65,7 +65,7 @@ Accessing legacy resources through sysfs
 ----------------------------------------
 
 Legacy I/O port and ISA memory resources are also provided in sysfs if the
-underlying platform supports them.  They're located in the PCI class heirarchy,
+underlying platform supports them.  They're located in the PCI class hierarchy,
 e.g.
 
        /sys/class/pci_bus/0000:17/
index 09dd510c4a5fef1ecff21d79ad0d961b3cd864d1..576ce463cf442d7fb806fea31eb373c883647d86 100644 (file)
@@ -78,7 +78,8 @@ Identifying GPIOs
 -----------------
 GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
 reserves "negative" numbers for other purposes like marking signals as
-"not available on this board", or indicating faults.
+"not available on this board", or indicating faults.  Code that doesn't
+touch the underlying hardware treats these integers as opaque cookies.
 
 Platforms define how they use those integers, and usually #define symbols
 for the GPIO lines so that board-specific setup code directly corresponds
@@ -139,10 +140,10 @@ issues including wire-OR and output latencies.
 The get/set calls have no error returns because "invalid GPIO" should have
 been reported earlier in gpio_set_direction().  However, note that not all
 platforms can read the value of output pins; those that can't should always
-return zero.  Also, these calls will be ignored for GPIOs that can't safely
-be accessed wihtout sleeping (see below).
+return zero.  Also, using these calls for GPIOs that can't safely be accessed
+without sleeping (see below) is an error.
 
-Platform-specific implementations are encouraged to optimise the two
+Platform-specific implementations are encouraged to optimize the two
 calls to access the GPIO value in cases where the GPIO number (and for
 output, value) are constant.  It's normal for them to need only a couple
 of instructions in such cases (reading or writing a hardware register),
@@ -239,7 +240,8 @@ options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
 system wakeup capabilities.
 
 Non-error values returned from irq_to_gpio() would most commonly be used
-with gpio_get_value().
+with gpio_get_value(), for example to initialize or update driver state
+when the IRQ is edge-triggered.
 
 
 
@@ -260,9 +262,10 @@ pullups (or pulldowns) so that the on-chip ones should not be used.
 There are other system-specific mechanisms that are not specified here,
 like the aforementioned options for input de-glitching and wire-OR output.
 Hardware may support reading or writing GPIOs in gangs, but that's usually
-configuration dependednt:  for GPIOs sharing the same bank.  (GPIOs are
+configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
 commonly grouped in banks of 16 or 32, with a given SOC having several such
-banks.)  Code relying on such mechanisms will necessarily be nonportable.
+banks.)  Some systems can trigger IRQs from output GPIOs.  Code relying on
+such mechanisms will necessarily be nonportable.
 
 Dynamic definition of GPIOs is not currently supported; for example, as
 a side effect of configuring an add-on board with some GPIO expanders.
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
new file mode 100644 (file)
index 0000000..27f782e
--- /dev/null
@@ -0,0 +1,68 @@
+timer_stats - timer usage statistics
+------------------------------------
+
+timer_stats is a debugging facility to make the timer (ab)usage in a Linux
+system visible to kernel and userspace developers. It is not intended for
+production usage as it adds significant overhead to the (hr)timer code and the
+(hr)timer data structures.
+
+timer_stats should be used by kernel and userspace developers to verify that
+their code does not make unduly use of timers. This helps to avoid unnecessary
+wakeups, which should be avoided to optimize power consumption.
+
+It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
+section.
+
+timer_stats collects information about the timer events which are fired in a
+Linux system over a sample period:
+
+- the pid of the task(process) which initialized the timer
+- the name of the process which initialized the timer
+- the function where the timer was intialized
+- the callback function which is associated to the timer
+- the number of events (callbacks)
+
+timer_stats adds an entry to /proc: /proc/timer_stats
+
+This entry is used to control the statistics functionality and to read out the
+sampled information.
+
+The timer_stats functionality is inactive on bootup.
+
+To activate a sample period issue:
+# echo 1 >/proc/timer_stats
+
+To stop a sample period issue:
+# echo 0 >/proc/timer_stats
+
+The statistics can be retrieved by:
+# cat /proc/timer_stats
+
+The readout of /proc/timer_stats automatically disables sampling. The sampled
+information is kept until a new sample period is started. This allows multiple
+readouts.
+
+Sample output of /proc/timer_stats:
+
+Timerstats sample period: 3.888770 s
+  12,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+  15,     1 swapper          hcd_submit_urb (rh_timer_func)
+   4,   959 kedac            schedule_timeout (process_timeout)
+   1,     0 swapper          page_writeback_init (wb_timer_fn)
+  28,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+  22,  2948 IRQ 4            tty_flip_buffer_push (delayed_work_timer_fn)
+   3,  3100 bash             schedule_timeout (process_timeout)
+   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+   1,     1 swapper          neigh_table_init_no_netlink (neigh_periodic_timer)
+   1,  2292 ip               __netdev_watchdog_up (dev_watchdog)
+   1,    23 events/1         do_cache_clean (delayed_work_timer_fn)
+90 total events, 30.0 events/sec
+
+The first column is the number of events, the second column the pid, the third
+column is the name of the process. The forth column shows the function which
+initialized the timer and in parantheses the callback function which was
+executed on expiry.
+
+    Thomas, Ingo
+
diff --git a/Documentation/hrtimers/highres.txt b/Documentation/hrtimers/highres.txt
new file mode 100644 (file)
index 0000000..ce0e9a9
--- /dev/null
@@ -0,0 +1,249 @@
+High resolution timers and dynamic ticks design notes
+-----------------------------------------------------
+
+Further information can be found in the paper of the OLS 2006 talk "hrtimers
+and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
+be found on the OLS website:
+http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
+
+The slides to this talk are available from:
+http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
+
+The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
+changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
+design of the Linux time(r) system before hrtimers and other building blocks
+got merged into mainline.
+
+Note: the paper and the slides are talking about "clock event source", while we
+switched to the name "clock event devices" in meantime.
+
+The design contains the following basic building blocks:
+
+- hrtimer base infrastructure
+- timeofday and clock source management
+- clock event management
+- high resolution timer functionality
+- dynamic ticks
+
+
+hrtimer base infrastructure
+---------------------------
+
+The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
+the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+also figure #2 (OLS slides p. 15)
+
+The main differences to the timer wheel, which holds the armed timer_list type
+timers are:
+       - time ordered enqueueing into a rb-tree
+       - independent of ticks (the processing is based on nanoseconds)
+
+
+timeofday and clock source management
+-------------------------------------
+
+John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
+code out of the architecture-specific areas into a generic management
+framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
+specific portion is reduced to the low level hardware details of the clock
+sources, which are registered in the framework and selected on a quality based
+decision. The low level code provides hardware setup and readout routines and
+initializes data structures, which are used by the generic time keeping code to
+convert the clock ticks to nanosecond based time values. All other time keeping
+related functionality is moved into the generic code. The GTOD base patch got
+merged into the 2.6.18 kernel.
+
+Further information about the Generic Time Of Day framework is available in the
+OLS 2005 Proceedings Volume 1:
+http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
+
+The paper "We Are Not Getting Any Younger: A New Approach to Time and
+Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
+
+Figure #3 (OLS slides p.18) illustrates the transformation.
+
+
+clock event management
+----------------------
+
+While clock sources provide read access to the monotonically increasing time
+value, clock event devices are used to schedule the next event
+interrupt(s). The next event is currently defined to be periodic, with its
+period defined at compile time. The setup and selection of the event device
+for various event driven functionalities is hardwired into the architecture
+dependent code. This results in duplicated code across all architectures and
+makes it extremely difficult to change the configuration of the system to use
+event interrupt devices other than those already built into the
+architecture. Another implication of the current design is that it is necessary
+to touch all the architecture-specific implementations in order to provide new
+functionality like high resolution timers or dynamic ticks.
+
+The clock events subsystem tries to address this problem by providing a generic
+solution to manage clock event devices and their usage for the various clock
+event driven kernel functionalities. The goal of the clock event subsystem is
+to minimize the clock event related architecture dependent code to the pure
+hardware related handling and to allow easy addition and utilization of new
+clock event devices. It also minimizes the duplicated code across the
+architectures as it provides generic functionality down to the interrupt
+service handler, which is almost inherently hardware dependent.
+
+Clock event devices are registered either by the architecture dependent boot
+code or at module insertion time. Each clock event device fills a data
+structure with clock-specific property parameters and callback functions. The
+clock event management decides, by using the specified property parameters, the
+set of system functions a clock event device will be used to support. This
+includes the distinction of per-CPU and per-system global event devices.
+
+System-level global event devices are used for the Linux periodic tick. Per-CPU
+event devices are used to provide local CPU functionality such as process
+accounting, profiling, and high resolution timers.
+
+The management layer assignes one or more of the folliwing functions to a clock
+event device:
+      - system global periodic tick (jiffies update)
+      - cpu local update_process_times
+      - cpu local profiling
+      - cpu local next event interrupt (non periodic mode)
+
+The clock event device delegates the selection of those timer interrupt related
+functions completely to the management layer. The clock management layer stores
+a function pointer in the device description structure, which has to be called
+from the hardware level handler. This removes a lot of duplicated code from the
+architecture specific timer interrupt handlers and hands the control over the
+clock event devices and the assignment of timer interrupt related functionality
+to the core code.
+
+The clock event layer API is rather small. Aside from the clock event device
+registration interface it provides functions to schedule the next event
+interrupt, clock event device notification service and support for suspend and
+resume.
+
+The framework adds about 700 lines of code which results in a 2KB increase of
+the kernel binary size. The conversion of i386 removes about 100 lines of
+code. The binary size decrease is in the range of 400 byte. We believe that the
+increase of flexibility and the avoidance of duplicated code across
+architectures justifies the slight increase of the binary size.
+
+The conversion of an architecture has no functional impact, but allows to
+utilize the high resolution and dynamic tick functionalites without any change
+to the clock event device and timer interrupt code. After the conversion the
+enabling of high resolution timers and dynamic ticks is simply provided by
+adding the kernel/time/Kconfig file to the architecture specific Kconfig and
+adding the dynamic tick specific calls to the idle routine (a total of 3 lines
+added to the idle function and the Kconfig file)
+
+Figure #4 (OLS slides p.20) illustrates the transformation.
+
+
+high resolution timer functionality
+-----------------------------------
+
+During system boot it is not possible to use the high resolution timer
+functionality, while making it possible would be difficult and would serve no
+useful function. The initialization of the clock event device framework, the
+clock source framework (GTOD) and hrtimers itself has to be done and
+appropriate clock sources and clock event devices have to be registered before
+the high resolution functionality can work. Up to the point where hrtimers are
+initialized, the system works in the usual low resolution periodic mode. The
+clock source and the clock event device layers provide notification functions
+which inform hrtimers about availability of new hardware. hrtimers validates
+the usability of the registered clock sources and clock event devices before
+switching to high resolution mode. This ensures also that a kernel which is
+configured for high resolution timers can run on a system which lacks the
+necessary hardware support.
+
+The high resolution timer code does not support SMP machines which have only
+global clock event devices. The support of such hardware would involve IPI
+calls when an interrupt happens. The overhead would be much larger than the
+benefit. This is the reason why we currently disable high resolution and
+dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
+state. A workaround is available as an idea, but the problem has not been
+tackled yet.
+
+The time ordered insertion of timers provides all the infrastructure to decide
+whether the event device has to be reprogrammed when a timer is added. The
+decision is made per timer base and synchronized across per-cpu timer bases in
+a support function. The design allows the system to utilize separate per-CPU
+clock event devices for the per-CPU timer bases, but currently only one
+reprogrammable clock event device per-CPU is utilized.
+
+When the timer interrupt happens, the next event interrupt handler is called
+from the clock event distribution code and moves expired timers from the
+red-black tree to a separate double linked list and invokes the softirq
+handler. An additional mode field in the hrtimer structure allows the system to
+execute callback functions directly from the next event interrupt handler. This
+is restricted to code which can safely be executed in the hard interrupt
+context. This applies, for example, to the common case of a wakeup function as
+used by nanosleep. The advantage of executing the handler in the interrupt
+context is the avoidance of up to two context switches - from the interrupted
+context to the softirq and to the task which is woken up by the expired
+timer.
+
+Once a system has switched to high resolution mode, the periodic tick is
+switched off. This disables the per system global periodic clock event device -
+e.g. the PIT on i386 SMP systems.
+
+The periodic tick functionality is provided by an per-cpu hrtimer. The callback
+function is executed in the next event interrupt context and updates jiffies
+and calls update_process_times and profiling. The implementation of the hrtimer
+based periodic tick is designed to be extended with dynamic tick functionality.
+This allows to use a single clock event device to schedule high resolution
+timer and periodic events (jiffies tick, profiling, process accounting) on UP
+systems. This has been proved to work with the PIT on i386 and the Incrementer
+on PPC.
+
+The softirq for running the hrtimer queues and executing the callbacks has been
+separated from the tick bound timer softirq to allow accurate delivery of high
+resolution timer signals which are used by itimer and POSIX interval
+timers. The execution of this softirq can still be delayed by other softirqs,
+but the overall latencies have been significantly improved by this separation.
+
+Figure #5 (OLS slides p.22) illustrates the transformation.
+
+
+dynamic ticks
+-------------
+
+Dynamic ticks are the logical consequence of the hrtimer based periodic tick
+replacement (sched_tick). The functionality of the sched_tick hrtimer is
+extended by three functions:
+
+- hrtimer_stop_sched_tick
+- hrtimer_restart_sched_tick
+- hrtimer_update_jiffies
+
+hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
+evaluates the next scheduled timer event (from both hrtimers and the timer
+wheel) and in case that the next event is further away than the next tick it
+reprograms the sched_tick to this future event, to allow longer idle sleeps
+without worthless interruption by the periodic tick. The function is also
+called when an interrupt happens during the idle period, which does not cause a
+reschedule. The call is necessary as the interrupt handler might have armed a
+new timer whose expiry time is before the time which was identified as the
+nearest event in the previous call to hrtimer_stop_sched_tick.
+
+hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
+it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
+which is kept active until the next call to hrtimer_stop_sched_tick().
+
+hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
+in the idle period to make sure that jiffies are up to date and the interrupt
+handler has not to deal with an eventually stale jiffy value.
+
+The dynamic tick feature provides statistical values which are exported to
+userspace via /proc/stats and can be made available for enhanced power
+management control.
+
+The implementation leaves room for further development like full tickless
+systems, where the time slice is controlled by the scheduler, variable
+frequency profiling, and a complete removal of jiffies in the future.
+
+
+Aside the current initial submission of i386 support, the patchset has been
+extended to x86_64 and ARM already. Initial (work in progress) support is also
+available for MIPS and PowerPC.
+
+         Thomas, Ingo
+
+
+
index 4b3d6710c504c6257b7abd7d03129f9320e7c2c5..bb5306e9a5c331c781aceef4d168c8710d482cb4 100644 (file)
@@ -34,7 +34,7 @@ This document describes the Linux kernel Makefiles.
           --- 6.1 Set variables to tweak the build to the architecture
           --- 6.2 Add prerequisites to archprepare:
           --- 6.3 List directories to visit when descending
-          --- 6.4 Architecture specific boot images
+          --- 6.4 Architecture-specific boot images
           --- 6.5 Building non-kbuild targets
           --- 6.6 Commands useful for building a boot image
           --- 6.7 Custom kbuild commands
@@ -124,7 +124,7 @@ more details, with real examples.
        Example:
                obj-y += foo.o
 
-       This tell kbuild that there is one object in that directory, named
+       This tells kbuild that there is one object in that directory, named
        foo.o. foo.o will be built from foo.c or foo.S.
 
        If foo.o shall be built as a module, the variable obj-m is used.
@@ -353,7 +353,7 @@ more details, with real examples.
        Special rules are used when the kbuild infrastructure does
        not provide the required support. A typical example is
        header files generated during the build process.
-       Another example are the architecture specific Makefiles which
+       Another example are the architecture-specific Makefiles which
        need special rules to prepare boot images etc.
 
        Special rules are written as normal Make rules.
@@ -416,7 +416,7 @@ more details, with real examples.
                #arch/i386/kernel/Makefile
                vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)
 
-       In the above example vsyscall-flags will be assigned the option
+       In the above example, vsyscall-flags will be assigned the option
        -Wl$(comma)--hash-style=sysv if it is supported by $(CC).
        The second argument is optional, and if supplied will be used
        if first argument is not supported.
@@ -434,7 +434,7 @@ more details, with real examples.
                #arch/i386/Makefile
                cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
 
-       In the above example cflags-y will be assigned the option
+       In the above example, cflags-y will be assigned the option
        -march=pentium-mmx if supported by $(CC), otherwise -march=i586.
        The second argument to cc-option is optional, and if omitted,
        cflags-y will be assigned no value if first option is not supported.
@@ -750,10 +750,10 @@ When kbuild executes, the following steps are followed (roughly):
    located at the root of the obj tree.
    The very first objects linked are listed in head-y, assigned by
    arch/$(ARCH)/Makefile.
-7) Finally, the architecture specific part does any required post processing
+7) Finally, the architecture-specific part does any required post processing
    and builds the final bootimage.
    - This includes building boot records
-   - Preparing initrd images and thelike
+   - Preparing initrd images and the like
 
 
 --- 6.1 Set variables to tweak the build to the architecture
@@ -880,7 +880,7 @@ When kbuild executes, the following steps are followed (roughly):
 
        $(head-y) lists objects to be linked first in vmlinux.
        $(libs-y) lists directories where a lib.a archive can be located.
-       The rest lists directories where a built-in.o object file can be
+       The rest list directories where a built-in.o object file can be
        located.
 
        $(init-y) objects will be located after $(head-y).
@@ -888,7 +888,7 @@ When kbuild executes, the following steps are followed (roughly):
        $(core-y), $(libs-y), $(drivers-y) and $(net-y).
 
        The top level Makefile defines values for all generic directories,
-       and arch/$(ARCH)/Makefile only adds architecture specific directories.
+       and arch/$(ARCH)/Makefile only adds architecture-specific directories.
 
        Example:
                #arch/sparc64/Makefile
@@ -897,7 +897,7 @@ When kbuild executes, the following steps are followed (roughly):
                drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/
 
 
---- 6.4 Architecture specific boot images
+--- 6.4 Architecture-specific boot images
 
        An arch Makefile specifies goals that take the vmlinux file, compress
        it, wrap it in bootstrapping code, and copy the resulting files
@@ -924,7 +924,7 @@ When kbuild executes, the following steps are followed (roughly):
        "$(Q)$(MAKE) $(build)=<dir>" is the recommended way to invoke
        make in a subdirectory.
 
-       There are no rules for naming architecture specific targets,
+       There are no rules for naming architecture-specific targets,
        but executing "make help" will list all relevant targets.
        To support this, $(archhelp) must be defined.
 
@@ -982,7 +982,7 @@ When kbuild executes, the following steps are followed (roughly):
                        $(call if_changed,ld/objcopy/gzip)
 
        When the rule is evaluated, it is checked to see if any files
-       needs an update, or the command line has changed since the last
+       need an update, or the command line has changed since the last
        invocation. The latter will force a rebuild if any options
        to the executable have changed.
        Any target that utilises if_changed must be listed in $(targets),
@@ -1089,7 +1089,7 @@ When kbuild executes, the following steps are followed (roughly):
                          assignment.
 
        The kbuild infrastructure for *lds file are used in several
-       architecture specific files.
+       architecture-specific files.
 
 
 === 7 Kbuild Variables
@@ -1133,7 +1133,7 @@ The top Makefile exports the following variables:
 
        This variable defines a place for the arch Makefiles to install
        the resident kernel image and System.map file.
-       Use this for architecture specific install targets.
+       Use this for architecture-specific install targets.
 
     INSTALL_MOD_PATH, MODLIB
 
index b53bccbd97270f37871964fda6ba46b0f706365a..c68dafeda7a70ae6db56523816fa2280cd13e1b9 100644 (file)
@@ -1,10 +1,10 @@
 
-       Index of Documentation for People Interested in Writing and/or
-                                      
-                      Understanding the Linux Kernel.
-                                      
-               Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
-                                      
+    Index of Documentation for People Interested in Writing and/or
+
+                   Understanding the Linux Kernel.
+
+          Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
+
 /*
  * The latest version of this document may be found at:
  *   http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
        13.-The Linux Kernel Sources, A.-Linux Data Structures, B.-The
        Alpha AXP Processor, C.-Useful Web and FTP Sites, D.-The GNU
        General Public License, Glossary". In short: a must have.
-       
-     * Title: "The Linux Kernel Hackers' Guide"
-       Author: Michael K.Johnson and others.
-       URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
-       Keywords: everything!
-       Description: No more Postscript book-like version. Only HTML now.
-       Many people have contributed. The interface is similar to web
-       available mailing lists archives. You can find some articles and
-       then some mails asking questions about them and/or complementing
-       previous contributions. A little bit anarchic in this aspect, but
-       with some valuable information in some cases.
-       
+
+     * Title: "Linux Device Drivers, 2nd Edition"
+       Author: Alessandro Rubini and Jonathan Corbet.
+       URL: http://www.xml.com/ldd/chapter/book/index.html
+       Keywords: device drivers, modules, debugging, memory, hardware,
+       interrupt handling, char drivers, block drivers, kmod, mmap, DMA,
+       buses.
+       Description: O'Reilly's popular book, now also on-line under the
+       GNU Free Documentation License.
+       Notes: You can also buy it in paper-form from O'Reilly. See below
+       under BOOKS (Not on-line).
+
      * Title: "Conceptual Architecture of the Linux Kernel"
        Author: Ivan T. Bowman.
        URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a1.html
        Description: Conceptual software arquitecture of the Linux kernel,
        automatically extracted from the source code. Very detailed. Good
        figures. Gives good overall kernel understanding.
-       
+
      * Title: "Concrete Architecture of the Linux Kernel"
        Author: Ivan T. Bowman, Saheem Siddiqi, and Meyer C. Tanuan.
        URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a2.html
-       Keywords: concrete arquitecture, extracted design, reverse
+       Keywords: concrete architecture, extracted design, reverse
        engineering, system structure, dependencies.
-       Description: Concrete arquitecture of the Linux kernel,
+       Description: Concrete architecture of the Linux kernel,
        automatically extracted from the source code. Very detailed. Good
        figures. Gives good overall kernel understanding. This papers
        focus on lower details than its predecessor (files, variables...).
-       
+
      * Title: "Linux as a Case Study: Its Extracted Software
        Architecture"
        Author: Ivan T. Bowman, Richard C. Holt and Neil V. Brewster.
        Description: Paper appeared at ICSE'99, Los Angeles, May 16-22,
        1999. A mixture of the previous two documents from the same
        author.
-       
+
      * Title: "Overview of the Virtual File System"
        Author: Richard Gooch.
        URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt
        What is it, how it works, operations taken when opening a file or
        mounting a file system and description of important data
        structures explaining the purpose of each of their entries.
-       
+
      * Title: "The Linux RAID-1, 4, 5 Code"
        Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
-       URL: http://www2.linuxjournal.com/lj-issues/issue44/2391.html
+       URL: http://www.linuxjournal.com/article.php?sid=2391
        Keywords: RAID, MD driver.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "A description of the implementation of the RAID-1,
        RAID-4 and RAID-5 personalities of the MD device driver in the
        Linux kernel, providing users with high performance and reliable,
        secondary-storage capability using software".
-       
+
      * Title: "Dynamic Kernels: Modularized Device Drivers"
        Author: Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue23/1219.html
+       URL: http://www.linuxjournal.com/article.php?sid=1219
        Keywords: device driver, module, loading/unloading modules,
        allocating resources.
        Description: Linux Journal Kernel Korner article. Here is it's
        loadable modules. This installment presents an introduction to the
        topic, preparing the reader to understand next month's
        installment".
-       
+
      * Title: "Dynamic Kernels: Discovery"
        Author: Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue24/1220.html
+       URL: http://www.linuxjournal.com/article.php?sid=1220
        Keywords: character driver, init_module, clean_up module,
        autodetection, mayor number, minor number, file operations,
        open(), close().
        the actual code to create custom module implementing a character
        device driver. It describes the code for module initialization and
        cleanup, as well as the open() and close() system calls".
-       
+
      * Title: "The Devil's in the Details"
        Author: Georg v. Zezschwitz and Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue25/1221.html
+       URL: http://www.linuxjournal.com/article.php?sid=1221
        Keywords: read(), write(), select(), ioctl(), blocking/non
        blocking mode, interrupt handler.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This article, the third of four on writing character
        device drivers, introduces concepts of reading, writing, and using
        ioctl-calls".
-       
+
      * Title: "Dissecting Interrupts and Browsing DMA"
        Author: Alessandro Rubini and Georg v. Zezschwitz.
-       URL: http://www2.linuxjournal.com/lj-issues/issue26/1222.html
+       URL: http://www.linuxjournal.com/article.php?sid=1222
        Keywords: interrupts, irqs, DMA, bottom halves, task queues.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This is the fourth in a series of articles about
        writing, and several different facilities have been provided for
        different situations. We also investigate the complex topic of
        DMA".
-       
+
      * Title: "Device Drivers Concluded"
        Author: Georg v. Zezschwitz.
-       URL: http://www2.linuxjournal.com/lj-issues/issue28/1287.html
+       URL: http://www.linuxjournal.com/article.php?sid=1287
        Keywords: address spaces, pages, pagination, page management,
        demand loading, swapping, memory protection, memory mapping, mmap,
        virtual memory areas (VMAs), vremap, PCI.
        five articles about character device drivers. In this final
        section, Georg deals with memory mapping devices, beginning with
        an overall description of the Linux memory management concepts".
-       
+
      * Title: "Network Buffers And Memory Management"
        Author: Alan Cox.
-       URL: http://www2.linuxjournal.com/lj-issues/issue30/1312.html
+       URL: http://www.linuxjournal.com/article.php?sid=1312
        Keywords: sk_buffs, network devices, protocol/link layer
        variables, network devices flags, transmit, receive,
        configuration, multicast.
        of the Coda filesystem. This version document is meant to describe
        the current interface (version 1.0) as well as improvements we
        envisage".
-       
+
      * Title: "Programming PCI-Devices under Linux"
        Author: Claus Schroeter.
        URL:
-       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pcip.ps
-       .gz
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pcip.ps.gz
        Keywords: PCI, device, busmastering.
        Description: 6 pages tutorial on PCI programming under Linux.
        Gives the basic concepts on the architecture of the PCI subsystem,
        as long as basic functions and macros to read/write the devices
        and perform busmastering.
-       
+
      * Title: "Writing Character Device Driver for Linux"
        Author: R. Baruch and C. Schroeter.
        URL:
-       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers
-       .ps.gz
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers.ps.gz
        Keywords: character device drivers, I/O, signals, DMA, accessing
        ports in user space, kernel environment.
        Description: 68 pages paper on writing character drivers. A little
        bit old (1.993, 1.994) although still useful.
-       
+
      * Title: "Design and Implementation of the Second Extended
        Filesystem"
        Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
        e2fsck's passes description... A must read!
        Notes: This paper was first published in the Proceedings of the
        First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
-       
+
      * Title: "Analysis of the Ext2fs structure"
        Author: Louis-Dominique Dubeau.
-       URL: http://step.polymtl.ca/~ldd/ext2fs/ext2fs_toc.html
+       URL: http://www.nondot.org/sabre/os/files/FileSystems/ext2fs/
        Keywords: ext2, filesystem, ext2fs.
        Description: Description of ext2's blocks, directories, inodes,
        bitmaps, invariants...
-       
+
      * Title: "Journaling the Linux ext2fs Filesystem"
        Author: Stephen C. Tweedie.
        URL:
        Description: Excellent 8-pages paper explaining the journaling
        capabilities added to ext2 by the author, showing different
        problems faced and the alternatives chosen.
-       
+
      * Title: "Kernel API changes from 2.0 to 2.2"
        Author: Richard Gooch.
        URL:
        Keywords: 2.2, changes.
        Description: Kernel functions/structures/variables which changed
        from 2.0.x to 2.2.x.
-       
+
      * Title: "Kernel API changes from 2.2 to 2.4"
        Author: Richard Gooch.
        URL:
        Notes: Beware: the main page states: "This document may not be
        published, printed or used in excerpts without explicit permission
        of the author". Fortunately, it may still be read...
-       
-     * Title: "Tour Of the Linux Kernel Source"
-       Author: Vijo Cherian.
-       URL: http://www.geocities.com/vijoc/tolks/tolks.html
-       Keywords: .
-       Description: A classic of this page! Was lost for a while and is
-       back again. Thanks Vijo! TOLKS: the name says it all. A tour of
-       the sources, describing directories, files, variables, data
-       structures... It covers general stuff, device drivers,
-       filesystems, IPC and Networking Code.
-       
+
      * Title: "Linux Kernel Mailing List Glossary"
        Author: various
        URL: http://kernelnewbies.org/glossary/
        kernels, but most of it applies to 2.2 too; 2.0 is slightly
        different". Freely redistributable under the conditions of the GNU
        General Public License.
-       
+
+     * Title: "Global spinlock list and usage"
+       Author: Rick Lindsley.
+       URL: http://lse.sourceforge.net/lockhier/global-spin-lock
+       Keywords: spinlock.
+       Description: This is an attempt to document both the existence and
+       usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
+       list of spinlocks showing when they are used, which functions
+       access them, how each lock is acquired, under what conditions it
+       is held, whether interrupts can occur or not while it is held...
+
      * Title: "Porting Linux 2.0 Drivers To Linux 2.2: Changes and New
        Features "
        Author: Alan Cox.
        Keywords: ports, porting.
        Description: Article from Linux Magazine on porting from 2.0 to
        2.2 kernels.
-       
+
      * Title: "Porting Device Drivers To Linux 2.2: part II"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-06/gear_01.html
        Keywords: ports, porting.
        Description: Second part on porting from 2.0 to 2.2 kernels.
-       
+
      * Title: "How To Make Sure Your Driver Will Work On The Power
        Macintosh"
        Author: Paul Mackerras.
        URL: http://www.linux-mag.com/1999-07/gear_01.html
        Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
        Description: The title says it all.
-       
+
      * Title: "An Introduction to SCSI Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-08/gear_01.html
        Keywords: SCSI, device, driver.
        Description: The title says it all.
-       
+
      * Title: "Advanced SCSI Drivers And Other Tales"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-09/gear_01.html
        Keywords: SCSI, device, driver, advanced.
        Description: The title says it all.
-       
+
      * Title: "Writing Linux Mouse Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-10/gear_01.html
        Keywords: mouse, driver, gpm.
        Description: The title says it all.
-       
+
      * Title: "More on Mouse Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-11/gear_01.html
        Keywords: mouse, driver, gpm, races, asynchronous I/O.
        Description: The title still says it all.
-       
+
      * Title: "Writing Video4linux Radio Driver"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-12/gear_01.html
        Keywords: video4linux, driver, radio, radio devices.
        Description: The title says it all.
-       
+
      * Title: "Video4linux Drivers, Part 1: Video-Capture Device"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-01/gear_01.html
        Keywords: video4linux, driver, video capture, capture devices,
        camera driver.
        Description: The title says it all.
-       
+
      * Title: "Video4linux Drivers, Part 2: Video-capture Devices"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-02/gear_01.html
        Keywords: video4linux, driver, video capture, capture devices,
        camera driver, control, query capabilities, capability, facility.
        Description: The title says it all.
-       
+
      * Title: "PCI Management in Linux 2.2"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-03/gear_01.html
        Keywords: PCI, bus, bus-mastering.
        Description: The title says it all.
-       
+
      * Title: "Linux 2.4 Kernel Internals"
        Author: Tigran Aivazian and Christoph Hellwig.
        URL: http://www.moses.uklinux.net/patches/lki.html
        Description: A little book used for a short training course.
        Covers building the kernel image, booting (including SMP bootup),
        process management, VFS and more.
-       
+
      * Title: "Linux IP Networking. A Guide to the Implementation and
        Modification of the Linux Protocol Stack."
        Author: Glenn Herrin.
-       URL:
-       http://kernelnewbies.org/documents/ipnetworking/linuxipnetworking.
-       html
+       URL: http://www.cs.unh.edu/cnrg/gherrin
        Keywords: network, networking, protocol, IP, UDP, TCP, connection,
        socket, receiving, transmitting, forwarding, routing, packets,
        modules, /proc, sk_buff, FIB, tags.
        drivers for the Linux PCMCIA Card Services interface. It also
        describes how to write user-mode utilities for communicating with
        Card Services.
-       
+
      * Title: "The Linux Kernel NFSD Implementation"
        Author: Neil Brown.
        URL:
        Pages: 520.
        ISBN: 2-212-08932-5
        Notes: French.
-       
-     * Title: "The Linux Kernel Book"
-       Author: Remy Card, Eric Dumas, Franck Mevel.
-       Publisher: John Wiley & Sons.
-       Date: 1998.
-       ISBN: 0-471-98141-9
-       Notes: English translation.
-       
-     * Title: "Linux 2.0"
-       Author: Remy Card, Eric Dumas, Franck Mevel.
-       Publisher: Gestión 2000.
-       Date: 1997.
-       Pages: 501.
-       ISBN: 8-480-88208-5
-       Notes: Spanish translation.
-       
+
      * Title: "Unix internals -- the new frontiers"
        Author: Uresh Vahalia.
        Publisher: Prentice Hall.
        Date: 1996.
        Pages: 600.
        ISBN: 0-13-101908-2
-       
-     * Title: "Linux Core Kernel Commentary. Guide to Insider's Knowledge
-       on the Core Kernel of the Linux Code"
-       Author: Scott Maxwell.
-       Publisher: Coriolis.
-       Date: 1999.
-       Pages: 592.
-       ISBN: 1-57610-469-9
-       Notes: CD-ROM included. Line by line commentary of the kernel
-       code.
-       
-     * Title: "Linux IP Stacks Commentary"
-       Author: Stephen Satchell and HBJ Clifford.
-       Publisher: Coriolis.
-       Date: 2000.
-       Pages: ???.
-       ISBN: 1-57610-470-2
-       Notes: Line by line source code commentary book.
-       
+
+     * Title:  "The  Design  and Implementation of the 4.4 BSD UNIX
+       Operating System"
+       Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
+       John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1996.
+       ISBN: 0-201-54979-4
+
      * Title: "Programming for the real world - POSIX.4"
        Author: Bill O. Gallmeister.
        Publisher: O'Reilly & Associates, Inc..
        ISBN: I-56592-074-0
        Notes: Though not being directly about Linux, Linux aims to be
        POSIX. Good reference.
-       
-     * Title: "Understanding the Linux Kernel"
-       Author: Daniel P. Bovet and Marco Cesati.
-       Publisher: O'Reilly & Associates, Inc..
-       Date: 2000.
-       Pages: 702.
-       ISBN: 0-596-00002-2
-       Notes: Further information in
-       http://www.oreilly.com/catalog/linuxkernel/
-       
+
+     * Title:  "UNIX  Systems  for  Modern Architectures: Symmetric
+       Multiprocesssing and Caching for Kernel Programmers"
+       Author: Curt Schimmel.
+       Publisher: Addison Wesley.
+       Date: June, 1994.
+       Pages: 432.
+       ISBN: 0-201-63338-8
+
+     * Title:  "The  Design  and Implementation of the 4.3 BSD UNIX
+       Operating System"
+       Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J.
+       Karels, John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1989 (reprinted with corrections on October, 1990).
+       ISBN: 0-201-06196-1
+
+     * Title: "The Design of the UNIX Operating System"
+       Author: Maurice J. Bach.
+       Publisher: Prentice Hall.
+       Date: 1986.
+       Pages: 471.
+       ISBN: 0-13-201757-1
+
      MISCELLANEOUS:
-   
+
      * Name: linux/Documentation
        Author: Many.
        URL: Just look inside your kernel sources.
        inside the Documentation directory. Some pages from this document
        (including this document itself) have been moved there, and might
        be more up to date than the web version.
-       
+
      * Name: "Linux Source Driver"
        URL: http://lsd.linux.cz
        Keywords: Browsing source code.
        you can search Linux kernel (fulltext, macros, types, functions
        and variables) and LSD can generate patches for you on the fly
        (files, directories or kernel)".
-       
+
      * Name: "Linux Kernel Source Reference"
        Author: Thomas Graichen.
        URL: http://innominate.org/~graichen/projects/lksr/
        sources of any version starting from 1.0 up to the (daily updated)
        current version available. Also you can check the differences
        between two versions of a file".
-       
+
      * Name: "Cross-Referencing Linux"
        URL: http://lxr.linux.no/source/
        Keywords: Browsing source code.
        Description: Another web-based Linux kernel source code browser.
        Lots of cross references to variables and functions. You can see
        where they are defined and where they are used.
-       
+
      * Name: "Linux Weekly News"
        URL: http://lwn.net
        Keywords: latest kernel news.
        Description: The title says it all. There's a fixed kernel section
        summarizing developers' work, bug fixes, new features and versions
        produced during the week. Published every Thursday.
-       
+
      * Name: "Kernel Traffic"
-       URL: http://www.kerneltraffic.org/kernel-traffic/
+       URL: http://kt.zork.net/kernel-traffic/
        Keywords: linux-kernel mailing list, weekly kernel news.
        Description: Weekly newsletter covering the most relevant
        discussions of the linux-kernel mailing list.
-       
+
      * Name: "CuTTiNG.eDGe.LiNuX"
        URL: http://edge.kernelnotes.org
        Keywords: changelist.
        release. What's new, what's better, what's changed. Myrdraal reads
        the patches and describes them. Pointers to the patches are there,
        too.
-       
+
      * Name: "New linux-kernel Mailing List FAQ"
        URL: http://www.tux.org/lkml/
        Keywords: linux-kernel mailing list FAQ.
        it. Read it to see how to join the mailing list. Dozens of
        interesting questions regarding the list, Linux, developers (who
        is ...?), terms (what is...?) are answered here too. Just read it.
-       
+
      * Name: "Linux Virtual File System"
        Author: Peter J. Braam.
        URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
        Description: Set of slides, presumably from a presentation on the
        Linux VFS layer. Covers version 2.1.x, with dentries and the
        dcache.
-       
+
      * Name: "Gary's Encyclopedia - The Linux Kernel"
        Author: Gary (I suppose...).
-       URL: http://members.aa.net/~swear/pedia/kernel.html
+       URL: http://www.lisoleg.net/cgi-bin/lisoleg.pl?view=kernel.htm
        Keywords: links, not found here?.
        Description: Gary's Encyclopedia exists to allow the rapid finding
        of documentation and other information of interest to GNU/Linux
        categories. This link is for kernel-specific links, documents,
        sites... Look there if you could not find here what you were
        looking for.
-       
+
      * Name: "The home page of Linux-MM"
        Author: The Linux-MM team.
        URL: http://linux-mm.org/
        Description: Site devoted to Linux Memory Management development.
        Memory related patches, HOWTOs, links, mm developers... Don't miss
        it if you are interested in memory management development!
-       
+
      * Name: "Kernel Newbies IRC Channel"
        URL: http://www.kernelnewbies.org
        Keywords: IRC, newbies, channel, asking doubts.
index d25acd51e18105aca3f3d0811d37f39aa8d3119c..c479d30eeaa384c019550194d12c94c10bf1e948 100644 (file)
@@ -48,6 +48,7 @@ parameter is applicable:
        ISAPNP  ISA PnP code is enabled.
        ISDN    Appropriate ISDN support is enabled.
        JOY     Appropriate joystick support is enabled.
+       LIBATA  Libata driver is enabled
        LP      Printer support is enabled.
        LOOP    Loopback device support is enabled.
        M68k    M68k architecture is enabled.
@@ -104,6 +105,9 @@ loader, and have no meaning to the kernel directly.
 Do not modify the syntax of boot loader parameters without extreme
 need or coordination with <Documentation/i386/boot.txt>.
 
+There are also arch-specific kernel-parameters not documented here.
+See for example <Documentation/x86_64/boot-options.txt>.
+
 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
 a trailing = on the name of any parameter states that that parameter will
 be entered as an environment variable, whereas its absence indicates that
@@ -361,6 +365,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        clocksource is not available, it defaults to PIT.
                        Format: { pit | tsc | cyclone | pmtmr }
 
+       code_bytes      [IA32] How many bytes of object code to print in an
+                       oops report.
+                       Range: 0 - 8192
+                       Default: 64
+
        disable_8254_timer
        enable_8254_timer
                        [IA32/X86_64] Disable/Enable interrupt 0 timer routing
@@ -601,6 +610,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        highmem otherwise. This also works to reduce highmem
                        size on bigger boxes.
 
+       highres=        [KNL] Enable/disable high resolution timer mode.
+                       Valid parameters: "on", "off"
+                       Default: "on"
+
        hisax=          [HW,ISDN]
                        See Documentation/isdn/README.HiSax.
 
@@ -851,7 +864,14 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: <1-256>
 
        maxcpus=        [SMP] Maximum number of processors that an SMP kernel
-                       should make use of
+                       should make use of.
+                       Using "nosmp" or "maxcpus=0" will disable SMP
+                       entirely (the MPS table probe still happens, though).
+                       A command-line option of "maxcpus=<NUM>", where <NUM>
+                       is an integer greater than 0, limits the maximum number
+                       of CPUs activated in SMP mode to <NUM>.
+                       Using "maxcpus=1" on an SMP kernel is the trivial
+                       case of an SMP kernel with only one CPU.
 
        max_addr=[KMG]  [KNL,BOOT,ia64] All physical memory greater than or
                        equal to this physical address is ignored.
@@ -1026,6 +1046,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        emulation library even if a 387 maths coprocessor
                        is present.
 
+       noacpi          [LIBATA] Disables use of ACPI in libata suspend/resume
+                       when set.
+                       Format: <int>
+
        noaliencache    [MM, NUMA] Disables the allcoation of alien caches in
                        the slab allocator.  Saves per-node memory, but will
                        impact performance on real NUMA hardware.
@@ -1070,6 +1094,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        in certain environments such as networked servers or
                        real-time systems.
 
+       nohz=           [KNL] Boottime enable/disable dynamic ticks
+                       Valid arguments: on, off
+                       Default: on
+
        noirqbalance    [IA-32,SMP,KNL] Disable kernel irq balancing
 
        noirqdebug      [IA-32] Disables the code which attempts to detect and
@@ -1259,6 +1287,12 @@ and is between 256 and 4096 characters. It is defined in the file
                                This sorting is done to get a device
                                order compatible with older (<= 2.4) kernels.
                nobfsort        Don't sort PCI devices into breadth-first order.
+               cbiosize=nn[KMG]        The fixed amount of bus space which is
+                               reserved for the CardBus bridge's IO window.
+                               The default value is 256 bytes.
+               cbmemsize=nn[KMG]       The fixed amount of bus space which is
+                               reserved for the CardBus bridge's memory
+                               window. The default value is 64 megabytes.
 
        pcmv=           [HW,PCMCIA] BadgePAD 4
 
index fd5028eca13e68a99cee05d613eff1ac43b9b9a2..cdf2f3c0ab14f8398bee52c1e4a39c41984b28b6 100644 (file)
@@ -205,8 +205,8 @@ Tips on when/where to use the above attributes:
          exclusively called by the probe() routine, can be marked __devinit.
          Ditto for remove() and __devexit.
 
-       o If mydriver_probe() is marked with __devinit(), then all address
-         references to mydriver_probe must use __devexit_p(mydriver_probe)
+       o If mydriver_remove() is marked with __devexit(), then all address
+         references to mydriver_remove must use __devexit_p(mydriver_remove)
          (in the struct pci_driver declaration for example).
          __devexit_p() will generate the function name _or_ NULL if the
          function will be discarded.  For an example, see drivers/net/tg3.c.
index 3b514672b80ed3ef6d34b179dc65d35e366f0126..b41397d6430aa4a6a589d278e07d74f739b2f60e 100644 (file)
@@ -497,7 +497,7 @@ looks like in practice.
       |   |- device_type = "cpu"
       |   |- reg = <0>
       |   |- clock-frequency = <5f5e1000>
-      |   |- linux,boot-cpu
+      |   |- 64-bit
       |   |- linux,phandle = <2>
       |
       o memory@0
@@ -509,7 +509,6 @@ looks like in practice.
       o chosen
         |- name = "chosen"
         |- bootargs = "root=/dev/sda2"
-        |- linux,platform = <00000600>
         |- linux,phandle = <4>
 
 This tree is almost a minimal tree. It pretty much contains the
@@ -519,7 +518,7 @@ physical memory layout.  It also includes misc information passed
 through /chosen, like in this example, the platform type (mandatory)
 and the kernel command line arguments (optional).
 
-The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a
+The /cpus/PowerPC,970@0/64-bit property is an example of a
 property without a value. All other properties have a value. The
 significance of the #address-cells and #size-cells properties will be
 explained in chapter IV which defines precisely the required nodes and
@@ -733,8 +732,7 @@ address which can extend beyond that limit.
       that typically get driven by the same platform code in the
       kernel, you would use a different "model" property but put a
       value in "compatible". The kernel doesn't directly use that
-      value (see /chosen/linux,platform for how the kernel chooses a
-      platform type) but it is generally useful.
+      value but it is generally useful.
 
   The root node is also generally where you add additional properties
   specific to your board like the serial number if any, that sort of
@@ -778,7 +776,6 @@ address which can extend beyond that limit.
       bytes
     - d-cache-size : one cell, size of L1 data cache in bytes
     - i-cache-size : one cell, size of L1 instruction cache in bytes
-    - linux, boot-cpu : Should be defined if this cpu is the boot cpu.
 
   Recommended properties:
 
@@ -843,11 +840,6 @@ address which can extend beyond that limit.
   the prom_init() trampoline when booting with an OF client interface,
   but that you have to provide yourself when using the flattened format.
 
-  Required properties:
-
-    - linux,platform : This is your platform number as assigned by the
-      architecture maintainers
-
   Recommended properties:
 
     - bootargs : This zero-terminated string is passed as the kernel
index 73988e0d112b490ad187144e88a7904b2ab49000..5482bf5d005b9a950364dc1dcc37462bc4f62782 100644 (file)
@@ -17,7 +17,7 @@ of the board-specific code (with the exception of stboards) ended up
 in arch/sh/kernel/ directly, with board-specific headers ending up in
 include/asm-sh/. For the new kernel, things are broken out by board type,
 companion chip type, and CPU type. Looking at a tree view of this directory
-heirarchy looks like the following:
+hierarchy looks like the following:
 
 Board-specific code:
 
@@ -108,7 +108,7 @@ overloading), and you can feel free to name the directory after the family
 member itself.
 
 There are a few things that each board is required to have, both in the
-arch/sh/boards and the include/asm-sh/ heirarchy. In order to better
+arch/sh/boards and the include/asm-sh/ hierarchy. In order to better
 explain this, we use some examples for adding an imaginary board. For
 setup code, we're required at the very least to provide definitions for
 get_system_type() and platform_setup(). For our imaginary board, this
diff --git a/Documentation/sony-laptop.txt b/Documentation/sony-laptop.txt
new file mode 100644 (file)
index 0000000..dfd26df
--- /dev/null
@@ -0,0 +1,106 @@
+Sony Notebook Control Driver (SNC) Readme
+-----------------------------------------
+       Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
+       Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+
+This mini-driver drives the SNC device present in the ACPI BIOS of
+the Sony Vaio laptops.
+
+It gives access to some extra laptop functionalities. In its current
+form, this driver let the user set or query the screen brightness
+through the backlight subsystem and remove/apply power to some devices.
+
+Backlight control:
+------------------
+If your laptop model supports it, you will find sysfs files in the
+/sys/class/backlight/sony/
+directory. You will be able to query and set the current screen
+brightness:
+       brightness              get/set screen brightness (an iteger
+                               between 0 and 7)
+       actual_brightness       reading from this file will query the HW
+                               to get real brightness value
+       max_brightness          the maximum brightness value
+
+
+Platform specific:
+------------------
+Loading the sony-laptop module will create a
+/sys/devices/platform/sony-laptop/
+directory populated with some files.
+
+You then read/write integer values from/to those files by using
+standard UNIX tools.
+
+The files are:
+       brightness_default      screen brightness which will be set
+                               when the laptop will be rebooted
+       cdpower                 power on/off the internal CD drive
+       audiopower              power on/off the internal sound card
+       lanpower                power on/off the internal ethernet card
+                               (only in debug mode)
+
+Note that some files may be missing if they are not supported
+by your particular laptop model.
+
+Example usage:
+       # echo "1" > /sys/devices/platform/sony-laptop/brightness_default
+sets the lowest screen brightness for the next and later reboots,
+       # echo "8" > /sys/devices/platform/sony-laptop/brightness_default
+sets the highest screen brightness for the next and later reboots,
+       # cat /sys/devices/platform/sony-laptop/brightness_default
+retrieves the value.
+
+       # echo "0" > /sys/devices/platform/sony-laptop/audiopower
+powers off the sound card,
+       # echo "1" > /sys/devices/platform/sony-laptop/audiopower
+powers on the sound card.
+
+Development:
+------------
+
+If you want to help with the development of this driver (and
+you are not afraid of any side effects doing strange things with
+your ACPI BIOS could have on your laptop), load the driver and
+pass the option 'debug=1'.
+
+REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS.
+
+In your kernel logs you will find the list of all ACPI methods
+the SNC device has on your laptop. You can see the GCDP/GCDP methods
+used to pwer on/off the CD drive, but there are others.
+
+I HAVE NO IDEA WHAT THOSE METHODS DO.
+
+The sony-laptop driver creates, for some of those methods (the most
+current ones found on several Vaio models), an entry under
+/sys/devices/platform/sony-laptop, just like the 'cdpower' one.
+You can create other entries corresponding to your own laptop methods by
+further editing the source (see the 'sony_acpi_values' table, and add a new
+entry to this table with your get/set method names using the
+HANDLE_NAMES macro).
+
+Your mission, should you accept it, is to try finding out what
+those entries are for, by reading/writing random values from/to those
+files and find out what is the impact on your laptop.
+
+Should you find anything interesting, please report it back to me,
+I will not disavow all knowledge of your actions :)
+
+Bugs/Limitations:
+-----------------
+
+* This driver is not based on official documentation from Sony
+  (because there is none), so there is no guarantee this driver
+  will work at all, or do the right thing. Although this hasn't
+  happened to me, this driver could do very bad things to your
+  laptop, including permanent damage.
+
+* The sony-laptop and sonypi drivers do not interact at all. In the
+  future, sonypi could use sony-laptop to do (part of) its business.
+
+* spicctrl, which is the userspace tool used to communicate with the
+  sonypi driver (through /dev/sonypi) does not try to use the
+  sony-laptop driver. In the future, spicctrl could try sonypi first,
+  and if it isn't present, try sony-laptop instead.
+
index bb7c2cac7917e97bd206442747eb6b0e77356c42..5ef75787f83a271c3916614d61549c87b5087af3 100644 (file)
@@ -57,7 +57,7 @@ bttv.o
                i2c_udelay=     Allow reduce I2C speed. Default is 5 usecs
                                (meaning 66,67 Kbps). The default is the
                                maximum supported speed by kernel bitbang
-                               algoritm. You may use lower numbers, if I2C
+                               algorithm. You may use lower numbers, if I2C
                                messages are lost (16 is known to work on
                                all supported cards).
 
index 5c86ed6f0448a8e2378a4ba62d6cedecf236215c..625a21db0c2a7e8f1825bf1cacc18b7131a37a82 100644 (file)
@@ -180,40 +180,81 @@ PCI
   pci=lastbus=NUMBER          Scan upto NUMBER busses, no matter what the mptable says.
   pci=noacpi           Don't use ACPI to set up PCI interrupt routing.
 
-IOMMU
-
- iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge][,noaperture][,calgary]
-   size  set size of iommu (in bytes)
-   noagp don't initialize the AGP driver and use full aperture.
-   off   don't use the IOMMU
-   leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
-   memaper[=order] allocate an own aperture over RAM with size 32MB^order.
-   noforce don't force IOMMU usage. Default.
-   force  Force IOMMU.
-   merge  Do SG merging. Implies force (experimental)
-   nomerge Don't do SG merging.
-   forcesac For SAC mode for masks <40bits  (experimental)
-   fullflush Flush IOMMU on each allocation (default)
-   nofullflush Don't use IOMMU fullflush
-   allowed  overwrite iommu off workarounds for specific chipsets.
-   soft         Use software bounce buffering (default for Intel machines)
-   noaperture Don't touch the aperture for AGP.
-   allowdac Allow DMA >4GB
-           When off all DMA over >4GB is forced through an IOMMU or bounce
-           buffering.
-   nodac    Forbid DMA >4GB
-   panic    Always panic when IOMMU overflows
-   calgary  Use the Calgary IOMMU if it is available
-
-  swiotlb=pages[,force]
-
-  pages  Prereserve that many 128K pages for the software IO bounce buffering.
-  force  Force all IO through the software TLB.
-
-  calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
-  calgary=[translate_empty_slots]
-  calgary=[disable=<PCI bus number>]
+IOMMU (input/output memory management unit)
+
+ Currently four x86-64 PCI-DMA mapping implementations exist:
+
+   1. <arch/x86_64/kernel/pci-nommu.c>: use no hardware/software IOMMU at all
+      (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.
+      Kernel boot message: "PCI-DMA: using GART IOMMU"
+
+   3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
+      e.g. if there is no hardware IOMMU in the system and it is need because
+      you have >3GB memory or told the kernel to us it (iommu=soft))
+      Kernel boot message: "PCI-DMA: Using software bounce buffering
+      for IO (SWIOTLB)"
+
+   4. <arch/x86_64/pci-calgary.c> : IBM Calgary hardware IOMMU. Used in IBM
+      pSeries and xSeries servers. This hardware IOMMU supports DMA address
+      mapping with memory protection, etc.
+      Kernel boot message: "PCI-DMA: Using Calgary IOMMU"
+
+ iommu=[<size>][,noagp][,off][,force][,noforce][,leak[=<nr_of_leak_pages>]
+       [,memaper[=<order>]][,merge][,forcesac][,fullflush][,nomerge]
+       [,noaperture][,calgary]
+
+  General iommu options:
+    off                Don't initialize and use any kind of IOMMU.
+    noforce            Don't force hardware IOMMU usage when it is not needed.
+                       (default).
+    force              Force the use of the hardware IOMMU even when it is
+                       not actually needed (e.g. because < 3 GB memory).
+    soft               Use software bounce buffering (SWIOTLB) (default for
+                       Intel machines). This can be used to prevent the usage
+                       of an available hardware IOMMU.
+
+  iommu options only relevant to the AMD GART hardware IOMMU:
+    <size>             Set the size of the remapping area in bytes.
+    allowed            Overwrite iommu off workarounds for specific chipsets.
+    fullflush          Flush IOMMU on each allocation (default).
+    nofullflush        Don't use IOMMU fullflush.
+    leak               Turn on simple iommu leak tracing (only when
+                       CONFIG_IOMMU_LEAK is on). Default number of leak pages
+                       is 20.
+    memaper[=<order>]  Allocate an own aperture over RAM with size 32MB<<order.
+                       (default: order=1, i.e. 64MB)
+    merge              Do scatter-gather (SG) merging. Implies "force"
+                       (experimental).
+    nomerge            Don't do scatter-gather (SG) merging.
+    noaperture         Ask the IOMMU not to touch the aperture for AGP.
+    forcesac           Force single-address cycle (SAC) mode for masks <40bits
+                       (experimental).
+    noagp              Don't initialize the AGP driver and use full aperture.
+    allowdac           Allow double-address cycle (DAC) mode, i.e. DMA >4GB.
+                       DAC is used with 32-bit PCI to push a 64-bit address in
+                       two cycles. When off all DMA over >4GB is forced through
+                       an IOMMU or software bounce buffering.
+    nodac              Forbid DAC mode, i.e. DMA >4GB.
+    panic              Always panic when IOMMU overflows.
+    calgary            Use the Calgary IOMMU if it is available
+
+  iommu options only relevant to the software bounce buffering (SWIOTLB) IOMMU
+  implementation:
+    swiotlb=<pages>[,force]
+    <pages>            Prereserve that many 128K pages for the software IO
+                       bounce buffering.
+    force              Force all IO through the software TLB.
+
+  Settings for the IBM Calgary hardware IOMMU currently found in IBM
+  pSeries and xSeries machines:
+
+    calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
+    calgary=[translate_empty_slots]
+    calgary=[disable=<PCI bus number>]
+    panic              Always panic when IOMMU overflows
 
     64k,...,8M - Set the size of each PCI slot's translation table
     when using the Calgary IOMMU. This is the size of the translation
@@ -234,14 +275,14 @@ IOMMU
 
 Debugging
 
-  oops=panic Always panic on oopses. Default is to just kill the process,
-            but there is a small probability of deadlocking the machine.
-            This will also cause panics on machine check exceptions.
-            Useful together with panic=30 to trigger a reboot.
+  oops=panic   Always panic on oopses. Default is to just kill the process,
+               but there is a small probability of deadlocking the machine.
+               This will also cause panics on machine check exceptions.
+               Useful together with panic=30 to trigger a reboot.
 
-  kstack=N   Print that many words from the kernel stack in oops dumps.
+  kstack=N     Print N words from the kernel stack in oops dumps.
 
-  pagefaulttrace Dump all page faults. Only useful for extreme debugging
+  pagefaulttrace  Dump all page faults. Only useful for extreme debugging
                and will create a lot of output.
 
   call_trace=[old|both|newfallback|new]
@@ -251,15 +292,8 @@ Debugging
                newfallback: use new unwinder but fall back to old if it gets
                        stuck (default)
 
-  call_trace=[old|both|newfallback|new]
-               old: use old inexact backtracer
-               new: use new exact dwarf2 unwinder
-               both: print entries from both
-               newfallback: use new unwinder but fall back to old if it gets
-                       stuck (default)
-
-Misc
+Miscellaneous
 
   noreplacement  Don't replace instructions with more appropriate ones
                 for the CPU. This may be useful on asymmetric MP systems
-                where some CPU have less capabilities than the others.
+                where some CPUs have less capabilities than others.
index 5c0fa345e556113e77506286f243c6e34f01d815..3c23e0587db33421e8a09fded674114b0c8a90ac 100644 (file)
@@ -2,7 +2,7 @@ Firmware support for CPU hotplug under Linux/x86-64
 ---------------------------------------------------
 
 Linux/x86-64 supports CPU hotplug now. For various reasons Linux wants to
-know in advance boot time the maximum number of CPUs that could be plugged
+know in advance of boot time the maximum number of CPUs that could be plugged
 into the system. ACPI 3.0 currently has no official way to supply
 this information from the firmware to the operating system.
 
index bddfddd466ab6355440c5d6710b2f753c4d8f7c1..5ad65d51fb95a64e1fbc646bb416c06e30a77541 100644 (file)
@@ -9,9 +9,9 @@ zombie. While the thread is in user space the kernel stack is empty
 except for the thread_info structure at the bottom.
 
 In addition to the per thread stacks, there are specialized stacks
-associated with each cpu.  These stacks are only used while the kernel
-is in control on that cpu, when a cpu returns to user space the
-specialized stacks contain no useful data.  The main cpu stacks is
+associated with each CPU.  These stacks are only used while the kernel
+is in control on that CPU; when a CPU returns to user space the
+specialized stacks contain no useful data.  The main CPU stacks are:
 
 * Interrupt stack.  IRQSTACKSIZE
 
@@ -32,17 +32,17 @@ x86_64 also has a feature which is not available on i386, the ability
 to automatically switch to a new stack for designated events such as
 double fault or NMI, which makes it easier to handle these unusual
 events on x86_64.  This feature is called the Interrupt Stack Table
-(IST).  There can be up to 7 IST entries per cpu. The IST code is an
-index into the Task State Segment (TSS), the IST entries in the TSS
-point to dedicated stacks, each stack can be a different size.
+(IST).  There can be up to 7 IST entries per CPU. The IST code is an
+index into the Task State Segment (TSS). The IST entries in the TSS
+point to dedicated stacks; each stack can be a different size.
 
-An IST is selected by an non-zero value in the IST field of an
+An IST is selected by a non-zero value in the IST field of an
 interrupt-gate descriptor.  When an interrupt occurs and the hardware
 loads such a descriptor, the hardware automatically sets the new stack
 pointer based on the IST value, then invokes the interrupt handler.  If
 software wants to allow nested IST interrupts then the handler must
 adjust the IST values on entry to and exit from the interrupt handler.
-(this is occasionally done, e.g. for debug exceptions)
+(This is occasionally done, e.g. for debug exceptions.)
 
 Events with different IST codes (i.e. with different stacks) can be
 nested.  For example, a debug interrupt can safely be interrupted by an
@@ -58,17 +58,17 @@ The currently assigned IST stacks are :-
 
   Used for interrupt 12 - Stack Fault Exception (#SS).
 
-  This allows to recover from invalid stack segments. Rarely
+  This allows the CPU to recover from invalid stack segments. Rarely
   happens.
 
 * DOUBLEFAULT_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
 
   Used for interrupt 8 - Double Fault Exception (#DF).
 
-  Invoked when handling a exception causes another exception. Happens
-  when the kernel is very confused (e.g. kernel stack pointer corrupt)
-  Using a separate stack allows to recover from it well enough in many
-  cases to still output an oops.
+  Invoked when handling one exception causes another exception. Happens
+  when the kernel is very confused (e.g. kernel stack pointer corrupt).
+  Using a separate stack allows the kernel to recover from it well enough
+  in many cases to still output an oops.
 
 * NMI_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
 
diff --git a/Documentation/x86_64/machinecheck b/Documentation/x86_64/machinecheck
new file mode 100644 (file)
index 0000000..068a6d9
--- /dev/null
@@ -0,0 +1,70 @@
+
+Configurable sysfs parameters for the x86-64 machine check code.
+
+Machine checks report internal hardware error conditions detected
+by the CPU. Uncorrected errors typically cause a machine check
+(often with panic), corrected ones cause a machine check log entry.
+
+Machine checks are organized in banks (normally associated with
+a hardware subsystem) and subevents in a bank. The exact meaning
+of the banks and subevent is CPU specific.
+
+mcelog knows how to decode them.
+
+When you see the "Machine check errors logged" message in the system
+log then mcelog should run to collect and decode machine check entries
+from /dev/mcelog. Normally mcelog should be run regularly from a cronjob.
+
+Each CPU has a directory in /sys/devices/system/machinecheck/machinecheckN
+(N = CPU number)
+
+The directory contains some configurable entries:
+
+Entries:
+
+bankNctl
+(N bank number)
+       64bit Hex bitmask enabling/disabling specific subevents for bank N
+       When a bit in the bitmask is zero then the respective
+       subevent will not be reported.
+       By default all events are enabled.
+       Note that BIOS maintain another mask to disable specific events
+       per bank.  This is not visible here
+
+The following entries appear for each CPU, but they are truly shared
+between all CPUs.
+
+check_interval
+       How often to poll for corrected machine check errors, in seconds
+       (Note output is hexademical). Default 5 minutes.
+
+tolerant
+       Tolerance level. When a machine check exception occurs for a non
+       corrected machine check the kernel can take different actions.
+       Since machine check exceptions can happen any time it is sometimes
+       risky for the kernel to kill a process because it defies
+       normal kernel locking rules. The tolerance level configures
+       how hard the kernel tries to recover even at some risk of deadlock.
+
+       0: always panic,
+       1: panic if deadlock possible,
+       2: try to avoid panic,
+       3: never panic or exit (for testing only)
+
+       Default: 1
+
+       Note this only makes a difference if the CPU allows recovery
+       from a machine check exception. Current x86 CPUs generally do not.
+
+trigger
+       Program to run when a machine check event is detected.
+       This is an alternative to running mcelog regularly from cron
+       and allows to detect events faster.
+
+TBD document entries for AMD threshold interrupt configuration
+
+For more details about the x86 machine check architecture
+see the Intel and AMD architecture manuals from their developer websites.
+
+For more details about the architecture see
+see http://one.firstfloor.org/~andi/mce.pdf
index 133561b9cb0c32f03f840af433bdd4976f68a3c0..f42798ed1c54c326be5021877757fef5e841f3f8 100644 (file)
@@ -3,26 +3,26 @@
 
 Virtual memory map with 4 level page tables:
 
-0000000000000000 - 00007fffffffffff (=47bits) user space, different per mm
+0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
 hole caused by [48:63] sign extension
-ffff800000000000 - ffff80ffffffffff (=40bits) guard hole
-ffff810000000000 - ffffc0ffffffffff (=46bits) direct mapping of all phys. memory
-ffffc10000000000 - ffffc1ffffffffff (=40bits) hole
-ffffc20000000000 - ffffe1ffffffffff (=45bits) vmalloc/ioremap space
+ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
+ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory
+ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole
+ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space
 ... unused hole ...
-ffffffff80000000 - ffffffff82800000 (=40MB)   kernel text mapping, from phys 0
+ffffffff80000000 - ffffffff82800000 (=40 MB)   kernel text mapping, from phys 0
 ... unused hole ...
-ffffffff88000000 - fffffffffff00000 (=1919MB) module mapping space
+ffffffff88000000 - fffffffffff00000 (=1919 MB) module mapping space
 
-The direct mapping covers all memory in the system upto the highest
+The direct mapping covers all memory in the system up to the highest
 memory address (this means in some cases it can also include PCI memory
-holes)
+holes).
 
 vmalloc space is lazily synchronized into the different PML4 pages of
 the processes using the page fault handler, with init_level4_pgt as
 reference.
 
-Current X86-64 implementations only support 40 bit of address space,
-but we support upto 46bits. This expands into MBZ space in the page tables.
+Current X86-64 implementations only support 40 bits of address space,
+but we support up to 46 bits. This expands into MBZ space in the page tables.
 
 -Andi Kleen, Jul 2004
index 0556a8de857c1b4098ce4ab72a69ddac92b4dc61..6261597a1bce3037b386628760f0821189c498a5 100644 (file)
@@ -247,6 +247,13 @@ L: linux-acpi@vger.kernel.org
 W:     http://acpi.sourceforge.net/
 S:     Supported
 
+ACPI VIDEO DRIVER
+P:     Luming Yu
+M:     luming.yu@intel.com
+L:     linux-acpi@vger.kernel.org
+W:     http://acpi.sourceforge.net/
+S:     Supported
+
 AD1816 SOUND DRIVER
 P:     Thorsten Knabe
 M:     Thorsten Knabe <linux@thorsten-knabe.de>
@@ -626,6 +633,11 @@ P: Haavard Skinnemoen
 M:     hskinnemoen@atmel.com
 S:     Supported
 
+ATMEL SPI DRIVER
+P:     Haavard Skinnemoen
+M:     hskinnemoen@atmel.com
+S:     Supported
+
 ATMEL WIRELESS DRIVER
 P:     Simon Kelley
 M:     simon@thekelleys.org.uk
@@ -2624,8 +2636,8 @@ T:        git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
 S:     Maintained
 
 PCNET32 NETWORK DRIVER
-P:     Thomas Bogendörfer
-M:     tsbogend@alpha.franken.de
+P:     Don Fry
+M:     pcnet32@verizon.net
 L:     netdev@vger.kernel.org
 S:     Maintained
 
@@ -3062,6 +3074,8 @@ S:        Maintained
 SONY VAIO CONTROL DEVICE DRIVER
 P:     Stelian Pop
 M:     stelian@popies.net
+P:     Mattia Dongili
+M:     malattia@linux.it
 W:     http://popies.net/sonypi/
 S:     Maintained
 
@@ -3780,6 +3794,7 @@ P:        Andi Kleen
 M:     ak@suse.de
 L:     discuss@x86-64.org
 W:     http://www.x86-64.org
+T:     quilt ftp://ftp.firstfloor.org/pub/ak/x86_64/quilt-current
 S:     Maintained
 
 YAM DRIVER FOR AX.25
index 7e4968fb2134d3b90206dbcd9a08a773c934399c..b6c8790925bfe1f4c51442e06941f34207b0cc02 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -825,9 +825,6 @@ include/config/kernel.release: include/config/auto.conf FORCE
 # Listed in dependency order
 PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
 
-# prepare-all is deprecated, use prepare as valid replacement
-PHONY += prepare-all
-
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
@@ -860,7 +857,7 @@ prepare0: archprepare FORCE
        $(Q)$(MAKE) $(build)=.
 
 # All the preparing..
-prepare prepare-all: prepare0
+prepare: prepare0
 
 # Leave this as default for preprocessing vmlinux.lds.S, which is now
 # done in arch/$(ARCH)/kernel/Makefile
@@ -931,6 +928,12 @@ headers_install: include/linux/version.h scripts_basic FORCE
        $(Q)$(MAKE) $(build)=scripts scripts/unifdef
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include
 
+PHONY += headers_check_all
+headers_check_all: headers_install_all
+       $(Q)for arch in $(HDRARCHES); do \
+        $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
+        done
+
 PHONY += headers_check
 headers_check: headers_install
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include HDRCHECK=1
diff --git a/README b/README
index 46a66c6e76df3d14b1f3a50896c6100b02c2227c..159912cf515549455ed5f579b8825d28962bd22e 100644 (file)
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ ON WHAT HARDWARE DOES IT RUN?
   today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
   UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
   IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
-  Cris, Xtensa, AVR32 and Renesas M32R architectures.
+  Xtensa, AVR32 and Renesas M32R architectures.
 
   Linux is easily portable to most general-purpose 32- or 64-bit architectures
   as long as they have a paged memory management unit (PMMU) and a port of the
index 5c795193ebbad56bcde85161ffaab4fde02e2e90..4409561ea32c44ed2e76d88a543cd9492a36380b 100644 (file)
@@ -245,6 +245,8 @@ config ARCH_IOP33X
 
 config ARCH_IOP13XX
        bool "IOP13xx-based"
+       depends on MMU
+       select PLAT_IOP
        select PCI
        help
          Support for Intel's IOP13XX (XScale) family of processors.
@@ -283,6 +285,14 @@ config ARCH_L7200
          If you have any questions or comments about the Linux kernel port
          to this board, send e-mail to <sjhill@cotw.com>.
 
+config ARCH_NS9XXX
+       bool "NetSilicon NS9xxx"
+       help
+         Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
+         System.
+
+         <http://www.digi.com/products/microprocessors/index.jsp>
+
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
        help
@@ -292,6 +302,7 @@ config ARCH_PXA
        bool "PXA2xx-based"
        depends on MMU
        select ARCH_MTD_XIP
+       select GENERIC_TIME
        help
          Support for Intel's PXA2XX processor line.
 
@@ -316,7 +327,7 @@ config ARCH_SA1100
          Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
-       bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
+       bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -376,7 +387,16 @@ source "arch/arm/mach-omap1/Kconfig"
 
 source "arch/arm/mach-omap2/Kconfig"
 
+source "arch/arm/plat-s3c24xx/Kconfig"
+
+if ARCH_S3C2410
+source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
+source "arch/arm/mach-s3c2412/Kconfig"
+source "arch/arm/mach-s3c2440/Kconfig"
+source "arch/arm/mach-s3c2442/Kconfig"
+source "arch/arm/mach-s3c2443/Kconfig"
+endif
 
 source "arch/arm/mach-lh7a40x/Kconfig"
 
@@ -390,10 +410,12 @@ source "arch/arm/mach-aaec2000/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
 
-source "arch/arm/mach-at91rm9200/Kconfig"
+source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-netx/Kconfig"
 
+source "arch/arm/mach-ns9xxx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
        bool
@@ -405,7 +427,7 @@ source arch/arm/mm/Kconfig
 
 config IWMMXT
        bool "Enable iWMMXt support"
-       depends CPU_XSCALE || CPU_XSC3
+       depends on CPU_XSCALE || CPU_XSC3
        default y if PXA27x
        help
          Enable support for iWMMXt context switching at run time if
@@ -751,6 +773,20 @@ config XIP_PHYS_ADDR
          be linked for and stored to.  This address is dependent on your
          own flash usage.
 
+config KEXEC
+       bool "Kexec system call (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         kexec is a system call that implements the ability to shutdown your
+         current kernel, and to start another kernel.  It is like a reboot
+         but it is indepedent of the system firmware.   And like a reboot
+         you can start any kernel with it, not just Linux.
+
+         It is an ongoing process to be certain the hardware in a machine
+         is properly shutdown, so do not be surprised if this code does not
+         initially work for you.  It may help to enable device hotplugging
+         support.
+
 endmenu
 
 if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
index 000f1100b5538f9f69da886fc0054d2d16746864..1320418b5d6f7328a383d023bac7ac1daadfe1db 100644 (file)
@@ -124,10 +124,12 @@ endif
  machine-$(CONFIG_ARCH_H720X)     := h720x
  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
- machine-$(CONFIG_ARCH_AT91)       := at91rm9200
- machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
- machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
- machine-$(CONFIG_ARCH_NETX)       := netx
+ machine-$(CONFIG_ARCH_AT91)      := at91rm9200
+ machine-$(CONFIG_ARCH_EP93XX)    := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)           := pnx4008
+ machine-$(CONFIG_ARCH_NETX)      := netx
+ machine-$(CONFIG_ARCH_NS9XXX)    := ns9xxx
+ textofs-$(CONFIG_ARCH_NS9XXX)    := 0x00108000
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
@@ -149,7 +151,7 @@ MACHINE  := arch/arm/mach-$(machine-y)/
 else
 MACHINE  :=
 endif
-  
+
 export TEXT_OFFSET GZFLAGS MMUEXT
 
 # Do we have FASTFPE?
@@ -161,6 +163,11 @@ endif
 # If we have a machine-specific directory, then include it in the build.
 core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y                         += $(MACHINE)
+core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2400/
+core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2412/
+core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2440/
+core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2442/
+core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2443/
 core-$(CONFIG_FPE_NWFPE)       += arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)     += $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)             += arch/arm/vfp/
@@ -168,6 +175,7 @@ core-$(CONFIG_VFP)          += arch/arm/vfp/
 # If we have a common platform directory, then include it in the build.
 core-$(CONFIG_PLAT_IOP)                += arch/arm/plat-iop/
 core-$(CONFIG_ARCH_OMAP)       += arch/arm/plat-omap/
+core-$(CONFIG_PLAT_S3C24XX)            += arch/arm/plat-s3c24xx/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 drivers-$(CONFIG_ARCH_CLPS7500)        += drivers/acorn/char/
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
new file mode 100644 (file)
index 0000000..171a085
--- /dev/null
@@ -0,0 +1,2 @@
+Image
+zImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
new file mode 100644 (file)
index 0000000..aefee20
--- /dev/null
@@ -0,0 +1 @@
+piggy.gz
index 2e635b814c14b06dd7cf84cbba4ccc2afd72cf58..6fbe7722aa44086403599f64f26c04aebece4568 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <asm/cacheflush.h>
 
-#undef DEBUG
 #undef STATS
 
 #ifdef STATS
@@ -66,14 +65,13 @@ struct dmabounce_pool {
 };
 
 struct dmabounce_device_info {
-       struct list_head node;
-
        struct device *dev;
        struct list_head safe_buffers;
 #ifdef STATS
        unsigned long total_allocs;
        unsigned long map_op_count;
        unsigned long bounce_count;
+       int attr_res;
 #endif
        struct dmabounce_pool   small;
        struct dmabounce_pool   large;
@@ -81,33 +79,23 @@ struct dmabounce_device_info {
        rwlock_t lock;
 };
 
-static LIST_HEAD(dmabounce_devs);
-
 #ifdef STATS
-static void print_alloc_stats(struct dmabounce_device_info *device_info)
+static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
+                             char *buf)
 {
-       printk(KERN_INFO
-               "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
-               device_info->dev->bus_id,
-               device_info->small.allocs, device_info->large.allocs,
+       struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+       return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
+               device_info->small.allocs,
+               device_info->large.allocs,
                device_info->total_allocs - device_info->small.allocs -
                        device_info->large.allocs,
-               device_info->total_allocs);
+               device_info->total_allocs,
+               device_info->map_op_count,
+               device_info->bounce_count);
 }
-#endif
-
-/* find the given device in the dmabounce device list */
-static inline struct dmabounce_device_info *
-find_dmabounce_dev(struct device *dev)
-{
-       struct dmabounce_device_info *d;
 
-       list_for_each_entry(d, &dmabounce_devs, node)
-               if (d->dev == dev)
-                       return d;
-
-       return NULL;
-}
+static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
+#endif
 
 
 /* allocate a 'safe' buffer and keep track of it */
@@ -162,8 +150,6 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
        if (pool)
                pool->allocs++;
        device_info->total_allocs++;
-       if (device_info->total_allocs % 1000 == 0)
-               print_alloc_stats(device_info);
 #endif
 
        write_lock_irqsave(&device_info->lock, flags);
@@ -218,20 +204,11 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *
 
 /* ************************************************** */
 
-#ifdef STATS
-static void print_map_stats(struct dmabounce_device_info *device_info)
-{
-       dev_info(device_info->dev,
-               "dmabounce: map_op_count=%lu, bounce_count=%lu\n",
-               device_info->map_op_count, device_info->bounce_count);
-}
-#endif
-
 static inline dma_addr_t
 map_single(struct device *dev, void *ptr, size_t size,
                enum dma_data_direction dir)
 {
-       struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+       struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
        dma_addr_t dma_addr;
        int needs_bounce = 0;
 
@@ -281,10 +258,14 @@ map_single(struct device *dev, void *ptr, size_t size,
                ptr = buf->safe;
 
                dma_addr = buf->safe_dma_addr;
+       } else {
+               /*
+                * We don't need to sync the DMA buffer since
+                * it was allocated via the coherent allocators.
+                */
+               consistent_sync(ptr, size, dir);
        }
 
-       consistent_sync(ptr, size, dir);
-
        return dma_addr;
 }
 
@@ -292,7 +273,7 @@ static inline void
 unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
-       struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+       struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
        struct safe_buffer *buf = NULL;
 
        /*
@@ -317,12 +298,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                DO_STATS ( device_info->bounce_count++ );
 
                if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
-                       unsigned long ptr;
+                       void *ptr = buf->ptr;
 
                        dev_dbg(dev,
                                "%s: copy back safe %p to unsafe %p size %d\n",
-                               __func__, buf->safe, buf->ptr, size);
-                       memcpy(buf->ptr, buf->safe, size);
+                               __func__, buf->safe, ptr, size);
+                       memcpy(ptr, buf->safe, size);
 
                        /*
                         * DMA buffers must have the same cache properties
@@ -332,8 +313,8 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                         * bidirectional case because we know the cache
                         * lines will be coherent with the data written.
                         */
-                       ptr = (unsigned long)buf->ptr;
                        dmac_clean_range(ptr, ptr + size);
+                       outer_clean_range(__pa(ptr), __pa(ptr) + size);
                }
                free_safe_buffer(device_info, buf);
        }
@@ -343,7 +324,7 @@ static inline void
 sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
-       struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+       struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
        struct safe_buffer *buf = NULL;
 
        if (device_info)
@@ -397,7 +378,10 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                default:
                        BUG();
                }
-               consistent_sync(buf->safe, size, dir);
+               /*
+                * No need to sync the safe buffer - it was allocated
+                * via the coherent allocators.
+                */
        } else {
                consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
        }
@@ -604,9 +588,10 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
        device_info->total_allocs = 0;
        device_info->map_op_count = 0;
        device_info->bounce_count = 0;
+       device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats);
 #endif
 
-       list_add(&device_info->node, &dmabounce_devs);
+       dev->archdata.dmabounce = device_info;
 
        printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
                dev->bus_id, dev->bus->name);
@@ -623,7 +608,9 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
 void
 dmabounce_unregister_dev(struct device *dev)
 {
-       struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+       struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+
+       dev->archdata.dmabounce = NULL;
 
        if (!device_info) {
                printk(KERN_WARNING
@@ -645,12 +632,10 @@ dmabounce_unregister_dev(struct device *dev)
                dma_pool_destroy(device_info->large.pool);
 
 #ifdef STATS
-       print_alloc_stats(device_info);
-       print_map_stats(device_info);
+       if (device_info->attr_res == 0)
+               device_remove_file(dev, &dev_attr_dmabounce_stats);
 #endif
 
-       list_del(&device_info->node);
-
        kfree(device_info);
 
        printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
index 09b9d1b6844c05315dc50af6e0ea0ffacdfad725..4deece5fbdf467ac1161a24dff612f0b973d3fbb 100644 (file)
@@ -14,7 +14,9 @@
  *
  * o There is one CPU Interface per CPU, which sends interrupts sent
  *   by the Distributor, and interrupts generated locally, to the
- *   associated CPU.
+ *   associated CPU. The base address of the CPU interface is usually
+ *   aliased so that the same address points to different chips depending
+ *   on the CPU it is accessed from.
  *
  * Note that IRQs 0-31 are special - they are local to each CPU.
  * As such, the enable set/clear, pending set/clear and active bit
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
-static void __iomem *gic_dist_base;
-static void __iomem *gic_cpu_base;
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+struct gic_chip_data {
+       unsigned int irq_offset;
+       void __iomem *dist_base;
+       void __iomem *cpu_base;
+};
+
+#ifndef MAX_GIC_NR
+#define MAX_GIC_NR     1
+#endif
+
+static struct gic_chip_data gic_data[MAX_GIC_NR];
+
+static inline void __iomem *gic_dist_base(unsigned int irq)
+{
+       struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+       return gic_data->dist_base;
+}
+
+static inline void __iomem *gic_cpu_base(unsigned int irq)
+{
+       struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+       return gic_data->cpu_base;
+}
+
+static inline unsigned int gic_irq(unsigned int irq)
+{
+       struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+       return irq - gic_data->irq_offset;
+}
+
 /*
  * Routines to acknowledge, disable and enable interrupts
  *
@@ -55,8 +85,8 @@ static void gic_ack_irq(unsigned int irq)
        u32 mask = 1 << (irq % 32);
 
        spin_lock(&irq_controller_lock);
-       writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
-       writel(irq, gic_cpu_base + GIC_CPU_EOI);
+       writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
+       writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
        spin_unlock(&irq_controller_lock);
 }
 
@@ -65,7 +95,7 @@ static void gic_mask_irq(unsigned int irq)
        u32 mask = 1 << (irq % 32);
 
        spin_lock(&irq_controller_lock);
-       writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+       writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
        spin_unlock(&irq_controller_lock);
 }
 
@@ -74,14 +104,14 @@ static void gic_unmask_irq(unsigned int irq)
        u32 mask = 1 << (irq % 32);
 
        spin_lock(&irq_controller_lock);
-       writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
+       writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4);
        spin_unlock(&irq_controller_lock);
 }
 
 #ifdef CONFIG_SMP
 static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
 {
-       void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
+       void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
        unsigned int shift = (irq % 4) * 8;
        unsigned int cpu = first_cpu(mask_val);
        u32 val;
@@ -95,6 +125,37 @@ static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
 }
 #endif
 
+static void fastcall gic_handle_cascade_irq(unsigned int irq,
+                                           struct irq_desc *desc)
+{
+       struct gic_chip_data *chip_data = get_irq_data(irq);
+       struct irq_chip *chip = get_irq_chip(irq);
+       unsigned int cascade_irq;
+       unsigned long status;
+
+       /* primary controller ack'ing */
+       chip->ack(irq);
+
+       spin_lock(&irq_controller_lock);
+       status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
+       spin_unlock(&irq_controller_lock);
+
+       cascade_irq = (status & 0x3ff);
+       if (cascade_irq > 1020)
+               goto out;
+       if (cascade_irq < 32 || cascade_irq >= NR_IRQS) {
+               do_bad_IRQ(cascade_irq, desc);
+               goto out;
+       }
+
+       cascade_irq += chip_data->irq_offset;
+       generic_handle_irq(cascade_irq);
+
+ out:
+       /* primary controller unmasking */
+       chip->unmask(irq);
+}
+
 static struct irq_chip gic_chip = {
        .name           = "GIC",
        .ack            = gic_ack_irq,
@@ -105,15 +166,29 @@ static struct irq_chip gic_chip = {
 #endif
 };
 
-void __init gic_dist_init(void __iomem *base)
+void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
+{
+       if (gic_nr >= MAX_GIC_NR)
+               BUG();
+       if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
+               BUG();
+       set_irq_chained_handler(irq, gic_handle_cascade_irq);
+}
+
+void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
+                         unsigned int irq_start)
 {
        unsigned int max_irq, i;
        u32 cpumask = 1 << smp_processor_id();
 
+       if (gic_nr >= MAX_GIC_NR)
+               BUG();
+
        cpumask |= cpumask << 8;
        cpumask |= cpumask << 16;
 
-       gic_dist_base = base;
+       gic_data[gic_nr].dist_base = base;
+       gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
 
        writel(0, base + GIC_DIST_CTRL);
 
@@ -158,8 +233,9 @@ void __init gic_dist_init(void __iomem *base)
        /*
         * Setup the Linux IRQ subsystem.
         */
-       for (i = 29; i < max_irq; i++) {
+       for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) {
                set_irq_chip(i, &gic_chip);
+               set_irq_chip_data(i, &gic_data[gic_nr]);
                set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
@@ -167,9 +243,13 @@ void __init gic_dist_init(void __iomem *base)
        writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(void __iomem *base)
+void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
 {
-       gic_cpu_base = base;
+       if (gic_nr >= MAX_GIC_NR)
+               BUG();
+
+       gic_data[gic_nr].cpu_base = base;
+
        writel(0xf0, base + GIC_CPU_PRIMASK);
        writel(1, base + GIC_CPU_CTRL);
 }
@@ -179,6 +259,7 @@ void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
 {
        unsigned long map = *cpus_addr(cpumask);
 
-       writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
+       /* this always happens on GIC0 */
+       writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
new file mode 100644 (file)
index 0000000..c72ab82
--- /dev/null
@@ -0,0 +1,1184 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20-rc1
+# Mon Jan  8 16:06:54 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+CONFIG_ARCH_AT91SAM9263=y
+
+#
+# AT91SAM9263 Board Type
+#
+CONFIG_MACH_AT91SAM9263EK=y
+
+#
+# AT91 Board Options
+#
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_AT91=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91=m
+# CONFIG_MMC_TIFM_SD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
index 3de5c643848c744229ed614af7836ee7f54774a0..baa97698c744171069b92985e2c82a6dc8d4ba63 100644 (file)
@@ -1066,7 +1066,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 
 #
index 2cadd51506bb574c747e9935d8fbb86e67bdaa19..88e5d28aeec72585b974590ed68601845852c8d5 100644 (file)
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB337=y
 
 #
 # Self-contained MTD device drivers
@@ -986,7 +988,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
index 94908c1df4cf36c05673376db78048b6ecb1667f..669f035896f9fc9882d8b77a5b05036dac518ba3 100644 (file)
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB637=y
 
 #
 # Self-contained MTD device drivers
index a4cdafc1548a1113abe42de978a1595a3bfc83d9..a0f48d54fbcc7f0d8402d21cbead1157d330099d 100644 (file)
@@ -718,7 +718,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 
 #
diff --git a/arch/arm/configs/ns9xxx_defconfig b/arch/arm/configs/ns9xxx_defconfig
new file mode 100644 (file)
index 0000000..0e5794c
--- /dev/null
@@ -0,0 +1,621 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Thu Feb 15 20:51:47 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_NS9XXX=y
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# NS9xxx Implementations
+#
+CONFIG_MACH_CC9P9360DEV=y
+CONFIG_PROCESSOR_NS9360=y
+CONFIG_BOARD_A9M9750DEV=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_ICEDCC=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
index 3b31a33d0080eab75165a7f1166a02ab2da00bd1..df19e3632038d8bc0d3252afa41a5fbd44cc7df0 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Fri Nov  3 17:41:31 2006
+# Linux kernel version: 2.6.20
+# Thu Feb 15 11:26:24 2007
 #
 CONFIG_ARM=y
 # CONFIG_GENERIC_TIME is not set
@@ -11,6 +11,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_VECTORS_BASE=0xffff0000
@@ -37,13 +39,14 @@ CONFIG_SYSVIPC=y
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,7 +79,9 @@ CONFIG_KMOD=y
 # Block layer
 #
 CONFIG_BLOCK=y
+# CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -110,6 +115,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
@@ -122,54 +128,73 @@ CONFIG_ARCH_S3C2410=y
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
+CONFIG_PLAT_S3C24XX=y
+CONFIG_CPU_S3C244X=y
+CONFIG_PM_SIMTEC=y
+# CONFIG_S3C2410_BOOT_WATCHDOG is not set
+# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_MACH_SMDK=y
 
 #
-# S3C24XX Implementations
+# S3C2400 Machines
 #
-# CONFIG_MACH_AML_M5900 is not set
-CONFIG_MACH_ANUBIS=y
-CONFIG_MACH_OSIRIS=y
-CONFIG_ARCH_BAST=y
-CONFIG_BAST_PC104_IRQ=y
+CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C2410_DMA=y
+CONFIG_S3C2410_PM=y
+CONFIG_S3C2410_GPIO=y
+CONFIG_S3C2410_CLOCK=y
+
+#
+# S3C2410 Machines
+#
+CONFIG_ARCH_SMDK2410=y
 CONFIG_ARCH_H1940=y
+CONFIG_PM_H1940=y
 CONFIG_MACH_N30=y
-CONFIG_MACH_SMDK=y
-CONFIG_ARCH_SMDK2410=y
-CONFIG_ARCH_S3C2440=y
-CONFIG_SMDK2440_CPU2440=y
-CONFIG_SMDK2440_CPU2442=y
-CONFIG_MACH_S3C2413=y
-CONFIG_MACH_SMDK2413=y
-CONFIG_MACH_VR1000=y
-CONFIG_MACH_RX3715=y
+CONFIG_ARCH_BAST=y
 CONFIG_MACH_OTOM=y
-CONFIG_MACH_NEXCODER_2440=y
-CONFIG_MACH_VSTMS=y
-CONFIG_S3C2410_CLOCK=y
-CONFIG_S3C2410_PM=y
-CONFIG_CPU_S3C2410_DMA=y
-CONFIG_CPU_S3C2410=y
-CONFIG_S3C2412_PM=y
+CONFIG_MACH_AML_M5900=y
+CONFIG_BAST_PC104_IRQ=y
+CONFIG_MACH_VR1000=y
 CONFIG_CPU_S3C2412=y
-CONFIG_CPU_S3C244X=y
+CONFIG_S3C2412_DMA=y
+CONFIG_S3C2412_PM=y
+
+#
+# S3C2412 Machines
+#
+CONFIG_MACH_SMDK2413=y
+CONFIG_MACH_S3C2413=y
+CONFIG_MACH_VSTMS=y
 CONFIG_CPU_S3C2440=y
+CONFIG_S3C2440_DMA=y
+
+#
+# S3C2440 Machines
+#
+CONFIG_MACH_ANUBIS=y
+CONFIG_MACH_OSIRIS=y
+CONFIG_MACH_RX3715=y
+CONFIG_ARCH_S3C2440=y
+CONFIG_MACH_NEXCODER_2440=y
+CONFIG_SMDK2440_CPU2440=y
 CONFIG_CPU_S3C2442=y
 
 #
-# S3C2410 Boot
+# S3C2442 Machines
 #
-# CONFIG_S3C2410_BOOT_WATCHDOG is not set
-# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+CONFIG_SMDK2440_CPU2442=y
+CONFIG_CPU_S3C2443=y
 
 #
-# S3C2410 Setup
+# S3C2443 Machines
 #
-CONFIG_S3C2410_DMA=y
-# CONFIG_S3C2410_DMA_DEBUG is not set
-# CONFIG_S3C2410_PM_DEBUG is not set
-# CONFIG_S3C2410_PM_CHECK is not set
-CONFIG_PM_SIMTEC=y
-CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_MACH_SMDK2443=y
 
 #
 # Processor Type
@@ -196,6 +221,7 @@ CONFIG_CPU_CP15_MMU=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
 
 #
 # Bus support
@@ -303,6 +329,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -385,6 +412,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -530,6 +558,11 @@ CONFIG_BLK_DEV_IDE_BAST=y
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
 
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
 #
 # Multi-device support (RAID and LVM)
 #
@@ -682,7 +715,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
@@ -700,13 +733,14 @@ CONFIG_SERIAL_8250_NR_UARTS=8
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
 # CONFIG_SERIAL_8250_FOURPORT is not set
 # CONFIG_SERIAL_8250_ACCENT is not set
 # CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
 # CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
@@ -755,10 +789,6 @@ CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -863,6 +893,7 @@ CONFIG_SENSORS_LM85=m
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
@@ -870,6 +901,7 @@ CONFIG_SENSORS_LM85=m
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
@@ -951,6 +983,11 @@ CONFIG_FONT_8x16=y
 #
 # CONFIG_SOUND is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+
 #
 # USB support
 #
@@ -1028,6 +1065,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1179,9 +1217,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-# CONFIG_JFFS_PROC_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1191,7 +1226,7 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1284,6 +1319,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Profiling support
 #
@@ -1296,6 +1336,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1311,12 +1353,10 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
@@ -1339,6 +1379,7 @@ CONFIG_DEBUG_S3C2410_UART=0
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1346,3 +1387,4 @@ CONFIG_CRC32=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
index 1b935fb94b8300a10552b45fc214e2e4d2735198..bb28087bf818df7022e9c6e2185068e102d52a6b 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARTHUR)          += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
 obj-$(CONFIG_SMP)              += smp.o
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_OABI_COMPAT)      += sys_oabi-compat.o
 
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
index f7598cbc7ec5a788cf6f032a548372682f679feb..ae89cdd82b1677d2b29494bed10391bd0be7c587 100644 (file)
                CALL(sys_move_pages)
 /* 345 */      CALL(sys_getcpu)
                CALL(sys_ni_syscall)            /* eventually epoll_pwait */
+               CALL(sys_kexec_load)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index cec83783206e335a11f9a88f225ad3eba3ab6620..627d79414c9d68212382eaefe64af6f896035509 100644 (file)
@@ -75,6 +75,7 @@ static struct notifier_block crunch_notifier_block = {
 static int __init crunch_init(void)
 {
        thread_register_notifier(&crunch_notifier_block);
+       elf_hwcap |= HWCAP_CRUNCH;
 
        return 0;
 }
index 71257e3d513f4604ed1d01c3db5eb8fb565bcf47..f1c0fb974177803c0ec2510d79d4e9c72669164b 100644 (file)
@@ -1009,7 +1009,7 @@ ecard_probe(int slot, card_type_t type)
                ec->fiqmask = 4;
        }
 
-       for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+       for (i = 0; i < ARRAY_SIZE(blacklist); i++)
                if (blacklist[i].manufacturer == ec->cid.manufacturer &&
                    blacklist[i].product == ec->cid.product) {
                        ec->card_desc = blacklist[i].type;
index 8517c3c3eb3393c8ba539add942342757c117f2b..cc10a093a5455fa9f1b156b502c5346e64a985b6 100644 (file)
@@ -99,7 +99,6 @@ common_invalid:
                                        @ cpsr_<exception>, "old_r0"
 
        mov     r0, sp
-       and     r2, r6, #0x1f
        b       bad_mode
 
 /*
index ec01f08f5642bef24e4e84ab6339042afabdb60d..e101846ab7dd960f485f4fd8a97d23dd8b81b960 100644 (file)
@@ -159,8 +159,7 @@ void __init init_IRQ(void)
        int irq;
 
        for (irq = 0; irq < NR_IRQS; irq++)
-               irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_DELAYED_DISABLE |
-                       IRQ_NOPROBE;
+               irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
 #ifdef CONFIG_SMP
        bad_irq_desc.affinity = CPU_MASK_ALL;
index 54bbd9fe255cab1a6acba22a2bef1bd2d4fbe3f8..50a30bc91872652c5d8f68ad2d013ce9afed7503 100644 (file)
@@ -70,5 +70,5 @@ register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int por
        isa_membase = membase;
        isa_portbase = portbase;
        isa_portshift = portshift;
-       isa_sysctl_header = register_sysctl_table(ctl_bus, 0);
+       isa_sysctl_header = register_sysctl_table(ctl_bus);
 }
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
new file mode 100644 (file)
index 0000000..863c664
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+extern void setup_mm_for_reboot(char mode);
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+extern unsigned long kexec_mach_type;
+
+/*
+ * Provide a dummy crash_notes definition while crash dump arrives to arm.
+ * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
+ */
+
+int machine_kexec_prepare(struct kimage *image)
+{
+       return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void machine_kexec(struct kimage *image)
+{
+       unsigned long page_list;
+       unsigned long reboot_code_buffer_phys;
+       void *reboot_code_buffer;
+
+
+       page_list = image->head & PAGE_MASK;
+
+       /* we need both effective and real address here */
+       reboot_code_buffer_phys =
+           page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+       reboot_code_buffer = page_address(image->control_code_page);
+
+       /* Prepare parameters for reboot_code_buffer*/
+       kexec_start_address = image->start;
+       kexec_indirection_page = page_list;
+       kexec_mach_type = machine_arch_type;
+
+       /* copy our kernel relocation code to the control code page */
+       memcpy(reboot_code_buffer,
+              relocate_new_kernel, relocate_new_kernel_size);
+
+
+       flush_icache_range((unsigned long) reboot_code_buffer,
+                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+       printk(KERN_INFO "Bye!\n");
+
+       cpu_proc_fin();
+       setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+       cpu_reset(reboot_code_buffer_phys);
+}
index a9e8f7e55fd61edc8242f1193c95d49fb5d14d42..782af3cb213f42b42f912115309480d73165c6d7 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mach/time.h>
 
-extern const char *processor_modes[];
+static const char *processor_modes[] = {
+  "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
+  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
+  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
+  "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
new file mode 100644 (file)
index 0000000..7baadae
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ */
+
+#include <asm/kexec.h>
+
+       .globl relocate_new_kernel
+relocate_new_kernel:
+
+       ldr     r0,kexec_indirection_page
+       ldr     r1,kexec_start_address
+
+
+0:     /* top, read another word for the indirection page */
+       ldr     r3, [r0],#4
+
+       /* Is it a destination page. Put destination address to r4 */
+       tst     r3,#1,0
+       beq     1f
+       bic     r4,r3,#1
+       b       0b
+1:
+       /* Is it an indirection page */
+       tst     r3,#2,0
+       beq     1f
+       bic     r0,r3,#2
+       b       0b
+1:
+
+       /* are we done ? */
+       tst     r3,#4,0
+       beq     1f
+       b       2f
+
+1:
+       /* is it source ? */
+       tst     r3,#8,0
+       beq     0b
+       bic r3,r3,#8
+       mov r6,#1024
+9:
+       ldr r5,[r3],#4
+       str r5,[r4],#4
+       subs r6,r6,#1
+       bne 9b
+       b 0b
+
+2:
+       /* Jump to relocated kernel */
+       mov lr,r1
+       mov r0,#0
+       ldr r1,kexec_mach_type
+       mov r2,#0
+       mov pc,lr
+
+       .globl kexec_start_address
+kexec_start_address:
+       .long   0x0
+
+       .globl kexec_indirection_page
+kexec_indirection_page:
+       .long   0x0
+
+       .globl kexec_mach_type
+kexec_mach_type:
+       .long   0x0
+
+relocate_new_kernel_end:
+
+       .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+       .long relocate_new_kernel_end - relocate_new_kernel
+
+
index ed522151878bdc5996def09b367892f95e8e4881..03e37af315d76cc702ca0af3b5bfae6da904147e 100644 (file)
@@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user;
 #ifdef MULTI_CACHE
 struct cpu_cache_fns cpu_cache;
 #endif
+#ifdef CONFIG_OUTER_CACHE
+struct outer_cache_fns outer_cache;
+#endif
 
 struct stack {
        u32 irq[3];
index ee47c532e2108b0879bef642c3a5ee174891b581..f61decb89ba25ffcb58933d8ece66a6918b0606e 100644 (file)
  */
 struct sys_timer *system_timer;
 
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
 
-#ifdef CONFIG_SA1100_RTC_MODULE
+#ifdef CONFIG_RTC_DRV_CMOS_MODULE
 EXPORT_SYMBOL(rtc_lock);
 #endif
+#endif /* pc-style 'CMOS' RTC support */
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY        (1000000/HZ)
index 908915675edcb3f66520c9a3765441d388ef29c0..24095601359b94e04b9d8b83b2b9ab70cb9a2135 100644 (file)
 #include "ptrace.h"
 #include "signal.h"
 
-const char *processor_modes[]=
-{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
-  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
-  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
-  "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
-};
-
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 #ifdef CONFIG_DEBUG_USER
@@ -289,7 +282,10 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
        regs->ARM_pc -= correction;
 
        pc = (void __user *)instruction_pointer(regs);
-       if (thumb_mode(regs)) {
+
+       if (processor_mode(regs) == SVC_MODE) {
+               instr = *(u32 *) pc;
+       } else if (thumb_mode(regs)) {
                get_user(instr, (u16 __user *)pc);
        } else {
                get_user(instr, (u32 __user *)pc);
@@ -337,12 +333,11 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
  * It never returns, and never tries to sync.  We hope that we can at least
  * dump out some state information...
  */
-asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
+asmlinkage void bad_mode(struct pt_regs *regs, int reason)
 {
        console_verbose();
 
-       printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n",
-               handler[reason], processor_modes[proc_mode]);
+       printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
 
        die("Oops - bad mode", regs, 0);
        local_irq_disable();
similarity index 76%
rename from arch/arm/mach-at91rm9200/Kconfig
rename to arch/arm/mach-at91/Kconfig
index 9f11db8af2339b5f2bb2170e7bff03e147707e50..bf0d96272e3a01b88063996fad0d4eeedef24afd 100644 (file)
@@ -9,11 +9,14 @@ config ARCH_AT91RM9200
        bool "AT91RM9200"
 
 config ARCH_AT91SAM9260
-       bool "AT91SAM9260"
+       bool "AT91SAM9260 or AT91SAM9XE"
 
 config ARCH_AT91SAM9261
        bool "AT91SAM9261"
 
+config ARCH_AT91SAM9263
+       bool "AT91SAM9263"
+
 endchoice
 
 # ----------------------------------------------------------
@@ -90,13 +93,22 @@ endif
 
 if ARCH_AT91SAM9260
 
-comment "AT91SAM9260 Board Type"
+comment "AT91SAM9260 Variants"
+
+config ARCH_AT91SAM9260_SAM9XE
+       bool "AT91SAM9XE"
+       depends on ARCH_AT91SAM9260
+       help
+         Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
+         They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+
+comment "AT91SAM9260 / AT91SAM9XE Board Type"
 
 config MACH_AT91SAM9260EK
-       bool "Atmel AT91SAM9260-EK Evaluation Kit"
+       bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
        depends on ARCH_AT91SAM9260
        help
-         Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit.
+         Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
          <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
 
 endif
@@ -118,17 +130,32 @@ endif
 
 # ----------------------------------------------------------
 
+if ARCH_AT91SAM9263
+
+comment "AT91SAM9263 Board Type"
+
+config MACH_AT91SAM9263EK
+       bool "Atmel AT91SAM9263-EK Evaluation Kit"
+       depends on ARCH_AT91SAM9263
+       help
+         Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
+         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
+
+endif
+
+# ----------------------------------------------------------
+
 comment "AT91 Board Options"
 
 config MTD_AT91_DATAFLASH_CARD
        bool "Enable DataFlash Card support"
-       depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK)
+       depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
        help
          Enable support for the DataFlash card.
 
 config MTD_NAND_AT91_BUSWIDTH_16
        bool "Enable 16-bit data bus interface to NAND flash"
-       depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK)
+       depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
        help
          On AT91SAM926x boards both types of NAND flash can be present
          (8 and 16 bit data bus width).
similarity index 88%
rename from arch/arm/mach-at91rm9200/Makefile
rename to arch/arm/mach-at91/Makefile
index cf777007847af4f2d88f63125102282b5ea97cdb..05de6cdc88f1bd9fbd6a5c20485f67222256c68b 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_PM)              += pm.o
 obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
 obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
 obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
 
 # AT91RM9200 board-specific support
 obj-$(CONFIG_MACH_ONEARM)      += board-1arm.o
@@ -31,6 +32,9 @@ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
 # AT91SAM9261 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
 
+# AT91SAM9263 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
+
 # LEDs support
 led-$(CONFIG_ARCH_AT91RM9200DK)        += leds.o
 led-$(CONFIG_MACH_AT91RM9200EK)        += leds.o
similarity index 89%
rename from arch/arm/mach-at91rm9200/at91rm9200.c
rename to arch/arm/mach-at91/at91rm9200.c
index a92e9a495b07a1bdc64e3093a1711abbaf3f0656..2ddcdd69df7d2267df116131323797f89a8ca3fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91rm9200.c
+ * arch/arm/mach-at91/at91rm9200.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -117,6 +117,36 @@ static struct clk pioD_clk = {
        .pmc_mask       = 1 << AT91RM9200_ID_PIOD,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk tc0_clk = {
+       .name           = "tc0_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+       .name           = "tc1_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+       .name           = "tc2_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+       .name           = "tc3_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC3,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+       .name           = "tc4_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC4,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+       .name           = "tc5_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TC5,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 
 static struct clk *periph_clocks[] __initdata = {
        &pioA_clk,
@@ -132,7 +162,12 @@ static struct clk *periph_clocks[] __initdata = {
        &twi_clk,
        &spi_clk,
        // ssc 0 .. ssc2
-       // tc0 .. tc5
+       &tc0_clk,
+       &tc1_clk,
+       &tc2_clk,
+       &tc3_clk,
+       &tc4_clk,
+       &tc5_clk,
        &ohci_clk,
        &ether_clk,
        // irq0 .. irq6
similarity index 98%
rename from arch/arm/mach-at91rm9200/at91rm9200_devices.c
rename to arch/arm/mach-at91/at91rm9200_devices.c
index 57fac7203fe4f79f6ad639f1be651a12411bbe82..2624a4f22d612391aad930a9696795893f654f98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91rm9200_devices.c
+ * arch/arm/mach-at91/at91rm9200_devices.c
  *
  *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
  *  Copyright (C) 2005 David Brownell
@@ -315,7 +315,7 @@ static struct platform_device at91rm9200_mmc_device = {
        .num_resources  = ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
 {
        if (!data)
                return;
@@ -361,7 +361,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
        platform_device_register(&at91rm9200_mmc_device);
 }
 #else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
 #endif
 
 
@@ -594,6 +594,10 @@ u8 at91_leds_timer;
 
 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
 {
+       /* Enable GPIO to access the LEDs */
+       at91_set_gpio_output(cpu_led, 1);
+       at91_set_gpio_output(timer_led, 1);
+
        at91_leds_cpu   = cpu_led;
        at91_leds_timer = timer_led;
 }
similarity index 98%
rename from arch/arm/mach-at91rm9200/at91rm9200_time.c
rename to arch/arm/mach-at91/at91rm9200_time.c
index b999e192a7e9c22719cd83c8cdc254584dc299df..949199a244c7bc680ceca9b952c0c55019e4a3a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c
+ * linux/arch/arm/mach-at91/at91rm9200_time.c
  *
  *  Copyright (C) 2003 SAN People
  *  Copyright (C) 2003 ATMEL
similarity index 79%
rename from arch/arm/mach-at91rm9200/at91sam9260.c
rename to arch/arm/mach-at91/at91sam9260.c
index b14871adc300151b4e8f73354690b34ba9319793..6ea41d8266cbfca7e007db35f66ea867ea5bfc33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91sam9260.c
+ * arch/arm/mach-at91/at91sam9260.c
  *
  *  Copyright (C) 2006 SAN People
  *
@@ -14,6 +14,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/at91sam9260.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_rstc.h>
@@ -27,7 +28,11 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(AT91_BASE_SYS),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
-       }, {
+       }
+};
+
+static struct map_desc at91sam9260_sram_desc[] __initdata = {
+       {
                .virtual        = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
                .pfn            = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
                .length         = AT91SAM9260_SRAM0_SIZE,
@@ -37,7 +42,14 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
                .length         = AT91SAM9260_SRAM1_SIZE,
                .type           = MT_DEVICE,
-       },
+       }
+};
+
+static struct map_desc at91sam9xe_sram_desc[] __initdata = {
+       {
+               .pfn            = __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
+               .type           = MT_DEVICE,
+       }
 };
 
 /* --------------------------------------------------------------------
@@ -107,13 +119,28 @@ static struct clk spi1_clk = {
        .pmc_mask       = 1 << AT91SAM9260_ID_SPI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk tc0_clk = {
+       .name           = "tc0_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+       .name           = "tc1_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+       .name           = "tc2_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk ohci_clk = {
        .name           = "ohci_clk",
        .pmc_mask       = 1 << AT91SAM9260_ID_UHP,
        .type           = CLK_TYPE_PERIPHERAL,
 };
-static struct clk ether_clk = {
-       .name           = "ether_clk",
+static struct clk macb_clk = {
+       .name           = "macb_clk",
        .pmc_mask       = 1 << AT91SAM9260_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -137,6 +164,21 @@ static struct clk usart5_clk = {
        .pmc_mask       = 1 << AT91SAM9260_ID_US5,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk tc3_clk = {
+       .name           = "tc3_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC3,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+       .name           = "tc4_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC4,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+       .name           = "tc5_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TC5,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 
 static struct clk *periph_clocks[] __initdata = {
        &pioA_clk,
@@ -152,14 +194,18 @@ static struct clk *periph_clocks[] __initdata = {
        &spi0_clk,
        &spi1_clk,
        // ssc
-       // tc0 .. tc2
+       &tc0_clk,
+       &tc1_clk,
+       &tc2_clk,
        &ohci_clk,
-       &ether_clk,
+       &macb_clk,
        &isi_clk,
        &usart3_clk,
        &usart4_clk,
        &usart5_clk,
-       // tc3 .. tc5
+       &tc3_clk,
+       &tc4_clk,
+       &tc5_clk,
        // irq0 .. irq2
 };
 
@@ -213,7 +259,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
 
 static void at91sam9260_reset(void)
 {
-       at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
 }
 
 
@@ -221,11 +267,37 @@ static void at91sam9260_reset(void)
  *  AT91SAM9260 processor initialization
  * -------------------------------------------------------------------- */
 
+static void __init at91sam9xe_initialize(void)
+{
+       unsigned long cidr, sram_size;
+
+       cidr = at91_sys_read(AT91_DBGU_CIDR);
+
+       switch (cidr & AT91_CIDR_SRAMSIZ) {
+               case AT91_CIDR_SRAMSIZ_32K:
+                       sram_size = 2 * SZ_16K;
+                       break;
+               case AT91_CIDR_SRAMSIZ_16K:
+               default:
+                       sram_size = SZ_16K;
+       }
+
+       at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
+       at91sam9xe_sram_desc->length = sram_size;
+
+       iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+}
+
 void __init at91sam9260_initialize(unsigned long main_clock)
 {
        /* Map peripherals */
        iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
 
+       if (cpu_is_at91sam9xe())
+               at91sam9xe_initialize();
+       else
+               iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
        at91_arch_reset = at91sam9260_reset;
        at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
                        | (1 << AT91SAM9260_ID_IRQ2);
similarity index 97%
rename from arch/arm/mach-at91rm9200/at91sam9260_devices.c
rename to arch/arm/mach-at91/at91sam9260_devices.c
index f42d3a40ec3cbd08a4c1757152b2dbe6bc4a7882..f7d342ccbebf823db392f75759cd6417b5a782d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91sam9260_devices.c
+ * arch/arm/mach-at91/at91sam9260_devices.c
  *
  *  Copyright (C) 2006 Atmel
  *
@@ -128,7 +128,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
 
 #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
 static u64 eth_dmamask = 0xffffffffUL;
-static struct eth_platform_data eth_data;
+static struct at91_eth_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -155,7 +155,7 @@ static struct platform_device at91sam9260_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct eth_platform_data *data)
+void __init at91_add_device_eth(struct at91_eth_data *data)
 {
        if (!data)
                return;
@@ -192,7 +192,7 @@ void __init at91_add_device_eth(struct eth_platform_data *data)
        platform_device_register(&at91sam9260_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct eth_platform_data *data) {}
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
 #endif
 
 
@@ -229,7 +229,7 @@ static struct platform_device at91sam9260_mmc_device = {
        .num_resources  = ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
 {
        if (!data)
                return;
@@ -275,7 +275,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
        platform_device_register(&at91sam9260_mmc_device);
 }
 #else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
 #endif
 
 
@@ -515,6 +515,10 @@ u8 at91_leds_timer;
 
 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
 {
+       /* Enable GPIO to access the LEDs */
+       at91_set_gpio_output(cpu_led, 1);
+       at91_set_gpio_output(timer_led, 1);
+
        at91_leds_cpu   = cpu_led;
        at91_leds_timer = timer_led;
 }
similarity index 92%
rename from arch/arm/mach-at91rm9200/at91sam9261.c
rename to arch/arm/mach-at91/at91sam9261.c
index d242bb885c6dabc2c1302e4873f5644a3fdfaf67..784d1e682d6db426fa19b2f4b1317da95a071e7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91sam9261.c
+ * arch/arm/mach-at91/at91sam9261.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -97,6 +97,21 @@ static struct clk spi1_clk = {
        .pmc_mask       = 1 << AT91SAM9261_ID_SPI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk tc0_clk = {
+       .name           = "tc0_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_TC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+       .name           = "tc1_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_TC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+       .name           = "tc2_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_TC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk ohci_clk = {
        .name           = "ohci_clk",
        .pmc_mask       = 1 << AT91SAM9261_ID_UHP,
@@ -121,7 +136,9 @@ static struct clk *periph_clocks[] __initdata = {
        &spi0_clk,
        &spi1_clk,
        // ssc 0 .. ssc2
-       // tc0 .. tc2
+       &tc0_clk,
+       &tc1_clk,
+       &tc2_clk,
        &ohci_clk,
        &lcdc_clk,
        // irq0 .. irq2
@@ -208,7 +225,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
 
 static void at91sam9261_reset(void)
 {
-       at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
 }
 
 
similarity index 98%
rename from arch/arm/mach-at91rm9200/at91sam9261_devices.c
rename to arch/arm/mach-at91/at91sam9261_devices.c
index ed1d79081b355575269df2eb46a0da92ffd6e445..e1504766fd6401127e1af02f7e8cd911c8707675 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/at91sam9261_devices.c
+ * arch/arm/mach-at91/at91sam9261_devices.c
  *
  *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
  *  Copyright (C) 2005 David Brownell
@@ -159,7 +159,7 @@ static struct platform_device at91sam9261_mmc_device = {
        .num_resources  = ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
 {
        if (!data)
                return;
@@ -192,7 +192,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
        platform_device_register(&at91sam9261_mmc_device);
 }
 #else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
 #endif
 
 
@@ -513,6 +513,10 @@ u8 at91_leds_timer;
 
 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
 {
+       /* Enable GPIO to access the LEDs */
+       at91_set_gpio_output(cpu_led, 1);
+       at91_set_gpio_output(timer_led, 1);
+
        at91_leds_cpu   = cpu_led;
        at91_leds_timer = timer_led;
 }
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
new file mode 100644 (file)
index 0000000..6aa342e
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-at91/at91sam9263.c
+ *
+ *  Copyright (C) 2007 Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9263_io_desc[] __initdata = {
+       {
+               .virtual        = AT91_VA_BASE_SYS,
+               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
+               .pfn            = __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
+               .length         = AT91SAM9263_SRAM0_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
+               .pfn            = __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
+               .length         = AT91SAM9263_SRAM1_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+       .name           = "pioA_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_PIOA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+       .name           = "pioB_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_PIOB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioCDE_clk = {
+       .name           = "pioCDE_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_PIOCDE,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+       .name           = "usart0_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_US0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+       .name           = "usart1_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_US1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+       .name           = "usart2_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_US2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc0_clk = {
+       .name           = "mci0_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_MCI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+       .name           = "mci1_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_MCI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+       .name           = "twi_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_TWI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+       .name           = "spi0_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_SPI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+       .name           = "spi1_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_SPI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb_clk = {
+       .name           = "tcb_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_TCB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+       .name           = "macb_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_EMAC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+       .name           = "udc_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_UDP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+       .name           = "isi_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_ISI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+       .name           = "lcdc_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_ISI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+       .name           = "ohci_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_UHP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+       &pioA_clk,
+       &pioB_clk,
+       &pioCDE_clk,
+       &usart0_clk,
+       &usart1_clk,
+       &usart2_clk,
+       &mmc0_clk,
+       &mmc1_clk,
+       // can
+       &twi_clk,
+       &spi0_clk,
+       &spi1_clk,
+       // ssc0 .. ssc1
+       // ac97
+       &tcb_clk,
+       // pwmc
+       &macb_clk,
+       // 2dge
+       &udc_clk,
+       &isi_clk,
+       &lcdc_clk,
+       // dma
+       &ohci_clk,
+       // irq0 .. irq1
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+       .name           = "pck0",
+       .pmc_mask       = AT91_PMC_PCK0,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 0,
+};
+static struct clk pck1 = {
+       .name           = "pck1",
+       .pmc_mask       = AT91_PMC_PCK1,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 1,
+};
+static struct clk pck2 = {
+       .name           = "pck2",
+       .pmc_mask       = AT91_PMC_PCK2,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 2,
+};
+static struct clk pck3 = {
+       .name           = "pck3",
+       .pmc_mask       = AT91_PMC_PCK3,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 3,
+};
+
+static void __init at91sam9263_register_clocks(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+               clk_register(periph_clocks[i]);
+
+       clk_register(&pck0);
+       clk_register(&pck1);
+       clk_register(&pck2);
+       clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9263_gpio[] = {
+       {
+               .id             = AT91SAM9263_ID_PIOA,
+               .offset         = AT91_PIOA,
+               .clock          = &pioA_clk,
+       }, {
+               .id             = AT91SAM9263_ID_PIOB,
+               .offset         = AT91_PIOB,
+               .clock          = &pioB_clk,
+       }, {
+               .id             = AT91SAM9263_ID_PIOCDE,
+               .offset         = AT91_PIOC,
+               .clock          = &pioCDE_clk,
+       }, {
+               .id             = AT91SAM9263_ID_PIOCDE,
+               .offset         = AT91_PIOD,
+               .clock          = &pioCDE_clk,
+       }, {
+               .id             = AT91SAM9263_ID_PIOCDE,
+               .offset         = AT91_PIOE,
+               .clock          = &pioCDE_clk,
+       }
+};
+
+static void at91sam9263_reset(void)
+{
+       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9263 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9263_initialize(unsigned long main_clock)
+{
+       /* Map peripherals */
+       iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+
+       at91_arch_reset = at91sam9263_reset;
+       at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at91sam9263_register_clocks();
+
+       /* Register GPIO subsystem */
+       at91_gpio_init(at91sam9263_gpio, 5);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
+       7,      /* Advanced Interrupt Controller (FIQ) */
+       7,      /* System Peripherals */
+       0,      /* Parallel IO Controller A */
+       0,      /* Parallel IO Controller B */
+       0,      /* Parallel IO Controller C, D and E */
+       0,
+       0,
+       6,      /* USART 0 */
+       6,      /* USART 1 */
+       6,      /* USART 2 */
+       0,      /* Multimedia Card Interface 0 */
+       0,      /* Multimedia Card Interface 1 */
+       4,      /* CAN */
+       0,      /* Two-Wire Interface */
+       6,      /* Serial Peripheral Interface 0 */
+       6,      /* Serial Peripheral Interface 1 */
+       5,      /* Serial Synchronous Controller 0 */
+       5,      /* Serial Synchronous Controller 1 */
+       6,      /* AC97 Controller */
+       0,      /* Timer Counter 0, 1 and 2 */
+       0,      /* Pulse Width Modulation Controller */
+       3,      /* Ethernet */
+       0,
+       0,      /* 2D Graphic Engine */
+       3,      /* USB Device Port */
+       0,      /* Image Sensor Interface */
+       3,      /* LDC Controller */
+       0,      /* DMA Controller */
+       0,
+       3,      /* USB Host port */
+       0,      /* Advanced Interrupt Controller (IRQ0) */
+       0,      /* Advanced Interrupt Controller (IRQ1) */
+};
+
+void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+       if (!priority)
+               priority = at91sam9263_default_irq_priority;
+
+       /* Initialize the AIC interrupt controller */
+       at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
new file mode 100644 (file)
index 0000000..d9af7ca
--- /dev/null
@@ -0,0 +1,818 @@
+/*
+ * arch/arm/mach-at91/at91sam9263_devices.c
+ *
+ *  Copyright (C) 2007 Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9263_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16  0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_UHP_BASE,
+               .end    = AT91SAM9263_UHP_BASE + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_UHP,
+               .end    = AT91SAM9263_ID_UHP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91_usbh_device = {
+       .name           = "at91_ohci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &ohci_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &usbh_data,
+       },
+       .resource       = usbh_resources,
+       .num_resources  = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+       int i;
+
+       if (!data)
+               return;
+
+       /* Enable VBus control for UHP ports */
+       for (i = 0; i < data->ports; i++) {
+               if (data->vbus_pin[i])
+                       at91_set_gpio_output(data->vbus_pin[i], 0);
+       }
+
+       usbh_data = *data;
+       platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_UDP,
+               .end    = AT91SAM9263_BASE_UDP + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_UDP,
+               .end    = AT91SAM9263_ID_UDP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91_udc_device = {
+       .name           = "at91_udc",
+       .id             = -1,
+       .dev            = {
+                               .platform_data          = &udc_data,
+       },
+       .resource       = udc_resources,
+       .num_resources  = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->vbus_pin) {
+               at91_set_gpio_input(data->vbus_pin, 0);
+               at91_set_deglitch(data->vbus_pin, 1);
+       }
+
+       /* Pullup pin is handled internally by USB device peripheral */
+
+       udc_data = *data;
+       platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_EMAC,
+               .end    = AT91SAM9263_BASE_EMAC + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_EMAC,
+               .end    = AT91SAM9263_ID_EMAC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_eth_device = {
+       .name           = "macb",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &eth_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &eth_data,
+       },
+       .resource       = eth_resources,
+       .num_resources  = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->phy_irq_pin) {
+               at91_set_gpio_input(data->phy_irq_pin, 0);
+               at91_set_deglitch(data->phy_irq_pin, 1);
+       }
+
+       /* Pins used for MII and RMII */
+       at91_set_A_periph(AT91_PIN_PE21, 0);    /* ETXCK_EREFCK */
+       at91_set_B_periph(AT91_PIN_PC25, 0);    /* ERXDV */
+       at91_set_A_periph(AT91_PIN_PE25, 0);    /* ERX0 */
+       at91_set_A_periph(AT91_PIN_PE26, 0);    /* ERX1 */
+       at91_set_A_periph(AT91_PIN_PE27, 0);    /* ERXER */
+       at91_set_A_periph(AT91_PIN_PE28, 0);    /* ETXEN */
+       at91_set_A_periph(AT91_PIN_PE23, 0);    /* ETX0 */
+       at91_set_A_periph(AT91_PIN_PE24, 0);    /* ETX1 */
+       at91_set_A_periph(AT91_PIN_PE30, 0);    /* EMDIO */
+       at91_set_A_periph(AT91_PIN_PE29, 0);    /* EMDC */
+
+       if (!data->is_rmii) {
+               at91_set_A_periph(AT91_PIN_PE22, 0);    /* ECRS */
+               at91_set_B_periph(AT91_PIN_PC26, 0);    /* ECOL */
+               at91_set_B_periph(AT91_PIN_PC22, 0);    /* ERX2 */
+               at91_set_B_periph(AT91_PIN_PC23, 0);    /* ERX3 */
+               at91_set_B_periph(AT91_PIN_PC27, 0);    /* ERXCK */
+               at91_set_B_periph(AT91_PIN_PC20, 0);    /* ETX2 */
+               at91_set_B_periph(AT91_PIN_PC21, 0);    /* ETX3 */
+               at91_set_B_periph(AT91_PIN_PC24, 0);    /* ETXER */
+       }
+
+       eth_data = *data;
+       platform_device_register(&at91sam9263_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_MCI0,
+               .end    = AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_MCI0,
+               .end    = AT91SAM9263_ID_MCI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_mmc0_device = {
+       .name           = "at91_mci",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &mmc0_data,
+       },
+       .resource       = mmc0_resources,
+       .num_resources  = ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_MCI1,
+               .end    = AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_MCI1,
+               .end    = AT91SAM9263_ID_MCI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_mmc1_device = {
+       .name           = "at91_mci",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &mmc1_data,
+       },
+       .resource       = mmc1_resources,
+       .num_resources  = ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+       if (!data)
+               return;
+
+       /* input/irq */
+       if (data->det_pin) {
+               at91_set_gpio_input(data->det_pin, 1);
+               at91_set_deglitch(data->det_pin, 1);
+       }
+       if (data->wp_pin)
+               at91_set_gpio_input(data->wp_pin, 1);
+       if (data->vcc_pin)
+               at91_set_gpio_output(data->vcc_pin, 0);
+
+       if (mmc_id == 0) {              /* MCI0 */
+               /* CLK */
+               at91_set_A_periph(AT91_PIN_PA12, 0);
+
+               if (data->slot_b) {
+                       /* CMD */
+                       at91_set_A_periph(AT91_PIN_PA16, 1);
+
+                       /* DAT0, maybe DAT1..DAT3 */
+                       at91_set_A_periph(AT91_PIN_PA17, 1);
+                       if (data->wire4) {
+                               at91_set_A_periph(AT91_PIN_PA18, 1);
+                               at91_set_A_periph(AT91_PIN_PA19, 1);
+                               at91_set_A_periph(AT91_PIN_PA20, 1);
+                       }
+               } else {
+                       /* CMD */
+                       at91_set_A_periph(AT91_PIN_PA1, 1);
+
+                       /* DAT0, maybe DAT1..DAT3 */
+                       at91_set_A_periph(AT91_PIN_PA0, 1);
+                       if (data->wire4) {
+                               at91_set_A_periph(AT91_PIN_PA3, 1);
+                               at91_set_A_periph(AT91_PIN_PA4, 1);
+                               at91_set_A_periph(AT91_PIN_PA5, 1);
+                       }
+               }
+
+               mmc0_data = *data;
+               at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+               platform_device_register(&at91sam9263_mmc0_device);
+       } else {                        /* MCI1 */
+               /* CLK */
+               at91_set_A_periph(AT91_PIN_PA6, 0);
+
+               if (data->slot_b) {
+                       /* CMD */
+                       at91_set_A_periph(AT91_PIN_PA21, 1);
+
+                       /* DAT0, maybe DAT1..DAT3 */
+                       at91_set_A_periph(AT91_PIN_PA22, 1);
+                       if (data->wire4) {
+                               at91_set_A_periph(AT91_PIN_PA23, 1);
+                               at91_set_A_periph(AT91_PIN_PA24, 1);
+                               at91_set_A_periph(AT91_PIN_PA25, 1);
+                       }
+               } else {
+                       /* CMD */
+                       at91_set_A_periph(AT91_PIN_PA7, 1);
+
+                       /* DAT0, maybe DAT1..DAT3 */
+                       at91_set_A_periph(AT91_PIN_PA8, 1);
+                       if (data->wire4) {
+                               at91_set_A_periph(AT91_PIN_PA9, 1);
+                               at91_set_A_periph(AT91_PIN_PA10, 1);
+                               at91_set_A_periph(AT91_PIN_PA11, 1);
+                       }
+               }
+
+               mmc1_data = *data;
+               at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+               platform_device_register(&at91sam9263_mmc1_device);
+       }
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE      AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+       {
+               .start  = NAND_BASE,
+               .end    = NAND_BASE + SZ_256M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device at91sam9263_nand_device = {
+       .name           = "at91_nand",
+       .id             = -1,
+       .dev            = {
+                               .platform_data  = &nand_data,
+       },
+       .resource       = nand_resources,
+       .num_resources  = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+       unsigned long csa, mode;
+
+       if (!data)
+               return;
+
+       csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+       at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC);
+
+       /* set the bus interface characteristics */
+       at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+                       | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+       at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3)
+                       | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
+
+       at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
+
+       if (data->bus_width_16)
+               mode = AT91_SMC_DBW_16;
+       else
+               mode = AT91_SMC_DBW_8;
+       at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2));
+
+       /* enable pin */
+       if (data->enable_pin)
+               at91_set_gpio_output(data->enable_pin, 1);
+
+       /* ready/busy pin */
+       if (data->rdy_pin)
+               at91_set_gpio_input(data->rdy_pin, 1);
+
+       /* card detect pin */
+       if (data->det_pin)
+               at91_set_gpio_input(data->det_pin, 1);
+
+       nand_data = *data;
+       platform_device_register(&at91sam9263_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_TWI,
+               .end    = AT91SAM9263_BASE_TWI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_TWI,
+               .end    = AT91SAM9263_ID_TWI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_twi_device = {
+       .name           = "at91_i2c",
+       .id             = -1,
+       .resource       = twi_resources,
+       .num_resources  = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+       /* pins used for TWI interface */
+       at91_set_A_periph(AT91_PIN_PB4, 0);             /* TWD */
+       at91_set_multi_drive(AT91_PIN_PB4, 1);
+
+       at91_set_A_periph(AT91_PIN_PB5, 0);             /* TWCK */
+       at91_set_multi_drive(AT91_PIN_PB5, 1);
+
+       platform_device_register(&at91sam9263_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_SPI0,
+               .end    = AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_SPI0,
+               .end    = AT91SAM9263_ID_SPI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_spi0_device = {
+       .name           = "atmel_spi",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi0_resources,
+       .num_resources  = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
+
+static struct resource spi1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_SPI1,
+               .end    = AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_SPI1,
+               .end    = AT91SAM9263_ID_SPI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_spi1_device = {
+       .name           = "atmel_spi",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi1_resources,
+       .num_resources  = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+       int i;
+       unsigned long cs_pin;
+       short enable_spi0 = 0;
+       short enable_spi1 = 0;
+
+       /* Choose SPI chip-selects */
+       for (i = 0; i < nr_devices; i++) {
+               if (devices[i].controller_data)
+                       cs_pin = (unsigned long) devices[i].controller_data;
+               else if (devices[i].bus_num == 0)
+                       cs_pin = spi0_standard_cs[devices[i].chip_select];
+               else
+                       cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+               if (devices[i].bus_num == 0)
+                       enable_spi0 = 1;
+               else
+                       enable_spi1 = 1;
+
+               /* enable chip-select pin */
+               at91_set_gpio_output(cs_pin, 1);
+
+               /* pass chip-select pin to driver */
+               devices[i].controller_data = (void *) cs_pin;
+       }
+
+       spi_register_board_info(devices, nr_devices);
+
+       /* Configure SPI bus(es) */
+       if (enable_spi0) {
+               at91_set_B_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
+               at91_set_B_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
+               at91_set_B_periph(AT91_PIN_PA2, 0);     /* SPI1_SPCK */
+
+               at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
+               platform_device_register(&at91sam9263_spi0_device);
+       }
+       if (enable_spi1) {
+               at91_set_A_periph(AT91_PIN_PB12, 0);    /* SPI1_MISO */
+               at91_set_A_periph(AT91_PIN_PB13, 0);    /* SPI1_MOSI */
+               at91_set_A_periph(AT91_PIN_PB14, 0);    /* SPI1_SPCK */
+
+               at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
+               platform_device_register(&at91sam9263_spi1_device);
+       }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+       /* Enable GPIO to access the LEDs */
+       at91_set_gpio_output(cpu_led, 1);
+       at91_set_gpio_output(timer_led, 1);
+
+       at91_leds_cpu   = cpu_led;
+       at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+
+static struct resource dbgu_resources[] = {
+       [0] = {
+               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
+               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91_ID_SYS,
+               .end    = AT91_ID_SYS,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data dbgu_data = {
+       .use_dma_tx     = 0,
+       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
+       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9263_dbgu_device = {
+       .name           = "atmel_usart",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &dbgu_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = dbgu_resources,
+       .num_resources  = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PC30, 0);            /* DRXD */
+       at91_set_A_periph(AT91_PIN_PC31, 1);            /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_US0,
+               .end    = AT91SAM9263_BASE_US0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_US0,
+               .end    = AT91SAM9263_ID_US0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart0_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9263_uart0_device = {
+       .name           = "atmel_usart",
+       .id             = 1,
+       .dev            = {
+                               .platform_data  = &uart0_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart0_resources,
+       .num_resources  = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PA26, 1);            /* TXD0 */
+       at91_set_A_periph(AT91_PIN_PA27, 0);            /* RXD0 */
+       at91_set_A_periph(AT91_PIN_PA28, 0);            /* RTS0 */
+       at91_set_A_periph(AT91_PIN_PA29, 0);            /* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_US1,
+               .end    = AT91SAM9263_BASE_US1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_US1,
+               .end    = AT91SAM9263_ID_US1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart1_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9263_uart1_device = {
+       .name           = "atmel_usart",
+       .id             = 2,
+       .dev            = {
+                               .platform_data  = &uart1_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart1_resources,
+       .num_resources  = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PD0, 1);             /* TXD1 */
+       at91_set_A_periph(AT91_PIN_PD1, 0);             /* RXD1 */
+       at91_set_B_periph(AT91_PIN_PD7, 0);             /* RTS1 */
+       at91_set_B_periph(AT91_PIN_PD8, 0);             /* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_US2,
+               .end    = AT91SAM9263_BASE_US2 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_US2,
+               .end    = AT91SAM9263_ID_US2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart2_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9263_uart2_device = {
+       .name           = "atmel_usart",
+       .id             = 3,
+       .dev            = {
+                               .platform_data  = &uart2_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart2_resources,
+       .num_resources  = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PD2, 1);             /* TXD2 */
+       at91_set_A_periph(AT91_PIN_PD3, 0);             /* RXD2 */
+       at91_set_B_periph(AT91_PIN_PD5, 0);             /* RTS2 */
+       at91_set_B_periph(AT91_PIN_PD6, 0);             /* CTS2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];    /* the UARTs to use */
+struct platform_device *atmel_default_console_device;  /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+       int i;
+
+       /* Fill in list of supported UARTs */
+       for (i = 0; i < config->nr_tty; i++) {
+               switch (config->tty_map[i]) {
+                       case 0:
+                               configure_usart0_pins();
+                               at91_uarts[i] = &at91sam9263_uart0_device;
+                               at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+                               break;
+                       case 1:
+                               configure_usart1_pins();
+                               at91_uarts[i] = &at91sam9263_uart1_device;
+                               at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+                               break;
+                       case 2:
+                               configure_usart2_pins();
+                               at91_uarts[i] = &at91sam9263_uart2_device;
+                               at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+                               break;
+                       case 3:
+                               configure_dbgu_pins();
+                               at91_uarts[i] = &at91sam9263_dbgu_device;
+                               at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+                               break;
+                       default:
+                               continue;
+               }
+               at91_uarts[i]->id = i;          /* update ID number to mapped ID */
+       }
+
+       /* Set serial console device */
+       if (config->console_tty < ATMEL_MAX_UART)
+               atmel_default_console_device = at91_uarts[config->console_tty];
+       if (!atmel_default_console_device)
+               printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+       int i;
+
+       for (i = 0; i < ATMEL_MAX_UART; i++) {
+               if (at91_uarts[i])
+                       platform_device_register(at91_uarts[i]);
+       }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+       return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
similarity index 94%
rename from arch/arm/mach-at91rm9200/at91sam926x_time.c
rename to arch/arm/mach-at91/at91sam926x_time.c
index 99df5f6ee42edaf03451f04c23040040884c03ef..a4dded27fa16a0dab13fa674293e7f2873b2a538 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c
+ * linux/arch/arm/mach-at91/at91sam926x_time.c
  *
  * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
  * Revision     2005 M. Nicolas Diremdjian, ATMEL Rousset, France
@@ -30,7 +30,6 @@
  * Returns number of microseconds since last timer interrupt.  Note that interrupts
  * will have been disabled by do_gettimeofday()
  *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- *  'tick' is usecs per jiffy (linux/timex.h).
  */
 static unsigned long at91sam926x_gettimeoffset(void)
 {
@@ -39,7 +38,7 @@ static unsigned long at91sam926x_gettimeoffset(void)
 
        elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);         /* hardware clock cycles */
 
-       return (unsigned long)(elapsed * 1000000) / LATCH;
+       return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
 }
 
 /*
similarity index 98%
rename from arch/arm/mach-at91rm9200/board-1arm.c
rename to arch/arm/mach-at91/board-1arm.c
index 971c3e2d8e367a6400b3f4c864af4fe611860346..2d3d4b6f7b02cccb1d421260b2577dee0fc6335d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-1arm.c
+ * linux/arch/arm/mach-at91/board-1arm.c
  *
  *  Copyright (C) 2005 SAN People
  *
similarity index 97%
rename from arch/arm/mach-at91rm9200/board-carmeva.c
rename to arch/arm/mach-at91/board-carmeva.c
index 654f0379550aef5d2e26a52d7c989b858dddf1c6..b4518619063a2b439c80837bf12545e80bf3d104 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-carmeva.c
+ * linux/arch/arm/mach-at91/board-carmeva.c
  *
  *  Copyright (c) 2005 Peer Georgi
  *                    Conitec Datasystems
@@ -134,7 +134,7 @@ static void __init carmeva_board_init(void)
        /* Compact Flash */
 //     at91_add_device_cf(&carmeva_cf_data);
        /* MMC */
-       at91_add_device_mmc(&carmeva_mmc_data);
+       at91_add_device_mmc(0, &carmeva_mmc_data);
 }
 
 MACHINE_START(CARMEVA, "Carmeva")
similarity index 78%
rename from arch/arm/mach-at91rm9200/board-csb337.c
rename to arch/arm/mach-at91/board-csb337.c
index b8bb8052607a8f44342c27d56e8fdf818d1372e4..e18a41e61f0c302698c165e9d532f7de44f6f6d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-csb337.c
+ * linux/arch/arm/mach-at91/board-csb337.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -112,6 +113,42 @@ static struct spi_board_info csb337_spi_devices[] = {
        },
 };
 
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x800000
+
+static struct mtd_partition csb_flash_partitions[] = {
+       {
+               .name           = "uMON flash",
+               .offset         = 0,
+               .size           = MTDPART_SIZ_FULL,
+               .mask_flags     = MTD_WRITEABLE,        /* read only */
+       }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+       .width          = 2,
+       .parts          = csb_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+       {
+               .start  = CSB_FLASH_BASE,
+               .end    = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device csb_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+                               .platform_data = &csb_flash_data,
+                       },
+       .resource       = csb_flash_resources,
+       .num_resources  = ARRAY_SIZE(csb_flash_resources),
+};
+
 static void __init csb337_board_init(void)
 {
        /* Serial */
@@ -130,7 +167,9 @@ static void __init csb337_board_init(void)
        /* SPI */
        at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
        /* MMC */
-       at91_add_device_mmc(&csb337_mmc_data);
+       at91_add_device_mmc(0, &csb337_mmc_data);
+       /* NOR flash */
+       platform_device_register(&csb_flash);
 }
 
 MACHINE_START(CSB337, "Cogent CSB337")
similarity index 75%
rename from arch/arm/mach-at91rm9200/board-csb637.c
rename to arch/arm/mach-at91/board-csb637.c
index a29fa0e822ce61af2ebec8f62b8450f89b9b0b0b..77f04b935b3ab9753110ab15678acdca7a402718 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-csb637.c
+ * linux/arch/arm/mach-at91/board-csb637.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -23,6 +23,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -81,6 +82,42 @@ static struct at91_udc_data __initdata csb637_udc_data = {
        .pullup_pin   = AT91_PIN_PB1,
 };
 
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x1000000
+
+static struct mtd_partition csb_flash_partitions[] = {
+       {
+               .name           = "uMON flash",
+               .offset         = 0,
+               .size           = MTDPART_SIZ_FULL,
+               .mask_flags     = MTD_WRITEABLE,        /* read only */
+       }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+       .width          = 2,
+       .parts          = csb_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+       {
+               .start  = CSB_FLASH_BASE,
+               .end    = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device csb_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+                               .platform_data = &csb_flash_data,
+                       },
+       .resource       = csb_flash_resources,
+       .num_resources  = ARRAY_SIZE(csb_flash_resources),
+};
+
 static void __init csb637_board_init(void)
 {
        /* Serial */
@@ -95,6 +132,8 @@ static void __init csb637_board_init(void)
        at91_add_device_i2c();
        /* SPI */
        at91_add_device_spi(NULL, 0);
+       /* NOR flash */
+       platform_device_register(&csb_flash);
 }
 
 MACHINE_START(CSB637, "Cogent CSB637")
similarity index 98%
rename from arch/arm/mach-at91rm9200/board-dk.c
rename to arch/arm/mach-at91/board-dk.c
index 7522bf91bce86adfcd4ad3828f9f5980aeb04129..6043c38c0a9e84b6063d52111cb9c9b2173b8eb6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-dk.c
+ * linux/arch/arm/mach-at91/board-dk.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -194,7 +194,7 @@ static void __init dk_board_init(void)
 #else
        /* MMC */
        at91_set_gpio_output(AT91_PIN_PB7, 1);  /* this MMC card slot can optionally use SPI signaling (CS3). */
-       at91_add_device_mmc(&dk_mmc_data);
+       at91_add_device_mmc(0, &dk_mmc_data);
 #endif
        /* NAND */
        at91_add_device_nand(&dk_nand_data);
similarity index 97%
rename from arch/arm/mach-at91rm9200/board-eb9200.c
rename to arch/arm/mach-at91/board-eb9200.c
index 80b72cf7264cc104766333dc1fb23379bc9041e7..20458b5548f0669708eeab4f64baf2ceec1301d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-eb9200.c
+ * linux/arch/arm/mach-at91/board-eb9200.c
  *
  *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
  *  by Andrew Patrikalakis
@@ -109,7 +109,7 @@ static void __init eb9200_board_init(void)
        at91_add_device_spi(NULL, 0);
        /* MMC */
        /* only supports 1 or 4 bit interface, not wired through to SPI */
-       at91_add_device_mmc(&eb9200_mmc_data);
+       at91_add_device_mmc(0, &eb9200_mmc_data);
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
similarity index 98%
rename from arch/arm/mach-at91rm9200/board-ek.c
rename to arch/arm/mach-at91/board-ek.c
index c4fdb415f20e435e3bf093adc4320b4e2b2ca272..322fdd75a1e431863729b478988cef8d7d8e708d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-ek.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -154,7 +154,7 @@ static void __init ek_board_init(void)
 #else
        /* MMC */
        at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-       at91_add_device_mmc(&ek_mmc_data);
+       at91_add_device_mmc(0, &ek_mmc_data);
 #endif
        /* NOR Flash */
        platform_device_register(&ek_flash);
similarity index 98%
rename from arch/arm/mach-at91rm9200/board-kafa.c
rename to arch/arm/mach-at91/board-kafa.c
index 6ef3c4879829010b2898d008ee326cd62e88c3fb..c77d84ce9cae89878b81f68648f49619fab768d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-kafa.c
+ * linux/arch/arm/mach-at91/board-kafa.c
  *
  *  Copyright (C) 2006 Sperry-Sun
  *
similarity index 97%
rename from arch/arm/mach-at91rm9200/board-kb9202.c
rename to arch/arm/mach-at91/board-kb9202.c
index 759d8191854f3b6e6976da422572a981bce21c5b..76f6e1e553eaeabc252b1f4e60d9ba86b59101db 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-kb9202.c
+ * linux/arch/arm/mach-at91/board-kb9202.c
  *
  *  Copyright (c) 2005 kb_admin
  *                    KwikByte, Inc.
@@ -122,7 +122,7 @@ static void __init kb9202_board_init(void)
        /* USB Device */
        at91_add_device_udc(&kb9202_udc_data);
        /* MMC */
-       at91_add_device_mmc(&kb9202_mmc_data);
+       at91_add_device_mmc(0, &kb9202_mmc_data);
        /* I2C */
        at91_add_device_i2c();
        /* SPI */
similarity index 96%
rename from arch/arm/mach-at91rm9200/board-sam9260ek.c
rename to arch/arm/mach-at91/board-sam9260ek.c
index da5d58ac870b59446be5015210d15df512e16c4e..57fb4499d969bd5246d984e8cbb725bc80a09182 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-sam9260ek.c
  *
  *  Copyright (C) 2005 SAN People
  *  Copyright (C) 2006 Atmel
@@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct __initdata eth_platform_data ek_macb_data = {
+static struct __initdata at91_eth_data ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 1,
 };
@@ -187,7 +187,7 @@ static void __init ek_board_init(void)
        /* Ethernet */
        at91_add_device_eth(&ek_macb_data);
        /* MMC */
-       at91_add_device_mmc(&ek_mmc_data);
+       at91_add_device_mmc(0, &ek_mmc_data);
 }
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
similarity index 98%
rename from arch/arm/mach-at91rm9200/board-sam9261ek.c
rename to arch/arm/mach-at91/board-sam9261ek.c
index 30b490d8886b1f4a5705acf54dca9ab62dcf332f..b7e772467cf6bb056f1d582a39e9fdf96fde718a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-sam9261ek.c
  *
  *  Copyright (C) 2005 SAN People
  *  Copyright (C) 2006 Atmel
@@ -243,7 +243,7 @@ static void __init ek_board_init(void)
        at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
 #else
        /* MMC */
-       at91_add_device_mmc(&ek_mmc_data);
+       at91_add_device_mmc(0, &ek_mmc_data);
 #endif
 }
 
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
new file mode 100644 (file)
index 0000000..8fdce11
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9263ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 2 = USART0 .. USART2
+ *    3      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 2,
+       .tty_map        = { 3, 0, -1, -1, }             /* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+       /* Initialize processor: 16.367 MHz crystal */
+       at91sam9263_initialize(16367660);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+       at91sam9263_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+       .ports          = 2,
+       .vbus_pin       = { AT91_PIN_PA24, AT91_PIN_PA21 },
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+       .vbus_pin       = AT91_PIN_PA25,
+       .pullup_pin     = 0,            /* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+       {       /* DataFlash card */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 0,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+       .wire4          = 1,
+       .det_pin        = AT91_PIN_PE18,
+       .wp_pin         = AT91_PIN_PE19,
+//     .vcc_pin        = ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+       {
+               .name   = "Partition 1",
+               .offset = 0,
+               .size   = 64 * 1024 * 1024,
+       },
+       {
+               .name   = "Partition 2",
+               .offset = 64 * 1024 * 1024,
+               .size   = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(ek_nand_partition);
+       return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+       .ale            = 21,
+       .cle            = 22,
+//     .det_pin        = ... not connected
+       .rdy_pin        = AT91_PIN_PA22,
+       .enable_pin     = AT91_PIN_PD15,
+       .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+       .bus_width_16   = 1,
+#else
+       .bus_width_16   = 0,
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* USB Host */
+       at91_add_device_usbh(&ek_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&ek_udc_data);
+       /* SPI */
+       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+       /* MMC */
+       at91_add_device_mmc(1, &ek_mmc_data);
+       /* NAND */
+       at91_add_device_nand(&ek_nand_data);
+}
+
+MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
+       /* Maintainer: Atmel */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = ek_map_io,
+       .init_irq       = ek_init_irq,
+       .init_machine   = ek_board_init,
+MACHINE_END
similarity index 94%
rename from arch/arm/mach-at91rm9200/clock.c
rename to arch/arm/mach-at91/clock.c
index 36a8e4d1cc6ddd3813786cfec9ff4494627ac5db..06c9a0507d0d8316137507979a62d631f2861769 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/clock.c
+ * linux/arch/arm/mach-at91/clock.c
  *
  * Copyright (C) 2005 David Brownell
  * Copyright (C) 2005 Ivan Kokshaysky
@@ -525,27 +525,6 @@ fail:
        return 0;
 }
 
-/*
- * Several unused clocks may be active.  Turn them off.
- */
-static void __init at91_periphclk_reset(void)
-{
-       unsigned long reg;
-       struct clk *clk;
-
-       reg = at91_sys_read(AT91_PMC_PCSR);
-
-       list_for_each_entry(clk, &clocks, node) {
-               if (clk->mode != pmc_periph_mode)
-                       continue;
-
-               if (clk->users > 0)
-                       reg &= ~clk->pmc_mask;
-       }
-
-       at91_sys_write(AT91_PMC_PCDR, reg);
-}
-
 static struct clk *const standard_pmc_clocks[] __initdata = {
        /* four primary clocks */
        &clk32k,
@@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock)
                pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
 
        /*
-        * USB clock init:  choose 48 MHz PLLB value, turn all clocks off,
+        * USB clock init:  choose 48 MHz PLLB value,
         * disable 48MHz clock during usb peripheral suspend.
         *
         * REVISIT:  assumes MCK doesn't derive from PLLB!
@@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock)
        if (cpu_is_at91rm9200()) {
                uhpck.pmc_mask = AT91RM9200_PMC_UHP;
                udpck.pmc_mask = AT91RM9200_PMC_UDP;
-               at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP);
                at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
-       } else if (cpu_is_at91sam9260()) {
+       } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
                uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
                udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-               at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP);
-       } else if (cpu_is_at91sam9261()) {
-               uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0);
-               udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-               at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP);
        }
        at91_sys_write(AT91_CKGR_PLLBR, 0);
 
@@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock)
                (unsigned) main_clock / 1000000,
                ((unsigned) main_clock % 1000000) / 1000);
 
-       /* disable all programmable clocks */
-       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
+       return 0;
+}
+
+/*
+ * Several unused clocks may be active.  Turn them off.
+ */
+static int __init at91_clock_reset(void)
+{
+       unsigned long pcdr = 0;
+       unsigned long scdr = 0;
+       struct clk *clk;
+
+       list_for_each_entry(clk, &clocks, node) {
+               if (clk->users > 0)
+                       continue;
+
+               if (clk->mode == pmc_periph_mode)
+                       pcdr |= clk->pmc_mask;
+
+               if (clk->mode == pmc_sys_mode)
+                       scdr |= clk->pmc_mask;
+
+               pr_debug("Clocks: disable unused %s\n", clk->name);
+       }
 
-       /* disable all other unused peripheral clocks */
-       at91_periphclk_reset();
+       at91_sys_write(AT91_PMC_PCDR, pcdr);
+       at91_sys_write(AT91_PMC_SCDR, scdr);
 
        return 0;
 }
+late_initcall(at91_clock_reset);
similarity index 94%
rename from arch/arm/mach-at91rm9200/clock.h
rename to arch/arm/mach-at91/clock.h
index b5c7a2eb2d1dd7a24f7acaf20da5e4e584ac2c77..1ba3b95ff3594f10cd30c7b433b38e0f0e497d4e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/clock.h
+ * linux/arch/arm/mach-at91/clock.h
  *
  * 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
similarity index 90%
rename from arch/arm/mach-at91rm9200/generic.h
rename to arch/arm/mach-at91/generic.h
index 8c4d5a77d485e52b9d367a9cf7b0b8233c942011..bda26221c5227580951cbd94cd2edfffeca3badf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/generic.h
+ * linux/arch/arm/mach-at91/generic.h
  *
  *  Copyright (C) 2005 David Brownell
  *
 extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
 extern void __init at91sam9260_initialize(unsigned long main_clock);
 extern void __init at91sam9261_initialize(unsigned long main_clock);
+extern void __init at91sam9263_initialize(unsigned long main_clock);
 
  /* Interrupts */
 extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
 extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
 extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
 
  /* Timer */
similarity index 99%
rename from arch/arm/mach-at91rm9200/gpio.c
rename to arch/arm/mach-at91/gpio.c
index 15eb5b6b29f2ed94ad36c7243d38d9832e2c9028..7b87f3f101b7d324cdda7409ff4945e634ec4638 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/gpio.c
+ * linux/arch/arm/mach-at91/gpio.c
  *
  * Copyright (C) 2005 HP Labs
  *
similarity index 99%
rename from arch/arm/mach-at91rm9200/irq.c
rename to arch/arm/mach-at91/irq.c
index 2148daafd29c3535e3b03e0ed0a90d9a4fb2d975..78a5cdb746dc851170a7a583e1d6016575939be6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91rm9200/irq.c
+ * linux/arch/arm/mach-at91/irq.c
  *
  *  Copyright (C) 2004 SAN People
  *  Copyright (C) 2004 ATMEL
similarity index 93%
rename from arch/arm/mach-at91rm9200/leds.c
rename to arch/arm/mach-at91/leds.c
index 1a333730466ef2d052d9dee907bce838a870bf60..0d5144973988e6484681d0cde72d233e93378cfb 100644 (file)
@@ -86,10 +86,6 @@ static int __init leds_init(void)
        if (!at91_leds_timer || !at91_leds_cpu)
                return -ENODEV;
 
-       /* Enable PIO to access the LEDs */
-       at91_set_gpio_output(at91_leds_timer, 1);
-       at91_set_gpio_output(at91_leds_cpu, 1);
-
        leds_event = at91_leds_event;
 
        leds_event(led_start);
similarity index 98%
rename from arch/arm/mach-at91rm9200/pm.c
rename to arch/arm/mach-at91/pm.c
index 67aa5572a3eaeb9c7e305a041b2254cdfc376b4e..b49bfda53d7fdb1bbc97964b6695dda6a8a2804e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/pm.c
+ * arch/arm/mach-at91/pm.c
  * AT91 Power Management
  *
  * Copyright (C) 2005 David Brownell
@@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void)
 #warning "Check SAM9260 USB clocks"
        } else if (cpu_is_at91sam9261()) {
 #warning "Check SAM9261 USB clocks"
+       } else if (cpu_is_at91sam9263()) {
+#warning "Check SAM9263 USB clocks"
        }
 
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
index af7904b3d0a864149593d38e307f7debbc49267f..575a21dabd2f530ab8dbb1c7a570d6c0ba8084e8 100644 (file)
@@ -51,6 +51,31 @@ config MACH_GESBC9312
          Say 'Y' here if you want your kernel to support the Glomation
          GESBC-9312-sx board.
 
+config MACH_MICRO9
+        bool
+        default n
+
+config MACH_MICRO9H
+       bool "Support Contec Hypercontrol Micro9-H"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-H board.
+
+config MACH_MICRO9M
+       bool "Support Contec Hypercontrol Micro9-M"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-M board.
+
+config MACH_MICRO9L
+       bool "Support Contec Hypercontrol Micro9-L"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-L board.
+
 config MACH_TS72XX
        bool "Support Technologic Systems TS-72xx SBC"
        help
index b06641dd450d5699c9bda5422d6dc2eabfe08027..0d3bf932654ee431bfc4d9b9682ca431114373e9 100644 (file)
@@ -13,4 +13,5 @@ obj-$(CONFIG_MACH_EDB9312)    += edb9312.o
 obj-$(CONFIG_MACH_EDB9315)     += edb9315.o
 obj-$(CONFIG_MACH_EDB9315A)    += edb9315a.o
 obj-$(CONFIG_MACH_GESBC9312)   += gesbc9312.o
+obj-$(CONFIG_MACH_MICRO9)      += micro9.o
 obj-$(CONFIG_MACH_TS72XX)      += ts72xx.o
index 08ad782c1649fb116987f14914f36872c481cd93..f174d1a3b11c7333d18a19f3524e39256af05add 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <asm/div64.h>
 #include <asm/hardware.h>
@@ -124,7 +125,7 @@ static unsigned long calc_pll_rate(u32 config_word)
        return (unsigned long)rate;
 }
 
-void ep93xx_clock_init(void)
+static int __init ep93xx_clock_init(void)
 {
        u32 value;
 
@@ -153,4 +154,7 @@ void ep93xx_clock_init(void)
        printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
                clk_f.rate / 1000000, clk_h.rate / 1000000,
                clk_p.rate / 1000000);
+
+       return 0;
 }
+arch_initcall(ep93xx_clock_init);
index 6b26346191c040f9949094232a7cf8e072949161..829aed696d982420b094280e8ff6cd9b3a029c6b 100644 (file)
@@ -152,22 +152,30 @@ struct sys_timer ep93xx_timer = {
 /*************************************************************************
  * GPIO handling for EP93xx
  *************************************************************************/
-static unsigned char gpio_int_enable[2];
-static unsigned char gpio_int_type1[2];
-static unsigned char gpio_int_type2[2];
+static unsigned char gpio_int_unmasked[3];
+static unsigned char gpio_int_enabled[3];
+static unsigned char gpio_int_type1[3];
+static unsigned char gpio_int_type2[3];
 
-static void update_gpio_ab_int_params(int port)
+static void update_gpio_int_params(int abf)
 {
-       if (port == 0) {
+       if (abf == 0) {
                __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
                __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
                __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
-               __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
-       } else if (port == 1) {
+               __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
+       } else if (abf == 1) {
                __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
                __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
                __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
-               __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
+               __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
+       } else if (abf == 2) {
+               __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
+               __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
+               __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
+               __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
+       } else {
+               BUG();
        }
 }
 
@@ -192,8 +200,13 @@ void gpio_line_config(int line, int direction)
        local_irq_save(flags);
        if (direction == GPIO_OUT) {
                if (line >= 0 && line < 16) {
-                       gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
-                       update_gpio_ab_int_params(line >> 3);
+                       /* Port A/B.  */
+                       gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+                       update_gpio_int_params(line >> 3);
+               } else if (line >= 40 && line < 48) {
+                       /* Port F.  */
+                       gpio_int_unmasked[2] &= ~(1 << (line & 7));
+                       update_gpio_int_params(2);
                }
 
                v = __raw_readb(data_direction_register);
@@ -244,8 +257,7 @@ EXPORT_SYMBOL(gpio_line_set);
 /*************************************************************************
  * EP93xx IRQ handling
  *************************************************************************/
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
-               struct irq_desc *desc)
+static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned char status;
        int i;
@@ -267,37 +279,46 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
        }
 }
 
-static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq)
+static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
+
+       desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
+}
+
+static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
 {
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] &= ~(1 << (line & 7));
-       update_gpio_ab_int_params(port);
+       gpio_int_unmasked[port] &= ~(1 << (line & 7));
+       update_gpio_int_params(port);
 
-       if (line >> 3) {
-               __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
-       } else {
+       if (port == 0) {
                __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
+       } else if (port == 1) {
+               __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
+       } else if (port == 2) {
+               __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
        }
 }
 
-static void ep93xx_gpio_ab_irq_mask(unsigned int irq)
+static void ep93xx_gpio_irq_mask(unsigned int irq)
 {
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] &= ~(1 << (line & 7));
-       update_gpio_ab_int_params(port);
+       gpio_int_unmasked[port] &= ~(1 << (line & 7));
+       update_gpio_int_params(port);
 }
 
-static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
+static void ep93xx_gpio_irq_unmask(unsigned int irq)
 {
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] |= 1 << (line & 7);
-       update_gpio_ab_int_params(port);
+       gpio_int_unmasked[port] |= 1 << (line & 7);
+       update_gpio_int_params(port);
 }
 
 
@@ -306,40 +327,51 @@ static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
  * edge (1) triggered, while gpio_int_type2 controls whether it
  * triggers on low/falling (0) or high/rising (1).
  */
-static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
+static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
 {
        int port;
        int line;
 
        line = irq - IRQ_EP93XX_GPIO(0);
-       gpio_line_config(line, GPIO_IN);
+       if (line >= 0 && line < 16) {
+               gpio_line_config(line, GPIO_IN);
+       } else {
+               gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
+       }
 
        port = line >> 3;
        line &= 7;
 
        if (type & IRQT_RISING) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] |= 1 << line;
                gpio_int_type2[port] |= 1 << line;
        } else if (type & IRQT_FALLING) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] |= 1 << line;
                gpio_int_type2[port] &= ~(1 << line);
        } else if (type & IRQT_HIGH) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] &= ~(1 << line);
                gpio_int_type2[port] |= 1 << line;
        } else if (type & IRQT_LOW) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] &= ~(1 << line);
                gpio_int_type2[port] &= ~(1 << line);
+       } else {
+               gpio_int_enabled[port] &= ~(1 << line);
        }
-       update_gpio_ab_int_params(port);
+       update_gpio_int_params(port);
 
        return 0;
 }
 
-static struct irq_chip ep93xx_gpio_ab_irq_chip = {
-       .ack            = ep93xx_gpio_ab_irq_mask_ack,
-       .mask           = ep93xx_gpio_ab_irq_mask,
-       .unmask         = ep93xx_gpio_ab_irq_unmask,
-       .set_type       = ep93xx_gpio_ab_irq_type,
+static struct irq_chip ep93xx_gpio_irq_chip = {
+       .name           = "GPIO",
+       .ack            = ep93xx_gpio_irq_mask_ack,
+       .mask           = ep93xx_gpio_irq_mask,
+       .unmask         = ep93xx_gpio_irq_unmask,
+       .set_type       = ep93xx_gpio_irq_type,
 };
 
 
@@ -350,12 +382,21 @@ void __init ep93xx_init_irq(void)
        vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
        vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
 
-       for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) {
-               set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip);
+       for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
+               set_irq_chip(irq, &ep93xx_gpio_irq_chip);
                set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
+
        set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
+       set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
 }
 
 
@@ -461,8 +502,6 @@ void __init ep93xx_init_devices(void)
 {
        unsigned int v;
 
-       ep93xx_clock_init();
-
        /*
         * Disallow access to MaverickCrunch initially.
         */
@@ -477,8 +516,4 @@ void __init ep93xx_init_devices(void)
 
        platform_device_register(&ep93xx_rtc_device);
        platform_device_register(&ep93xx_ohci_device);
-
-#ifdef CONFIG_CRUNCH
-       elf_hwcap |= HWCAP_CRUNCH;
-#endif
 }
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
new file mode 100644 (file)
index 0000000..f28c129
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/micro9.c
+ *
+ * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
+ *                   Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <linux/mtd/physmap.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+static struct ep93xx_eth_data micro9_eth_data = {
+       .phy_id                 = 0x1f,
+};
+
+static struct resource micro9_eth_resource[] = {
+       {
+               .start  = EP93XX_ETHERNET_PHYS_BASE,
+               .end    = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_EP93XX_ETHERNET,
+               .end    = IRQ_EP93XX_ETHERNET,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device micro9_eth_device = {
+       .name           = "ep93xx-eth",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &micro9_eth_data,
+       },
+       .num_resources = ARRAY_SIZE(micro9_eth_resource),
+       .resource       = micro9_eth_resource,
+};
+
+static void __init micro9_eth_init(void)
+{
+       memcpy(micro9_eth_data.dev_addr,
+               (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+       platform_device_register(&micro9_eth_device);
+}
+
+static void __init micro9_init(void)
+{
+       micro9_eth_init();
+}
+
+/*
+ * Micro9-H
+ */
+#ifdef CONFIG_MACH_MICRO9H
+static struct physmap_flash_data micro9h_flash_data = {
+       .width          = 4,
+};
+
+static struct resource micro9h_flash_resource = {
+       .start          = 0x10000000,
+       .end            = 0x13ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device micro9h_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &micro9h_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &micro9h_flash_resource,
+};
+
+static void __init micro9h_init(void)
+{
+       platform_device_register(&micro9h_flash);
+}
+
+static void __init micro9h_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+       micro9h_init();
+}
+
+MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9h_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-M
+ */
+#ifdef CONFIG_MACH_MICRO9M
+static void __init micro9m_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+}
+
+MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9m_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-L
+ */
+#ifdef CONFIG_MACH_MICRO9L
+static void __init micro9l_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+}
+
+MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9l_init_machine,
+MACHINE_END
+#endif
+
index 40039b2a90b39079a7af6f5fcdd5856f6452280e..2703a730baf77ff5cfd59a40faacc74e8e5cdd07 100644 (file)
@@ -87,7 +87,7 @@ static struct clocksource clocksource_imx = {
        .read           = imx_get_cycles,
        .mask           = 0xFFFFFFFF,
        .shift          = 20,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init imx_clocksource_init(void)
index dbbc07c38b141349f9883b78019407517cf32a33..162b93214965435d395a95b437162d49a49c935f 100644 (file)
@@ -250,11 +250,14 @@ static struct irq_chip iop13xx_irqchip4 = {
        .unmask = iop13xx_irq_unmask3,
 };
 
+extern void iop_init_cp6_handler(void);
+
 void __init iop13xx_init_irq(void)
 {
        unsigned int i;
 
        u32 cp_flags = iop13xx_cp6_save();
+       iop_init_cp6_handler();
 
        /* disable all interrupts */
        write_intctl_0(0);
index 3ec1cd5c4f99733e4b1e76a9116f27b6040709b9..8b0ac5590ae4611ad2ac519b220dd75bde0b33fd 100644 (file)
@@ -60,6 +60,8 @@ void __init iop32x_init_irq(void)
 {
        int i;
 
+       iop_init_cp6_handler();
+
        intctl_write(0);
        intstr_write(0);
        if (machine_is_glantank() ||
index 2499a7707e3ca8288ba84d3a18d1f70ed184b8f6..966aa51aee09f2a2ae2f430357234d7e178bce85 100644 (file)
@@ -120,6 +120,20 @@ static struct hw_pci n2100_pci __initdata = {
        .map_irq        = n2100_pci_map_irq,
 };
 
+/*
+ * Both r8169 chips on the n2100 exhibit PCI parity problems.  Set
+ * the ->broken_parity_status flag for both ports so that the r8169
+ * driver knows it should ignore error interrupts.
+ */
+static void n2100_fixup_r8169(struct pci_dev *dev)
+{
+       if (dev->bus->number == 0 &&
+           (dev->devfn == PCI_DEVFN(1, 0) ||
+            dev->devfn == PCI_DEVFN(2, 0)))
+               dev->broken_parity_status = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
+
 static int __init n2100_pci_init(void)
 {
        if (machine_is_n2100())
index 00b37f32d72e0c9a9314d93412850babd7c8c926..effbe6b782d04b2dc3d7f6f0abbc5839013ba044 100644 (file)
@@ -110,6 +110,8 @@ void __init iop33x_init_irq(void)
 {
        int i;
 
+       iop_init_cp6_handler();
+
        intctl0_write(0);
        intctl1_write(0);
        intstr0_write(0);
index e316bd93313f656215588f30488188860c9da7b7..8a339cdfe222f807ab32c3a18a0759003a9261b0 100644 (file)
@@ -17,7 +17,7 @@ config MACH_NSLU2
          NSLU2 NAS device. For more information on this platform,
          see http://www.nslu2-linux.org
 
-config ARCH_AVILA
+config MACH_AVILA
        bool "Avila"
        select PCI
        help
@@ -25,6 +25,14 @@ config ARCH_AVILA
          Avila Network Platform. For more information on this platform,
          see <file:Documentation/arm/IXP4xx>.
 
+config MACH_LOFT
+    bool "Loft"
+    depends on MACH_AVILA
+    help
+         Say 'Y' here if you want your kernel to support the Giant
+         Shoulder Inc Loft board (a minor variation on the standard
+         Gateworks Avila Network Platform).
+
 config ARCH_ADI_COYOTE
        bool "Coyote"
        select PCI
@@ -86,7 +94,7 @@ config MACH_NAS100D
 #
 config ARCH_IXDP4XX
        bool
-       depends on ARCH_IXDP425 || ARCH_AVILA || MACH_IXDP465
+       depends on ARCH_IXDP425 || MACH_IXDP465
        default y
 
 #
index 640315d8b96a2f0fedfdb374303b3074d7a5e030..746e297284ed9b7bd6b1ab2cff54fb0d37efedb0 100644 (file)
@@ -6,6 +6,7 @@ obj-pci-y       :=
 obj-pci-n      :=
 
 obj-pci-$(CONFIG_ARCH_IXDP4XX)         += ixdp425-pci.o
+obj-pci-$(CONFIG_MACH_AVILA)           += avila-pci.o
 obj-pci-$(CONFIG_MACH_IXDPG425)                += ixdpg425-pci.o
 obj-pci-$(CONFIG_ARCH_ADI_COYOTE)      += coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)                += gtwx5715-pci.o
@@ -15,6 +16,7 @@ obj-pci-$(CONFIG_MACH_NAS100D)                += nas100d-pci.o
 obj-y  += common.o
 
 obj-$(CONFIG_ARCH_IXDP4XX)     += ixdp425-setup.o
+obj-$(CONFIG_MACH_AVILA)       += avila-setup.o
 obj-$(CONFIG_MACH_IXDPG425)    += coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)  += coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)    += gtwx5715-setup.o
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
new file mode 100644 (file)
index 0000000..3f86769
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-pci.c
+ *
+ * Gateworks Avila board-level PCI initialization
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-pci.c
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+void __init avila_pci_preinit(void)
+{
+       set_irq_type(IRQ_AVILA_PCI_INTA, IRQT_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTB, IRQT_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTC, IRQT_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTD, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init avila_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       static int pci_irq_table[AVILA_PCI_IRQ_LINES] = {
+               IRQ_AVILA_PCI_INTA,
+               IRQ_AVILA_PCI_INTB,
+               IRQ_AVILA_PCI_INTC,
+               IRQ_AVILA_PCI_INTD
+       };
+
+       int irq = -1;
+
+       if (slot >= 1 &&
+       slot <= (machine_is_loft() ? LOFT_PCI_MAX_DEV : AVILA_PCI_MAX_DEV) &&
+               pin >= 1 && pin <= AVILA_PCI_IRQ_LINES) {
+               irq = pci_irq_table[(slot + pin - 2) % 4];
+       }
+
+       return irq;
+}
+
+struct hw_pci avila_pci __initdata = {
+       .nr_controllers = 1,
+       .preinit        = avila_pci_preinit,
+       .swizzle        = pci_std_swizzle,
+       .setup          = ixp4xx_setup,
+       .scan           = ixp4xx_scan_bus,
+       .map_irq        = avila_map_irq,
+};
+
+int __init avila_pci_init(void)
+{
+       if (machine_is_avila() || machine_is_loft())
+               pci_common_init(&avila_pci);
+       return 0;
+}
+
+subsys_initcall(avila_pci_init);
+
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
new file mode 100644 (file)
index 0000000..d59b8dc
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-setup.c
+ *
+ * Gateworks Avila board-setup
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-setup.c
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data avila_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+};
+
+static struct resource avila_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device avila_flash = {
+       .name           = "IXP4XX-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &avila_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &avila_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins avila_i2c_gpio_pins = {
+       .sda_pin        = AVILA_SDA_PIN,
+       .scl_pin        = AVILA_SCL_PIN,
+};
+
+static struct platform_device avila_i2c_controller = {
+       .name           = "IXP4XX-I2C",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &avila_i2c_gpio_pins,
+       },
+       .num_resources  = 0
+};
+
+static struct resource avila_uart_resources[] = {
+       {
+               .start          = IXP4XX_UART1_BASE_PHYS,
+               .end            = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM
+       },
+       {
+               .start          = IXP4XX_UART2_BASE_PHYS,
+               .end            = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM
+       }
+};
+
+static struct plat_serial8250_port avila_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART1_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART1,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { },
+};
+
+static struct platform_device avila_uart = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev.platform_data      = avila_uart_data,
+       .num_resources          = 2,
+       .resource               = avila_uart_resources
+};
+
+static struct resource avila_pata_resources[] = {
+       {
+               .flags  = IORESOURCE_MEM
+       },
+       {
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "intrq",
+               .start  = IRQ_IXP4XX_GPIO12,
+               .end    = IRQ_IXP4XX_GPIO12,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct ixp4xx_pata_data avila_pata_data = {
+       .cs0_bits       = 0xbfff0043,
+       .cs1_bits       = 0xbfff0043,
+};
+
+static struct platform_device avila_pata = {
+       .name                   = "pata_ixp4xx_cf",
+       .id                     = 0,
+       .dev.platform_data      = &avila_pata_data,
+       .num_resources          = ARRAY_SIZE(avila_pata_resources),
+       .resource               = avila_pata_resources,
+};
+
+static struct platform_device *avila_devices[] __initdata = {
+       &avila_i2c_controller,
+       &avila_flash,
+       &avila_uart
+};
+
+static void __init avila_init(void)
+{
+       ixp4xx_sys_init();
+
+       avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       avila_flash_resource.end =
+               IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+       platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
+
+       avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
+       avila_pata_resources[0].end = IXP4XX_EXP_BUS_END(1);
+
+       avila_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+       avila_pata_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+       avila_pata_data.cs0_cfg = IXP4XX_EXP_CS1;
+       avila_pata_data.cs1_cfg = IXP4XX_EXP_CS2;
+
+       platform_device_register(&avila_pata);
+
+}
+
+MACHINE_START(AVILA, "Gateworks Avila Network Platform")
+       /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = avila_init,
+MACHINE_END
+
+ /*
+  * Loft is functionally equivalent to Avila except that it has a
+  * different number for the maximum PCI devices.  The MACHINE
+  * structure below is identical to Avila except for the comment.
+  */
+#ifdef CONFIG_MACH_LOFT
+MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
+       /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = avila_init,
+MACHINE_END
+#endif
+
index 2ec9a9e9a04dd0e702c58faa8015dd0df5498fac..45068c3d8dcc2336f02a92d21557257dd31337f5 100644 (file)
@@ -395,7 +395,7 @@ static struct clocksource clocksource_ixp4xx = {
        .read           = ixp4xx_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 20,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 unsigned long ixp4xx_timer_freq = FREQ;
index d5156c043f0b09094ba5279c651afd52162f9466..99c1dc8033c8e89cef7d8a4f54c2d9f8d615a3d4 100644 (file)
@@ -66,7 +66,7 @@ struct hw_pci ixdp425_pci __initdata = {
 int __init ixdp425_pci_init(void)
 {
        if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
-                       machine_is_avila() || machine_is_ixdp465())
+                       machine_is_ixdp465())
                pci_common_init(&ixdp425_pci);
        return 0;
 }
index da72383ee301e15218a737cf91408b4c78ad3a86..04b1d56396a096b357fd3c23e3562aeee34bc96e 100644 (file)
@@ -156,23 +156,3 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        .init_machine   = ixdp425_init,
 MACHINE_END
 #endif
-
-/*
- * Avila is functionally equivalent to IXDP425 except that it adds
- * a CF IDE slot hanging off the expansion bus. When we have a 
- * driver for IXP4xx CF IDE with driver model support we'll move
- * Avila to it's own setup file.
- */
-#ifdef CONFIG_ARCH_AVILA
-MACHINE_START(AVILA, "Gateworks Avila Network Platform")
-       /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
-       .map_io         = ixp4xx_map_io,
-       .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
-       .init_machine   = ixdp425_init,
-MACHINE_END
-#endif
-
index 5773b55ef4a69f203dc83831d6452128094924b8..7e132fcccd47810de97955d9c3dc4146893027d5 100644 (file)
@@ -62,7 +62,7 @@ static struct clocksource clocksource_netx = {
        .read           = netx_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 20,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
new file mode 100644 (file)
index 0000000..8175ba9
--- /dev/null
@@ -0,0 +1,21 @@
+if ARCH_NS9XXX
+
+menu "NS9xxx Implementations"
+
+config MACH_CC9P9360DEV
+       bool "Connect Core 9P 9360 on an A9M9750 Devboard"
+       select PROCESSOR_NS9360
+       select BOARD_A9M9750DEV
+       help
+         Say Y here if you are using the Digi Connect Core 9P 9360
+         on an A9M9750 Development Board.
+
+config PROCESSOR_NS9360
+       bool
+
+config BOARD_A9M9750DEV
+       bool
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
new file mode 100644 (file)
index 0000000..91e945f
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y := irq.o time.o generic.o
+
+obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
+
+obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot
new file mode 100644 (file)
index 0000000..75ed64e
--- /dev/null
@@ -0,0 +1,2 @@
+zreladdr-y := 0x108000
+params_phys-y := 0x100
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
new file mode 100644 (file)
index 0000000..2528988
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.c
+ *
+ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/irq.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/arch-ns9xxx/board.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/regs-bbu.h>
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+#include "board-a9m9750dev.h"
+
+static struct map_desc board_a9m9750dev_io_desc[] __initdata = {
+       { /* FPGA on CS0 */
+               .virtual = io_p2v(NS9XXX_CSxSTAT_PHYS(0)),
+               .pfn = __phys_to_pfn(NS9XXX_CSxSTAT_PHYS(0)),
+               .length = NS9XXX_CS0STAT_LENGTH,
+               .type = MT_DEVICE,
+       },
+};
+
+void __init board_a9m9750dev_map_io(void)
+{
+       iotable_init(board_a9m9750dev_io_desc,
+                    ARRAY_SIZE(board_a9m9750dev_io_desc));
+}
+
+static void a9m9750dev_fpga_ack_irq(unsigned int irq)
+{
+       /* nothing */
+}
+
+static void a9m9750dev_fpga_mask_irq(unsigned int irq)
+{
+       FPGA_IER &= ~(1 << (irq - FPGA_IRQ(0)));
+}
+
+static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
+{
+       a9m9750dev_fpga_mask_irq(irq);
+       a9m9750dev_fpga_ack_irq(irq);
+}
+
+static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
+{
+       FPGA_IER |= 1 << (irq - FPGA_IRQ(0));
+}
+
+static struct irq_chip a9m9750dev_fpga_chip = {
+       .ack            = a9m9750dev_fpga_ack_irq,
+       .mask           = a9m9750dev_fpga_mask_irq,
+       .mask_ack       = a9m9750dev_fpga_maskack_irq,
+       .unmask         = a9m9750dev_fpga_unmask_irq,
+};
+
+static void a9m9750dev_fpga_demux_handler(unsigned int irq,
+               struct irq_desc *desc)
+{
+       int stat = FPGA_ISR;
+
+       while (stat != 0) {
+               int irqno = fls(stat) - 1;
+
+               stat &= ~(1 << irqno);
+
+               desc = irq_desc + FPGA_IRQ(irqno);
+
+               desc_handle_irq(irqno, desc);
+       }
+}
+
+void __init board_a9m9750dev_init_irq(void)
+{
+       u32 reg;
+       int i;
+
+       /*
+        * configure gpio for IRQ_EXT2
+        * use GPIO 11, because GPIO 32 is used for the LCD
+        */
+       /* XXX: proper GPIO handling */
+       BBU_GC(2) &= ~0x2000;
+
+       for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
+               set_irq_chip(i, &a9m9750dev_fpga_chip);
+               set_irq_handler(i, handle_level_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       /* IRQ_EXT2: level sensitive + active low */
+       reg = SYS_EIC(2);
+       REGSET(reg, SYS_EIC, PLTY, AL);
+       REGSET(reg, SYS_EIC, LVEDG, LEVEL);
+       SYS_EIC(2) = reg;
+
+       set_irq_chained_handler(IRQ_EXT2,
+                       a9m9750dev_fpga_demux_handler);
+}
+
+static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
+       {
+               .iobase         = FPGA_UARTA_BASE,
+               .membase        = (unsigned char*)FPGA_UARTA_BASE,
+               .mapbase        = FPGA_UARTA_BASE,
+               .irq            = IRQ_FPGA_UARTA,
+               .iotype         = UPIO_MEM,
+               .uartclk        = 18432000,
+               .regshift       = 0,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+       }, {
+               .iobase         = FPGA_UARTB_BASE,
+               .membase        = (unsigned char*)FPGA_UARTB_BASE,
+               .mapbase        = FPGA_UARTB_BASE,
+               .irq            = IRQ_FPGA_UARTB,
+               .iotype         = UPIO_MEM,
+               .uartclk        = 18432000,
+               .regshift       = 0,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+       }, {
+               .iobase         = FPGA_UARTC_BASE,
+               .membase        = (unsigned char*)FPGA_UARTC_BASE,
+               .mapbase        = FPGA_UARTC_BASE,
+               .irq            = IRQ_FPGA_UARTC,
+               .iotype         = UPIO_MEM,
+               .uartclk        = 18432000,
+               .regshift       = 0,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+       }, {
+               .iobase         = FPGA_UARTD_BASE,
+               .membase        = (unsigned char*)FPGA_UARTD_BASE,
+               .mapbase        = FPGA_UARTD_BASE,
+               .irq            = IRQ_FPGA_UARTD,
+               .iotype         = UPIO_MEM,
+               .uartclk        = 18432000,
+               .regshift       = 0,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+       }, {
+               /* end marker */
+       },
+};
+
+static struct platform_device board_a9m9750dev_serial_device = {
+       .name = "serial8250",
+       .dev = {
+               .platform_data = board_a9m9750dev_serial8250_port,
+       },
+};
+
+static struct platform_device *board_a9m9750dev_devices[] __initdata = {
+       &board_a9m9750dev_serial_device,
+};
+
+void __init board_a9m9750dev_init_machine(void)
+{
+       u32 reg;
+
+       /* setup static CS0: memory base ... */
+       REGSETIM(SYS_SMCSSMB(0), SYS_SMCSSMB, CSxB,
+                       NS9XXX_CSxSTAT_PHYS(0) >> 12);
+
+       /* ... and mask */
+       reg = SYS_SMCSSMM(0);
+       REGSETIM(reg, SYS_SMCSSMM, CSxM, 0xfffff);
+       REGSET(reg, SYS_SMCSSMM, CSEx, EN);
+       SYS_SMCSSMM(0) = reg;
+
+       /* setup static CS0: memory configuration */
+       reg = MEM_SMC(0);
+       REGSET(reg, MEM_SMC, WSMC, OFF);
+       REGSET(reg, MEM_SMC, BSMC, OFF);
+       REGSET(reg, MEM_SMC, EW, OFF);
+       REGSET(reg, MEM_SMC, PB, 1);
+       REGSET(reg, MEM_SMC, PC, AL);
+       REGSET(reg, MEM_SMC, PM, DIS);
+       REGSET(reg, MEM_SMC, MW, 8);
+       MEM_SMC(0) = reg;
+
+       /* setup static CS0: timing */
+       MEM_SMWED(0) = 0x2;
+       MEM_SMOED(0) = 0x2;
+       MEM_SMRD(0) = 0x6;
+       MEM_SMWD(0) = 0x6;
+
+       platform_add_devices(board_a9m9750dev_devices,
+                       ARRAY_SIZE(board_a9m9750dev_devices));
+}
+
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.h b/arch/arm/mach-ns9xxx/board-a9m9750dev.h
new file mode 100644 (file)
index 0000000..edc75ab
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/init.h>
+
+void __init board_a9m9750dev_map_io(void);
+void __init board_a9m9750dev_init_machine(void);
+void __init board_a9m9750dev_init_irq(void);
diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c
new file mode 100644 (file)
index 0000000..83e2b65
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/board.h>
+
+static struct map_desc standard_io_desc[] __initdata = {
+       { /* BBus */
+               .virtual = io_p2v(0x90000000),
+               .pfn = __phys_to_pfn(0x90000000),
+               .length = 0x00700000,
+               .type = MT_DEVICE,
+       }, { /* AHB */
+               .virtual = io_p2v(0xa0100000),
+               .pfn = __phys_to_pfn(0xa0100000),
+               .length = 0x00900000,
+               .type = MT_DEVICE,
+       },
+};
+
+void __init ns9xxx_map_io(void)
+{
+       iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+void __init ns9xxx_init_machine(void)
+{
+}
diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h
new file mode 100644 (file)
index 0000000..687e291
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/time.h>
+#include <asm/mach/time.h>
+#include <linux/init.h>
+
+void __init ns9xxx_init_irq(void);
+void __init ns9xxx_map_io(void);
+void __init ns9xxx_init_machine(void);
+
+extern struct sys_timer ns9xxx_timer;
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
new file mode 100644 (file)
index 0000000..83d9272
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/mach-ns9xxx/irq.c
+ *
+ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch-ns9xxx/board.h>
+
+#include "generic.h"
+
+static void ns9xxx_ack_irq_timer(unsigned int irq)
+{
+       u32 tc = SYS_TC(irq - IRQ_TIMER0);
+
+       REGSET(tc, SYS_TCx, INTC, SET);
+       SYS_TC(irq - IRQ_TIMER0) = tc;
+
+       REGSET(tc, SYS_TCx, INTC, UNSET);
+       SYS_TC(irq - IRQ_TIMER0) = tc;
+}
+
+void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
+       [IRQ_TIMER0] = ns9xxx_ack_irq_timer,
+       [IRQ_TIMER1] = ns9xxx_ack_irq_timer,
+       [IRQ_TIMER2] = ns9xxx_ack_irq_timer,
+       [IRQ_TIMER3] = ns9xxx_ack_irq_timer,
+};
+
+static void ns9xxx_mask_irq(unsigned int irq)
+{
+       /* XXX: better use cpp symbols */
+       SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+}
+
+static void ns9xxx_ack_irq(unsigned int irq)
+{
+       if (!ns9xxx_ack_irq_functions[irq]) {
+               printk(KERN_ERR "no ack function for irq %u\n", irq);
+               BUG();
+       }
+
+       ns9xxx_ack_irq_functions[irq](irq);
+       SYS_ISRADDR = 0;
+}
+
+static void ns9xxx_maskack_irq(unsigned int irq)
+{
+       ns9xxx_mask_irq(irq);
+       ns9xxx_ack_irq(irq);
+}
+
+static void ns9xxx_unmask_irq(unsigned int irq)
+{
+       /* XXX: better use cpp symbols */
+       SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
+}
+
+static struct irq_chip ns9xxx_chip = {
+       .ack            = ns9xxx_ack_irq,
+       .mask           = ns9xxx_mask_irq,
+       .mask_ack       = ns9xxx_maskack_irq,
+       .unmask         = ns9xxx_unmask_irq,
+};
+
+void __init ns9xxx_init_irq(void)
+{
+       int i;
+
+       /* disable all IRQs */
+       for (i = 0; i < 8; ++i)
+               SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
+                       (4 * i + 2) << 8 | (4 * i + 3);
+
+       /* simple interrupt prio table:
+        * prio(x) < prio(y) <=> x < y
+        */
+       for (i = 0; i < 32; ++i)
+               SYS_IVA(i) = i;
+
+       for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
+               set_irq_chip(i, &ns9xxx_chip);
+               set_irq_handler(i, handle_level_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+}
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
new file mode 100644 (file)
index 0000000..a193dd9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "board-a9m9750dev.h"
+#include "generic.h"
+
+static void __init mach_cc9p9360dev_map_io(void)
+{
+       ns9xxx_map_io();
+       board_a9m9750dev_map_io();
+}
+
+static void __init mach_cc9p9360dev_init_irq(void)
+{
+       ns9xxx_init_irq();
+       board_a9m9750dev_init_irq();
+}
+
+static void __init mach_cc9p9360dev_init_machine(void)
+{
+       ns9xxx_init_machine();
+       board_a9m9750dev_init_machine();
+}
+
+MACHINE_START(CC9P9360DEV, "Connect Core 9P 9360 on an A9M9750 Devboard")
+       .map_io = mach_cc9p9360dev_map_io,
+       .init_irq = mach_cc9p9360dev_init_irq,
+       .init_machine = mach_cc9p9360dev_init_machine,
+       .timer = &ns9xxx_timer,
+       .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
new file mode 100644 (file)
index 0000000..eec05f1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-ns9xxx/time.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/clock.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch/system.h>
+#include "generic.h"
+
+#define TIMERCLOCKSELECT 64
+
+static u32 usecs_per_tick;
+
+static irqreturn_t
+ns9xxx_timer_interrupt(int irq, void *dev_id)
+{
+       write_seqlock(&xtime_lock);
+       timer_tick();
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static unsigned long ns9xxx_timer_gettimeoffset(void)
+{
+       /* return the microseconds which have passed since the last interrupt
+        * was _serviced_.  That is, if an interrupt is pending or the counter
+        * reloads, return one periode more. */
+
+       u32 counter1 = SYS_TR(0);
+       int pending = SYS_ISR & (1 << IRQ_TIMER0);
+       u32 counter2 = SYS_TR(0);
+       u32 elapsed;
+
+       if (pending || counter2 > counter1)
+               elapsed = 2 * SYS_TRC(0) - counter2;
+       else
+               elapsed = SYS_TRC(0) - counter1;
+
+       return (elapsed * usecs_per_tick) >> 16;
+
+}
+
+static struct irqaction ns9xxx_timer_irq = {
+       .name = "NS9xxx Timer Tick",
+       .flags = IRQF_DISABLED | IRQF_TIMER,
+       .handler = ns9xxx_timer_interrupt,
+};
+
+static void __init ns9xxx_timer_init(void)
+{
+       int tc;
+
+       usecs_per_tick =
+               SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
+
+       /* disable timer */
+       if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
+               SYS_TC(0) = tc & ~SYS_TCx_TEN;
+
+       SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
+
+       REGSET(tc, SYS_TCx, TEN, EN);
+       REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
+       REGSET(tc, SYS_TCx, INTS, EN);
+       REGSET(tc, SYS_TCx, UDS, DOWN);
+       REGSET(tc, SYS_TCx, TDBG, STOP);
+       REGSET(tc, SYS_TCx, TSZ, 32);
+       REGSET(tc, SYS_TCx, REN, EN);
+       SYS_TC(0) = tc;
+
+       setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
+}
+
+struct sys_timer ns9xxx_timer = {
+       .init = ns9xxx_timer_init,
+       .offset = ns9xxx_timer_gettimeoffset,
+};
index 9de1278d234f86d655880c6f587e10b785cb843a..390524c4710f543384861206557a72cc514a1175 100644 (file)
@@ -338,6 +338,27 @@ static struct platform_device i2c_device = {
        .num_resources  = ARRAY_SIZE(i2c_resources),
 };
 
+#ifdef CONFIG_PXA27x
+static struct resource i2c_power_resources[] = {
+       {
+               .start  = 0x40f00180,
+               .end    = 0x40f001a3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_PWRI2C,
+               .end    = IRQ_PWRI2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_power_device = {
+       .name           = "pxa2xx-i2c",
+       .id             = 1,
+       .resource       = i2c_power_resources,
+       .num_resources  = ARRAY_SIZE(i2c_resources),
+};
+#endif
+
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
        i2c_device.dev.platform_data = info;
@@ -392,6 +413,9 @@ static struct platform_device *devices[] __initdata = {
        &stuart_device,
        &pxaficp_device,
        &i2c_device,
+#ifdef CONFIG_PXA27x
+       &i2c_power_device,
+#endif
        &i2s_device,
        &pxartc_device,
 };
index ee2beb400414653cdba4166df543633c62ca83b3..fc3b82a740a0b021f188d7801c3da29f93723b74 100644 (file)
@@ -112,7 +112,7 @@ static struct clocksource clocksource_pxa = {
        .read           = pxa_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 20,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init pxa_timer_init(void)
index 17f5f4439fe756a966391732a83a02018ed94bd7..35156ca39df77e6a62414f30f879119e12b513df 100644 (file)
@@ -10,10 +10,21 @@ config MACH_REALVIEW_EB
 config REALVIEW_MPCORE
        bool "Support MPcore tile"
        depends on MACH_REALVIEW_EB
+       select CACHE_L2X0
        help
          Enable support for the MPCore tile on the Realview platform.
          Since there are device address and interrupt differences, a
          kernel built with this option enabled is not compatible with
          other tiles.
 
+config REALVIEW_MPCORE_REVB
+       bool "Support MPcore RevB tile"
+       depends on REALVIEW_MPCORE
+       default n
+       help
+         Enable support for the MPCore RevB tile on the Realview platform.
+         Since there are device address differences, a
+         kernel built with this option enabled is not compatible with
+         other tiles.
+
 endmenu
index b8484e15dacb7f3e8f3d69ca09ea58334ea47b42..fce3596f9950a6aea5d8489d9d674a99759ad7b0 100644 (file)
@@ -52,13 +52,14 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+       gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
        pen_release = -1;
+       smp_wmb();
 
        /*
         * Synchronise with the boot thread.
@@ -102,6 +103,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
+               smp_rmb();
                if (pen_release == -1)
                        break;
 
index 9741b4d3c9cfca9c938db2c23c3f1c3e29ba6876..3dba666151dbb7be39bc22757701adacc012a447 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -57,7 +58,26 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       },
+#ifdef CONFIG_REALVIEW_MPCORE
+       {
+               .virtual        = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
+               .pfn            = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
+               .pfn            = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
        }, {
+               .virtual        = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
+               .pfn            = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
+               .length         = SZ_8K,
+               .type           = MT_DEVICE,
+       },
+#endif
+       {
                .virtual        = IO_ADDRESS(REALVIEW_SCTL_BASE),
                .pfn            = __phys_to_pfn(REALVIEW_SCTL_BASE),
                .length         = SZ_4K,
@@ -138,19 +158,29 @@ static void __init gic_init_irq(void)
 #ifdef CONFIG_REALVIEW_MPCORE
        unsigned int pldctrl;
        writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
-       pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8);
+       pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
        pldctrl |= 0x00800000;  /* New irq mode */
-       writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8);
+       writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
        writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 #endif
-       gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
-       gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+       gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
+       gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+#ifdef CONFIG_REALVIEW_MPCORE
+       gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
+       gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
+       gic_cascade_irq(1, IRQ_EB_IRQ1);
+#endif
 }
 
 static void __init realview_eb_init(void)
 {
        int i;
 
+#ifdef CONFIG_REALVIEW_MPCORE
+       /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+        * Bits:  .... ...0 0111 1001 0000 .... .... .... */
+       l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
+#endif
        clk_register(&realview_clcd_clk);
 
        platform_device_register(&realview_flash_device);
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
new file mode 100644 (file)
index 0000000..deab072
--- /dev/null
@@ -0,0 +1,13 @@
+# arch/arm/mach-s3c2400/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+
+
+menu "S3C2400 Machines"
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
new file mode 100644 (file)
index 0000000..7e23f4e
--- /dev/null
@@ -0,0 +1,15 @@
+# arch/arm/mach-s3c2400/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_CPU_S3C2400)      += gpio.o
+
+# Machine support
+
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2400-gpio.c
rename to arch/arm/mach-s3c2400/gpio.c
index 1576d01d5f829bb31ec78ec2976acf6e3443f41e..758e160410e95f2f77724f108022119a79a0c357 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2400-gpio.c
+/* linux/arch/arm/mach-s3c2400/gpio.c
  *
  * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
  *
index eb4ec411312ba8684d7e6830b2be578c8abf2262..d4b013b283c3680f63be0b9b8b05b4120ebf3777 100644 (file)
@@ -1,54 +1,51 @@
-if ARCH_S3C2410
+# arch/arm/mach-s3c2410/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
 
-menu "S3C24XX Implementations"
+config CPU_S3C2410
+       bool
+       depends on ARCH_S3C2410
+       select S3C2410_CLOCK
+       select S3C2410_GPIO
+       select S3C2410_PM if PM
+       help
+         Support for S3C2410 and S3C2410A family from the S3C24XX line
+         of Samsung Mobile CPUs.
 
-config MACH_AML_M5900
-       bool "AML M5900 Series"
-       select CPU_S3C2410
-       select PM_SIMTEC if PM
+config CPU_S3C2410_DMA
+       bool
+       depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+       default y if CPU_S3C2410 || CPU_S3C2442
        help
-          Say Y here if you are using the American Microsystems M5900 Series
-           <http://www.amltd.com>
+         DMA device selection for S3C2410 and compatible CPUs
 
-config MACH_ANUBIS
-       bool "Simtec Electronics ANUBIS"
-       select CPU_S3C2440
-       select PM_SIMTEC if PM
+config S3C2410_PM
+       bool
        help
-         Say Y here if you are using the Simtec Electronics ANUBIS
-         development system
+         Power Management code common to S3C2410 and better
 
-config MACH_OSIRIS
-       bool "Simtec IM2440D20 (OSIRIS) module"
-       select CPU_S3C2440
-       select PM_SIMTEC if PM
+config S3C2410_GPIO
+       bool
        help
-         Say Y here if you are using the Simtec IM2440D20 module, also
-         known as the Osiris.
+         GPIO code for S3C2410 and similar processors
 
-config ARCH_BAST
-       bool "Simtec Electronics BAST (EB2410ITX)"
-       select CPU_S3C2410
-       select PM_SIMTEC if PM
-       select ISA
+config S3C2410_CLOCK
+       bool
        help
-         Say Y here if you are using the Simtec Electronics EB2410ITX
-         development board (also known as BAST)
+         Clock code for the S3C2410, and similar processors
 
-         Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
 
-config BAST_PC104_IRQ
-       bool "BAST PC104 IRQ support"
-       depends on ARCH_BAST
-       default y
-       help
-         Say Y here to enable the PC104 IRQ routing on the
-         Simtec BAST (EB2410ITX)
+menu "S3C2410 Machines"
 
-config PM_H1940
-       bool
+config ARCH_SMDK2410
+       bool "SMDK2410/A9M2410"
+       select CPU_S3C2410
+       select MACH_SMDK
        help
-         Internal node for H1940 and related PM
+          Say Y here if you are using the SMDK2410 or the derived module A9M2410
+           <http://www.fsforth.de>
 
 config ARCH_H1940
        bool "IPAQ H1940"
@@ -57,7 +54,10 @@ config ARCH_H1940
        help
          Say Y here if you are using the HP IPAQ H1940
 
-         <http://www.handhelds.org/projects/h1940.html>.
+config PM_H1940
+       bool
+       help
+         Internal node for H1940 and related PM
 
 config MACH_N30
        bool "Acer N30"
@@ -65,53 +65,36 @@ config MACH_N30
        help
          Say Y here if you are using the Acer N30
 
-         <http://zoo.weinigel.se/n30>.
-
-config MACH_SMDK
-       bool
-       help
-         Common machine code for SMDK2410 and SMDK2440
-
-config ARCH_SMDK2410
-       bool "SMDK2410/A9M2410"
+config ARCH_BAST
+       bool "Simtec Electronics BAST (EB2410ITX)"
        select CPU_S3C2410
-       select MACH_SMDK
+       select PM_SIMTEC if PM
+       select ISA
        help
-          Say Y here if you are using the SMDK2410 or the derived module A9M2410
-           <http://www.fsforth.de>
+         Say Y here if you are using the Simtec Electronics EB2410ITX
+         development board (also known as BAST)
 
-config ARCH_S3C2440
-       bool "SMDK2440"
-       select CPU_S3C2440
-       select MACH_SMDK
+config MACH_OTOM
+       bool "NexVision OTOM Board"
+       select CPU_S3C2410
        help
-         Say Y here if you are using the SMDK2440.
-
-config SMDK2440_CPU2440
-       bool "SMDK2440 with S3C2440 CPU module"
-       depends on ARCH_S3C2440
-       default y if ARCH_S3C2440
-       select CPU_S3C2440
-
-config SMDK2440_CPU2442
-       bool "SMDM2440 with S3C2442 CPU module"
-       depends on ARCH_S3C2440
-       select CPU_S3C2442
+         Say Y here if you are using the Nex Vision OTOM board
 
-config MACH_S3C2413
-       bool
+config MACH_AML_M5900
+       bool "AML M5900 Series"
+       select CPU_S3C2410
+       select PM_SIMTEC if PM
        help
-         Internal node for S3C2413 version of SMDK2413, so that
-         machine_is_s3c2413() will work when MACH_SMDK2413 is
-         selected
+          Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
 
-config MACH_SMDK2413
-       bool "SMDK2413"
-       select CPU_S3C2412
-       select MACH_S3C2413
-       select MACH_SMDK
+config BAST_PC104_IRQ
+       bool "BAST PC104 IRQ support"
+       depends on ARCH_BAST
+       default y
        help
-         Say Y here if you are using an SMDK2413
+         Say Y here to enable the PC104 IRQ routing on the
+         Simtec BAST (EB2410ITX)
 
 config MACH_VR1000
        bool "Thorcom VR1000"
@@ -120,202 +103,11 @@ config MACH_VR1000
        help
          Say Y here if you are using the Thorcom VR1000 board.
 
-         This linux port is currently being maintained by Simtec, on behalf
-         of Thorcom. Any queries, please contact Thorcom first.
-
-config MACH_RX3715
-       bool "HP iPAQ rx3715"
-       select CPU_S3C2440
-       select PM_H1940 if PM
-       help
-         Say Y here if you are using the HP iPAQ rx3715.
-
-         See <http://www.handhelds.org/projects/rx3715.html> for more
-         information on this project
-
-config MACH_OTOM
-       bool "NexVision OTOM Board"
-       select CPU_S3C2410
-       help
-         Say Y here if you are using the Nex Vision OTOM board
-
-config MACH_NEXCODER_2440
-       bool "NexVision NEXCODER 2440 Light Board"
-       select CPU_S3C2440
-       help
-         Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
-
-config MACH_VSTMS
-       bool "VMSTMS"
-       select CPU_S3C2412
+config MACH_QT2410
+       bool "QT2410"
+       select CPU_S3C2410
        help
-         Say Y here if you are using an VSTMS board
+          Say Y here if you are using the Armzone QT2410
 
 endmenu
 
-config S3C2410_CLOCK
-       bool
-       help
-         Clock code for the S3C2410, and similar processors
-
-config S3C2410_PM
-       bool
-       help
-         Power Management code common to S3C2410 and better
-
-config CPU_S3C2410_DMA
-       bool
-       depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
-       default y if CPU_S3C2410 || CPU_S3C2442
-       help
-         DMA device selection for S3C2410 and compatible CPUs
-
-config CPU_S3C2410
-       bool
-       depends on ARCH_S3C2410
-       select S3C2410_CLOCK
-       select S3C2410_PM if PM
-       help
-         Support for S3C2410 and S3C2410A family from the S3C24XX line
-         of Samsung Mobile CPUs.
-
-# internal node to signify if we are only dealing with an S3C2412
-
-config CPU_S3C2412_ONLY
-       bool
-       depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-                  !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
-       default y if CPU_S3C2412
-
-config S3C2412_PM
-       bool
-       help
-         Internal config node to apply S3C2412 power management
-
-config CPU_S3C2412
-       bool
-       depends on ARCH_S3C2410
-       select S3C2412_PM if PM
-       help
-         Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
-
-config CPU_S3C244X
-       bool
-       depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
-       help
-         Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
-
-config CPU_S3C2440
-       bool
-       depends on ARCH_S3C2410
-       select S3C2410_CLOCK
-       select S3C2410_PM if PM
-       select CPU_S3C244X
-       help
-         Support for S3C2440 Samsung Mobile CPU based systems.
-
-config CPU_S3C2442
-       bool
-       depends on ARCH_S3C2420
-       select S3C2410_CLOCK
-       select S3C2410_PM if PM
-       select CPU_S3C244X
-       help
-         Support for S3C2442 Samsung Mobile CPU based systems.
-
-comment "S3C2410 Boot"
-
-config S3C2410_BOOT_WATCHDOG
-       bool "S3C2410 Initialisation watchdog"
-       depends on ARCH_S3C2410 && S3C2410_WATCHDOG
-       help
-         Say y to enable the watchdog during the kernel decompression
-         stage. If the kernel fails to uncompress, then the watchdog
-         will trigger a reset and the system should restart.
-
-         Although this uses the same hardware unit as the kernel watchdog
-         driver, it is not a replacement for it. If you use this option,
-         you will have to use the watchdg driver to either stop the timeout
-         or restart it. If you do not, then your kernel will reboot after
-         startup.
-
-         The driver uses a fixed timeout value, so the exact time till the
-         system resets depends on the value of PCLK. The timeout on an
-         200MHz s3c2410 should be about 30 seconds.
-
-config S3C2410_BOOT_ERROR_RESET
-       bool "S3C2410 Reboot on decompression error"
-       depends on ARCH_S3C2410
-       help
-         Say y here to use the watchdog to reset the system if the
-         kernel decompressor detects an error during decompression.
-
-
-comment "S3C2410 Setup"
-
-config S3C2410_DMA
-       bool "S3C2410 DMA support"
-       depends on ARCH_S3C2410
-       help
-         S3C2410 DMA support. This is needed for drivers like sound which
-         use the S3C2410's DMA system to move data to and from the
-         peripheral blocks.
-
-config S3C2410_DMA_DEBUG
-       bool "S3C2410 DMA support debug"
-       depends on ARCH_S3C2410 && S3C2410_DMA
-       help
-         Enable debugging output for the DMA code. This option sends info
-         to the kernel log, at priority KERN_DEBUG.
-
-         Note, it is easy to create and fill the log buffer in a small
-         amount of time, as well as using an significant percentage of
-         the CPU time doing so.
-
-
-config S3C2410_PM_DEBUG
-       bool "S3C2410 PM Suspend debug"
-       depends on ARCH_S3C2410 && PM
-       help
-         Say Y here if you want verbose debugging from the PM Suspend and
-         Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-         for more information.
-
-config S3C2410_PM_CHECK
-       bool "S3C2410 PM Suspend Memory CRC"
-       depends on ARCH_S3C2410 && PM && CRC32
-       help
-         Enable the PM code's memory area checksum over sleep. This option
-         will generate CRCs of all blocks of memory, and store them before
-         going to sleep. The blocks are then checked on resume for any
-         errors.
-
-config S3C2410_PM_CHECK_CHUNKSIZE
-       int "S3C2410 PM Suspend CRC Chunksize (KiB)"
-       depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
-       default 64
-       help
-         Set the chunksize in Kilobytes of the CRC for checking memory
-         corruption over suspend and resume. A smaller value will mean that
-         the CRC data block will take more memory, but wil identify any
-         faults with better precision.
-
-config PM_SIMTEC
-       bool
-       help
-         Common power management code for systems that are
-         compatible with the Simtec style of power management
-
-config S3C2410_LOWLEVEL_UART_PORT
-       int "S3C2410 UART to use for low-level messages"
-       default 0
-       help
-         Choice of which UART port to use for the low-level messages,
-         such as the `Uncompressing...` at start time. The value of
-         this configuration should be between zero and two. The port
-         must have been initialised by the boot-loader before use.
-
-         Note, this does not affect the port used by the debug messages,
-         which is a separate configuration.
-
-endif
index 27663e28cc8881bd49aefd1a59fba40b3b337862..9a3d3d24c08446621523649b89273e8564cb577d 100644 (file)
@@ -1,92 +1,31 @@
-
+# arch/arm/mach-s3c2410/Makefile
 #
-# Makefile for the linux kernel.
+# Copyright 2007 Simtec Electronics
 #
+# Licensed under GPLv2
 
-# Object file lists.
-
-obj-y                  := cpu.o irq.o time.o gpio.o clock.o devs.o
-obj-m                  :=
-obj-n                  :=
-obj-                   :=
-obj-dma-y              :=
-obj-dma-n              :=
-
-# DMA
-obj-$(CONFIG_S3C2410_DMA)      += dma.o
-
-# S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400)      += s3c2400-gpio.o
-
-# S3C2410 support files
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
 
 obj-$(CONFIG_CPU_S3C2410)      += s3c2410.o
-obj-$(CONFIG_CPU_S3C2410)      += s3c2410-gpio.o
-obj-$(CONFIG_CPU_S3C2410)      += s3c2410-irq.o
-
-obj-$(CONFIG_S3C2410_PM)       += s3c2410-pm.o s3c2410-sleep.o
-obj-$(CONFIG_CPU_S3C2410_DMA)  += s3c2410-dma.o
-
-# Power Management support
-
-obj-$(CONFIG_PM)               += pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC)                += pm-simtec.o
-obj-$(CONFIG_PM_H1940)         += pm-h1940.o
-
-# S3C2412 support
-obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o
-obj-$(CONFIG_CPU_S3C2412)      += s3c2412-irq.o
-obj-$(CONFIG_CPU_S3C2412)      += s3c2412-clock.o
-obj-dma-$(CONFIG_CPU_S3C2412)  += s3c2412-dma.o
-
-obj-$(CONFIG_S3C2412_PM)       += s3c2412-pm.o
-
-#
-# S3C244X support
-
-obj-$(CONFIG_CPU_S3C244X)      += s3c244x.o
-obj-$(CONFIG_CPU_S3C244X)      += s3c244x-irq.o
-
-# Clock control
-
-obj-$(CONFIG_S3C2410_CLOCK)    += s3c2410-clock.o
-
-# S3C2440 support
-
-obj-$(CONFIG_CPU_S3C2440)      += s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440)      += s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440)      += s3c2440-clock.o
-obj-$(CONFIG_CPU_S3C2440)      += s3c2410-gpio.o
-obj-dma-$(CONFIG_CPU_S3C2440)  += s3c2440-dma.o
+obj-$(CONFIG_CPU_S3C2410)      += irq.o
+obj-$(CONFIG_CPU_S3C2410_DMA)  += dma.o
+obj-$(CONFIG_CPU_S3C2410_DMA)  += dma.o
+obj-$(CONFIG_S3C2410_PM)       += pm.o sleep.o
+obj-$(CONFIG_S3C2410_GPIO)     += gpio.o
+obj-$(CONFIG_S3C2410_CLOCK)    += clock.o
 
-# S3C2442 support
+# Machine support
 
-obj-$(CONFIG_CPU_S3C2442)      += s3c2442.o
-obj-$(CONFIG_CPU_S3C2442)      += s3c2442-clock.o
-
-# bast extras
-
-obj-$(CONFIG_BAST_PC104_IRQ)   += bast-irq.o
-
-# merge in dma objects
-
-obj-y                          += $(obj-dma-y)
-
-# machine specific support
-
-obj-$(CONFIG_MACH_AML_M5900)   += mach-amlm5900.o
-obj-$(CONFIG_MACH_ANUBIS)      += mach-anubis.o
-obj-$(CONFIG_MACH_OSIRIS)      += mach-osiris.o
-obj-$(CONFIG_ARCH_BAST)                += mach-bast.o usb-simtec.o
+obj-$(CONFIG_ARCH_SMDK2410)    += mach-smdk2410.o
 obj-$(CONFIG_ARCH_H1940)       += mach-h1940.o
+obj-$(CONFIG_PM_H1940)         += pm-h1940.o
 obj-$(CONFIG_MACH_N30)         += mach-n30.o
-obj-$(CONFIG_ARCH_SMDK2410)    += mach-smdk2410.o
-obj-$(CONFIG_MACH_SMDK2413)    += mach-smdk2413.o
-obj-$(CONFIG_ARCH_S3C2440)     += mach-smdk2440.o
-obj-$(CONFIG_MACH_VR1000)      += mach-vr1000.o usb-simtec.o
-obj-$(CONFIG_MACH_RX3715)      += mach-rx3715.o
+obj-$(CONFIG_ARCH_BAST)                += mach-bast.o usb-simtec.o
 obj-$(CONFIG_MACH_OTOM)                += mach-otom.o
-obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
-obj-$(CONFIG_MACH_VSTMS)       += mach-vstms.o
-
-obj-$(CONFIG_MACH_SMDK)                += common-smdk.o
\ No newline at end of file
+obj-$(CONFIG_MACH_AML_M5900)   += mach-amlm5900.o
+obj-$(CONFIG_BAST_PC104_IRQ)   += bast-irq.o
+obj-$(CONFIG_MACH_VR1000)      += mach-vr1000.o usb-simtec.o
+obj-$(CONFIG_MACH_QT2410)      += mach-qt2410.o
index 379efe70778c6841d4b407d16b3a33c5f66070b5..daeba427d781bf9868396db7811941101e163c82 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
 
-#include "irq.h"
+#include <asm/plat-s3c24xx/irq.h>
 
 #if 0
 #include <asm/debug-ll.h>
index e5d03311752c06b4965c0c123112769f0b5ea1f4..e98543742eb936ae17da100530d63bf510999b5b 100644 (file)
@@ -1,2 +1,2 @@
-
+/* linux/arch/arm/mach-s3c2410/bast.h
 extern void bast_init_irq(void);
index e13fb6778890d6559f2a57e532cf16f4cf13dd38..5b4831c4c1d8dccb556c35a6502c92b238933672 100644 (file)
@@ -1,15 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/clock.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- **  Copyright (C) 2004 ARM Limited.
- **  Written by Deep Blue Solutions Limited.
- *
+ * S3C2410,S3C2440,S3C2442 Clock control support
  *
  * 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
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
 #include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
 
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 
+#include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "clock.h"
-#include "cpu.h"
-
-/* clock information */
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-static LIST_HEAD(clocks);
-
-DEFINE_MUTEX(clocks_mutex);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
 {
-       return 0;
-}
-
-/* Clock API calls */
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
 
-struct clk *clk_get(struct device *dev, const char *id)
-{
-       struct clk *p;
-       struct clk *clk = ERR_PTR(-ENOENT);
-       int idno;
+       clkcon = __raw_readl(S3C2410_CLKCON);
 
-       if (dev == NULL || dev->bus != &platform_bus_type)
-               idno = -1;
+       if (enable)
+               clkcon |= clocks;
        else
-               idno = to_platform_device(dev)->id;
-
-       mutex_lock(&clocks_mutex);
-
-       list_for_each_entry(p, &clocks, list) {
-               if (p->id == idno &&
-                   strcmp(id, p->name) == 0 &&
-                   try_module_get(p->owner)) {
-                       clk = p;
-                       break;
-               }
-       }
-
-       /* check for the case where a device was supplied, but the
-        * clock that was being searched for is not device specific */
-
-       if (IS_ERR(clk)) {
-               list_for_each_entry(p, &clocks, list) {
-                       if (p->id == -1 && strcmp(id, p->name) == 0 &&
-                           try_module_get(p->owner)) {
-                               clk = p;
-                               break;
-                       }
-               }
-       }
+               clkcon &= ~clocks;
 
-       mutex_unlock(&clocks_mutex);
-       return clk;
-}
+       /* ensure none of the special function bits set */
+       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
 
-void clk_put(struct clk *clk)
-{
-       module_put(clk->owner);
-}
+       __raw_writel(clkcon, S3C2410_CLKCON);
 
-int clk_enable(struct clk *clk)
-{
-       if (IS_ERR(clk) || clk == NULL)
-               return -EINVAL;
-
-       clk_enable(clk->parent);
-
-       mutex_lock(&clocks_mutex);
-
-       if ((clk->usage++) == 0)
-               (clk->enable)(clk, 1);
-
-       mutex_unlock(&clocks_mutex);
        return 0;
 }
 
-void clk_disable(struct clk *clk)
-{
-       if (IS_ERR(clk) || clk == NULL)
-               return;
-
-       mutex_lock(&clocks_mutex);
-
-       if ((--clk->usage) == 0)
-               (clk->enable)(clk, 0);
-
-       mutex_unlock(&clocks_mutex);
-       clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       if (IS_ERR(clk))
-               return 0;
-
-       if (clk->rate != 0)
-               return clk->rate;
-
-       if (clk->get_rate != NULL)
-               return (clk->get_rate)(clk);
-
-       if (clk->parent != NULL)
-               return clk_get_rate(clk->parent);
-
-       return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       if (!IS_ERR(clk) && clk->round_rate)
-               return (clk->round_rate)(clk, rate);
-
-       return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       int ret;
-
-       if (IS_ERR(clk))
-               return -EINVAL;
-
-       mutex_lock(&clocks_mutex);
-       ret = (clk->set_rate)(clk, rate);
-       mutex_unlock(&clocks_mutex);
-
-       return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
+static int s3c2410_upll_enable(struct clk *clk, int enable)
 {
-       return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       int ret = 0;
-
-       if (IS_ERR(clk))
-               return -EINVAL;
-
-       mutex_lock(&clocks_mutex);
-
-       if (clk->set_parent)
-               ret = (clk->set_parent)(clk, parent);
-
-       mutex_unlock(&clocks_mutex);
-
-       return ret;
-}
-
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-struct clk clk_xtal = {
-       .name           = "xtal",
-       .id             = -1,
-       .rate           = 0,
-       .parent         = NULL,
-       .ctrlbit        = 0,
-};
-
-struct clk clk_mpll = {
-       .name           = "mpll",
-       .id             = -1,
-};
-
-struct clk clk_upll = {
-       .name           = "upll",
-       .id             = -1,
-       .parent         = NULL,
-       .ctrlbit        = 0,
-};
-
-struct clk clk_f = {
-       .name           = "fclk",
-       .id             = -1,
-       .rate           = 0,
-       .parent         = &clk_mpll,
-       .ctrlbit        = 0,
-};
-
-struct clk clk_h = {
-       .name           = "hclk",
-       .id             = -1,
-       .rate           = 0,
-       .parent         = NULL,
-       .ctrlbit        = 0,
-};
-
-struct clk clk_p = {
-       .name           = "pclk",
-       .id             = -1,
-       .rate           = 0,
-       .parent         = NULL,
-       .ctrlbit        = 0,
-};
-
-struct clk clk_usb_bus = {
-       .name           = "usb-bus",
-       .id             = -1,
-       .rate           = 0,
-       .parent         = &clk_upll,
-};
-
-/* clocks that could be registered by external code */
-
-static int s3c24xx_dclk_enable(struct clk *clk, int enable)
-{
-       unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long orig = clkslow;
 
        if (enable)
-               dclkcon |= clk->ctrlbit;
+               clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
        else
-               dclkcon &= ~clk->ctrlbit;
+               clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
 
-       __raw_writel(dclkcon, S3C24XX_DCLKCON);
+       __raw_writel(clkslow, S3C2410_CLKSLOW);
 
-       return 0;
-}
+       /* if we started the UPLL, then allow to settle */
 
-static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
-{
-       unsigned long dclkcon;
-       unsigned int uclk;
-
-       if (parent == &clk_upll)
-               uclk = 1;
-       else if (parent == &clk_p)
-               uclk = 0;
-       else
-               return -EINVAL;
-
-       clk->parent = parent;
-
-       dclkcon = __raw_readl(S3C24XX_DCLKCON);
-
-       if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
-               if (uclk)
-                       dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
-               else
-                       dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
-       } else {
-               if (uclk)
-                       dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
-               else
-                       dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
-       }
-
-       __raw_writel(dclkcon, S3C24XX_DCLKCON);
+       if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+               udelay(200);
 
        return 0;
 }
 
-
-static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
-{
-       unsigned long mask;
-       unsigned long source;
-
-       /* calculate the MISCCR setting for the clock */
-
-       if (parent == &clk_xtal)
-               source = S3C2410_MISCCR_CLK0_MPLL;
-       else if (parent == &clk_upll)
-               source = S3C2410_MISCCR_CLK0_UPLL;
-       else if (parent == &clk_f)
-               source = S3C2410_MISCCR_CLK0_FCLK;
-       else if (parent == &clk_h)
-               source = S3C2410_MISCCR_CLK0_HCLK;
-       else if (parent == &clk_p)
-               source = S3C2410_MISCCR_CLK0_PCLK;
-       else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
-               source = S3C2410_MISCCR_CLK0_DCLK0;
-       else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
-               source = S3C2410_MISCCR_CLK0_DCLK0;
-       else
-               return -EINVAL;
-
-       clk->parent = parent;
-
-       if (clk == &s3c24xx_dclk0)
-               mask = S3C2410_MISCCR_CLK0_MASK;
-       else {
-               source <<= 4;
-               mask = S3C2410_MISCCR_CLK1_MASK;
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_NAND,
+       }, {
+               .name           = "sdi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_SDI,
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_ADC,
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_IIC,
+       }, {
+               .name           = "iis",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_IIS,
+       }, {
+               .name           = "spi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_SPI,
        }
-
-       s3c2410_modify_misccr(mask, source);
-       return 0;
-}
-
-/* external clock definitions */
-
-struct clk s3c24xx_dclk0 = {
-       .name           = "dclk0",
-       .id             = -1,
-       .ctrlbit        = S3C2410_DCLKCON_DCLK0EN,
-       .enable         = s3c24xx_dclk_enable,
-       .set_parent     = s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_dclk1 = {
-       .name           = "dclk1",
-       .id             = -1,
-       .ctrlbit        = S3C2410_DCLKCON_DCLK0EN,
-       .enable         = s3c24xx_dclk_enable,
-       .set_parent     = s3c24xx_dclk_setparent,
 };
 
-struct clk s3c24xx_clkout0 = {
-       .name           = "clkout0",
-       .id             = -1,
-       .set_parent     = s3c24xx_clkout_setparent,
+static struct clk init_clocks[] = {
+       {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_LCDC,
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_GPIO,
+       }, {
+               .name           = "usb-host",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_USBH,
+       }, {
+               .name           = "usb-device",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_USBD,
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_PWMT,
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART0,
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART1,
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART2,
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_RTC,
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = 0,
+       }, {
+               .name           = "usb-bus-host",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+       }, {
+               .name           = "usb-bus-gadget",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+       },
 };
 
-struct clk s3c24xx_clkout1 = {
-       .name           = "clkout1",
-       .id             = -1,
-       .set_parent     = s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_uclk = {
-       .name           = "uclk",
-       .id             = -1,
-};
-
-/* initialise the clock system */
-
-int s3c24xx_register_clock(struct clk *clk)
-{
-       clk->owner = THIS_MODULE;
-
-       if (clk->enable == NULL)
-               clk->enable = clk_null_enable;
-
-       /* add to the list of available clocks */
-
-       mutex_lock(&clocks_mutex);
-       list_add(&clk->list, &clocks);
-       mutex_unlock(&clocks_mutex);
-
-       return 0;
-}
-
-/* initalise all the clocks */
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
 
-int __init s3c24xx_setup_clocks(unsigned long xtal,
-                               unsigned long fclk,
-                               unsigned long hclk,
-                               unsigned long pclk)
+int __init s3c2410_baseclk_add(void)
 {
-       printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+       struct clk *clkp;
+       struct clk *xtal;
+       int ret;
+       int ptr;
 
-       /* initialise the main system clocks */
+       clk_upll.enable = s3c2410_upll_enable;
 
-       clk_xtal.rate = xtal;
-       clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+       if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+               printk(KERN_ERR "failed to register usb bus clock\n");
 
-       clk_mpll.rate = fclk;
-       clk_h.rate = hclk;
-       clk_p.rate = pclk;
-       clk_f.rate = fclk;
+       /* register clocks from clock array */
 
-       /* assume uart clocks are correctly setup */
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               /* ensure that we note the clock state */
 
-       /* register our clocks */
+               clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
 
-       if (s3c24xx_register_clock(&clk_xtal) < 0)
-               printk(KERN_ERR "failed to register master xtal\n");
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
 
-       if (s3c24xx_register_clock(&clk_mpll) < 0)
-               printk(KERN_ERR "failed to register mpll clock\n");
+       /* We must be careful disabling the clocks we are not intending to
+        * be using at boot time, as subsytems such as the LCD which do
+        * their own DMA requests to the bus can cause the system to lockup
+        * if they where in the middle of requesting bus access.
+        *
+        * Disabling the LCD clock if the LCD is active is very dangerous,
+        * and therefore the bootloader should be careful to not enable
+        * the LCD clock if it is not needed.
+       */
+
+       /* install (and disable) the clocks we do not need immediately */
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
 
-       if (s3c24xx_register_clock(&clk_upll) < 0)
-               printk(KERN_ERR "failed to register upll clock\n");
+               s3c2410_clkcon_enable(clkp, 0);
+       }
 
-       if (s3c24xx_register_clock(&clk_f) < 0)
-               printk(KERN_ERR "failed to register cpu fclk\n");
+       /* show the clock-slow value */
 
-       if (s3c24xx_register_clock(&clk_h) < 0)
-               printk(KERN_ERR "failed to register cpu hclk\n");
+       xtal = clk_get(NULL, "xtal");
 
-       if (s3c24xx_register_clock(&clk_p) < 0)
-               printk(KERN_ERR "failed to register cpu pclk\n");
+       printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+              print_mhz(clk_get_rate(xtal) /
+                        ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+              (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+              (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+              (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
 
        return 0;
 }
index fa860e716b4ff74e5af753a81ae3a2c8152b3e30..67d1ad36397344715a1c085a0abe0ce9b82632ea 100644 (file)
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/dma.c
  *
- * Copyright (c) 2003-2005,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 DMA core
+ * S3C2410 DMA selection
  *
  * http://armlinux.simtec.co.uk/
  *
  * published by the Free Software Foundation.
 */
 
-
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
 #include <linux/sysdev.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/serial_core.h>
 
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
 #include <asm/dma.h>
-
-#include <asm/mach/dma.h>
-#include <asm/arch/map.h>
-
-#include "dma.h"
-
-/* io map for dma */
-static void __iomem *dma_base;
-static struct kmem_cache *dma_kmem;
-
-struct s3c24xx_dma_selection dma_sel;
-
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-/* debugging functions */
-
-#define BUF_MAGIC (0xcafebabe)
-
-#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
-
-#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
-
-#if 1
-#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
-#else
-static inline void
-dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
-{
-       pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
-       writel(val, dma_regaddr(chan, reg));
-}
-#endif
-
-#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
-
-/* captured register state for debug */
-
-struct s3c2410_dma_regstate {
-       unsigned long         dcsrc;
-       unsigned long         disrc;
-       unsigned long         dstat;
-       unsigned long         dcon;
-       unsigned long         dmsktrig;
+#include <asm/arch/dma.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/dma.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+       [DMACH_XD0] = {
+               .name           = "xdreq0",
+               .channels[0]    = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+       },
+       [DMACH_XD1] = {
+               .name           = "xdreq1",
+               .channels[1]    = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+       },
+       [DMACH_SDI] = {
+               .name           = "sdi",
+               .channels[0]    = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_SPI0] = {
+               .name           = "spi0",
+               .channels[1]    = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
+       },
+       [DMACH_SPI1] = {
+               .name           = "spi1",
+               .channels[3]    = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+       },
+       [DMACH_UART0] = {
+               .name           = "uart0",
+               .channels[0]    = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1] = {
+               .name           = "uart1",
+               .channels[1]    = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2] = {
+               .name           = "uart2",
+               .channels[3]    = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_TIMER] = {
+               .name           = "timer",
+               .channels[0]    = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+       },
+       [DMACH_I2S_IN] = {
+               .name           = "i2s-sdi",
+               .channels[1]    = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_I2S_OUT] = {
+               .name           = "i2s-sdo",
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_USB_EP1] = {
+               .name           = "usb-ep1",
+               .channels[0]    = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP2] = {
+               .name           = "usb-ep2",
+               .channels[1]    = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP3] = {
+               .name           = "usb-ep3",
+               .channels[2]    = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP4] = {
+               .name           = "usb-ep4",
+               .channels[3]    =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+       },
 };
 
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-
-/* dmadbg_showregs
- *
- * simple debug routine to print the current state of the dma registers
-*/
-
-static void
-dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
-{
-       regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-       regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
-       regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
-       regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
-       regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-}
-
-static void
-dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
-                struct s3c2410_dma_regstate *regs)
-{
-       printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
-              chan->number, fname, line,
-              regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
-              regs->dcon);
-}
-
-static void
-dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-       struct s3c2410_dma_regstate state;
-
-       dmadbg_capture(chan, &state);
-
-       printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
-              chan->number, fname, line, chan->load_state,
-              chan->curr, chan->next, chan->end);
-
-       dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-static void
-dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-       struct s3c2410_dma_regstate state;
-
-       dmadbg_capture(chan, &state);
-       dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
-#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
-#else
-#define dbg_showregs(chan) do { } while(0)
-#define dbg_showchan(chan) do { } while(0)
-#endif /* CONFIG_S3C2410_DMA_DEBUG */
-
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
-
-/* lookup_dma_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
-{
-       if (channel & DMACH_LOW_LEVEL)
-               return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
-       else
-               return dma_chan_map[channel];
-}
-
-/* s3c2410_dma_stats_timeout
- *
- * Update DMA stats from timeout info
-*/
-
-static void
-s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
 {
-       if (stats == NULL)
-               return;
-
-       if (val > stats->timeout_longest)
-               stats->timeout_longest = val;
-       if (val < stats->timeout_shortest)
-               stats->timeout_shortest = val;
-
-       stats->timeout_avg += val;
+       chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
 }
 
-/* s3c2410_dma_waitforload
- *
- * wait for the DMA engine to load a buffer, and update the state accordingly
-*/
-
-static int
-s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
-{
-       int timeout = chan->load_timeout;
-       int took;
-
-       if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
-               printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
-               return 0;
-       }
-
-       if (chan->stats != NULL)
-               chan->stats->loads++;
-
-       while (--timeout > 0) {
-               if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
-                       took = chan->load_timeout - timeout;
-
-                       s3c2410_dma_stats_timeout(chan->stats, took);
-
-                       switch (chan->load_state) {
-                       case S3C2410_DMALOAD_1LOADED:
-                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
-                               break;
-
-                       default:
-                               printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
-                       }
-
-                       return 1;
-               }
-       }
-
-       if (chan->stats != NULL) {
-               chan->stats->timeout_failed++;
-       }
-
-       return 0;
-}
-
-
-
-/* s3c2410_dma_loadbuffer
- *
- * load a buffer, and update the channel state
-*/
-
-static inline int
-s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
-                      struct s3c2410_dma_buf *buf)
-{
-       unsigned long reload;
-
-       pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
-                buf, (unsigned long)buf->data, buf->size);
-
-       if (buf == NULL) {
-               dmawarn("buffer is NULL\n");
-               return -EINVAL;
-       }
-
-       /* check the state of the channel before we do anything */
-
-       if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-               dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
-       }
-
-       if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
-               dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
-       }
-
-       /* it would seem sensible if we are the last buffer to not bother
-        * with the auto-reload bit, so that the DMA engine will not try
-        * and load another transfer after this one has finished...
-        */
-       if (chan->load_state == S3C2410_DMALOAD_NONE) {
-               pr_debug("load_state is none, checking for noreload (next=%p)\n",
-                        buf->next);
-               reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
-       } else {
-               //pr_debug("load_state is %d => autoreload\n", chan->load_state);
-               reload = S3C2410_DCON_AUTORELOAD;
-       }
-
-       if ((buf->data & 0xf0000000) != 0x30000000) {
-               dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
-       }
-
-       writel(buf->data, chan->addr_reg);
-
-       dma_wrreg(chan, S3C2410_DMA_DCON,
-                 chan->dcon | reload | (buf->size/chan->xfer_unit));
-
-       chan->next = buf->next;
-
-       /* update the state of the channel */
-
-       switch (chan->load_state) {
-       case S3C2410_DMALOAD_NONE:
-               chan->load_state = S3C2410_DMALOAD_1LOADED;
-               break;
-
-       case S3C2410_DMALOAD_1RUNNING:
-               chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
-               break;
-
-       default:
-               dmawarn("dmaload: unknown state %d in loadbuffer\n",
-                       chan->load_state);
-               break;
-       }
-
-       return 0;
-}
-
-/* s3c2410_dma_call_op
- *
- * small routine to call the op routine with the given op if it has been
- * registered
-*/
-
-static void
-s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
-{
-       if (chan->op_fn != NULL) {
-               (chan->op_fn)(chan, op);
-       }
-}
-
-/* s3c2410_dma_buffdone
- *
- * small wrapper to check if callback routine needs to be called, and
- * if so, call it
-*/
-
-static inline void
-s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
-                    enum s3c2410_dma_buffresult result)
-{
-#if 0
-       pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
-                chan->callback_fn, buf, buf->id, buf->size, result);
-#endif
-
-       if (chan->callback_fn != NULL) {
-               (chan->callback_fn)(chan, buf->id, buf->size, result);
-       }
-}
-
-/* s3c2410_dma_start
- *
- * start a dma channel going
-*/
-
-static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
-{
-       unsigned long tmp;
-       unsigned long flags;
-
-       pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
-
-       local_irq_save(flags);
-
-       if (chan->state == S3C2410_DMA_RUNNING) {
-               pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
-               local_irq_restore(flags);
-               return 0;
-       }
-
-       chan->state = S3C2410_DMA_RUNNING;
-
-       /* check wether there is anything to load, and if not, see
-        * if we can find anything to load
-        */
-
-       if (chan->load_state == S3C2410_DMALOAD_NONE) {
-               if (chan->next == NULL) {
-                       printk(KERN_ERR "dma%d: channel has nothing loaded\n",
-                              chan->number);
-                       chan->state = S3C2410_DMA_IDLE;
-                       local_irq_restore(flags);
-                       return -EINVAL;
-               }
-
-               s3c2410_dma_loadbuffer(chan, chan->next);
-       }
-
-       dbg_showchan(chan);
-
-       /* enable the channel */
-
-       if (!chan->irq_enabled) {
-               enable_irq(chan->irq);
-               chan->irq_enabled = 1;
-       }
-
-       /* start the channel going */
-
-       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-       tmp &= ~S3C2410_DMASKTRIG_STOP;
-       tmp |= S3C2410_DMASKTRIG_ON;
-       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-       pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
-
-#if 0
-       /* the dma buffer loads should take care of clearing the AUTO
-        * reloading feature */
-       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-       tmp &= ~S3C2410_DCON_NORELOAD;
-       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-       s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
-
-       dbg_showchan(chan);
-
-       /* if we've only loaded one buffer onto the channel, then chec
-        * to see if we have another, and if so, try and load it so when
-        * the first buffer is finished, the new one will be loaded onto
-        * the channel */
-
-       if (chan->next != NULL) {
-               if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-                               pr_debug("%s: buff not yet loaded, no more todo\n",
-                                        __FUNCTION__);
-                       } else {
-                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
-                               s3c2410_dma_loadbuffer(chan, chan->next);
-                       }
-
-               } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-                       s3c2410_dma_loadbuffer(chan, chan->next);
-               }
-       }
-
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-/* s3c2410_dma_canload
- *
- * work out if we can queue another buffer into the DMA engine
-*/
-
-static int
-s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
-{
-       if (chan->load_state == S3C2410_DMALOAD_NONE ||
-           chan->load_state == S3C2410_DMALOAD_1RUNNING)
-               return 1;
-
-       return 0;
-}
-
-/* s3c2410_dma_enqueue
- *
- * queue an given buffer for dma transfer.
- *
- * id         the device driver's id information for this buffer
- * data       the physical address of the buffer data
- * size       the size of the buffer in bytes
- *
- * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
- * is checked, and if set, the channel is started. If this flag isn't set,
- * then an error will be returned.
- *
- * It is possible to queue more than one DMA buffer onto a channel at
- * once, and the code will deal with the re-loading of the next buffer
- * when necessary.
-*/
-
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
-                       dma_addr_t data, int size)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-       struct s3c2410_dma_buf *buf;
-       unsigned long flags;
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: id=%p, data=%08x, size=%d\n",
-                __FUNCTION__, id, (unsigned int)data, size);
-
-       buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
-       if (buf == NULL) {
-               pr_debug("%s: out of memory (%ld alloc)\n",
-                        __FUNCTION__, (long)sizeof(*buf));
-               return -ENOMEM;
-       }
-
-       //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
-       //dbg_showchan(chan);
-
-       buf->next  = NULL;
-       buf->data  = buf->ptr = data;
-       buf->size  = size;
-       buf->id    = id;
-       buf->magic = BUF_MAGIC;
-
-       local_irq_save(flags);
-
-       if (chan->curr == NULL) {
-               /* we've got nothing loaded... */
-               pr_debug("%s: buffer %p queued onto empty channel\n",
-                        __FUNCTION__, buf);
-
-               chan->curr = buf;
-               chan->end  = buf;
-               chan->next = NULL;
-       } else {
-               pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
-                        chan->number, __FUNCTION__, buf);
-
-               if (chan->end == NULL)
-                       pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
-                                chan->number, __FUNCTION__, chan);
-
-               chan->end->next = buf;
-               chan->end = buf;
-       }
-
-       /* if necessary, update the next buffer field */
-       if (chan->next == NULL)
-               chan->next = buf;
-
-       /* check to see if we can load a buffer */
-       if (chan->state == S3C2410_DMA_RUNNING) {
-               if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
-                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-                               printk(KERN_ERR "dma%d: loadbuffer:"
-                                      "timeout loading buffer\n",
-                                      chan->number);
-                               dbg_showchan(chan);
-                               local_irq_restore(flags);
-                               return -EINVAL;
-                       }
-               }
-
-               while (s3c2410_dma_canload(chan) && chan->next != NULL) {
-                       s3c2410_dma_loadbuffer(chan, chan->next);
-               }
-       } else if (chan->state == S3C2410_DMA_IDLE) {
-               if (chan->flags & S3C2410_DMAF_AUTOSTART) {
-                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
-               }
-       }
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-static inline void
-s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
-{
-       int magicok = (buf->magic == BUF_MAGIC);
-
-       buf->magic = -1;
-
-       if (magicok) {
-               kmem_cache_free(dma_kmem, buf);
-       } else {
-               printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
-       }
-}
-
-/* s3c2410_dma_lastxfer
- *
- * called when the system is out of buffers, to ensure that the channel
- * is prepared for shutdown.
-*/
-
-static inline void
-s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
-{
-#if 0
-       pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
-                chan->number, chan->load_state);
-#endif
-
-       switch (chan->load_state) {
-       case S3C2410_DMALOAD_NONE:
-               break;
-
-       case S3C2410_DMALOAD_1LOADED:
-               if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-                               /* flag error? */
-                       printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-                              chan->number, __FUNCTION__);
-                       return;
-               }
-               break;
-
-       case S3C2410_DMALOAD_1LOADED_1RUNNING:
-               /* I belive in this case we do not have anything to do
-                * until the next buffer comes along, and we turn off the
-                * reload */
-               return;
-
-       default:
-               pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
-                        chan->number, chan->load_state);
-               return;
-
-       }
-
-       /* hopefully this'll shut the damned thing up after the transfer... */
-       dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
-}
-
-
-#define dmadbg2(x...)
-
-static irqreturn_t
-s3c2410_dma_irq(int irq, void *devpw)
-{
-       struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
-       struct s3c2410_dma_buf  *buf;
-
-       buf = chan->curr;
-
-       dbg_showchan(chan);
-
-       /* modify the channel state */
-
-       switch (chan->load_state) {
-       case S3C2410_DMALOAD_1RUNNING:
-               /* TODO - if we are running only one buffer, we probably
-                * want to reload here, and then worry about the buffer
-                * callback */
-
-               chan->load_state = S3C2410_DMALOAD_NONE;
-               break;
-
-       case S3C2410_DMALOAD_1LOADED:
-               /* iirc, we should go back to NONE loaded here, we
-                * had a buffer, and it was never verified as being
-                * loaded.
-                */
-
-               chan->load_state = S3C2410_DMALOAD_NONE;
-               break;
-
-       case S3C2410_DMALOAD_1LOADED_1RUNNING:
-               /* we'll worry about checking to see if another buffer is
-                * ready after we've called back the owner. This should
-                * ensure we do not wait around too long for the DMA
-                * engine to start the next transfer
-                */
-
-               chan->load_state = S3C2410_DMALOAD_1LOADED;
-               break;
-
-       case S3C2410_DMALOAD_NONE:
-               printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
-                      chan->number);
-               break;
-
-       default:
-               printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
-                      chan->number, chan->load_state);
-               break;
-       }
-
-       if (buf != NULL) {
-               /* update the chain to make sure that if we load any more
-                * buffers when we call the callback function, things should
-                * work properly */
-
-               chan->curr = buf->next;
-               buf->next  = NULL;
-
-               if (buf->magic != BUF_MAGIC) {
-                       printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
-                              chan->number, __FUNCTION__, buf);
-                       return IRQ_HANDLED;
-               }
-
-               s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
-
-               /* free resouces */
-               s3c2410_dma_freebuf(buf);
-       } else {
-       }
-
-       /* only reload if the channel is still running... our buffer done
-        * routine may have altered the state by requesting the dma channel
-        * to stop or shutdown... */
-
-       /* todo: check that when the channel is shut-down from inside this
-        * function, we cope with unsetting reload, etc */
-
-       if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
-               unsigned long flags;
-
-               switch (chan->load_state) {
-               case S3C2410_DMALOAD_1RUNNING:
-                       /* don't need to do anything for this state */
-                       break;
-
-               case S3C2410_DMALOAD_NONE:
-                       /* can load buffer immediately */
-                       break;
-
-               case S3C2410_DMALOAD_1LOADED:
-                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-                               /* flag error? */
-                               printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-                                      chan->number, __FUNCTION__);
-                               return IRQ_HANDLED;
-                       }
-
-                       break;
-
-               case S3C2410_DMALOAD_1LOADED_1RUNNING:
-                       goto no_load;
-
-               default:
-                       printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
-                              chan->number, chan->load_state);
-                       return IRQ_HANDLED;
-               }
-
-               local_irq_save(flags);
-               s3c2410_dma_loadbuffer(chan, chan->next);
-               local_irq_restore(flags);
-       } else {
-               s3c2410_dma_lastxfer(chan);
-
-               /* see if we can stop this channel.. */
-               if (chan->load_state == S3C2410_DMALOAD_NONE) {
-                       pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
-                                chan->number, jiffies);
-                       s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
-                                        S3C2410_DMAOP_STOP);
-               }
-       }
-
- no_load:
-       return IRQ_HANDLED;
-}
-
-static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(unsigned int channel,
-                       struct s3c2410_dma_client *client,
-                       void *dev)
-{
-       struct s3c2410_dma_chan *chan;
-       unsigned long flags;
-       int err;
-
-       pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-                channel, client->name, dev);
-
-       local_irq_save(flags);
-
-       chan = s3c2410_dma_map_channel(channel);
-       if (chan == NULL) {
-               local_irq_restore(flags);
-               return -EBUSY;
-       }
-
-       dbg_showchan(chan);
-
-       chan->client = client;
-       chan->in_use = 1;
-
-       if (!chan->irq_claimed) {
-               pr_debug("dma%d: %s : requesting irq %d\n",
-                        channel, __FUNCTION__, chan->irq);
-
-               chan->irq_claimed = 1;
-               local_irq_restore(flags);
-
-               err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
-                                 client->name, (void *)chan);
-
-               local_irq_save(flags);
-
-               if (err) {
-                       chan->in_use = 0;
-                       chan->irq_claimed = 0;
-                       local_irq_restore(flags);
-
-                       printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
-                              client->name, chan->irq, chan->number);
-                       return err;
-               }
-
-               chan->irq_enabled = 1;
-       }
-
-       local_irq_restore(flags);
-
-       /* need to setup */
-
-       pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+       .select         = s3c2410_dma_select,
+       .dcon_mask      = 7 << 24,
+       .map            = s3c2410_dma_mappings,
+       .map_size       = ARRAY_SIZE(s3c2410_dma_mappings),
+};
 
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
+static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
+       .channels       = {
+               [DMACH_SDI]     = {
+                       .list   = {
+                               [0]     = 3 | DMA_CH_VALID,
+                               [1]     = 2 | DMA_CH_VALID,
+                               [2]     = 0 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_I2S_IN]  = {
+                       .list   = {
+                               [0]     = 1 | DMA_CH_VALID,
+                               [1]     = 2 | DMA_CH_VALID,
+                       },
+               },
+       },
+};
 
-int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+static int s3c2410_dma_add(struct sys_device *sysdev)
 {
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-       unsigned long flags;
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       local_irq_save(flags);
-
-       if (chan->client != client) {
-               printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-                      channel, chan->client, client);
-       }
-
-       /* sort out stopping and freeing the channel */
-
-       if (chan->state != S3C2410_DMA_IDLE) {
-               pr_debug("%s: need to stop dma channel %p\n",
-                      __FUNCTION__, chan);
-
-               /* possibly flush the channel */
-               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
-       }
-
-       chan->client = NULL;
-       chan->in_use = 0;
-
-       if (chan->irq_claimed)
-               free_irq(chan->irq, (void *)chan);
-
-       chan->irq_claimed = 0;
-
-       if (!(channel & DMACH_LOW_LEVEL))
-               dma_chan_map[channel] = NULL;
-
-       local_irq_restore(flags);
-
-       return 0;
+       s3c2410_dma_init();
+       s3c24xx_dma_order_set(&s3c2410_dma_order);
+       return s3c24xx_dma_init_map(&s3c2410_dma_sel);
 }
 
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
-{
-       unsigned long flags;
-       unsigned long tmp;
-
-       pr_debug("%s:\n", __FUNCTION__);
-
-       dbg_showchan(chan);
-
-       local_irq_save(flags);
-
-       s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
-
-       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-       tmp |= S3C2410_DMASKTRIG_STOP;
-       //tmp &= ~S3C2410_DMASKTRIG_ON;
-       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-#if 0
-       /* should also clear interrupts, according to WinCE BSP */
-       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-       tmp |= S3C2410_DCON_NORELOAD;
-       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-       /* should stop do this, or should we wait for flush? */
-       chan->state      = S3C2410_DMA_IDLE;
-       chan->load_state = S3C2410_DMALOAD_NONE;
-
-       local_irq_restore(flags);
-
-       return 0;
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_dma_driver = {
+       .add    = s3c2410_dma_add,
+};
 
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+static int __init s3c2410_dma_drvinit(void)
 {
-       unsigned long tmp;
-       unsigned int timeout = 0x10000;
-
-       while (timeout-- > 0) {
-               tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-
-               if (!(tmp & S3C2410_DMASKTRIG_ON))
-                       return;
-       }
-
-       pr_debug("dma%d: failed to stop?\n", chan->number);
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
 }
 
-
-/* s3c2410_dma_flush
- *
- * stop the channel, and remove all current and pending transfers
-*/
-
-static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
-{
-       struct s3c2410_dma_buf *buf, *next;
-       unsigned long flags;
-
-       pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
-
-       dbg_showchan(chan);
-
-       local_irq_save(flags);
-
-       if (chan->state != S3C2410_DMA_IDLE) {
-               pr_debug("%s: stopping channel...\n", __FUNCTION__ );
-               s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
-       }
-
-       buf = chan->curr;
-       if (buf == NULL)
-               buf = chan->next;
-
-       chan->curr = chan->next = chan->end = NULL;
-
-       if (buf != NULL) {
-               for ( ; buf != NULL; buf = next) {
-                       next = buf->next;
-
-                       pr_debug("%s: free buffer %p, next %p\n",
-                              __FUNCTION__, buf, buf->next);
-
-                       s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
-                       s3c2410_dma_freebuf(buf);
-               }
-       }
-
-       dbg_showregs(chan);
-
-       s3c2410_dma_waitforstop(chan);
-
-#if 0
-       /* should also clear interrupts, according to WinCE BSP */
-       {
-               unsigned long tmp;
-
-               tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-               tmp |= S3C2410_DCON_NORELOAD;
-               dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-       }
+arch_initcall(s3c2410_dma_drvinit);
 #endif
 
-       dbg_showregs(chan);
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-int
-s3c2410_dma_started(struct s3c2410_dma_chan *chan)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       dbg_showchan(chan);
-
-       /* if we've only loaded one buffer onto the channel, then chec
-        * to see if we have another, and if so, try and load it so when
-        * the first buffer is finished, the new one will be loaded onto
-        * the channel */
-
-       if (chan->next != NULL) {
-               if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-                               pr_debug("%s: buff not yet loaded, no more todo\n",
-                                        __FUNCTION__);
-                       } else {
-                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
-                               s3c2410_dma_loadbuffer(chan, chan->next);
-                       }
-
-               } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-                       s3c2410_dma_loadbuffer(chan, chan->next);
-               }
-       }
-
-
-       local_irq_restore(flags);
-
-       return 0;
-
-}
-
-int
-s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       switch (op) {
-       case S3C2410_DMAOP_START:
-               return s3c2410_dma_start(chan);
-
-       case S3C2410_DMAOP_STOP:
-               return s3c2410_dma_dostop(chan);
-
-       case S3C2410_DMAOP_PAUSE:
-       case S3C2410_DMAOP_RESUME:
-               return -ENOENT;
-
-       case S3C2410_DMAOP_FLUSH:
-               return s3c2410_dma_flush(chan);
-
-       case S3C2410_DMAOP_STARTED:
-               return s3c2410_dma_started(chan);
-
-       case S3C2410_DMAOP_TIMEOUT:
-               return 0;
-
-       }
-
-       return -ENOENT;      /* unknown, don't bother */
-}
-
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* DMA configuration for each channel
- *
- * DISRCC -> source of the DMA (AHB,APB)
- * DISRC  -> source address of the DMA
- * DIDSTC -> destination of the DMA (AHB,APD)
- * DIDST  -> destination address of the DMA
-*/
-
-/* s3c2410_dma_config
- *
- * xfersize:     size of unit in bytes (1,2,4)
- * dcon:         base value of the DCONx register
-*/
-
-int s3c2410_dma_config(dmach_t channel,
-                      int xferunit,
-                      int dcon)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
-                __FUNCTION__, channel, xferunit, dcon);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
-
-       dcon |= chan->dcon & dma_sel.dcon_mask;
-
-       pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
-
-       switch (xferunit) {
-       case 1:
-               dcon |= S3C2410_DCON_BYTE;
-               break;
-
-       case 2:
-               dcon |= S3C2410_DCON_HALFWORD;
-               break;
-
-       case 4:
-               dcon |= S3C2410_DCON_WORD;
-               break;
-
-       default:
-               pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
-               return -EINVAL;
-       }
-
-       dcon |= S3C2410_DCON_HWTRIG;
-       dcon |= S3C2410_DCON_INTREQ;
-
-       pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
-
-       chan->dcon = dcon;
-       chan->xfer_unit = xferunit;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
-
-       chan->flags = flags;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
-
-       chan->op_fn = rtn;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
-
-       chan->callback_fn = rtn;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-/* s3c2410_dma_devconfig
- *
- * configure the dma source/destination hardware type and address
- *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
- *
- * hwcfg:     the value for xxxSTCn register,
- *            bit 0: 0=increment pointer, 1=leave pointer
- *            bit 1: 0=soucre is AHB, 1=soucre is APB
- *
- * devaddr:   physical address of the source
-*/
-
-int s3c2410_dma_devconfig(int channel,
-                         enum s3c2410_dmasrc source,
-                         int hwcfg,
-                         unsigned long devaddr)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
-                __FUNCTION__, (int)source, hwcfg, devaddr);
-
-       chan->source = source;
-       chan->dev_addr = devaddr;
-
-       switch (source) {
-       case S3C2410_DMASRC_HW:
-               /* source is hardware */
-               pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
-                        __FUNCTION__, devaddr, hwcfg);
-               dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
-               dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
-               dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
-
-               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
-               return 0;
-
-       case S3C2410_DMASRC_MEM:
-               /* source is memory */
-               pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
-                         __FUNCTION__, devaddr, hwcfg);
-               dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
-               dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
-               dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
-
-               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
-               return 0;
-       }
-
-       printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
-       return -EINVAL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-/* s3c2410_dma_getposition
- *
- * returns the current transfer points for the dma source and destination
-*/
-
-int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
-{
-       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       if (src != NULL)
-               *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-
-       if (dst != NULL)
-               *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-
-/* system device class */
-
-#ifdef CONFIG_PM
-
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
-{
-       struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
-
-       printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
-
-       if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
-               /* the dma channel is still working, which is probably
-                * a bad thing to do over suspend/resume. We stop the
-                * channel and assume that the client is either going to
-                * retry after resume, or that it is broken.
-                */
-
-               printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
-                      cp->number);
-
-               s3c2410_dma_dostop(cp);
-       }
-
-       return 0;
-}
-
-static int s3c2410_dma_resume(struct sys_device *dev)
-{
-       return 0;
-}
-
-#else
-#define s3c2410_dma_suspend NULL
-#define s3c2410_dma_resume  NULL
-#endif /* CONFIG_PM */
-
-struct sysdev_class dma_sysclass = {
-       set_kset_name("s3c24xx-dma"),
-       .suspend        = s3c2410_dma_suspend,
-       .resume         = s3c2410_dma_resume,
+#if defined(CONFIG_CPU_S3C2442)
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+static struct sysdev_driver s3c2442_dma_driver = {
+       .add    = s3c2410_dma_add,
 };
 
-/* kmem cache implementation */
-
-static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
-{
-       memset(p, 0, sizeof(struct s3c2410_dma_buf));
-}
-
-/* initialisation code */
-
-static int __init s3c2410_init_dma(void)
-{
-       struct s3c2410_dma_chan *cp;
-       int channel;
-       int ret;
-
-       printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
-
-       dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
-       if (dma_base == NULL) {
-               printk(KERN_ERR "dma failed to remap register block\n");
-               return -ENOMEM;
-       }
-
-       printk("Registering sysclass\n");
-
-       ret = sysdev_class_register(&dma_sysclass);
-       if (ret != 0) {
-               printk(KERN_ERR "dma sysclass registration failed\n");
-               goto err;
-       }
-
-       dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    s3c2410_dma_cache_ctor, NULL);
-
-       if (dma_kmem == NULL) {
-               printk(KERN_ERR "dma failed to make kmem cache\n");
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
-               cp = &s3c2410_chans[channel];
-
-               memset(cp, 0, sizeof(struct s3c2410_dma_chan));
-
-               /* dma channel irqs are in order.. */
-               cp->number = channel;
-               cp->irq    = channel + IRQ_DMA0;
-               cp->regs   = dma_base + (channel*0x40);
-
-               /* point current stats somewhere */
-               cp->stats  = &cp->stats_store;
-               cp->stats_store.timeout_shortest = LONG_MAX;
-
-               /* basic channel configuration */
-
-               cp->load_timeout = 1<<18;
-
-               /* register system device */
-
-               cp->dev.cls = &dma_sysclass;
-               cp->dev.id  = channel;
-               ret = sysdev_register(&cp->dev);
-
-               printk("DMA channel %d at %p, irq %d\n",
-                      cp->number, cp->regs, cp->irq);
-       }
-
-       return 0;
-
- err:
-       kmem_cache_destroy(dma_kmem);
-       iounmap(dma_base);
-       dma_base = NULL;
-       return ret;
-}
-
-core_initcall(s3c2410_init_dma);
-
-static inline int is_channel_valid(unsigned int channel)
+static int __init s3c2442_dma_drvinit(void)
 {
-       return (channel & DMA_CH_VALID);
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
 }
 
-/* s3c2410_dma_map_channel()
- *
- * turn the virtual channel number into a real, and un-used hardware
- * channel.
- *
- * currently this code uses first-free channel from the specified harware
- * map, not taking into account anything that the board setup code may
- * have to say about the likely peripheral set to be in use.
-*/
-
-struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
-{
-       struct s3c24xx_dma_map *ch_map;
-       struct s3c2410_dma_chan *dmach;
-       int ch;
-
-       if (dma_sel.map == NULL || channel > dma_sel.map_size)
-               return NULL;
-
-       ch_map = dma_sel.map + channel;
-
-       for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
-               if (!is_channel_valid(ch_map->channels[ch]))
-                       continue;
-
-               if (s3c2410_chans[ch].in_use == 0) {
-                       printk("mapped channel %d to %d\n", channel, ch);
-                       break;
-               }
-       }
-
-       if (ch >= S3C2410_DMA_CHANNELS)
-               return NULL;
-
-       /* update our channel mapping */
-
-       dmach = &s3c2410_chans[ch];
-       dma_chan_map[channel] = dmach;
-
-       /* select the channel */
-
-       (dma_sel.select)(dmach, ch_map);
-
-       return dmach;
-}
-
-static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
-{
-       /* show the channel configuration */
-
-       printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
-              (is_channel_valid(map->channels[0]) ? '0' : '-'),
-              (is_channel_valid(map->channels[1]) ? '1' : '-'),
-              (is_channel_valid(map->channels[2]) ? '2' : '-'),
-              (is_channel_valid(map->channels[3]) ? '3' : '-'));
-}
-
-static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
-{
-       if (1)
-               s3c24xx_dma_show_ch(map, ch);
-
-       return 0;
-}
-
-int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
-{
-       struct s3c24xx_dma_map *nmap;
-       size_t map_sz = sizeof(*nmap) * sel->map_size;
-       int ptr;
-
-       nmap = kmalloc(map_sz, GFP_KERNEL);
-       if (nmap == NULL)
-               return -ENOMEM;
-
-       memcpy(nmap, sel->map, map_sz);
-       memcpy(&dma_sel, sel, sizeof(*sel));
-
-       dma_sel.map = nmap;
-
-       for (ptr = 0; ptr < sel->map_size; ptr++)
-               s3c24xx_dma_check_entry(nmap+ptr, ptr);
+arch_initcall(s3c2442_dma_drvinit);
+#endif
 
-       return 0;
-}
index f6fb215bb48c2a7d6f5dc108cc1ffe70ccd532c3..01e795d1146eec85691ff1d1f41495e94108a5bf 100644 (file)
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/gpio.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX GPIO support
+ * S3C2410 GPIO support
  *
  * 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
@@ -18,8 +18,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
+ */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/arch/regs-gpio.h>
 
-void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
-{
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long mask;
-       unsigned long con;
-       unsigned long flags;
-
-       if (pin < S3C2410_GPIO_BANKB) {
-               mask = 1 << S3C2410_GPIO_OFFSET(pin);
-       } else {
-               mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
-       }
-
-       switch (function) {
-       case S3C2410_GPIO_LEAVE:
-               mask = 0;
-               function = 0;
-               break;
-
-       case S3C2410_GPIO_INPUT:
-       case S3C2410_GPIO_OUTPUT:
-       case S3C2410_GPIO_SFN2:
-       case S3C2410_GPIO_SFN3:
-               if (pin < S3C2410_GPIO_BANKB) {
-                       function -= 1;
-                       function &= 1;
-                       function <<= S3C2410_GPIO_OFFSET(pin);
-               } else {
-                       function &= 3;
-                       function <<= S3C2410_GPIO_OFFSET(pin)*2;
-               }
-       }
-
-       /* modify the specified register wwith IRQs off */
-
-       local_irq_save(flags);
-
-       con  = __raw_readl(base + 0x00);
-       con &= ~mask;
-       con |= function;
-
-       __raw_writel(con, base + 0x00);
-
-       local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
-
-unsigned int s3c2410_gpio_getcfg(unsigned int pin)
-{
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long val = __raw_readl(base);
-
-       if (pin < S3C2410_GPIO_BANKB) {
-               val >>= S3C2410_GPIO_OFFSET(pin);
-               val &= 1;
-               val += 1;
-       } else {
-               val >>= S3C2410_GPIO_OFFSET(pin)*2;
-               val &= 3;
-       }
-
-       return val | S3C2410_GPIO_INPUT;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getcfg);
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                          unsigned int config)
 {
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+       void __iomem *reg = S3C24XX_EINFLT0;
        unsigned long flags;
-       unsigned long up;
-
-       if (pin < S3C2410_GPIO_BANKB)
-               return;
-
-       local_irq_save(flags);
-
-       up = __raw_readl(base + 0x08);
-       up &= ~(1L << offs);
-       up |= to << offs;
-       __raw_writel(up, base + 0x08);
+       unsigned long val;
 
-       local_irq_restore(flags);
-}
+       if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+               return -1;
 
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
+       config &= 0xff;
 
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-       unsigned long flags;
-       unsigned long dat;
+       pin -= S3C2410_GPG8;
+       reg += pin & ~3;
 
        local_irq_save(flags);
 
-       dat = __raw_readl(base + 0x04);
-       dat &= ~(1 << offs);
-       dat |= to << offs;
-       __raw_writel(dat, base + 0x04);
-
-       local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+       /* update filter width and clock source */
 
-       return __raw_readl(base + 0x04) & (1<< offs);
-}
+       val = __raw_readl(reg);
+       val &= ~(0xff << ((pin & 3) * 8));
+       val |= config << ((pin & 3) * 8);
+       __raw_writel(val, reg);
 
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
+       /* update filter enable */
 
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-       unsigned long flags;
-       unsigned long misccr;
+       val = __raw_readl(S3C24XX_EXTINT2);
+       val &= ~(1 << ((pin * 4) + 3));
+       val |= on << ((pin * 4) + 3);
+       __raw_writel(val, S3C24XX_EXTINT2);
 
-       local_irq_save(flags);
-       misccr = __raw_readl(S3C24XX_MISCCR);
-       misccr &= ~clear;
-       misccr ^= change;
-       __raw_writel(misccr, S3C24XX_MISCCR);
        local_irq_restore(flags);
 
-       return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
-       if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
-               return -1;      /* not valid interrupts */
-
-       if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
-               return -1;      /* not valid pin */
-
-       if (pin < S3C2410_GPF4)
-               return (pin - S3C2410_GPF0) + IRQ_EINT0;
-
-       if (pin < S3C2410_GPG0)
-               return (pin - S3C2410_GPF4) + IRQ_EINT4;
-
-       return (pin - S3C2410_GPG0) + IRQ_EINT8;
+       return 0;
 }
 
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
index 3c0ed7871c55dc51c0c4dbf41a7a0d4e92fbb70f..53cbdaa43ac666a0d4ab5f2e05531c71910095ea 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Changelog:
- *
- *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
- *                Fixed compile warnings
- *
- *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
- *                Fixed s3c_extirq_type
- *
- *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
- *                Addition of ADC/TC demux
- *
- *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
- *               Fix for set_irq_type() on low EINT numbers
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *               Tidy up KF's patch and sort out new release
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *               Add support for power management controls
- *
- *   04-Nov-2004  Ben Dooks
- *               Fix standard IRQ wake for EINT0..4 and RTC
- *
- *   22-Feb-2005  Ben Dooks
- *               Fixed edge-triggering on ADC IRQ
- *
- *   28-Jun-2005  Ben Dooks
- *               Mark IRQ_LCD valid
- *
- *   25-Jul-2005  Ben Dooks
- *               Split the S3C2440 IRQ code to seperate file
 */
 
 #include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* wakeup irq control */
-
-#ifdef CONFIG_PM
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow     = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
-unsigned long s3c_irqwake_intmask      = 0xffffffffL;
-unsigned long s3c_irqwake_eintallow    = 0x0000fff0L;
-unsigned long s3c_irqwake_eintmask     = 0xffffffffL;
-
-int
-s3c_irq_wake(unsigned int irqno, unsigned int state)
-{
-       unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
-
-       if (!(s3c_irqwake_intallow & irqbit))
-               return -ENOENT;
-
-       printk(KERN_INFO "wake %s for irq %d\n",
-              state ? "enabled" : "disabled", irqno);
-
-       if (!state)
-               s3c_irqwake_intmask |= irqbit;
-       else
-               s3c_irqwake_intmask &= ~irqbit;
-
-       return 0;
-}
-
-static int
-s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
-       unsigned long bit = 1L << (irqno - EXTINT_OFF);
-
-       if (!(s3c_irqwake_eintallow & bit))
-               return -ENOENT;
-
-       printk(KERN_INFO "wake %s for irq %d\n",
-              state ? "enabled" : "disabled", irqno);
-
-       if (!state)
-               s3c_irqwake_eintmask |= bit;
-       else
-               s3c_irqwake_eintmask &= ~bit;
-
-       return 0;
-}
-
-#else
-#define s3c_irqext_wake NULL
-#define s3c_irq_wake NULL
-#endif
-
-
-static void
-s3c_irq_mask(unsigned int irqno)
-{
-       unsigned long mask;
-
-       irqno -= IRQ_EINT0;
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       mask |= 1UL << irqno;
-       __raw_writel(mask, S3C2410_INTMSK);
-}
-
-static inline void
-s3c_irq_ack(unsigned int irqno)
-{
-       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-
-       __raw_writel(bitval, S3C2410_SRCPND);
-       __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c_irq_maskack(unsigned int irqno)
-{
-       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-       unsigned long mask;
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       __raw_writel(mask|bitval, S3C2410_INTMSK);
-
-       __raw_writel(bitval, S3C2410_SRCPND);
-       __raw_writel(bitval, S3C2410_INTPND);
-}
-
-
-static void
-s3c_irq_unmask(unsigned int irqno)
-{
-       unsigned long mask;
-
-       if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
-               irqdbf2("s3c_irq_unmask %d\n", irqno);
-
-       irqno -= IRQ_EINT0;
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       mask &= ~(1UL << irqno);
-       __raw_writel(mask, S3C2410_INTMSK);
-}
-
-struct irq_chip s3c_irq_level_chip = {
-       .name           = "s3c-level",
-       .ack            = s3c_irq_maskack,
-       .mask           = s3c_irq_mask,
-       .unmask         = s3c_irq_unmask,
-       .set_wake       = s3c_irq_wake
-};
-
-static struct irq_chip s3c_irq_chip = {
-       .name           = "s3c",
-       .ack            = s3c_irq_ack,
-       .mask           = s3c_irq_mask,
-       .unmask         = s3c_irq_unmask,
-       .set_wake       = s3c_irq_wake
-};
-
-static void
-s3c_irqext_mask(unsigned int irqno)
-{
-       unsigned long mask;
-
-       irqno -= EXTINT_OFF;
-
-       mask = __raw_readl(S3C24XX_EINTMASK);
-       mask |= ( 1UL << irqno);
-       __raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-static void
-s3c_irqext_ack(unsigned int irqno)
-{
-       unsigned long req;
-       unsigned long bit;
-       unsigned long mask;
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-       bit = 1UL << (irqno - EXTINT_OFF);
-
-       mask = __raw_readl(S3C24XX_EINTMASK);
-
-       __raw_writel(bit, S3C24XX_EINTPEND);
-
-       req = __raw_readl(S3C24XX_EINTPEND);
-       req &= ~mask;
-
-       /* not sure if we should be acking the parent irq... */
-
-       if (irqno <= IRQ_EINT7 ) {
-               if ((req & 0xf0) == 0)
-                       s3c_irq_ack(IRQ_EINT4t7);
-       } else {
-               if ((req >> 8) == 0)
-                       s3c_irq_ack(IRQ_EINT8t23);
-       }
-}
-
-static void
-s3c_irqext_unmask(unsigned int irqno)
+static int s3c2410_irq_add(struct sys_device *sysdev)
 {
-       unsigned long mask;
-
-       irqno -= EXTINT_OFF;
-
-       mask = __raw_readl(S3C24XX_EINTMASK);
-       mask &= ~( 1UL << irqno);
-       __raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-int
-s3c_irqext_type(unsigned int irq, unsigned int type)
-{
-       void __iomem *extint_reg;
-       void __iomem *gpcon_reg;
-       unsigned long gpcon_offset, extint_offset;
-       unsigned long newvalue = 0, value;
-
-       if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
-       {
-               gpcon_reg = S3C2410_GPFCON;
-               extint_reg = S3C24XX_EXTINT0;
-               gpcon_offset = (irq - IRQ_EINT0) * 2;
-               extint_offset = (irq - IRQ_EINT0) * 4;
-       }
-       else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
-       {
-               gpcon_reg = S3C2410_GPFCON;
-               extint_reg = S3C24XX_EXTINT0;
-               gpcon_offset = (irq - (EXTINT_OFF)) * 2;
-               extint_offset = (irq - (EXTINT_OFF)) * 4;
-       }
-       else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
-       {
-               gpcon_reg = S3C2410_GPGCON;
-               extint_reg = S3C24XX_EXTINT1;
-               gpcon_offset = (irq - IRQ_EINT8) * 2;
-               extint_offset = (irq - IRQ_EINT8) * 4;
-       }
-       else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
-       {
-               gpcon_reg = S3C2410_GPGCON;
-               extint_reg = S3C24XX_EXTINT2;
-               gpcon_offset = (irq - IRQ_EINT8) * 2;
-               extint_offset = (irq - IRQ_EINT16) * 4;
-       } else
-               return -1;
-
-       /* Set the GPIO to external interrupt mode */
-       value = __raw_readl(gpcon_reg);
-       value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-       __raw_writel(value, gpcon_reg);
-
-       /* Set the external interrupt to pointed trigger type */
-       switch (type)
-       {
-               case IRQT_NOEDGE:
-                       printk(KERN_WARNING "No edge setting!\n");
-                       break;
-
-               case IRQT_RISING:
-                       newvalue = S3C2410_EXTINT_RISEEDGE;
-                       break;
-
-               case IRQT_FALLING:
-                       newvalue = S3C2410_EXTINT_FALLEDGE;
-                       break;
-
-               case IRQT_BOTHEDGE:
-                       newvalue = S3C2410_EXTINT_BOTHEDGE;
-                       break;
-
-               case IRQT_LOW:
-                       newvalue = S3C2410_EXTINT_LOWLEV;
-                       break;
-
-               case IRQT_HIGH:
-                       newvalue = S3C2410_EXTINT_HILEV;
-                       break;
-
-               default:
-                       printk(KERN_ERR "No such irq type %d", type);
-                       return -1;
-       }
-
-       value = __raw_readl(extint_reg);
-       value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-       __raw_writel(value, extint_reg);
-
        return 0;
 }
 
-static struct irq_chip s3c_irqext_chip = {
-       .name           = "s3c-ext",
-       .mask           = s3c_irqext_mask,
-       .unmask         = s3c_irqext_unmask,
-       .ack            = s3c_irqext_ack,
-       .set_type       = s3c_irqext_type,
-       .set_wake       = s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
-       .name           = "s3c-ext0",
-       .ack            = s3c_irq_ack,
-       .mask           = s3c_irq_mask,
-       .unmask         = s3c_irq_unmask,
-       .set_wake       = s3c_irq_wake,
-       .set_type       = s3c_irqext_type,
-};
-
-/* mask values for the parent registers for each of the interrupt types */
-
-#define INTMSK_UART0    (1UL << (IRQ_UART0 - IRQ_EINT0))
-#define INTMSK_UART1    (1UL << (IRQ_UART1 - IRQ_EINT0))
-#define INTMSK_UART2    (1UL << (IRQ_UART2 - IRQ_EINT0))
-#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-
-
-/* UART0 */
-
-static void
-s3c_irq_uart0_mask(unsigned int irqno)
-{
-       s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
-}
-
-static void
-s3c_irq_uart0_unmask(unsigned int irqno)
-{
-       s3c_irqsub_unmask(irqno, INTMSK_UART0);
-}
-
-static void
-s3c_irq_uart0_ack(unsigned int irqno)
-{
-       s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
-}
-
-static struct irq_chip s3c_irq_uart0 = {
-       .name           = "s3c-uart0",
-       .mask           = s3c_irq_uart0_mask,
-       .unmask         = s3c_irq_uart0_unmask,
-       .ack            = s3c_irq_uart0_ack,
-};
-
-/* UART1 */
-
-static void
-s3c_irq_uart1_mask(unsigned int irqno)
-{
-       s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static void
-s3c_irq_uart1_unmask(unsigned int irqno)
-{
-       s3c_irqsub_unmask(irqno, INTMSK_UART1);
-}
-
-static void
-s3c_irq_uart1_ack(unsigned int irqno)
-{
-       s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static struct irq_chip s3c_irq_uart1 = {
-       .name           = "s3c-uart1",
-       .mask           = s3c_irq_uart1_mask,
-       .unmask         = s3c_irq_uart1_unmask,
-       .ack            = s3c_irq_uart1_ack,
-};
-
-/* UART2 */
-
-static void
-s3c_irq_uart2_mask(unsigned int irqno)
-{
-       s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static void
-s3c_irq_uart2_unmask(unsigned int irqno)
-{
-       s3c_irqsub_unmask(irqno, INTMSK_UART2);
-}
-
-static void
-s3c_irq_uart2_ack(unsigned int irqno)
-{
-       s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static struct irq_chip s3c_irq_uart2 = {
-       .name           = "s3c-uart2",
-       .mask           = s3c_irq_uart2_mask,
-       .unmask         = s3c_irq_uart2_unmask,
-       .ack            = s3c_irq_uart2_ack,
-};
-
-/* ADC and Touchscreen */
-
-static void
-s3c_irq_adc_mask(unsigned int irqno)
-{
-       s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static void
-s3c_irq_adc_unmask(unsigned int irqno)
-{
-       s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
-}
-
-static void
-s3c_irq_adc_ack(unsigned int irqno)
-{
-       s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static struct irq_chip s3c_irq_adc = {
-       .name           = "s3c-adc",
-       .mask           = s3c_irq_adc_mask,
-       .unmask         = s3c_irq_adc_unmask,
-       .ack            = s3c_irq_adc_ack,
-};
-
-/* irq demux for adc */
-static void s3c_irq_demux_adc(unsigned int irq,
-                             struct irq_desc *desc)
-{
-       unsigned int subsrc, submsk;
-       unsigned int offset = 9;
-       struct irq_desc *mydesc;
-
-       /* read the current pending interrupts, and the mask
-        * for what it is available */
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       subsrc &= ~submsk;
-       subsrc >>= offset;
-       subsrc &= 3;
-
-       if (subsrc != 0) {
-               if (subsrc & 1) {
-                       mydesc = irq_desc + IRQ_TC;
-                       desc_handle_irq(IRQ_TC, mydesc);
-               }
-               if (subsrc & 2) {
-                       mydesc = irq_desc + IRQ_ADC;
-                       desc_handle_irq(IRQ_ADC, mydesc);
-               }
-       }
-}
-
-static void s3c_irq_demux_uart(unsigned int start)
-{
-       unsigned int subsrc, submsk;
-       unsigned int offset = start - IRQ_S3CUART_RX0;
-       struct irq_desc *desc;
-
-       /* read the current pending interrupts, and the mask
-        * for what it is available */
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
-               start, offset, subsrc, submsk);
-
-       subsrc &= ~submsk;
-       subsrc >>= offset;
-       subsrc &= 7;
-
-       if (subsrc != 0) {
-               desc = irq_desc + start;
-
-               if (subsrc & 1)
-                       desc_handle_irq(start, desc);
-
-               desc++;
-
-               if (subsrc & 2)
-                       desc_handle_irq(start+1, desc);
-
-               desc++;
-
-               if (subsrc & 4)
-                       desc_handle_irq(start+2, desc);
-       }
-}
-
-/* uart demux entry points */
-
-static void
-s3c_irq_demux_uart0(unsigned int irq,
-                   struct irq_desc *desc)
-{
-       irq = irq;
-       s3c_irq_demux_uart(IRQ_S3CUART_RX0);
-}
-
-static void
-s3c_irq_demux_uart1(unsigned int irq,
-                   struct irq_desc *desc)
-{
-       irq = irq;
-       s3c_irq_demux_uart(IRQ_S3CUART_RX1);
-}
-
-static void
-s3c_irq_demux_uart2(unsigned int irq,
-                   struct irq_desc *desc)
-{
-       irq = irq;
-       s3c_irq_demux_uart(IRQ_S3CUART_RX2);
-}
-
-static void
-s3c_irq_demux_extint8(unsigned int irq,
-                     struct irq_desc *desc)
-{
-       unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-       unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-       eintpnd &= ~eintmsk;
-       eintpnd &= ~0xff;       /* ignore lower irqs */
-
-       /* we may as well handle all the pending IRQs here */
-
-       while (eintpnd) {
-               irq = __ffs(eintpnd);
-               eintpnd &= ~(1<<irq);
-
-               irq += (IRQ_EINT4 - 4);
-               desc_handle_irq(irq, irq_desc + irq);
-       }
-
-}
-
-static void
-s3c_irq_demux_extint4t7(unsigned int irq,
-                       struct irq_desc *desc)
-{
-       unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-       unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-       eintpnd &= ~eintmsk;
-       eintpnd &= 0xff;        /* only lower irqs */
-
-       /* we may as well handle all the pending IRQs here */
-
-       while (eintpnd) {
-               irq = __ffs(eintpnd);
-               eintpnd &= ~(1<<irq);
-
-               irq += (IRQ_EINT4 - 4);
-
-               desc_handle_irq(irq, irq_desc + irq);
-       }
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save irq_save[] = {
-       SAVE_ITEM(S3C2410_INTMSK),
-       SAVE_ITEM(S3C2410_INTSUBMSK),
+static struct sysdev_driver s3c2410_irq_driver = {
+       .add            = s3c2410_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
 };
 
-/* the extint values move between the s3c2410/s3c2440 and the s3c2412
- * so we use an array to hold them, and to calculate the address of
- * the register at run-time
-*/
-
-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)
+static int s3c2410_irq_init(void)
 {
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-               save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
-
-       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-               save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
-
-       s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-       save_eintmask = __raw_readl(S3C24XX_EINTMASK);
-
-       return 0;
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
 }
 
-int s3c24xx_irq_resume(struct sys_device *dev)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-               __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-
-       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-               __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
-
-       s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-       __raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-       return 0;
-}
-
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-void __init s3c24xx_init_irq(void)
-{
-       unsigned long pend;
-       unsigned long last;
-       int irqno;
-       int i;
-
-       irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
-
-       /* first, clear all interrupts pending... */
-
-       last = 0;
-       for (i = 0; i < 4; i++) {
-               pend = __raw_readl(S3C24XX_EINTPEND);
-
-               if (pend == 0 || pend == last)
-                       break;
-
-               __raw_writel(pend, S3C24XX_EINTPEND);
-               printk("irq: clearing pending ext status %08x\n", (int)pend);
-               last = pend;
-       }
-
-       last = 0;
-       for (i = 0; i < 4; i++) {
-               pend = __raw_readl(S3C2410_INTPND);
-
-               if (pend == 0 || pend == last)
-                       break;
-
-               __raw_writel(pend, S3C2410_SRCPND);
-               __raw_writel(pend, S3C2410_INTPND);
-               printk("irq: clearing pending status %08x\n", (int)pend);
-               last = pend;
-       }
-
-       last = 0;
-       for (i = 0; i < 4; i++) {
-               pend = __raw_readl(S3C2410_SUBSRCPND);
-
-               if (pend == 0 || pend == last)
-                       break;
-
-               printk("irq: clearing subpending status %08x\n", (int)pend);
-               __raw_writel(pend, S3C2410_SUBSRCPND);
-               last = pend;
-       }
-
-       /* register the main interrupts */
-
-       irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
-
-       for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
-               /* set all the s3c2410 internal irqs */
-
-               switch (irqno) {
-                       /* deal with the special IRQs (cascaded) */
-
-               case IRQ_EINT4t7:
-               case IRQ_EINT8t23:
-               case IRQ_UART0:
-               case IRQ_UART1:
-               case IRQ_UART2:
-               case IRQ_ADCPARENT:
-                       set_irq_chip(irqno, &s3c_irq_level_chip);
-                       set_irq_handler(irqno, handle_level_irq);
-                       break;
-
-               case IRQ_RESERVED6:
-               case IRQ_RESERVED24:
-                       /* no IRQ here */
-                       break;
-
-               default:
-                       //irqdbf("registering irq %d (s3c irq)\n", irqno);
-                       set_irq_chip(irqno, &s3c_irq_chip);
-                       set_irq_handler(irqno, handle_edge_irq);
-                       set_irq_flags(irqno, IRQF_VALID);
-               }
-       }
-
-       /* setup the cascade irq handlers */
-
-       set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
-       set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
-
-       set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
-       set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
-       set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-       set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
-
-       /* external interrupts */
-
-       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-               irqdbf("registering irq %d (ext int)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_eint0t4);
-               set_irq_handler(irqno, handle_edge_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
-               irqdbf("registering irq %d (extended s3c irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irqext_chip);
-               set_irq_handler(irqno, handle_edge_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       /* register the uart interrupts */
-
-       irqdbf("s3c2410: registering external interrupts\n");
-
-       for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
-               irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart0);
-               set_irq_handler(irqno, handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
-               irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart1);
-               set_irq_handler(irqno, handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
-               irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_uart2);
-               set_irq_handler(irqno, handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
-               irqdbf("registering irq %d (s3c adc irq)\n", irqno);
-               set_irq_chip(irqno, &s3c_irq_adc);
-               set_irq_handler(irqno, handle_edge_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       irqdbf("s3c2410: registered interrupt handlers\n");
-}
+arch_initcall(s3c2410_irq_init);
index 817e2c684410bce25eeae0d383f296bad14cb644..72f2cc4fcd03b2cc901bdd02472f71ff21238809 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
  * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
@@ -35,7 +35,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/proc_fs.h>
-
+#include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -52,8 +52,8 @@
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
@@ -113,12 +113,6 @@ static struct platform_device amlm5900_device_nor = {
 #endif
 
 static struct map_desc amlm5900_iodesc[] __initdata = {
-       {
-               .virtual        = (u32)S3C24XX_VA_SPI,
-               .pfn            = __phys_to_pfn(S3C2410_PA_SPI),
-               .length         = SZ_1M,
-               .type           = MT_DEVICE
-       }
 };
 
 #define UCON S3C2410_UCON_DEFAULT
index b8b76757ec54a70272a9107b06f5b554a50d299f..7b81296427ebc54ce28cc519575e57e23eb58a95 100644 (file)
@@ -50,9 +50,9 @@
 
 #include <linux/serial_8250.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 #define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
index 15b625eae499e2e13b0d3e61dea07a7963347520..01c60d0923cd49d86da8d98b31e1c4dc85ed1f41 100644 (file)
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
 
 #include <asm/arch/h1940.h>
 #include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
+#include <asm/arch/udc.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc h1940_iodesc[] __initdata = {
        [0] = {
@@ -102,6 +103,32 @@ void h1940_latch_control(unsigned int clear, unsigned int set)
 
 EXPORT_SYMBOL_GPL(h1940_latch_control);
 
+static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+       printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+       switch (cmd)
+       {
+               case S3C2410_UDC_P_ENABLE :
+                       h1940_latch_control(0, H1940_LATCH_USB_DP);
+                       break;
+               case S3C2410_UDC_P_DISABLE :
+                       h1940_latch_control(H1940_LATCH_USB_DP, 0);
+                       break;
+               case S3C2410_UDC_P_RESET :
+                       break;
+               default:
+                       break;
+       }
+}
+
+static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
+       .udc_command            = h1940_udc_pullup,
+       .vbus_pin               = S3C2410_GPG5,
+       .vbus_pin_inverted      = 1,
+};
+
+
 
 /**
  * Set lcd on or off
@@ -146,12 +173,19 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
        .bpp=           {16,16,16},
 };
 
+static struct platform_device s3c_device_leds = {
+       .name             = "h1940-leds",
+       .id               = -1,
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
        &s3c_device_usb,
        &s3c_device_lcd,
        &s3c_device_wdt,
        &s3c_device_i2c,
        &s3c_device_iis,
+       &s3c_device_usbgadget,
+       &s3c_device_leds,
 };
 
 static struct s3c24xx_board h1940_board __initdata = {
@@ -179,7 +213,23 @@ static void __init h1940_init_irq(void)
 
 static void __init h1940_init(void)
 {
+       u32 tmp;
+
        s3c24xx_fb_set_platdata(&h1940_lcdcfg);
+       s3c24xx_udc_set_platdata(&h1940_udc_cfg);
+
+       /* Turn off suspend on both USB ports, and switch the
+        * selectable USB port to USB device mode. */
+
+       s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+                             S3C2410_MISCCR_USBSUSPND0 |
+                             S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+       tmp = (
+                0x78 << S3C2410_PLLCON_MDIVSHIFT)
+             | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
+             | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
+       writel(tmp, S3C2410_UPLLCON);
 }
 
 MACHINE_START(H1940, "IPAQ-H1940")
@@ -189,6 +239,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = h1940_map_io,
        .init_irq       = h1940_init_irq,
-       .init_machine   = h1940_init,
+       .init_machine   = h1940_init,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index 0411e9adb54d9b208682d849859a5dd16c97f08d..261aa4cc07700e509be8ee96907df184e9414307 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/iic.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc n30_iodesc[] __initdata = {
        /* nothing here yet */
index 2c738b375e4d6da64359154ea3f0073f6e6a2ea9..c78ab75b44f30cb33d198e4ba455baadd4af5aa2 100644 (file)
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc otom11_iodesc[] __initdata = {
   /* Device area */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
new file mode 100644 (file)
index 0000000..c6a4159
--- /dev/null
@@ -0,0 +1,448 @@
+/* linux/arch/arm/mach-s3c2410/mach-qt2410.c
+ *
+ * Copyright (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/mmc/protocol.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/fb.h>
+#include <asm/arch/nand.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/spi-gpio.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+static struct map_desc qt2410_iodesc[] __initdata = {
+       { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       }
+};
+
+/* LCD driver info */
+
+/* Configuration for 640x480 SHARP LQ080V3DG01 */
+static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
+       .regs   = {
+
+               .lcdcon1        = S3C2410_LCDCON1_TFT16BPP |
+                                 S3C2410_LCDCON1_TFT |
+                                 S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
+
+               .lcdcon2        = S3C2410_LCDCON2_VBPD(18) |    /* 19 */
+                                 S3C2410_LCDCON2_LINEVAL(479) |
+                                 S3C2410_LCDCON2_VFPD(10) |    /* 11 */
+                                 S3C2410_LCDCON2_VSPW(14),     /* 15 */
+
+               .lcdcon3        = S3C2410_LCDCON3_HBPD(43) |    /* 44 */
+                                 S3C2410_LCDCON3_HOZVAL(639) | /* 640 */
+                                 S3C2410_LCDCON3_HFPD(115),    /* 116 */
+
+               .lcdcon4        = S3C2410_LCDCON4_MVAL(0) |
+                                 S3C2410_LCDCON4_HSPW(95),     /* 96 */
+
+               .lcdcon5        = S3C2410_LCDCON5_FRM565 |
+                                 S3C2410_LCDCON5_INVVLINE |
+                                 S3C2410_LCDCON5_INVVFRAME |
+                                 S3C2410_LCDCON5_PWREN |
+                                 S3C2410_LCDCON5_HWSWP,
+       },
+
+       .lpcsel         = ((0xCE6) & ~7) | 1<<4,
+
+       .width          = 640,
+       .height         = 480,
+
+       .xres           = {
+               .min    = 640,
+               .max    = 640,
+               .defval = 640,
+       },
+
+       .yres           = {
+               .min    = 480,
+               .max    = 480,
+               .defval = 480,
+       },
+
+       .bpp            = {
+               .min    = 16,
+               .max    = 16,
+               .defval = 16,
+       },
+};
+
+/* Configuration for 480x640 toppoly TD028TTEC1 */
+static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
+       .regs   = {
+
+               .lcdcon1        = S3C2410_LCDCON1_TFT16BPP |
+                                 S3C2410_LCDCON1_TFT |
+                                 S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
+
+               .lcdcon2        = S3C2410_LCDCON2_VBPD(1) |     /* 2 */
+                                 S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
+                                 S3C2410_LCDCON2_VFPD(3) |     /* 4 */
+                                 S3C2410_LCDCON2_VSPW(1),      /* 2 */
+
+               .lcdcon3        = S3C2410_LCDCON3_HBPD(7) |     /* 8 */
+                                 S3C2410_LCDCON3_HOZVAL(479) | /* 479 */
+                                 S3C2410_LCDCON3_HFPD(23),     /* 24 */
+
+               .lcdcon4        = S3C2410_LCDCON4_MVAL(0) |
+                                 S3C2410_LCDCON4_HSPW(7),      /* 8 */
+
+               .lcdcon5        = S3C2410_LCDCON5_FRM565 |
+                                 S3C2410_LCDCON5_INVVLINE |
+                                 S3C2410_LCDCON5_INVVFRAME |
+                                 S3C2410_LCDCON5_PWREN |
+                                 S3C2410_LCDCON5_HWSWP,
+       },
+
+       .lpcsel         = ((0xCE6) & ~7) | 1<<4,
+
+       .width          = 480,
+       .height         = 640,
+
+       .xres           = {
+               .min    = 480,
+               .max    = 480,
+               .defval = 480,
+       },
+
+       .yres           = {
+               .min    = 640,
+               .max    = 640,
+               .defval = 640,
+       },
+
+       .bpp            = {
+               .min    = 16,
+               .max    = 16,
+               .defval = 16,
+       },
+};
+
+/* Config for 240x320 LCD */
+static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
+       .regs   = {
+
+               .lcdcon1        = S3C2410_LCDCON1_TFT16BPP |
+                                 S3C2410_LCDCON1_TFT |
+                                 S3C2410_LCDCON1_CLKVAL(0x04),
+
+               .lcdcon2        = S3C2410_LCDCON2_VBPD(1) |
+                                 S3C2410_LCDCON2_LINEVAL(319) |
+                                 S3C2410_LCDCON2_VFPD(6) |
+                                 S3C2410_LCDCON2_VSPW(3),
+
+               .lcdcon3        = S3C2410_LCDCON3_HBPD(12) |
+                                 S3C2410_LCDCON3_HOZVAL(239) |
+                                 S3C2410_LCDCON3_HFPD(7),
+
+               .lcdcon4        = S3C2410_LCDCON4_MVAL(0) |
+                                 S3C2410_LCDCON4_HSPW(3),
+
+               .lcdcon5        = S3C2410_LCDCON5_FRM565 |
+                                 S3C2410_LCDCON5_INVVLINE |
+                                 S3C2410_LCDCON5_INVVFRAME |
+                                 S3C2410_LCDCON5_PWREN |
+                                 S3C2410_LCDCON5_HWSWP,
+       },
+
+       .lpcsel         = ((0xCE6) & ~7) | 1<<4,
+
+       .width          = 240,
+       .height         = 320,
+
+       .xres           = {
+               .min    = 240,
+               .max    = 240,
+               .defval = 240,
+       },
+
+       .yres           = {
+               .min    = 320,
+               .max    = 320,
+               .defval = 320,
+       },
+
+       .bpp            = {
+               .min    = 16,
+               .max    = 16,
+               .defval = 16,
+       },
+};
+
+/* CS8900 */
+
+static struct resource qt2410_cs89x0_resources[] = {
+       [0] = {
+               .start  = 0x19000000,
+               .end    = 0x19000000 + 16,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_EINT9,
+               .end    = IRQ_EINT9,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device qt2410_cs89x0 = {
+       .name           = "cirrus-cs89x0",
+       .num_resources  = ARRAY_SIZE(qt2410_cs89x0_resources),
+       .resource       = qt2410_cs89x0_resources,
+};
+
+/* LED */
+
+static struct s3c24xx_led_platdata qt2410_pdata_led = {
+       .gpio           = S3C2410_GPB0,
+       .flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+       .name           = "led",
+       .def_trigger    = "timer",
+};
+
+static struct platform_device qt2410_led = {
+       .name           = "s3c24xx_led",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &qt2410_pdata_led,
+       },
+};
+
+/* SPI */
+
+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
+{
+       switch (cs) {
+       case BITBANG_CS_ACTIVE:
+               s3c2410_gpio_setpin(S3C2410_GPB5, 0);
+               break;
+       case BITBANG_CS_INACTIVE:
+               s3c2410_gpio_setpin(S3C2410_GPB5, 1);
+               break;
+       }
+}
+
+static struct s3c2410_spigpio_info spi_gpio_cfg = {
+       .pin_clk        = S3C2410_GPG7,
+       .pin_mosi       = S3C2410_GPG6,
+       .pin_miso       = S3C2410_GPG5,
+       .chip_select    = &spi_gpio_cs,
+};
+
+
+static struct platform_device qt2410_spi = {
+       .name             = "s3c24xx-spi-gpio",
+       .id               = 1,
+       .dev = {
+               .platform_data = &spi_gpio_cfg,
+       },
+};
+
+/* Board devices */
+
+static struct platform_device *qt2410_devices[] __initdata = {
+       &s3c_device_usb,
+       &s3c_device_lcd,
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+       &s3c_device_iis,
+       &s3c_device_sdi,
+       &s3c_device_usbgadget,
+       &qt2410_spi,
+       &qt2410_cs89x0,
+       &qt2410_led,
+};
+
+static struct s3c24xx_board qt2410_board __initdata = {
+       .devices       = qt2410_devices,
+       .devices_count = ARRAY_SIZE(qt2410_devices)
+};
+
+static struct mtd_partition qt2410_nand_part[] = {
+       [0] = {
+               .name   = "U-Boot",
+               .size   = 0x30000,
+               .offset = 0,
+       },
+       [1] = {
+               .name   = "U-Boot environment",
+               .offset = 0x30000,
+               .size   = 0x4000,
+       },
+       [2] = {
+               .name   = "kernel",
+               .offset = 0x34000,
+               .size   = SZ_2M,
+       },
+       [3] = {
+               .name   = "initrd",
+               .offset = 0x234000,
+               .size   = SZ_4M,
+       },
+       [4] = {
+               .name   = "jffs2",
+               .offset = 0x634000,
+               .size   = 0x39cc000,
+       },
+};
+
+static struct s3c2410_nand_set qt2410_nand_sets[] = {
+       [0] = {
+               .name           = "NAND",
+               .nr_chips       = 1,
+               .nr_partitions  = ARRAY_SIZE(qt2410_nand_part),
+               .partitions     = qt2410_nand_part,
+       },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+ */
+
+static struct s3c2410_platform_nand qt2410_nand_info = {
+       .tacls          = 20,
+       .twrph0         = 60,
+       .twrph1         = 20,
+       .nr_sets        = ARRAY_SIZE(qt2410_nand_sets),
+       .sets           = qt2410_nand_sets,
+};
+
+/* UDC */
+
+static struct s3c2410_udc_mach_info qt2410_udc_cfg = {
+};
+
+static char tft_type = 's';
+
+static int __init qt2410_tft_setup(char *str)
+{
+       tft_type = str[0];
+       return 1;
+}
+
+__setup("tft=", qt2410_tft_setup);
+
+static void __init qt2410_map_io(void)
+{
+       s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
+       s3c24xx_init_clocks(12*1000*1000);
+       s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+       s3c24xx_set_board(&qt2410_board);
+}
+
+static void __init qt2410_machine_init(void)
+{
+       s3c_device_nand.dev.platform_data = &qt2410_nand_info;
+
+       switch (tft_type) {
+       case 'p': /* production */
+               s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
+               break;
+       case 'b': /* big */
+               s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
+               break;
+       case 's': /* small */
+       default:
+               s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
+               break;
+       }
+
+       s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
+       s3c2410_gpio_setpin(S3C2410_GPB0, 1);
+
+       s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
+
+       s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
+
+       s3c2410_pm_init();
+}
+
+MACHINE_START(QT2410, "QT2410")
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .map_io         = qt2410_map_io,
+       .init_irq       = s3c24xx_init_irq,
+       .init_machine   = qt2410_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
+
+
index 01c0c986d827de5d12f775aaf4abce49a7bd988e..57b8a80f33d0c53c2672d72c496b88255add8072 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
  * linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
 
 #include <asm/arch/regs-serial.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
index a382fc095110ec21b9b07563a0b140893e40db98..c947c75bcbf0f982f13566db3a0fe61b45ea7eb5 100644 (file)
@@ -43,9 +43,9 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/leds-gpio.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
index ebf294dd31da7cf25410ac4327f58a230833a1b9..3b3a7db4e0dd961028ad43869fc22f5e6a2d365e 100644 (file)
@@ -1,11 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/pm.c
  *
- * Copyright (c) 2004,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Power Manager (Suspend-To-RAM) support
- *
- * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
  *
  * 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
  * 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
- *
- * Parts based on arch/arm/mach-pxa/pm.c
- *
- * Thanks to Dimitry Andric for debugging
 */
 
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
+#include <linux/sysdev.h>
 
-#include <asm/cacheflush.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-irq.h>
-
-#include <asm/mach/time.h>
-
-#include "pm.h"
-
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
-#define PFX "s3c24xx-pm: "
-
-static struct sleep_save core_save[] = {
-       SAVE_ITEM(S3C2410_LOCKTIME),
-       SAVE_ITEM(S3C2410_CLKCON),
-
-       /* we restore the timings here, with the proviso that the board
-        * brings the system up in an slower, or equal frequency setting
-        * to the original system.
-        *
-        * if we cannot guarantee this, then things are going to go very
-        * wrong here, as we modify the refresh and both pll settings.
-        */
-
-       SAVE_ITEM(S3C2410_BWSCON),
-       SAVE_ITEM(S3C2410_BANKCON0),
-       SAVE_ITEM(S3C2410_BANKCON1),
-       SAVE_ITEM(S3C2410_BANKCON2),
-       SAVE_ITEM(S3C2410_BANKCON3),
-       SAVE_ITEM(S3C2410_BANKCON4),
-       SAVE_ITEM(S3C2410_BANKCON5),
-
-       SAVE_ITEM(S3C2410_CLKDIVN),
-       SAVE_ITEM(S3C2410_MPLLCON),
-       SAVE_ITEM(S3C2410_UPLLCON),
-       SAVE_ITEM(S3C2410_CLKSLOW),
-       SAVE_ITEM(S3C2410_REFRESH),
-};
-
-static struct sleep_save gpio_save[] = {
-       SAVE_ITEM(S3C2410_GPACON),
-       SAVE_ITEM(S3C2410_GPADAT),
-
-       SAVE_ITEM(S3C2410_GPBCON),
-       SAVE_ITEM(S3C2410_GPBDAT),
-       SAVE_ITEM(S3C2410_GPBUP),
-
-       SAVE_ITEM(S3C2410_GPCCON),
-       SAVE_ITEM(S3C2410_GPCDAT),
-       SAVE_ITEM(S3C2410_GPCUP),
-
-       SAVE_ITEM(S3C2410_GPDCON),
-       SAVE_ITEM(S3C2410_GPDDAT),
-       SAVE_ITEM(S3C2410_GPDUP),
-
-       SAVE_ITEM(S3C2410_GPECON),
-       SAVE_ITEM(S3C2410_GPEDAT),
-       SAVE_ITEM(S3C2410_GPEUP),
-
-       SAVE_ITEM(S3C2410_GPFCON),
-       SAVE_ITEM(S3C2410_GPFDAT),
-       SAVE_ITEM(S3C2410_GPFUP),
+#include <asm/mach-types.h>
 
-       SAVE_ITEM(S3C2410_GPGCON),
-       SAVE_ITEM(S3C2410_GPGDAT),
-       SAVE_ITEM(S3C2410_GPGUP),
-
-       SAVE_ITEM(S3C2410_GPHCON),
-       SAVE_ITEM(S3C2410_GPHDAT),
-       SAVE_ITEM(S3C2410_GPHUP),
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/h1940.h>
 
-       SAVE_ITEM(S3C2410_DCLKCON),
-};
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 #ifdef CONFIG_S3C2410_PM_DEBUG
-
-#define SAVE_UART(va) \
-       SAVE_ITEM((va) + S3C2410_ULCON), \
-       SAVE_ITEM((va) + S3C2410_UCON), \
-       SAVE_ITEM((va) + S3C2410_UFCON), \
-       SAVE_ITEM((va) + S3C2410_UMCON), \
-       SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
-       SAVE_UART(S3C24XX_VA_UART0),
-       SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
-       SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-extern void printascii(const char *);
-
-void pm_dbg(const char *fmt, ...)
-{
-       va_list va;
-       char buff[256];
-
-       va_start(va, fmt);
-       vsprintf(buff, fmt, va);
-       va_end(va);
-
-       printascii(buff);
-}
-
-static void s3c2410_pm_debug_init(void)
-{
-       unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-       /* re-start uart clocks */
-       tmp |= S3C2410_CLKCON_UART0;
-       tmp |= S3C2410_CLKCON_UART1;
-       tmp |= S3C2410_CLKCON_UART2;
-
-       __raw_writel(tmp, S3C2410_CLKCON);
-       udelay(10);
-}
-
+extern void pm_dbg(const char *fmt, ...);
 #define DBG(fmt...) pm_dbg(fmt)
 #else
 #define DBG(fmt...) printk(KERN_DEBUG fmt)
-
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
 #endif
 
-#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size;   /* size needed for the crc block */
-static u32 *crcs;      /* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c2410_pm_run_res
- *
- * go thorugh the given resource list, and look for system ram
-*/
-
-static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
-{
-       while (ptr != NULL) {
-               if (ptr->child != NULL)
-                       s3c2410_pm_run_res(ptr->child, fn, arg);
-
-               if ((ptr->flags & IORESOURCE_MEM) &&
-                   strcmp(ptr->name, "System RAM") == 0) {
-                       DBG("Found system RAM at %08lx..%08lx\n",
-                           ptr->start, ptr->end);
-                       arg = (fn)(ptr, arg);
-               }
-
-               ptr = ptr->sibling;
-       }
-}
-
-static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
-       s3c2410_pm_run_res(&iomem_resource, fn, arg);
-}
-
-static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
-{
-       u32 size = (u32)(res->end - res->start)+1;
-
-       size += CHECK_CHUNKSIZE-1;
-       size /= CHECK_CHUNKSIZE;
-
-       DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
-
-       *val += size * sizeof(u32);
-       return val;
-}
-
-/* s3c2410_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-static void s3c2410_pm_check_prepare(void)
+static void s3c2410_pm_prepare(void)
 {
-       crc_size = 0;
+       /* ensure at least GSTATUS3 has the resume address */
 
-       s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+       __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
 
-       DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+       DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+       DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
-       crcs = kmalloc(crc_size+4, GFP_KERNEL);
-       if (crcs == NULL)
-               printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
+       if (machine_is_h1940()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
 
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
-       unsigned long addr, left;
+               /* generate check for the bootloader to check on resume */
 
-       for (addr = res->start; addr < res->end;
-            addr += CHECK_CHUNKSIZE) {
-               left = res->end - addr;
+               for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+                       calc += __raw_readl(base+ptr);
 
-               if (left > CHECK_CHUNKSIZE)
-                       left = CHECK_CHUNKSIZE;
-
-               *val = crc32_le(~0, phys_to_virt(addr), left);
-               val++;
+               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
        }
 
-       return val;
-}
-
-/* s3c2410_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-static void s3c2410_pm_check_store(void)
-{
-       if (crcs != NULL)
-               s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
-}
-
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contatins the
- * what..what+whatsz
-*/
-
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
-       if ((what+whatsz) < ptr)
-               return 0;
-
-       if (what > (ptr+size))
-               return 0;
-
-       return 1;
-}
-
-static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
-{
-       void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
-       unsigned long addr;
-       unsigned long left;
-       void *ptr;
-       u32 calc;
-
-       for (addr = res->start; addr < res->end;
-            addr += CHECK_CHUNKSIZE) {
-               left = res->end - addr;
+       /* the RX3715 uses similar code and the same H1940 and the
+        * same offsets for resume and checksum pointers */
 
-               if (left > CHECK_CHUNKSIZE)
-                       left = CHECK_CHUNKSIZE;
+       if (machine_is_rx3715()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
 
-               ptr = phys_to_virt(addr);
+               /* generate check for the bootloader to check on resume */
 
-               if (in_region(ptr, left, crcs, crc_size)) {
-                       DBG("skipping %08lx, has crc block in\n", addr);
-                       goto skip_check;
-               }
+               for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+                       calc += __raw_readl(base+ptr);
 
-               if (in_region(ptr, left, save_at, 32*4 )) {
-                       DBG("skipping %08lx, has save block in\n", addr);
-                       goto skip_check;
-               }
-
-               /* calculate and check the checksum */
-
-               calc = crc32_le(~0, ptr, left);
-               if (calc != *val) {
-                       printk(KERN_ERR PFX "Restore CRC error at "
-                              "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
-                       DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
-                           addr, calc, *val);
-               }
-
-       skip_check:
-               val++;
+               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
        }
 
-       return val;
-}
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 1);
 
-/* s3c2410_pm_check_restore
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-
-static void s3c2410_pm_check_restore(void)
-{
-       if (crcs != NULL) {
-               s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
-               kfree(crcs);
-               crcs = NULL;
-       }
 }
 
-#else
-
-#define s3c2410_pm_check_prepare() do { } while(0)
-#define s3c2410_pm_check_restore() do { } while(0)
-#define s3c2410_pm_check_store()   do { } while(0)
-#endif
-
-/* helper functions to save and restore register state */
-
-void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+static int s3c2410_pm_resume(struct sys_device *dev)
 {
-       for (; count > 0; count--, ptr++) {
-               ptr->val = __raw_readl(ptr->reg);
-               DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-       }
-}
+       unsigned long tmp;
 
-/* s3c2410_pm_do_restore
- *
- * restore the system from the given list of saved registers
- *
- * Note, we do not use DBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
+       /* unset the return-from-sleep flag, to ensure reset */
 
-void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
-{
-       for (; count > 0; count--, ptr++) {
-               printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
-                      ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
-               __raw_writel(ptr->val, ptr->reg);
-       }
-}
+       tmp = __raw_readl(S3C2410_GSTATUS2);
+       tmp &= S3C2410_GSTATUS2_OFFRESET;
+       __raw_writel(tmp, S3C2410_GSTATUS2);
 
-/* s3c2410_pm_do_restore_core
- *
- * similar to s3c2410_pm_do_restore_core
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 0);
 
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-       for (; count > 0; count--, ptr++) {
-               __raw_writel(ptr->val, ptr->reg);
-       }
+       return 0;
 }
 
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
-                                       unsigned long mask)
+static int s3c2410_pm_add(struct sys_device *dev)
 {
-       int i;
+       pm_cpu_prep = s3c2410_pm_prepare;
+       pm_cpu_sleep = s3c2410_cpu_suspend;
 
-       which &= ~mask;
-
-       for (i = 0; i <= 31; i++) {
-               if ((which) & (1L<<i)) {
-                       DBG("IRQ %d asserted at resume\n", start+i);
-               }
-       }
+       return 0;
 }
 
-/* s3c2410_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
-       unsigned long irqstate;
-       unsigned long pinstate;
-       int irq = s3c2410_gpio_getirq(pin);
-
-       if (irqoffs < 4)
-               irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
-       else
-               irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
-
-       pinstate = s3c2410_gpio_getcfg(pin);
-
-       if (!irqstate) {
-               if (pinstate == S3C2410_GPIO_IRQ)
-                       DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
-       } else {
-               if (pinstate == S3C2410_GPIO_IRQ) {
-                       DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
-                       s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
-               }
-       }
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
 
-/* s3c2410_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
+/* register ourselves */
 
-static void s3c2410_pm_configure_extint(void)
+static int __init s3c2410_pm_drvinit(void)
 {
-       int pin;
-
-       /* for each of the external interrupts (EINT0..EINT15) we
-        * need to check wether it is an external interrupt source,
-        * and then configure it as an input if it is not
-       */
-
-       for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
-               s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
-       }
-
-       for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
-               s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
-       }
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
 }
 
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
-{
-       unsigned long regs_save[16];
-
-       /* ensure the debug is initialised (if enabled) */
-
-       s3c2410_pm_debug_init();
-
-       DBG("s3c2410_pm_enter(%d)\n", state);
-
-       if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
-               printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
-               return -EINVAL;
-       }
-
-       if (state != PM_SUSPEND_MEM) {
-               printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
-               return -EINVAL;
-       }
-
-       /* check if we have anything to wake-up with... bad things seem
-        * to happen if you suspend with no wakeup (system will often
-        * require a full power-cycle)
-       */
-
-       if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-           !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-               printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
-               printk(KERN_ERR PFX "Aborting sleep\n");
-               return -EINVAL;
-       }
-
-       /* prepare check area if configured */
-
-       s3c2410_pm_check_prepare();
-
-       /* store the physical address of the register recovery block */
-
-       s3c2410_sleep_save_phys = virt_to_phys(regs_save);
-
-       DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
-
-       /* save all necessary core registers not covered by the drivers */
-
-       s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
-       s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
-       s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
-       /* set the irq configuration for wake */
-
-       s3c2410_pm_configure_extint();
-
-       DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-           s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-       __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-       __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-       /* ack any outstanding external interrupts before we go to sleep */
-
-       __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
-       __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
-       __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
-       /* call cpu specific preperation */
-
-       pm_cpu_prep();
-
-       /* flush cache back to ram */
-
-       flush_cache_all();
-
-       s3c2410_pm_check_store();
-
-       /* send the cpu to sleep... */
-
-       __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-
-       /* s3c2410_cpu_save will also act as our return point from when
-        * we resume as it saves its own register state, so use the return
-        * code to differentiate return from save and return from sleep */
-
-       if (s3c2410_cpu_save(regs_save) == 0) {
-               flush_cache_all();
-               pm_cpu_sleep();
-       }
-
-       /* restore the cpu state */
-
-       cpu_init();
-
-       /* restore the system state */
-
-       s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
-       s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
-       s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-
-       s3c2410_pm_debug_init();
-
-       /* check what irq (if any) restored the system */
-
-       DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-           __raw_readl(S3C2410_SRCPND),
-           __raw_readl(S3C2410_EINTPEND));
-
-       s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-                                   s3c_irqwake_intmask);
-
-       s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-                                   s3c_irqwake_eintmask);
-
-       DBG("post sleep, preparing to return\n");
-
-       s3c2410_pm_check_restore();
-
-       /* ok, let's return from sleep */
+arch_initcall(s3c2410_pm_drvinit);
+#endif
 
-       DBG("S3C2410 PM Resume (post-restore)\n");
-       return 0;
-}
+#if defined(CONFIG_CPU_S3C2440)
+static struct sysdev_driver s3c2440_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
+static int __init s3c2440_pm_drvinit(void)
 {
-       return 0;
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
 }
 
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
-       return 0;
-}
+arch_initcall(s3c2440_pm_drvinit);
+#endif
 
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
-static struct pm_ops s3c2410_pm_ops = {
-       .pm_disk_mode   = PM_DISK_FIRMWARE,
-       .prepare        = s3c2410_pm_prepare,
-       .enter          = s3c2410_pm_enter,
-       .finish         = s3c2410_pm_finish,
+#if defined(CONFIG_CPU_S3C2442)
+static struct sysdev_driver s3c2442_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
 };
 
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
-
-int __init s3c2410_pm_init(void)
+static int __init s3c2442_pm_drvinit(void)
 {
-       printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-       pm_set_ops(&s3c2410_pm_ops);
-       return 0;
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
 }
+
+arch_initcall(s3c2442_pm_drvinit);
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
deleted file mode 100644 (file)
index 992cc6a..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410,S3C2440,S3C2442 Clock control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "s3c2410.h"
-#include "clock.h"
-#include "cpu.h"
-
-int s3c2410_clkcon_enable(struct clk *clk, int enable)
-{
-       unsigned int clocks = clk->ctrlbit;
-       unsigned long clkcon;
-
-       clkcon = __raw_readl(S3C2410_CLKCON);
-
-       if (enable)
-               clkcon |= clocks;
-       else
-               clkcon &= ~clocks;
-
-       /* ensure none of the special function bits set */
-       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
-       __raw_writel(clkcon, S3C2410_CLKCON);
-
-       return 0;
-}
-
-static int s3c2410_upll_enable(struct clk *clk, int enable)
-{
-       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-       unsigned long orig = clkslow;
-
-       if (enable)
-               clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
-       else
-               clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
-       __raw_writel(clkslow, S3C2410_CLKSLOW);
-
-       /* if we started the UPLL, then allow to settle */
-
-       if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
-               udelay(200);
-
-       return 0;
-}
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
-       {
-               .name           = "nand",
-               .id             = -1,
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_NAND,
-       }, {
-               .name           = "sdi",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_SDI,
-       }, {
-               .name           = "adc",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_ADC,
-       }, {
-               .name           = "i2c",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_IIC,
-       }, {
-               .name           = "iis",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_IIS,
-       }, {
-               .name           = "spi",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_SPI,
-       }
-};
-
-static struct clk init_clocks[] = {
-       {
-               .name           = "lcd",
-               .id             = -1,
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_LCDC,
-       }, {
-               .name           = "gpio",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_GPIO,
-       }, {
-               .name           = "usb-host",
-               .id             = -1,
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBH,
-       }, {
-               .name           = "usb-device",
-               .id             = -1,
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBD,
-       }, {
-               .name           = "timers",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_PWMT,
-       }, {
-               .name           = "uart",
-               .id             = 0,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART0,
-       }, {
-               .name           = "uart",
-               .id             = 1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART1,
-       }, {
-               .name           = "uart",
-               .id             = 2,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART2,
-       }, {
-               .name           = "rtc",
-               .id             = -1,
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_RTC,
-       }, {
-               .name           = "watchdog",
-               .id             = -1,
-               .parent         = &clk_p,
-               .ctrlbit        = 0,
-       }, {
-               .name           = "usb-bus-host",
-               .id             = -1,
-               .parent         = &clk_usb_bus,
-       }, {
-               .name           = "usb-bus-gadget",
-               .id             = -1,
-               .parent         = &clk_usb_bus,
-       },
-};
-
-/* s3c2410_baseclk_add()
- *
- * Add all the clocks used by the s3c2410 or compatible CPUs
- * such as the S3C2440 and S3C2442.
- *
- * We cannot use a system device as we are needed before any
- * of the init-calls that initialise the devices are actually
- * done.
-*/
-
-int __init s3c2410_baseclk_add(void)
-{
-       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-       struct clk *clkp;
-       struct clk *xtal;
-       int ret;
-       int ptr;
-
-       clk_upll.enable = s3c2410_upll_enable;
-
-       if (s3c24xx_register_clock(&clk_usb_bus) < 0)
-               printk(KERN_ERR "failed to register usb bus clock\n");
-
-       /* register clocks from clock array */
-
-       clkp = init_clocks;
-       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-               /* ensure that we note the clock state */
-
-               clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
-               ret = s3c24xx_register_clock(clkp);
-               if (ret < 0) {
-                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
-                              clkp->name, ret);
-               }
-       }
-
-       /* We must be careful disabling the clocks we are not intending to
-        * be using at boot time, as subsytems such as the LCD which do
-        * their own DMA requests to the bus can cause the system to lockup
-        * if they where in the middle of requesting bus access.
-        *
-        * Disabling the LCD clock if the LCD is active is very dangerous,
-        * and therefore the bootloader should be careful to not enable
-        * the LCD clock if it is not needed.
-       */
-
-       /* install (and disable) the clocks we do not need immediately */
-
-       clkp = init_clocks_disable;
-       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-               ret = s3c24xx_register_clock(clkp);
-               if (ret < 0) {
-                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
-                              clkp->name, ret);
-               }
-
-               s3c2410_clkcon_enable(clkp, 0);
-       }
-
-       /* show the clock-slow value */
-
-       xtal = clk_get(NULL, "xtal");
-
-       printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
-              print_mhz(clk_get_rate(xtal) /
-                        ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
-              (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
-              (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
-              (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
-       return 0;
-}
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
deleted file mode 100644 (file)
index e67ba39..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include "dma.h"
-
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
-       [DMACH_XD0] = {
-               .name           = "xdreq0",
-               .channels[0]    = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
-       },
-       [DMACH_XD1] = {
-               .name           = "xdreq1",
-               .channels[1]    = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
-       },
-       [DMACH_SDI] = {
-               .name           = "sdi",
-               .channels[0]    = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
-               .channels[2]    = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
-               .channels[3]    = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
-               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
-       },
-       [DMACH_SPI0] = {
-               .name           = "spi0",
-               .channels[1]    = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
-               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
-       },
-       [DMACH_SPI1] = {
-               .name           = "spi1",
-               .channels[3]    = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
-       },
-       [DMACH_UART0] = {
-               .name           = "uart0",
-               .channels[0]    = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
-               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
-       },
-       [DMACH_UART1] = {
-               .name           = "uart1",
-               .channels[1]    = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
-               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
-       },
-       [DMACH_UART2] = {
-               .name           = "uart2",
-               .channels[3]    = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
-               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
-       },
-       [DMACH_TIMER] = {
-               .name           = "timer",
-               .channels[0]    = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
-               .channels[2]    = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
-               .channels[3]    = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
-       },
-       [DMACH_I2S_IN] = {
-               .name           = "i2s-sdi",
-               .channels[1]    = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
-               .channels[2]    = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
-       },
-       [DMACH_I2S_OUT] = {
-               .name           = "i2s-sdo",
-               .channels[2]    = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
-       },
-       [DMACH_USB_EP1] = {
-               .name           = "usb-ep1",
-               .channels[0]    = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
-       },
-       [DMACH_USB_EP2] = {
-               .name           = "usb-ep2",
-               .channels[1]    = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
-       },
-       [DMACH_USB_EP3] = {
-               .name           = "usb-ep3",
-               .channels[2]    = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
-       },
-       [DMACH_USB_EP4] = {
-               .name           = "usb-ep4",
-               .channels[3]    =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
-       },
-};
-
-static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
-                              struct s3c24xx_dma_map *map)
-{
-       chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
-       .select         = s3c2410_dma_select,
-       .dcon_mask      = 7 << 24,
-       .map            = s3c2410_dma_mappings,
-       .map_size       = ARRAY_SIZE(s3c2410_dma_mappings),
-};
-
-static int s3c2410_dma_add(struct sys_device *sysdev)
-{
-       return s3c24xx_dma_init_map(&s3c2410_dma_sel);
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_dma_driver = {
-       .add    = s3c2410_dma_add,
-};
-
-static int __init s3c2410_dma_init(void)
-{
-       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
-}
-
-arch_initcall(s3c2410_dma_init);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-/* S3C2442 DMA contains the same selection table as the S3C2410 */
-static struct sysdev_driver s3c2442_dma_driver = {
-       .add    = s3c2410_dma_add,
-};
-
-static int __init s3c2442_dma_init(void)
-{
-       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
-}
-
-arch_initcall(s3c2442_dma_init);
-#endif
-
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
deleted file mode 100644 (file)
index ec3a276..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-                          unsigned int config)
-{
-       void __iomem *reg = S3C24XX_EINFLT0;
-       unsigned long flags;
-       unsigned long val;
-
-       if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
-               return -1;
-
-       config &= 0xff;
-
-       pin -= S3C2410_GPG8;
-       reg += pin & ~3;
-
-       local_irq_save(flags);
-
-       /* update filter width and clock source */
-
-       val = __raw_readl(reg);
-       val &= ~(0xff << ((pin & 3) * 8));
-       val |= config << ((pin & 3) * 8);
-       __raw_writel(val, reg);
-
-       /* update filter enable */
-
-       val = __raw_readl(S3C24XX_EXTINT2);
-       val &= ~(1 << ((pin * 4) + 3));
-       val |= on << ((pin * 4) + 3);
-       __raw_writel(val, S3C24XX_EXTINT2);
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
deleted file mode 100644 (file)
index c796c9c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
-       return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
-       .add            = s3c2410_irq_add,
-       .suspend        = s3c24xx_irq_suspend,
-       .resume         = s3c24xx_irq_resume,
-};
-
-static int s3c2410_irq_init(void)
-{
-       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
deleted file mode 100644 (file)
index 8bb6e5e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/time.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/h1940.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
-static void s3c2410_pm_prepare(void)
-{
-       /* ensure at least GSTATUS3 has the resume address */
-
-       __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
-       DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-       DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
-       if (machine_is_h1940()) {
-               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-               unsigned long ptr;
-               unsigned long calc = 0;
-
-               /* generate check for the bootloader to check on resume */
-
-               for (ptr = 0; ptr < 0x40000; ptr += 0x400)
-                       calc += __raw_readl(base+ptr);
-
-               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-       }
-
-       /* the RX3715 uses similar code and the same H1940 and the
-        * same offsets for resume and checksum pointers */
-
-       if (machine_is_rx3715()) {
-               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-               unsigned long ptr;
-               unsigned long calc = 0;
-
-               /* generate check for the bootloader to check on resume */
-
-               for (ptr = 0; ptr < 0x40000; ptr += 0x4)
-                       calc += __raw_readl(base+ptr);
-
-               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-       }
-
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF2, 1);
-
-}
-
-static int s3c2410_pm_resume(struct sys_device *dev)
-{
-       unsigned long tmp;
-
-       /* unset the return-from-sleep flag, to ensure reset */
-
-       tmp = __raw_readl(S3C2410_GSTATUS2);
-       tmp &= S3C2410_GSTATUS2_OFFRESET;
-       __raw_writel(tmp, S3C2410_GSTATUS2);
-
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-
-       return 0;
-}
-
-static int s3c2410_pm_add(struct sys_device *dev)
-{
-       pm_cpu_prep = s3c2410_pm_prepare;
-       pm_cpu_sleep = s3c2410_cpu_suspend;
-
-       return 0;
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_pm_driver = {
-       .add            = s3c2410_pm_add,
-       .resume         = s3c2410_pm_resume,
-};
-
-/* register ourselves */
-
-static int __init s3c2410_pm_drvinit(void)
-{
-       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
-}
-
-arch_initcall(s3c2410_pm_drvinit);
-#endif
-
-#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)
-{
-       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
-}
-
-arch_initcall(s3c2440_pm_drvinit);
-#endif
-
-#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)
-{
-       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
-}
-
-arch_initcall(s3c2442_pm_drvinit);
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
deleted file mode 100644 (file)
index 9179a10..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 Power Manager (Suspend-To-RAM) support
- *
- * Based on PXA/SA1100 sleep code by:
- *     Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *     Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-#include <asm/arch/map.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-serial.h>
-
-       /* s3c2410_cpu_suspend
-        *
-        * put the cpu into sleep mode
-       */
-
-ENTRY(s3c2410_cpu_suspend)
-       @@ prepare cpu to sleep
-
-       ldr     r4, =S3C2410_REFRESH
-       ldr     r5, =S3C24XX_MISCCR
-       ldr     r6, =S3C2410_CLKCON
-       ldr     r7, [ r4 ]              @ get REFRESH (and ensure in TLB)
-       ldr     r8, [ r5 ]              @ get MISCCR (and ensure in TLB)
-       ldr     r9, [ r6 ]              @ get CLKCON (and ensure in TLB)
-
-       orr     r7, r7, #S3C2410_REFRESH_SELF   @ SDRAM sleep command
-       orr     r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
-       orr     r9, r9, #S3C2410_CLKCON_POWER   @ power down command
-
-       teq     pc, #0                  @ first as a trial-run to load cache
-       bl      s3c2410_do_sleep
-       teq     r0, r0                  @ now do it for real
-       b       s3c2410_do_sleep        @
-
-       @@ align next bit of code to cache line
-       .align  8
-s3c2410_do_sleep:
-       streq   r7, [ r4 ]                      @ SDRAM sleep command
-       streq   r8, [ r5 ]                      @ SDRAM power-down config
-       streq   r9, [ r6 ]                      @ CPU sleep
-1:     beq     1b
-       mov     pc, r14
index 4cdc0d70c19f3fa6203440a6ea2f3082575c9861..1a86a9803753470acb87ea3476d30c9ece2a87d8 100644 (file)
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
-#include "s3c2410.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
 
 /* Initial IO mappings */
 
@@ -110,7 +110,7 @@ static struct sys_device s3c2410_sysdev = {
 
 /* need to register class before we actually register the device, and
  * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
+ * drivers even try to use it (even if not on an s3c2410 based system)
  * as a driver which may support both 2410 and 2440 may try and use it.
 */
 
index 2018c2e1dcc5aecc97a9c9ec1825fc3c6b2fc29c..637aaba653901a23f640edfdfa7c2569c0a41c93 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-serial.h>
 
-/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
- * reset the UART configuration, only enable if you really need this!
-*/
-//#define CONFIG_DEBUG_RESUME
-
-       .text
-
-       /* s3c2410_cpu_save
-        *
-        * save enough of the CPU state to allow us to re-start
-        * pm.c code. as we store items like the sp/lr, we will
-        * end up returning from this function when the cpu resumes
-        * so the return value is set to mark this.
-        *
-        * This arangement means we avoid having to flush the cache
-        * from this code.
-        *
-        * entry:
-        *      r0 = pointer to save block
-        *
-        * exit:
-        *      r0 = 0 => we stored everything
-        *           1 => resumed from sleep
-       */
-
-ENTRY(s3c2410_cpu_save)
-       stmfd   sp!, { r4 - r12, lr }
-
-       @@ store co-processor registers
-
-       mrc     p15, 0, r4, c15, c1, 0  @ CP access register
-       mrc     p15, 0, r5, c13, c0, 0  @ PID
-       mrc     p15, 0, r6, c3, c0, 0   @ Domain ID
-       mrc     p15, 0, r7, c2, c0, 0   @ translation table base address
-       mrc     p15, 0, r8, c1, c0, 0   @ control register
-
-       stmia   r0, { r4 - r13 }
-
-       mov     r0, #0
-       ldmfd   sp, { r4 - r12, pc }
-
-       @@ return to the caller, after having the MMU
-       @@ turned on, this restores the last bits from the
-       @@ stack
-resume_with_mmu:
-       mov     r0, #1
-       ldmfd   sp!, { r4 - r12, pc }
-
-       .ltorg
-
-       @@ the next bits sit in the .data segment, even though they
-       @@ happen to be code... the s3c2410_sleep_save_phys needs to be
-       @@ accessed by the resume code before it can restore the MMU.
-       @@ This means that the variable has to be close enough for the
-       @@ code to read it... since the .text segment needs to be RO,
-       @@ the data segment can be the only place to put this code.
-
-       .data
-
-       .global s3c2410_sleep_save_phys
-s3c2410_sleep_save_phys:
-       .word   0
-
-       /* s3c2410_cpu_resume
+       /* s3c2410_cpu_suspend
         *
-        * resume code entry for bootloader to call
-        *
-        * we must put this code here in the data segment as we have no
-        * other way of restoring the stack pointer after sleep, and we
-        * must not write to the code segment (code is read-only)
+        * put the cpu into sleep mode
        */
 
-ENTRY(s3c2410_cpu_resume)
-       mov     r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-       msr     cpsr_c, r0
-
-       @@ load UART to allow us to print the two characters for
-       @@ resume debug
-
-       mov     r2, #S3C24XX_PA_UART & 0xff000000
-       orr     r2, r2, #S3C24XX_PA_UART & 0xff000
-
-#if 0
-       /* SMDK2440 LED set */
-       mov     r14, #S3C24XX_PA_GPIO
-       ldr     r12, [ r14, #0x54 ]
-       bic     r12, r12, #3<<4
-       orr     r12, r12, #1<<7
-       str     r12, [ r14, #0x54 ]
-#endif
-
-#ifdef CONFIG_DEBUG_RESUME
-       mov     r3, #'L'
-       strb    r3, [ r2, #S3C2410_UTXH ]
-1001:
-       ldrb    r14, [ r3, #S3C2410_UTRSTAT ]
-       tst     r14, #S3C2410_UTRSTAT_TXE
-       beq     1001b
-#endif /* CONFIG_DEBUG_RESUME */
-
-       mov     r1, #0
-       mcr     p15, 0, r1, c8, c7, 0           @@ invalidate I & D TLBs
-       mcr     p15, 0, r1, c7, c7, 0           @@ invalidate I & D caches
-
-       ldr     r0, s3c2410_sleep_save_phys     @ address of restore block
-       ldmia   r0, { r4 - r13 }
-
-       mcr     p15, 0, r4, c15, c1, 0          @ CP access register
-       mcr     p15, 0, r5, c13, c0, 0          @ PID
-       mcr     p15, 0, r6, c3, c0, 0           @ Domain ID
-       mcr     p15, 0, r7, c2, c0, 0           @ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
-       mov     r3, #'R'
-       strb    r3, [ r2, #S3C2410_UTXH ]
-#endif
-
-       ldr     r2, =resume_with_mmu
-       mcr     p15, 0, r8, c1, c0, 0           @ turn on MMU, etc
-       nop                                     @ second-to-last before mmu
-       mov     pc, r2                          @ go back to virtual address
-
-       .ltorg
+ENTRY(s3c2410_cpu_suspend)
+       @@ prepare cpu to sleep
+
+       ldr     r4, =S3C2410_REFRESH
+       ldr     r5, =S3C24XX_MISCCR
+       ldr     r6, =S3C2410_CLKCON
+       ldr     r7, [ r4 ]              @ get REFRESH (and ensure in TLB)
+       ldr     r8, [ r5 ]              @ get MISCCR (and ensure in TLB)
+       ldr     r9, [ r6 ]              @ get CLKCON (and ensure in TLB)
+
+       orr     r7, r7, #S3C2410_REFRESH_SELF   @ SDRAM sleep command
+       orr     r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+       orr     r9, r9, #S3C2410_CLKCON_POWER   @ power down command
+
+       teq     pc, #0                  @ first as a trial-run to load cache
+       bl      s3c2410_do_sleep
+       teq     r0, r0                  @ now do it for real
+       b       s3c2410_do_sleep        @
+
+       @@ align next bit of code to cache line
+       .align  5
+s3c2410_do_sleep:
+       streq   r7, [ r4 ]                      @ SDRAM sleep command
+       streq   r8, [ r5 ]                      @ SDRAM power-down config
+       streq   r9, [ r6 ]                      @ CPU sleep
+1:     beq     1b
+       mov     pc, r14
index 22b0e1cdd4bf3d4e584588b4399c54646c673847..bcd562ac1d3da4899dca3b73ac3e9184e6c2d55e 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "devs.h"
+#include <asm/plat-s3c24xx/devs.h>
 #include "usb-simtec.h"
 
 /* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
new file mode 100644 (file)
index 0000000..befc5fd
--- /dev/null
@@ -0,0 +1,58 @@
+# arch/arm/mach-s3c2412/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2412
+       bool
+       depends on ARCH_S3C2410
+       select S3C2412_PM if PM
+       select S3C2412_DMA if S3C2410_DMA
+       help
+         Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C2412_ONLY
+       bool
+       depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+                  !CPU_S3C2440 && !CPU_S3C2442 && !CPU_S3C2443 && CPU_S3C2412
+       default y if CPU_S3C2412
+
+config S3C2412_DMA
+       bool
+       depends on CPU_S3C2412
+       help
+         Internal config node for S3C2412 DMA support
+
+config S3C2412_PM
+       bool
+       help
+         Internal config node to apply S3C2412 power management
+
+
+menu "S3C2412 Machines"
+
+config MACH_SMDK2413
+       bool "SMDK2413"
+       select CPU_S3C2412
+       select MACH_S3C2413
+       select MACH_SMDK
+       help
+         Say Y here if you are using an SMDK2413
+
+config MACH_S3C2413
+       bool
+       help
+         Internal node for S3C2413 version of SMDK2413, so that
+         machine_is_s3c2413() will work when MACH_SMDK2413 is
+         selected
+
+config MACH_VSTMS
+       bool "VMSTMS"
+       select CPU_S3C2412
+       help
+         Say Y here if you are using an VSTMS board
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
new file mode 100644 (file)
index 0000000..f8e0116
--- /dev/null
@@ -0,0 +1,21 @@
+# arch/arm/mach-s3c2412/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)      += irq.o
+obj-$(CONFIG_CPU_S3C2412)      += clock.o
+obj-$(CONFIG_S3C2412_DMA)      += dma.o
+obj-$(CONFIG_S3C2412_PM)       += pm.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2413)    += mach-smdk2413.o
+obj-$(CONFIG_MACH_VSTMS)       += mach-vstms.o
similarity index 99%
rename from arch/arm/mach-s3c2410/s3c2412-clock.c
rename to arch/arm/mach-s3c2412/clock.c
index 8f94ad83901db64ed762ba6c2c400cc8d12d1937..6a8e4448770bdce38870138b780db90477932bcf 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+/* linux/arch/arm/mach-s3c2412/clock.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -41,9 +41,9 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "s3c2412.h"
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* We currently have to assume that the system is running
  * from the XTPll input, and that all ***REFCLKs are being
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2412-dma.c
rename to arch/arm/mach-s3c2412/dma.c
index 138f726ac6bfa8efcbd38bae070fb83ee5ecee40..d0f4695c09d9c7bdf7b0413e2588f070d8e87491 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
+/* linux/arch/arm/mach-s3c2412/dma.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -21,8 +21,8 @@
 #include <asm/arch/dma.h>
 #include <asm/io.h>
 
-#include "dma.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
@@ -146,6 +146,7 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
 
 static int s3c2412_dma_add(struct sys_device *sysdev)
 {
+       s3c2410_dma_init();
        return s3c24xx_dma_init_map(&s3c2412_dma_sel);
 }
 
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2412-irq.c
rename to arch/arm/mach-s3c2412/irq.c
index ffcc30b23a8052d1a0abf920b4cdeed0ad203f9e..e89dbdcb1b7bf70c68d8a3b8288a69dd2ad80cd9 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
+/* linux/arch/arm/mach-s3c2412/irq.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "irq.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/irq.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 /* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
  * having them turn up in both the INT* and the EINT* registers. Whilst
similarity index 67%
rename from arch/arm/mach-s3c2410/mach-smdk2413.c
rename to arch/arm/mach-s3c2412/mach-smdk2413.c
index 4f89abd7a6dfcd03a58365e562fe205b73414618..b5befce6c8d3ba517858d6852484edd6fcee228b 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+/* linux/arch/arm/mach-s3c2412/mach-smdk2413.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/arch/regs-lcd.h>
 
 #include <asm/arch/idle.h>
+#include <asm/arch/udc.h>
 #include <asm/arch/fb.h>
 
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2413_iodesc[] __initdata = {
 };
@@ -75,12 +76,38 @@ static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
        }
 };
 
+static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+       printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+       switch (cmd)
+       {
+               case S3C2410_UDC_P_ENABLE :
+                       s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+                       break;
+               case S3C2410_UDC_P_DISABLE :
+                       s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+                       break;
+               case S3C2410_UDC_P_RESET :
+                       break;
+               default:
+                       break;
+       }
+}
+
+
+static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
+       .udc_command            = smdk2413_udc_pullup,
+};
+
+
 static struct platform_device *smdk2413_devices[] __initdata = {
        &s3c_device_usb,
        //&s3c_device_lcd,
        &s3c_device_wdt,
        &s3c_device_i2c,
        &s3c_device_iis,
+       &s3c_device_usbgadget,
 };
 
 static struct s3c24xx_board smdk2413_board __initdata = {
@@ -109,7 +136,19 @@ static void __init smdk2413_map_io(void)
 }
 
 static void __init smdk2413_machine_init(void)
-{
+{      /* Turn off suspend on both USB ports, and switch the
+        * selectable USB port to USB device mode. */
+
+       s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+       s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPIO_OUTPUT);
+
+       s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+                             S3C2410_MISCCR_USBSUSPND0 |
+                             S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+
+       s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
+
        smdk_machine_init();
 }
 
@@ -126,6 +165,19 @@ MACHINE_START(S3C2413, "S3C2413")
        .timer          = &s3c24xx_timer,
 MACHINE_END
 
+MACHINE_START(SMDK2412, "SMDK2412")
+       /* Maintainer: Ben Dooks <ben@fluff.org> */
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+
+       .fixup          = smdk2413_fixup,
+       .init_irq       = s3c24xx_init_irq,
+       .map_io         = smdk2413_map_io,
+       .init_machine   = smdk2413_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
+
 MACHINE_START(SMDK2413, "SMDK2413")
        /* Maintainer: Ben Dooks <ben@fluff.org> */
        .phys_io        = S3C2410_PA_UART,
similarity index 93%
rename from arch/arm/mach-s3c2410/mach-vstms.c
rename to arch/arm/mach-s3c2412/mach-vstms.c
index 0360e1055bcd7485e1b6f8e0cfee40310644e4c4..4231b549d7975b42f1b9d84d5246d18769d18a8b 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-vstms.c
+/* linux/arch/arm/mach-s3c2412/mach-vstms.c
  *
  * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
  *
@@ -28,7 +28,6 @@
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
 #include <asm/arch/nand.h>
 
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 
 static struct map_desc vstms_iodesc[] __initdata = {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2412-pm.c
rename to arch/arm/mach-s3c2412/pm.c
index 19b63322d2592c32404b23acb194f2c40c3f4feb..8988dac388a9cf83e3182f4aac1a0d19c3431f29 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
+/* linux/arch/arm/mach-s3c2412/pm.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
 
 static void s3c2412_cpu_suspend(void)
 {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2412.c
rename to arch/arm/mach-s3c2412/s3c2412.c
index 2f651a811ecd5f6c513a5731274192ba28c03673..aafe0bc593f17bb92f8e32c0b82391c260bf0a7d 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412.c
+/* linux/arch/arm/mach-s3c2412/s3c2412.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/arch/regs-gpioj.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "s3c2412.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 #ifndef CONFIG_CPU_S3C2412_ONLY
 void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
new file mode 100644 (file)
index 0000000..e3bfda0
--- /dev/null
@@ -0,0 +1,71 @@
+# arch/arm/mach-s3c2440/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2440
+       bool
+       depends on ARCH_S3C2410
+       select S3C2410_CLOCK
+       select S3C2410_PM if PM
+       select S3C2410_GPIO
+       select S3C2440_DMA if S3C2410_DMA
+       select CPU_S3C244X
+       help
+         Support for S3C2440 Samsung Mobile CPU based systems.
+
+config S3C2440_DMA
+       bool
+       depends on ARCH_S3C2410 && CPU_S3C24405B
+       help
+         Support for S3C2440 specific DMA code5A
+
+
+menu "S3C2440 Machines"
+
+config MACH_ANUBIS
+       bool "Simtec Electronics ANUBIS"
+       select CPU_S3C2440
+       select PM_SIMTEC if PM
+       help
+         Say Y here if you are using the Simtec Electronics ANUBIS
+         development system
+
+config MACH_OSIRIS
+       bool "Simtec IM2440D20 (OSIRIS) module"
+       select CPU_S3C2440
+       select PM_SIMTEC if PM
+       help
+         Say Y here if you are using the Simtec IM2440D20 module, also
+         known as the Osiris.
+
+config MACH_RX3715
+       bool "HP iPAQ rx3715"
+       select CPU_S3C2440
+       select PM_H1940 if PM
+       help
+         Say Y here if you are using the HP iPAQ rx3715.
+
+config ARCH_S3C2440
+       bool "SMDK2440"
+       select CPU_S3C2440
+       select MACH_SMDK
+       help
+         Say Y here if you are using the SMDK2440.
+
+config MACH_NEXCODER_2440
+       bool "NexVision NEXCODER 2440 Light Board"
+       select CPU_S3C2440
+       help
+         Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
+
+config SMDK2440_CPU2440
+       bool "SMDK2440 with S3C2440 CPU module"
+       depends on ARCH_S3C2440
+       default y if ARCH_S3C2440
+       select CPU_S3C2440
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
new file mode 100644 (file)
index 0000000..c81ed62
--- /dev/null
@@ -0,0 +1,23 @@
+# arch/arm/mach-s3c2440/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_CPU_S3C2440)      += s3c2440.o dsc.o
+obj-$(CONFIG_CPU_S3C2440)      += irq.o
+obj-$(CONFIG_CPU_S3C2440)      += clock.o
+obj-$(CONFIG_S3C2440_DMA)      += dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_ANUBIS)      += mach-anubis.o
+obj-$(CONFIG_MACH_OSIRIS)      += mach-osiris.o
+obj-$(CONFIG_MACH_RX3715)      += mach-rx3715.o
+obj-$(CONFIG_ARCH_S3C2440)     += mach-smdk2440.o
+obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2440-clock.c
rename to arch/arm/mach-s3c2440/clock.c
index ba13c1d079d100c9b4759b6c89039bd46cf782b5..79e2ea4adaf36defb9b1f863c1a0444146d2a9e0 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
+/* linux/arch/arm/mach-s3c2440/clock.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
 
 #include <asm/arch/regs-clock.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* S3C2440 extended clock support */
 
similarity index 83%
rename from arch/arm/mach-s3c2410/s3c2440-dma.c
rename to arch/arm/mach-s3c2440/dma.c
index 47b861b9443d7d0a864e0f3d367987e8c0e251de..cd035a3ec878be42d8d75b53229db416d04a274a 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
+/* linux/arch/arm/mach-s3c2440/dma.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -19,9 +19,9 @@
 
 #include <asm/dma.h>
 #include <asm/arch/dma.h>
-#include "dma.h"
 
-#include "cpu.h"
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
@@ -147,8 +147,53 @@ static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
        .map_size       = ARRAY_SIZE(s3c2440_dma_mappings),
 };
 
+static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
+       .channels       = {
+               [DMACH_SDI]     = {
+                       .list   = {
+                               [0]     = 3 | DMA_CH_VALID,
+                               [1]     = 2 | DMA_CH_VALID,
+                               [2]     = 1 | DMA_CH_VALID,
+                               [3]     = 0 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_I2S_IN]  = {
+                       .list   = {
+                               [0]     = 1 | DMA_CH_VALID,
+                               [1]     = 2 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_I2S_OUT] = {
+                       .list   = {
+                               [0]     = 2 | DMA_CH_VALID,
+                               [1]     = 1 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_PCM_IN] = {
+                       .list   = {
+                               [0]     = 2 | DMA_CH_VALID,
+                               [1]     = 1 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_PCM_OUT] = {
+                       .list   = {
+                               [0]     = 1 | DMA_CH_VALID,
+                               [1]     = 3 | DMA_CH_VALID,
+                       },
+               },
+               [DMACH_MIC_IN] = {
+                       .list   = {
+                               [0]     = 3 | DMA_CH_VALID,
+                               [1]     = 2 | DMA_CH_VALID,
+                       },
+               },
+       },
+};
+
 static int s3c2440_dma_add(struct sys_device *sysdev)
 {
+       s3c2410_dma_init();
+       s3c24xx_dma_order_set(&s3c2440_dma_order);
        return s3c24xx_dma_init_map(&s3c2440_dma_sel);
 }
 
similarity index 91%
rename from arch/arm/mach-s3c2410/s3c2440-dsc.c
rename to arch/arm/mach-s3c2440/dsc.c
index c92ea66ba45e5599b99d59efae967268630a5046..2995ff5681bbde83f82c1ee065950d6611959bf5 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
+/* linux/arch/arm/mach-s3c2440/dsc.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -27,8 +27,8 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "cpu.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
 
 int s3c2440_set_dsc(unsigned int pin, unsigned int value)
 {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2440-irq.c
rename to arch/arm/mach-s3c2440/irq.c
index 1ba19b27ab0560c18bde1709aad224de3d47fc0a..1069d13d8c5792732871471c228e025f13a029a6 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+/* linux/arch/arm/mach-s3c2440/irq.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
 
 /* WDT/AC97 */
 
similarity index 98%
rename from arch/arm/mach-s3c2410/mach-anubis.c
rename to arch/arm/mach-s3c2440/mach-anubis.c
index 0fad0c2fe07b3b33d72b5d92dc2f0629dddd6934..3f0288eb1ed5c9e69abbfee77e1c489f2125daba 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-anubis.c
+/* linux/arch/arm/mach-s3c2440/mach-anubis.c
  *
  * Copyright (c) 2003-2005 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
@@ -42,9 +42,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
similarity index 94%
rename from arch/arm/mach-s3c2410/mach-nexcoder.c
rename to arch/arm/mach-s3c2440/mach-nexcoder.c
index d6dfdad8c90bbdd9d4d442dd0c64ec40086c510a..6d551d88330b4b48af834cd84a01f88b01c05690 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c
+/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
  *
  * Copyright (c) 2004 Nex Vision
  *   Guillaume GOURAT <guillaume.gourat@nexvision.tv>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-serial.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc nexcoder_iodesc[] __initdata = {
        /* nothing here yet */
similarity index 97%
rename from arch/arm/mach-s3c2410/mach-osiris.c
rename to arch/arm/mach-s3c2440/mach-osiris.c
index 37b40850c9b9006d9caeef435fc2a08ce24ee4a6..2ed8e51f20c8525378ced153896b11e080db0cbe 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-osiris.c
+/* linux/arch/arm/mach-s3c2440/mach-osiris.c
  *
  * Copyright (c) 2005 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
@@ -41,9 +41,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* onboard perihpheral map */
 
similarity index 96%
rename from arch/arm/mach-s3c2410/mach-rx3715.c
rename to arch/arm/mach-s3c2440/mach-rx3715.c
index ecbcdf79d739b9abf1f4f5e248aca5292a412e39..480ccde63fb4e9a8d679f300255da09763f968dd 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-rx3715.c
+/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -33,7 +33,6 @@
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/arch/nand.h>
 #include <asm/arch/fb.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc rx3715_iodesc[] __initdata = {
        /* dump ISA space somewhere unused */
similarity index 93%
rename from arch/arm/mach-s3c2410/mach-smdk2440.c
rename to arch/arm/mach-s3c2440/mach-smdk2440.c
index 2b61f4ed1da410fa21449d3ce95af14c80b0c005..c17eb5b1f6b465a4446c1cf0b05ad981f38eb7a3 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
+/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
  *
  * Copyright (c) 2004,2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-//#include <asm/debug-ll.h>
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/idle.h>
 #include <asm/arch/fb.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
@@ -144,6 +142,7 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
 #endif
 
        .lpcsel         = ((0xCE6) & ~7) | 1<<4,
+       .type           = S3C2410_LCDCON1_TFT16BPP,
 
        .width          = 240,
        .height         = 320,
similarity index 88%
rename from arch/arm/mach-s3c2410/s3c2440.c
rename to arch/arm/mach-s3c2440/s3c2440.c
index 344eb27cca48cf7ecb8138431348bf6d46d03c15..90e1da61fbc3641b0f4d90045e138c4e09bc8c00 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440.c
+/* linux/arch/arm/mach-s3c2440/s3c2440.c
  *
  * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,9 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "s3c2440.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct sys_device s3c2440_sysdev = {
        .cls            = &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
new file mode 100644 (file)
index 0000000..bf8d87a
--- /dev/null
@@ -0,0 +1,27 @@
+# arch/arm/mach-s3c2442/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2442
+       bool
+       depends on ARCH_S3C2420
+       select S3C2410_CLOCK
+       select S3C2410_GPIO
+       select S3C2410_PM if PM
+       select CPU_S3C244X
+       help
+         Support for S3C2442 Samsung Mobile CPU based systems.
+
+
+menu "S3C2442 Machines"
+
+config SMDK2440_CPU2442
+       bool "SMDM2440 with S3C2442 CPU module"
+       depends on ARCH_S3C2440
+       select CPU_S3C2442
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
new file mode 100644 (file)
index 0000000..2a909c6
--- /dev/null
@@ -0,0 +1,16 @@
+# arch/arm/mach-s3c2442/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_CPU_S3C2442)      += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)      += clock.o
+
+# Machine support
+
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2442-clock.c
rename to arch/arm/mach-s3c2442/clock.c
index 4e292ca7c9be7f7731fffe76ee2a1c358384546c..5b9e830ac4d30a337529ad5e3609e786932f5954 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+/* linux/arch/arm/mach-s3c2442/clock.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
 
 #include <asm/arch/regs-clock.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* S3C2442 extended clock support */
 
similarity index 86%
rename from arch/arm/mach-s3c2410/s3c2442.c
rename to arch/arm/mach-s3c2442/s3c2442.c
index 428732ee68c41520c4cf4acb72ff4b5f6d11c166..fbf8264249da376879221f29e82b08a4138657e3 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442.c
+/* linux/arch/arm/mach-s3c2442/s3c2442.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -19,8 +19,8 @@
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
 
-#include "s3c2442.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct sys_device s3c2442_sysdev = {
        .cls            = &s3c2442_sysclass,
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
new file mode 100644 (file)
index 0000000..c649bb2
--- /dev/null
@@ -0,0 +1,29 @@
+# arch/arm/mach-s3c2443/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2443
+       bool
+       depends on ARCH_S3C2410
+       select S3C2443_DMA if S3C2410_DMA
+       help
+         Support for the S3C2443 SoC from the S3C24XX line
+
+config S3C2443_DMA
+       bool
+       depends on CPU_S3C2443
+       help
+         Internal config node for S3C2443 DMA support
+
+menu "S3C2443 Machines"
+
+config MACH_SMDK2443
+       bool "SMDK2443"
+       select CPU_S3C2443
+       select MACH_SMDK
+       help
+         Say Y here if you are using an SMDK2443
+
+endmenu
diff --git a/arch/arm/mach-s3c2443/Makefile b/arch/arm/mach-s3c2443/Makefile
new file mode 100644 (file)
index 0000000..d1843c9
--- /dev/null
@@ -0,0 +1,20 @@
+# arch/arm/mach-s3c2443/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_CPU_S3C2443)      += s3c2443.o
+obj-$(CONFIG_CPU_S3C2443)      += irq.o
+obj-$(CONFIG_CPU_S3C2443)      += clock.o
+
+obj-$(CONFIG_S3C2443_DMA)      += dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2443)    += mach-smdk2443.o
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
new file mode 100644 (file)
index 0000000..dd2272f
--- /dev/null
@@ -0,0 +1,1007 @@
+/* linux/arch/arm/mach-s3c2443/clock.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-s3c2443-clock.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
+
+       clkcon = __raw_readl(S3C2443_HCLKCON);
+
+       if (enable)
+               clkcon |= clocks;
+       else
+               clkcon &= ~clocks;
+
+       __raw_writel(clkcon, S3C2443_HCLKCON);
+
+       return 0;
+}
+
+static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
+
+       clkcon = __raw_readl(S3C2443_PCLKCON);
+
+       if (enable)
+               clkcon |= clocks;
+       else
+               clkcon &= ~clocks;
+
+       __raw_writel(clkcon, S3C2443_HCLKCON);
+
+       return 0;
+}
+
+static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
+
+       clkcon = __raw_readl(S3C2443_SCLKCON);
+
+       if (enable)
+               clkcon |= clocks;
+       else
+               clkcon &= ~clocks;
+
+       __raw_writel(clkcon, S3C2443_SCLKCON);
+
+       return 0;
+}
+
+static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
+                                             unsigned long rate,
+                                             unsigned int max)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       int div;
+
+       if (rate > parent_rate)
+               return parent_rate;
+
+       /* note, we remove the +/- 1 calculations as they cancel out */
+
+       div = (rate / parent_rate);
+
+       if (div < 1)
+               div = 1;
+       else if (div > max)
+               div = max;
+
+       return parent_rate / div;
+}
+
+static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
+                                              unsigned long rate)
+{
+       return s3c2443_roundrate_clksrc(clk, rate, 4);
+}
+
+static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
+                                               unsigned long rate)
+{
+       return s3c2443_roundrate_clksrc(clk, rate, 16);
+}
+
+static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
+                                                unsigned long rate)
+{
+       return s3c2443_roundrate_clksrc(clk, rate, 256);
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+       .name           = "ext",
+       .id             = -1,
+};
+
+static struct clk clk_mpllref = {
+       .name           = "mpllref",
+       .parent         = &clk_xtal,
+       .id             = -1,
+};
+
+#if 0
+static struct clk clk_mpll = {
+       .name           = "mpll",
+       .parent         = &clk_mpllref,
+       .id             = -1,
+};
+#endif
+
+static struct clk clk_epllref;
+
+static struct clk clk_epll = {
+       .name           = "epll",
+       .parent         = &clk_epllref,
+       .id             = -1,
+};
+
+static struct clk clk_i2s_ext = {
+       .name           = "i2s-ext",
+       .id             = -1,
+};
+
+static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+       clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
+
+       if (parent == &clk_xtal)
+               clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
+       else if (parent == &clk_ext)
+               clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
+       else if (parent != &clk_mpllref)
+               return -EINVAL;
+
+       __raw_writel(clksrc, S3C2443_CLKSRC);
+       clk->parent = parent;
+
+       return 0;
+}
+
+static struct clk clk_epllref = {
+       .name           = "epllref",
+       .id             = -1,
+       .set_parent     = s3c2443_setparent_epllref,
+};
+
+static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV0);
+
+       div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
+       div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);       /* x2 */
+
+       return parent_rate / (div + 1);
+}
+
+static struct clk clk_mdivclk = {
+       .name           = "mdivclk",
+       .parent         = &clk_mpllref,
+       .id             = -1,
+       .get_rate       = s3c2443_getrate_mdivclk,
+};
+
+
+static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+       clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
+                   S3C2443_CLKSRC_EXTCLK_DIV);
+
+       if (parent == &clk_mpll)
+               clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
+       else if (parent == &clk_mdivclk)
+               clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
+       else if (parent != &clk_mpllref)
+               return -EINVAL;
+
+       __raw_writel(clksrc, S3C2443_CLKSRC);
+       clk->parent = parent;
+
+       return 0;
+}
+
+static struct clk clk_msysclk = {
+       .name           = "msysclk",
+       .parent         = &clk_xtal,
+       .id             = -1,
+       .set_parent     = s3c2443_setparent_msysclk,
+};
+
+
+/* esysclk
+ *
+ * this is sourced from either the EPLL or the EPLLref clock
+*/
+
+static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+       if (parent == &clk_epll)
+               clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
+       else if (parent == &clk_epllref)
+               clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
+       else
+               return -EINVAL;
+
+       __raw_writel(clksrc, S3C2443_CLKSRC);
+       clk->parent = parent;
+
+       return 0;
+}
+
+static struct clk clk_esysclk = {
+       .name           = "esysclk",
+       .parent         = &clk_epll,
+       .id             = -1,
+       .set_parent     = s3c2443_setparent_esysclk,
+};
+
+/* uartclk
+ *
+ * UART baud-rate clock sourced from esysclk via a divisor
+*/
+
+static unsigned long s3c2443_getrate_uart(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_UARTDIV_MASK;
+       div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc16(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_uart = {
+       .name           = "uartclk",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .get_rate       = s3c2443_getrate_uart,
+       .set_rate       = s3c2443_setrate_uart,
+       .round_rate     = s3c2443_roundrate_clksrc16,
+};
+
+/* hsspi
+ *
+ * high-speed spi clock, sourced from esysclk
+*/
+
+static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
+       div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc4(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_hsspi = {
+       .name           = "hsspi",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
+       .enable         = s3c2443_clkcon_enable_s,
+       .get_rate       = s3c2443_getrate_hsspi,
+       .set_rate       = s3c2443_setrate_hsspi,
+       .round_rate     = s3c2443_roundrate_clksrc4,
+};
+
+/* usbhost
+ *
+ * usb host bus-clock, usually 48MHz to provide USB bus clock timing
+*/
+
+static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+       div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc4(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+struct clk clk_usb_bus_host = {
+       .name           = "usb-bus-host-parent",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .ctrlbit        = S3C2443_SCLKCON_USBHOST,
+       .enable         = s3c2443_clkcon_enable_s,
+       .get_rate       = s3c2443_getrate_usbhost,
+       .set_rate       = s3c2443_setrate_usbhost,
+       .round_rate     = s3c2443_roundrate_clksrc4,
+};
+
+/* clk_hsmcc_div
+ *
+ * this clock is sourced from epll, and is fed through a divider,
+ * to a mux controlled by sclkcon where either it or a extclk can
+ * be fed to the hsmmc block
+*/
+
+static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
+       div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc4(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_hsmmc_div = {
+       .name           = "hsmmc-div",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .get_rate       = s3c2443_getrate_hsmmc_div,
+       .set_rate       = s3c2443_setrate_hsmmc_div,
+       .round_rate     = s3c2443_roundrate_clksrc4,
+};
+
+static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
+
+       clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
+                   S3C2443_SCLKCON_HSMMCCLK_EPLL);
+
+       if (parent == &clk_epll)
+               clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
+       else if (parent == &clk_ext)
+               clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
+       else
+               return -EINVAL;
+
+       if (clk->usage > 0) {
+               __raw_writel(clksrc, S3C2443_SCLKCON);
+       }
+
+       clk->parent = parent;
+       return 0;
+}
+
+static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
+{
+       return s3c2443_setparent_hsmmc(clk, clk->parent);
+}
+
+static struct clk clk_hsmmc = {
+       .name           = "hsmmc-if",
+       .id             = -1,
+       .parent         = &clk_hsmmc_div,
+       .enable         = s3c2443_enable_hsmmc,
+       .set_parent     = s3c2443_setparent_hsmmc,
+};
+
+/* i2s_eplldiv
+ *
+ * this clock is the output from the i2s divisor of esysclk
+*/
+
+static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_I2SDIV_MASK;
+       div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc16(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_i2s_eplldiv = {
+       .name           = "i2s-eplldiv",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .get_rate       = s3c2443_getrate_i2s_eplldiv,
+       .set_rate       = s3c2443_setrate_i2s_eplldiv,
+       .round_rate     = s3c2443_roundrate_clksrc16,
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+*/
+
+static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+       clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
+
+       if (parent == &clk_epllref)
+               clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
+       else if (parent == &clk_i2s_ext)
+               clksrc |= S3C2443_CLKSRC_I2S_EXT;
+       else if (parent != &clk_i2s_eplldiv)
+               return -EINVAL;
+
+       clk->parent = parent;
+       __raw_writel(clksrc, S3C2443_CLKSRC);
+
+       return 0;
+}
+
+static struct clk clk_i2s = {
+       .name           = "i2s-if",
+       .id             = -1,
+       .parent         = &clk_i2s_eplldiv,
+       .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
+       .enable         = s3c2443_clkcon_enable_s,
+       .set_parent     = s3c2443_setparent_i2s,
+};
+
+/* cam-if
+ *
+ * camera interface bus-clock, divided down from esysclk
+*/
+
+static unsigned long s3c2443_getrate_cam(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div  &= S3C2443_CLKDIV1_CAMDIV_MASK;
+       div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc16(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
+       clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+       __raw_writel(clkdiv1, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_cam = {
+       .name           = "camif-upll",         /* same as 2440 name */
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .ctrlbit        = S3C2443_SCLKCON_CAMCLK,
+       .enable         = s3c2443_clkcon_enable_s,
+       .get_rate       = s3c2443_getrate_cam,
+       .set_rate       = s3c2443_setrate_cam,
+       .round_rate     = s3c2443_roundrate_clksrc16,
+};
+
+/* display-if
+ *
+ * display interface clock, divided from esysclk
+*/
+
+static unsigned long s3c2443_getrate_display(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+       div &= S3C2443_CLKDIV1_DISPDIV_MASK;
+       div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+       rate = s3c2443_roundrate_clksrc256(clk, rate);
+       rate = parent_rate / rate;
+
+       clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+       clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2443_CLKDIV1);
+       return 0;
+}
+
+static struct clk clk_display = {
+       .name           = "display-if",
+       .id             = -1,
+       .parent         = &clk_esysclk,
+       .ctrlbit        = S3C2443_SCLKCON_DISPCLK,
+       .enable         = s3c2443_clkcon_enable_s,
+       .get_rate       = s3c2443_getrate_display,
+       .set_rate       = s3c2443_setrate_display,
+       .round_rate     = s3c2443_roundrate_clksrc256,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_h,
+       }, {
+               .name           = "sdi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_SDI,
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_ADC,
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_IIC,
+       }, {
+               .name           = "iis",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_IIS,
+       }, {
+               .name           = "spi",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_SPI0,
+       }, {
+               .name           = "spi",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_SPI1,
+       }
+};
+
+static struct clk init_clocks[] = {
+       {
+               .name           = "dma",
+               .id             = 0,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA0,
+       }, {
+               .name           = "dma",
+               .id             = 1,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA1,
+       }, {
+               .name           = "dma",
+               .id             = 2,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA2,
+       }, {
+               .name           = "dma",
+               .id             = 3,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA3,
+       }, {
+               .name           = "dma",
+               .id             = 4,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA4,
+       }, {
+               .name           = "dma",
+               .id             = 5,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_DMA5,
+       }, {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_LCDC,
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_GPIO,
+       }, {
+               .name           = "usb-host",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_USBH,
+       }, {
+               .name           = "usb-device",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2443_clkcon_enable_h,
+               .ctrlbit        = S3C2443_HCLKCON_USBD,
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_PWMT,
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_UART0,
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_UART1,
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_UART2,
+       }, {
+               .name           = "uart",
+               .id             = 3,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_UART3,
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_RTC,
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = S3C2443_PCLKCON_WDT,
+       }, {
+               .name           = "usb-bus-host",
+               .id             = -1,
+               .parent         = &clk_usb_bus_host,
+       }
+};
+
+/* clocks to add where we need to check their parentage */
+
+/* s3c2443_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
+{
+       printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
+       return clk_set_parent(clk, parent);
+}
+
+static void __init s3c2443_clk_initparents(void)
+{
+       unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+       struct clk *parent;
+
+       switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
+       case S3C2443_CLKSRC_EPLLREF_EXTCLK:
+               parent = &clk_ext;
+               break;
+
+       case S3C2443_CLKSRC_EPLLREF_XTAL:
+       default:
+               parent = &clk_xtal;
+               break;
+
+       case S3C2443_CLKSRC_EPLLREF_MPLLREF:
+       case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
+               parent = &clk_mpllref;
+               break;
+       }
+
+       clk_init_set_parent(&clk_epllref, parent);
+
+       switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
+       case S3C2443_CLKSRC_I2S_EXT:
+               parent = &clk_i2s_ext;
+               break;
+
+       case S3C2443_CLKSRC_I2S_EPLLDIV:
+       default:
+               parent = &clk_i2s_eplldiv;
+               break;
+
+       case S3C2443_CLKSRC_I2S_EPLLREF:
+       case S3C2443_CLKSRC_I2S_EPLLREF3:
+               parent = &clk_epllref;
+       }
+
+       clk_init_set_parent(&clk_i2s, &clk_epllref);
+
+       /* esysclk source */
+
+       parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
+               &clk_epll : &clk_epllref;
+
+       clk_init_set_parent(&clk_esysclk, parent);
+
+       /* msysclk source */
+
+       if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
+               parent = &clk_mpll;
+       } else {
+               parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
+                       &clk_mdivclk : &clk_mpllref;
+       }
+
+       clk_init_set_parent(&clk_msysclk, parent);
+}
+
+/* armdiv divisor table */
+
+static unsigned int armdiv[16] = {
+       [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 1,
+       [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 2,
+       [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 3,
+       [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 4,
+       [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 6,
+       [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 8,
+       [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 12,
+       [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 16,
+};
+
+static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
+{
+       clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
+
+       return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
+}
+
+static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0)
+{
+       clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;
+       clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
+
+       return clkcon0 + 1;
+}
+
+/* clocks to add straight away */
+
+static struct clk *clks[] __initdata = {
+       &clk_ext,
+       &clk_epll,
+       &clk_usb_bus_host,
+       &clk_usb_bus,
+       &clk_esysclk,
+       &clk_epllref,
+       &clk_mpllref,
+       &clk_msysclk,
+       &clk_uart,
+       &clk_display,
+       &clk_cam,
+       &clk_i2s_eplldiv,
+       &clk_i2s,
+       &clk_hsspi,
+       &clk_hsmmc_div,
+       &clk_hsmmc,
+};
+
+void __init s3c2443_init_clocks(int xtal)
+{
+       unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
+       unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
+       unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
+       unsigned long pll;
+       unsigned long fclk;
+       unsigned long hclk;
+       unsigned long pclk;
+       struct clk *clkp;
+       int ret;
+       int ptr;
+
+       pll = s3c2443_get_mpll(mpllcon, xtal);
+
+       fclk = pll / s3c2443_fclk_div(clkdiv0);
+       hclk = fclk / s3c2443_get_prediv(clkdiv0);
+       hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
+       pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
+
+       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+
+       printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
+              (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+              print_mhz(pll), print_mhz(fclk),
+              print_mhz(hclk), print_mhz(pclk));
+
+       s3c2443_clk_initparents();
+
+       for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+               clkp = clks[ptr];
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
+
+       clk_usb_bus.parent = &clk_usb_bus_host;
+
+       /* ensure usb bus clock is within correct rate of 48MHz */
+
+       if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
+               printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
+               clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
+       }
+
+       printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+              (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+              print_mhz(clk_get_rate(&clk_epll)),
+              print_mhz(clk_get_rate(&clk_usb_bus)));
+
+       /* register clocks from clock array */
+
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       /* We must be careful disabling the clocks we are not intending to
+        * be using at boot time, as subsytems such as the LCD which do
+        * their own DMA requests to the bus can cause the system to lockup
+        * if they where in the middle of requesting bus access.
+        *
+        * Disabling the LCD clock if the LCD is active is very dangerous,
+        * and therefore the bootloader should be careful to not enable
+        * the LCD clock if it is not needed.
+       */
+
+       /* install (and disable) the clocks we do not need immediately */
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+
+               (clkp->enable)(clkp, 0);
+       }
+}
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
new file mode 100644 (file)
index 0000000..f70e8cc
--- /dev/null
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s3c2443/dma.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { \
+               [0]     = (x) | DMA_CH_VALID,   \
+               [1]     = (x) | DMA_CH_VALID,   \
+               [2]     = (x) | DMA_CH_VALID,   \
+               [3]     = (x) | DMA_CH_VALID,   \
+               [4]     = (x) | DMA_CH_VALID,   \
+               [5]     = (x) | DMA_CH_VALID,   \
+       }
+
+static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
+       [DMACH_XD0] = {
+               .name           = "xdreq0",
+               .channels       = MAP(S3C2443_DMAREQSEL_XDREQ0),
+       },
+       [DMACH_XD1] = {
+               .name           = "xdreq1",
+               .channels       = MAP(S3C2443_DMAREQSEL_XDREQ1),
+       },
+       [DMACH_SDI] = {
+               .name           = "sdi",
+               .channels       = MAP(S3C2443_DMAREQSEL_SDI),
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_SPI0] = {
+               .name           = "spi0",
+               .channels       = MAP(S3C2443_DMAREQSEL_SPI0TX),
+               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
+       },
+       [DMACH_SPI1] = {
+               .name           = "spi1",
+               .channels       = MAP(S3C2443_DMAREQSEL_SPI1TX),
+               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+       },
+       [DMACH_UART0] = {
+               .name           = "uart0",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART0_0),
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1] = {
+               .name           = "uart1",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART1_0),
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2] = {
+               .name           = "uart2",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART2_0),
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_UART3] = {
+               .name           = "uart3",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART3_0),
+               .hw_addr.to     = S3C2443_PA_UART3 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2443_PA_UART3 + S3C2410_URXH,
+       },
+       [DMACH_UART0_SRC2] = {
+               .name           = "uart0",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART0_1),
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1_SRC2] = {
+               .name           = "uart1",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART1_1),
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2_SRC2] = {
+               .name           = "uart2",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART2_1),
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_UART3_SRC2] = {
+               .name           = "uart3",
+               .channels       = MAP(S3C2443_DMAREQSEL_UART3_1),
+               .hw_addr.to     = S3C2443_PA_UART3 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2443_PA_UART3 + S3C2410_URXH,
+       },
+       [DMACH_TIMER] = {
+               .name           = "timer",
+               .channels       = MAP(S3C2443_DMAREQSEL_TIMER),
+       },
+       [DMACH_I2S_IN] = {
+               .name           = "i2s-sdi",
+               .channels       = MAP(S3C2443_DMAREQSEL_I2SRX),
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_I2S_OUT] = {
+               .name           = "i2s-sdo",
+               .channels       = MAP(S3C2443_DMAREQSEL_I2STX),
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_PCM_IN] = {
+               .name           = "pcm-in",
+               .channels       = MAP(S3C2443_DMAREQSEL_PCMIN),
+               .hw_addr.from   = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+       },
+       [DMACH_PCM_OUT] = {
+               .name           = "pcm-out",
+               .channels       = MAP(S3C2443_DMAREQSEL_PCMOUT),
+               .hw_addr.to     = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+       },
+       [DMACH_MIC_IN] = {
+               .name           = "mic-in",
+               .channels       = MAP(S3C2443_DMAREQSEL_MICIN),
+               .hw_addr.from   = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+       },
+};
+
+static void s3c2443_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
+{
+       writel(map->channels[0] | S3C2443_DMAREQSEL_HW,
+              chan->regs + S3C2443_DMA_DMAREQSEL);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
+       .select         = s3c2443_dma_select,
+       .dcon_mask      = 0,
+       .map            = s3c2443_dma_mappings,
+       .map_size       = ARRAY_SIZE(s3c2443_dma_mappings),
+};
+
+static int s3c2443_dma_add(struct sys_device *sysdev)
+{
+       s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
+       return s3c24xx_dma_init_map(&s3c2443_dma_sel);
+}
+
+static struct sysdev_driver s3c2443_dma_driver = {
+       .add    = s3c2443_dma_add,
+};
+
+static int __init s3c2443_dma_init(void)
+{
+       return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_dma_driver);
+}
+
+arch_initcall(s3c2443_dma_init);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
new file mode 100644 (file)
index 0000000..7a45b6d
--- /dev/null
@@ -0,0 +1,290 @@
+/* linux/arch/arm/mach-s3c2443/irq.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+
+static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
+{
+       unsigned int subsrc, submsk;
+       unsigned int end;
+       struct irq_desc *mydesc;
+
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
+
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+       subsrc  &= ~submsk;
+       subsrc >>= (irq - S3C2410_IRQSUB(0));
+       subsrc  &= (1 << len)-1;
+
+       end = len + irq;
+       mydesc = irq_desc + irq;
+
+       for (; irq < end && subsrc; irq++) {
+               if (subsrc & 1)
+                       desc_handle_irq(irq, mydesc);
+
+               mydesc++;
+               subsrc >>= 1;
+       }
+}
+
+/* WDT/AC97 sub interrupts */
+
+static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
+{
+       s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
+}
+
+#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
+#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
+
+static void s3c2443_irq_wdtac97_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static struct irq_chip s3c2443_irq_wdtac97 = {
+       .mask       = s3c2443_irq_wdtac97_mask,
+       .unmask     = s3c2443_irq_wdtac97_unmask,
+       .ack        = s3c2443_irq_wdtac97_ack,
+};
+
+
+/* LCD sub interrupts */
+
+static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
+{
+       s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
+}
+
+#define INTMSK_LCD     (1UL << (IRQ_LCD - IRQ_EINT0))
+#define SUBMSK_LCD     INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
+
+static void s3c2443_irq_lcd_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static struct irq_chip s3c2443_irq_lcd = {
+       .mask       = s3c2443_irq_lcd_mask,
+       .unmask     = s3c2443_irq_lcd_unmask,
+       .ack        = s3c2443_irq_lcd_ack,
+};
+
+
+/* DMA sub interrupts */
+
+static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
+{
+       s3c2443_irq_demux(IRQ_S3C2443_DMA1, 6);
+}
+
+#define INTMSK_DMA     (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
+#define SUBMSK_DMA     INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
+
+
+static void s3c2443_irq_dma_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static void s3c2443_irq_dma_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_DMA);
+}
+
+static void s3c2443_irq_dma_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static struct irq_chip s3c2443_irq_dma = {
+       .mask       = s3c2443_irq_dma_mask,
+       .unmask     = s3c2443_irq_dma_unmask,
+       .ack        = s3c2443_irq_dma_ack,
+};
+
+
+/* UART3 sub interrupts */
+
+static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
+{
+       s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
+}
+
+#define INTMSK_UART3   (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
+#define SUBMSK_UART3   (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
+
+
+static void s3c2443_irq_uart3_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static struct irq_chip s3c2443_irq_uart3 = {
+       .mask       = s3c2443_irq_uart3_mask,
+       .unmask     = s3c2443_irq_uart3_unmask,
+       .ack        = s3c2443_irq_uart3_ack,
+};
+
+
+/* CAM sub interrupts */
+
+static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
+{
+       s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
+}
+
+#define INTMSK_CAM     (1UL << (IRQ_CAM - IRQ_EINT0))
+#define SUBMSK_CAM     INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
+
+static void s3c2443_irq_cam_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static void s3c2443_irq_cam_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void s3c2443_irq_cam_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static struct irq_chip s3c2443_irq_cam = {
+       .mask       = s3c2443_irq_cam_mask,
+       .unmask     = s3c2443_irq_cam_unmask,
+       .ack        = s3c2443_irq_cam_ack,
+};
+
+/* IRQ initialisation code */
+
+static int __init s3c2443_add_sub(unsigned int base,
+                                  void (*demux)(unsigned int,
+                                                struct irq_desc *),
+                                  struct irq_chip *chip,
+                                  unsigned int start, unsigned int end)
+{
+       unsigned int irqno;
+
+       set_irq_chip(base, &s3c_irq_level_chip);
+       set_irq_handler(base, handle_level_irq);
+       set_irq_chained_handler(base, demux);
+
+       for (irqno = start; irqno <= end; irqno++) {
+               set_irq_chip(irqno, chip);
+               set_irq_handler(irqno, handle_level_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       return 0;
+}
+
+static int s3c2443_irq_add(struct sys_device *sysdev)
+{
+       printk("S3C2443: IRQ Support\n");
+
+       s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
+                       IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
+
+       s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
+                       IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
+
+       s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
+                       &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+
+       s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
+                       &s3c2443_irq_uart3,
+                       IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+
+       s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
+                       &s3c2443_irq_wdtac97,
+                       IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2443_irq_driver = {
+       .add            = s3c2443_irq_add,
+};
+
+static int s3c2443_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver);
+}
+
+arch_initcall(s3c2443_irq_init);
+
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
new file mode 100644 (file)
index 0000000..e82aaff
--- /dev/null
@@ -0,0 +1,137 @@
+/* linux/arch/arm/mach-s3c2443/mach-smdk2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2443/
+ *
+ * Thanks to Samsung for the loan of an SMDK2443
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+
+static struct map_desc smdk2443_iodesc[] __initdata = {
+       /* ISA IO Space map (memory space selected by A24) */
+
+       {
+               .virtual        = (u32)S3C24XX_VA_ISA_WORD,
+               .pfn            = __phys_to_pfn(S3C2410_CS2),
+               .length         = 0x10000,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+               .pfn            = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+               .length         = SZ_4M,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (u32)S3C24XX_VA_ISA_BYTE,
+               .pfn            = __phys_to_pfn(S3C2410_CS2),
+               .length         = 0x10000,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+               .pfn            = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+               .length         = SZ_4M,
+               .type           = MT_DEVICE,
+       }
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       /* IR port */
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x43,
+               .ufcon       = 0x51,
+       }
+};
+
+static struct platform_device *smdk2443_devices[] __initdata = {
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+};
+
+static struct s3c24xx_board smdk2443_board __initdata = {
+       .devices       = smdk2443_devices,
+       .devices_count = ARRAY_SIZE(smdk2443_devices)
+};
+
+static void __init smdk2443_map_io(void)
+{
+       s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
+       s3c24xx_set_board(&smdk2443_board);
+}
+
+static void __init smdk2443_machine_init(void)
+{
+       smdk_machine_init();
+}
+
+MACHINE_START(SMDK2443, "SMDK2443")
+       /* Maintainer: Ben Dooks <ben@fluff.org> */
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+
+       .init_irq       = s3c24xx_init_irq,
+       .map_io         = smdk2443_map_io,
+       .init_machine   = smdk2443_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
new file mode 100644 (file)
index 0000000..11b1d0b
--- /dev/null
@@ -0,0 +1,97 @@
+/* linux/arch/arm/mach-s3c2443/s3c2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2443 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-s3c2443-clock.h>
+#include <asm/arch/reset.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct map_desc s3c2443_iodesc[] __initdata = {
+       IODESC_ENT(WATCHDOG),
+       IODESC_ENT(CLKPWR),
+       IODESC_ENT(TIMER),
+};
+
+struct sysdev_class s3c2443_sysclass = {
+       set_kset_name("s3c2443-core"),
+};
+
+static struct sys_device s3c2443_sysdev = {
+       .cls            = &s3c2443_sysclass,
+};
+
+static void s3c2443_hard_reset(void)
+{
+       __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
+}
+
+int __init s3c2443_init(void)
+{
+       printk("S3C2443: Initialising architecture\n");
+
+       s3c24xx_reset_hook = s3c2443_hard_reset;
+
+       s3c_device_nand.name = "s3c2412-nand";
+
+       return sysdev_register(&s3c2443_sysdev);
+}
+
+void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+/* s3c2443_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+ */
+
+void __init s3c2443_map_io(struct map_desc *mach_desc, int mach_size)
+{
+       iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
+       iotable_init(mach_desc, mach_size);
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2443 based system)
+ * as a driver which may support both 2443 and 2440 may try and use it.
+*/
+
+static int __init s3c2443_core_init(void)
+{
+       return sysdev_class_register(&s3c2443_sysclass);
+}
+
+core_initcall(s3c2443_core_init);
index aade2f72c9209f995b4f7e70461742610648bccf..e684e9b38216dce35440d32025208f2041a41454 100644 (file)
@@ -171,8 +171,8 @@ config CPU_ARM925T
 # ARM926T
 config CPU_ARM926T
        bool "Support ARM926T processor"
-       depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
-       default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
+       depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
+       default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_CACHE_VIVT
@@ -525,7 +525,7 @@ config CPU_BIG_ENDIAN
          of your chipset/board/processor.
 
 config CPU_HIGH_VECTOR
-       depends !MMU && CPU_CP15 && !CPU_ARM740T
+       depends on !MMU && CPU_CP15 && !CPU_ARM740T
        bool "Select the High exception vector"
        default n
        help
@@ -609,3 +609,10 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
          Forget about fast user space cmpxchg support.
          It is just not possible.
 
+config OUTER_CACHE
+       bool
+       default n
+
+config CACHE_L2X0
+       bool
+       select OUTER_CACHE
index d2f5672ecf62e2a06967884f9edf1c7b53975ab6..2f8b95947774dc8d263ce753ba7cb64e2299d241 100644 (file)
@@ -66,3 +66,5 @@ obj-$(CONFIG_CPU_SA1100)      += proc-sa1100.o
 obj-$(CONFIG_CPU_XSCALE)       += proc-xscale.o
 obj-$(CONFIG_CPU_XSC3)         += proc-xsc3.o
 obj-$(CONFIG_CPU_V6)           += proc-v6.o
+
+obj-$(CONFIG_CACHE_L2X0)       += cache-l2x0.o
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
new file mode 100644 (file)
index 0000000..08a36f1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * 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
+ */
+#include <linux/init.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#define CACHE_LINE_SIZE                32
+
+static void __iomem *l2x0_base;
+
+static inline void sync_writel(unsigned long val, unsigned long reg,
+                              unsigned long complete_mask)
+{
+       writel(val, l2x0_base + reg);
+       /* wait for the operation to complete */
+       while (readl(l2x0_base + reg) & complete_mask)
+               ;
+}
+
+static inline void cache_sync(void)
+{
+       sync_writel(0, L2X0_CACHE_SYNC, 1);
+}
+
+static inline void l2x0_inv_all(void)
+{
+       /* invalidate all ways */
+       sync_writel(0xff, L2X0_INV_WAY, 0xff);
+       cache_sync();
+}
+
+static void l2x0_inv_range(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(CACHE_LINE_SIZE - 1);
+       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+               sync_writel(addr, L2X0_INV_LINE_PA, 1);
+       cache_sync();
+}
+
+static void l2x0_clean_range(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(CACHE_LINE_SIZE - 1);
+       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+               sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
+       cache_sync();
+}
+
+static void l2x0_flush_range(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(CACHE_LINE_SIZE - 1);
+       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+               sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
+       cache_sync();
+}
+
+void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+{
+       __u32 aux;
+
+       l2x0_base = base;
+
+       /* disable L2X0 */
+       writel(0, l2x0_base + L2X0_CTRL);
+
+       aux = readl(l2x0_base + L2X0_AUX_CTRL);
+       aux &= aux_mask;
+       aux |= aux_val;
+       writel(aux, l2x0_base + L2X0_AUX_CTRL);
+
+       l2x0_inv_all();
+
+       /* enable L2X0 */
+       writel(1, l2x0_base + L2X0_CTRL);
+
+       outer_cache.inv_range = l2x0_inv_range;
+       outer_cache.clean_range = l2x0_clean_range;
+       outer_cache.flush_range = l2x0_flush_range;
+
+       printk(KERN_INFO "L2X0 cache controller enabled\n");
+}
index 6a9c362fef5e241969c42c6133456fb901ce31a2..1f9f94f9af4bac8d99137cad55204afcc279c0e4 100644 (file)
@@ -205,9 +205,10 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
         * kernel direct-mapped region for device DMA.
         */
        {
-               unsigned long kaddr = (unsigned long)page_address(page);
-               memset(page_address(page), 0, size);
-               dmac_flush_range(kaddr, kaddr + size);
+               void *ptr = page_address(page);
+               memset(ptr, 0, size);
+               dmac_flush_range(ptr, ptr + size);
+               outer_flush_range(__pa(ptr), __pa(ptr) + size);
        }
 
        /*
@@ -480,20 +481,24 @@ core_initcall(consistent_init);
  * platforms with CONFIG_DMABOUNCE.
  * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
  */
-void consistent_sync(void *vaddr, size_t size, int direction)
+void consistent_sync(const void *start, size_t size, int direction)
 {
-       unsigned long start = (unsigned long)vaddr;
-       unsigned long end   = start + size;
+       const void *end = start + size;
+
+       BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
 
        switch (direction) {
        case DMA_FROM_DEVICE:           /* invalidate only */
                dmac_inv_range(start, end);
+               outer_inv_range(__pa(start), __pa(end));
                break;
        case DMA_TO_DEVICE:             /* writeback only */
                dmac_clean_range(start, end);
+               outer_clean_range(__pa(start), __pa(end));
                break;
        case DMA_BIDIRECTIONAL:         /* writeback and invalidate */
                dmac_flush_range(start, end);
+               outer_flush_range(__pa(start), __pa(end));
                break;
        default:
                BUG();
index 79e8002024240238aa86ff5086ad165b0bb91aa5..9da43a0fdcdffc5ff09b4e8fd1bdf6d95ac0452b 100644 (file)
@@ -19,7 +19,8 @@ unsigned int cpu_last_asid = { 1 << ASID_BITS };
 /*
  * We fork()ed a process, and we need a new context for the child
  * to run in.  We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
  */
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -38,8 +39,15 @@ void __new_context(struct mm_struct *mm)
         * If we've used up all our ASIDs, we need
         * to start a new version and flush the TLB.
         */
-       if ((asid & ~ASID_MASK) == 0)
+       if ((asid & ~ASID_MASK) == 0) {
+               asid = ++cpu_last_asid;
+               /* set the reserved ASID before flushing the TLB */
+               asm("mcr        p15, 0, %0, c13, c0, 1  @ set reserved context ID\n"
+                   :
+                   : "r" (0));
+               isb();
                flush_tlb_all();
+       }
 
        mm->context.id = asid;
 }
index cf95c5d0ce4cdb60f4ea317f07cde2c8de0764ba..44558d5f9313c0e22d476bc07cd995c466666e66 100644 (file)
@@ -119,8 +119,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigne
                flush_cache_page(vma, addr, pfn);
 }
 
-void __flush_dcache_page(struct address_space *mapping, struct page *page);
-
 /*
  * Take care of architecture specific things when placing a new PTE into
  * a page table, or changing an existing PTE.  Basically, there are two
index 655c8376f0b57b73ee48dca75ce0197e619605ac..94fd4bf5cb9e4f31dcd0c41f68b31dfce332b15a 100644 (file)
@@ -49,8 +49,10 @@ pmd_t *top_pmd;
 
 static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
 static unsigned int ecc_mask __initdata = 0;
+pgprot_t pgprot_user;
 pgprot_t pgprot_kernel;
 
+EXPORT_SYMBOL(pgprot_user);
 EXPORT_SYMBOL(pgprot_kernel);
 
 struct cachepolicy {
@@ -345,6 +347,7 @@ static void __init build_mem_type_table(void)
                mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
        }
 
+       pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
        pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
                                 L_PTE_DIRTY | L_PTE_WRITE |
                                 L_PTE_EXEC | kern_pgprot);
index 7b1843befb9c2deb693947e5cac5e1f5f8823d57..eb42e5b948630d106372b6296d71bdf02e7943d6 100644 (file)
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/elf.h>
-#include <asm/hardware/arm_scu.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_SMP
+#include <asm/hardware/arm_scu.h>
+#endif
+
 #include "proc-macros.S"
 
 #define D_CACHE_LINE_SIZE      32
 #define TTB_RGN_WT     (2 << 3)
 #define TTB_RGN_WB     (3 << 3)
 
+#ifndef CONFIG_SMP
+#define TTB_FLAGS      TTB_RGN_WBWA
+#else
+#define TTB_FLAGS      TTB_RGN_WBWA|TTB_S
+#endif
+
 ENTRY(cpu_v6_proc_init)
        mov     pc, lr
 
@@ -92,9 +101,7 @@ ENTRY(cpu_v6_switch_mm)
 #ifdef CONFIG_MMU
        mov     r2, #0
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
-#ifdef CONFIG_SMP
-       orr     r0, r0, #TTB_RGN_WBWA|TTB_S     @ mark PTWs shared, outer cacheable
-#endif
+       orr     r0, r0, #TTB_FLAGS
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
        mcr     p15, 0, r2, c7, c10, 4          @ drain write buffer
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
@@ -183,8 +190,7 @@ __v6_setup:
        /* Set up the SCU on core 0 only */
        mrc     p15, 0, r0, c0, c0, 5           @ CPU core number
        ands    r0, r0, #15
-       moveq   r0, #0x10000000 @ SCU_BASE
-       orreq   r0, r0, #0x00100000
+       ldreq   r0, =SCU_BASE
        ldreq   r5, [r0, #SCU_CTRL]
        orreq   r5, r5, #1
        streq   r5, [r0, #SCU_CTRL]
@@ -204,9 +210,7 @@ __v6_setup:
 #ifdef CONFIG_MMU
        mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
        mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
-#ifdef CONFIG_SMP
-       orr     r4, r4, #TTB_RGN_WBWA|TTB_S     @ mark PTWs shared, outer cacheable
-#endif
+       orr     r4, r4, #TTB_FLAGS
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
 #endif /* CONFIG_MMU */
        adr     r5, v6_crval
index 94a58455f346cca45fd759af3cb899b03594efd0..d95921a2ab99b81cc0c17cdab5cc433df6b9a9cc 100644 (file)
@@ -5,23 +5,23 @@
  * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
  *
  * Copyright 2004 (C) Intel Corp.
- * Copyright 2005 (c) MontaVista Software, Inc.
+ * Copyright 2005 (C) MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is an
- * extension to Intel's original XScale core that adds the following
+ * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is
+ * an extension to Intel's original XScale core that adds the following
  * features:
  *
  * - ARMv6 Supersections
  * - Low Locality Reference pages (replaces mini-cache)
  * - 36-bit addressing
  * - L2 cache
- * - Cache-coherency if chipset supports it
+ * - Cache coherency if chipset supports it
  *
- * Based on orignal XScale code by Nicolas Pitre
+ * Based on original XScale code by Nicolas Pitre.
  */
 
 #include <linux/linkage.h>
 #define MAX_AREA_SIZE  32768
 
 /*
- * The cache line size of the I and D cache.
+ * The cache line size of the L1 I, L1 D and unified L2 cache.
  */
 #define CACHELINESIZE  32
 
 /*
- * The size of the data cache.
+ * The size of the L1 D cache.
  */
 #define CACHESIZE      32768
 
@@ -57,9 +57,9 @@
 #define L2_CACHE_ENABLE        1
 
 /*
- * This macro is used to wait for a CP15 write and is needed
- * when we have to ensure that the last operation to the co-pro
- * was completed before continuing with operation.
+ * This macro is used to wait for a CP15 write and is needed when we
+ * have to ensure that the last operation to the coprocessor was
+ * completed before continuing with operation.
  */
        .macro  cpwait_ret, lr, rd
        mrc     p15, 0, \rd, c2, c0, 0          @ arbitrary read of cp15
        .endm
 
 /*
- * This macro cleans & invalidates the entire xsc3 dcache by set & way.
+ * This macro cleans and invalidates the entire L1 D cache.
  */
 
        .macro  clean_d_cache rd, rs
        mov     \rd, #0x1f00
        orr     \rd, \rd, #0x00e0
-1:     mcr     p15, 0, \rd, c7, c14, 2         @ clean/inv set/way
+1:     mcr     p15, 0, \rd, c7, c14, 2         @ clean/invalidate L1 D line
        adds    \rd, \rd, #0x40000000
        bcc     1b
        subs    \rd, \rd, #0x20
@@ -119,15 +119,15 @@ ENTRY(cpu_xsc3_reset)
        mov     r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
        msr     cpsr_c, r1                      @ reset CPSR
        mrc     p15, 0, r1, c1, c0, 0           @ ctrl register
-       bic     r1, r1, #0x0086                 @ ........B....CA.
        bic     r1, r1, #0x3900                 @ ..VIZ..S........
+       bic     r1, r1, #0x0086                 @ ........B....CA.
        mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
-       mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches & BTB
+       mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
        bic     r1, r1, #0x0001                 @ ...............M
        mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
        @ CAUTION: MMU turned off from this point.  We count on the pipeline
        @ already containing those two last instructions to survive.
-       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
+       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
        mov     pc, r0
 
 /*
@@ -139,14 +139,12 @@ ENTRY(cpu_xsc3_reset)
  *
  * XScale supports clock switching, but using idle mode support
  * allows external hardware to react to system state changes.
-
- MMG: Come back to this one.
  */
        .align  5
 
 ENTRY(cpu_xsc3_do_idle)
        mov     r0, #1
-       mcr     p14, 0, r0, c7, c0, 0           @ Go to IDLE
+       mcr     p14, 0, r0, c7, c0, 0           @ go to idle
        mov     pc, lr
 
 /* ================================= CACHE ================================ */
@@ -171,9 +169,9 @@ ENTRY(xsc3_flush_kern_cache_all)
 __flush_whole_cache:
        clean_d_cache r0, r1
        tst     r2, #VM_EXEC
-       mcrne   p15, 0, ip, c7, c5, 0           @ Invalidate I cache & BTB
-       mcrne   p15, 0, ip, c7, c10, 4          @ Drain Write Buffer
-       mcrne   p15, 0, ip, c7, c5, 4           @ Prefetch Flush
+       mcrne   p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
+       mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
+       mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
        mov     pc, lr
 
 /*
@@ -194,21 +192,21 @@ ENTRY(xsc3_flush_user_cache_range)
        bhs     __flush_whole_cache
 
 1:     tst     r2, #VM_EXEC
-       mcrne   p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
-       mcr     p15, 0, r0, c7, c14, 1          @ Clean/invalidate D cache line
+       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate L1 I line
+       mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
        tst     r2, #VM_EXEC
-       mcrne   p15, 0, ip, c7, c5, 6           @ Invalidate BTB
-       mcrne   p15, 0, ip, c7, c10, 4          @ Drain Write Buffer
-       mcrne   p15, 0, ip, c7, c5, 4           @ Prefetch Flush
+       mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
+       mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
+       mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
        mov     pc, lr
 
 /*
  *     coherent_kern_range(start, end)
  *
- *     Ensure coherency between the Icache and the Dcache in the
+ *     Ensure coherency between the I cache and the D cache in the
  *     region described by start.  If you have non-snooping
  *     Harvard caches, you need to implement this function.
  *
@@ -222,34 +220,34 @@ ENTRY(xsc3_coherent_kern_range)
 /* FALLTHROUGH */
 ENTRY(xsc3_coherent_user_range)
        bic     r0, r0, #CACHELINESIZE - 1
-1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
        mov     r0, #0
-       mcr     p15, 0, r0, c7, c5, 0           @ Invalidate I cache & BTB
-       mcr     p15, 0, r0, c7, c10, 4          @ Drain Write Buffer
-       mcr     p15, 0, r0, c7, c5, 4           @ Prefetch Flush
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
+       mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
+       mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
        mov     pc, lr
 
 /*
  *     flush_kern_dcache_page(void *page)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
- *     the I cache
+ *     the I cache.
  *
  *     - addr  - page aligned address
  */
 ENTRY(xsc3_flush_kern_dcache_page)
        add     r1, r0, #PAGE_SZ
-1:     mcr     p15, 0, r0, c7, c14, 1          @ Clean/Invalidate D Cache line
+1:     mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
        mov     r0, #0
-       mcr     p15, 0, r0, c7, c5, 0           @ Invalidate I cache & BTB
-       mcr     p15, 0, r0, c7, c10, 4          @ Drain Write Buffer
-       mcr     p15, 0, r0, c7, c5, 4           @ Prefetch Flush
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
+       mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
+       mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
        mov     pc, lr
 
 /*
@@ -266,17 +264,17 @@ ENTRY(xsc3_flush_kern_dcache_page)
 ENTRY(xsc3_dma_inv_range)
        tst     r0, #CACHELINESIZE - 1
        bic     r0, r0, #CACHELINESIZE - 1
-       mcrne   p15, 0, r0, c7, c10, 1          @ clean L1 D entry
-       mcrne   p15, 1, r0, c7, c11, 1          @ clean L2 D entry
+       mcrne   p15, 0, r0, c7, c10, 1          @ clean L1 D line
+       mcrne   p15, 1, r0, c7, c11, 1          @ clean L2 line
        tst     r1, #CACHELINESIZE - 1
-       mcrne   p15, 0, r1, c7, c10, 1          @ clean L1 D entry
-       mcrne   p15, 1, r1, c7, c11, 1          @ clean L2 D entry
-1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate L1 D entry
-       mcr     p15, 1, r0, c7, c7, 1           @ Invalidate L2 D cache line
+       mcrne   p15, 0, r1, c7, c10, 1          @ clean L1 D line
+       mcrne   p15, 1, r1, c7, c11, 1          @ clean L2 line
+1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate L1 D line
+       mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
-       mcr     p15, 0, r0, c7, c10, 4          @ Drain Write Buffer
+       mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
        mov     pc, lr
 
 /*
@@ -289,12 +287,12 @@ ENTRY(xsc3_dma_inv_range)
  */
 ENTRY(xsc3_dma_clean_range)
        bic     r0, r0, #CACHELINESIZE - 1
-1:     mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D entry
-       mcr     p15, 1, r0, c7, c11, 1          @ clean L2 D entry
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
+       mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
-       mcr     p15, 0, r0, c7, c10, 4          @ Drain Write Buffer
+       mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
        mov     pc, lr
 
 /*
@@ -307,13 +305,13 @@ ENTRY(xsc3_dma_clean_range)
  */
 ENTRY(xsc3_dma_flush_range)
        bic     r0, r0, #CACHELINESIZE - 1
-1:     mcr     p15, 0, r0, c7, c14, 1  @ Clean/invalidate L1 D cache line
-       mcr     p15, 1, r0, c7, c11, 1  @ Clean L2 D cache line
-       mcr     p15, 1, r0, c7, c7, 1   @ Invalidate L2 D cache line
+1:     mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
+       mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
+       mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
        blo     1b
-       mcr     p15, 0, r0, c7, c10, 4          @ Drain Write Buffer
+       mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
        mov     pc, lr
 
 ENTRY(xsc3_cache_fns)
@@ -328,7 +326,7 @@ ENTRY(xsc3_cache_fns)
        .long   xsc3_dma_flush_range
 
 ENTRY(cpu_xsc3_dcache_clean_area)
-1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
        add     r0, r0, #CACHELINESIZE
        subs    r1, r1, #CACHELINESIZE
        bhi     1b
@@ -346,14 +344,14 @@ ENTRY(cpu_xsc3_dcache_clean_area)
        .align  5
 ENTRY(cpu_xsc3_switch_mm)
        clean_d_cache r1, r2
-       mcr     p15, 0, ip, c7, c5, 0           @ Invalidate I cache & BTB
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write Buffer
-       mcr     p15, 0, ip, c7, c5, 4           @ Prefetch Flush
+       mcr     p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
+       mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
+       mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
 #ifdef L2_CACHE_ENABLE
        orr     r0, r0, #0x18                   @ cache the page table in L2
 #endif
        mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
-       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
+       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
        cpwait_ret lr, ip
 
 /*
@@ -366,34 +364,34 @@ ENTRY(cpu_xsc3_switch_mm)
 ENTRY(cpu_xsc3_set_pte_ext)
        str     r1, [r0], #-2048                @ linux version
 
-       bic     r2, r1, #0xff0                  @ Keep C, B bits
+       bic     r2, r1, #0xff0                  @ keep C, B bits
        orr     r2, r2, #PTE_TYPE_EXT           @ extended page
-       tst     r1, #L_PTE_SHARED               @ Shared?
+       tst     r1, #L_PTE_SHARED               @ shared?
        orrne   r2, r2, #0x200
 
        eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
 
-       tst     r3, #L_PTE_USER                 @ User?
+       tst     r3, #L_PTE_USER                 @ user?
        orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
 
-       tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
+       tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
        orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
                                                @ combined with user -> user r/w
 
 #if L2_CACHE_ENABLE
-       @ If its cacheable it needs to be in L2 also.
+       @ If it's cacheable, it needs to be in L2 also.
        eor     ip, r1, #L_PTE_CACHEABLE
        tst     ip, #L_PTE_CACHEABLE
        orreq   r2, r2, #PTE_EXT_TEX(0x5)
 #endif
 
-       tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
+       tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
        movne   r2, #0                          @ no -> fault
 
        str     r2, [r0]                        @ hardware version
        mov     ip, #0
-       mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line mcr
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write Buffer
+       mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
+       mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
        mov     pc, lr
 
        .ltorg
@@ -406,17 +404,18 @@ ENTRY(cpu_xsc3_set_pte_ext)
 __xsc3_setup:
        mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
        msr     cpsr_c, r0
-       mcr     p15, 0, ip, c7, c7, 0           @ invalidate I, D caches & BTB
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write Buffer
-       mcr     p15, 0, ip, c7, c5, 4           @ Prefetch Flush
-       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I, D TLBs
+       mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
+       mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
+       mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
+       mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
 #if L2_CACHE_ENABLE
        orr     r4, r4, #0x18                   @ cache the page table in L2
 #endif
        mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
-       mov     r0, #1                          @ Allow access to CP0 and CP13
-       orr     r0, r0, #1 << 13                @ Its undefined whether this
-       mcr     p15, 0, r0, c15, c1, 0          @ affects USR or SVC modes
+
+       mov     r0, #0                          @ don't allow CP access
+       mcr     p15, 0, r0, c15, c1, 0          @ write CP access register
+
        mrc     p15, 0, r0, c1, c0, 1           @ get auxiliary control reg
        and     r0, r0, #2                      @ preserve bit P bit setting
 #if L2_CACHE_ENABLE
@@ -427,9 +426,9 @@ __xsc3_setup:
        adr     r5, xsc3_crval
        ldmia   r5, {r5, r6}
        mrc     p15, 0, r0, c1, c0, 0           @ get control register
-       bic     r0, r0, r5                      @ .... .... .... ..A.
-       orr     r0, r0, r6                      @ .... .... .... .C.M
-       orr     r0, r0, #0x00000800             @ ..VI Z..S .... ....
+       bic     r0, r0, r5                      @ ..V. ..R. .... ..A.
+       orr     r0, r0, r6                      @ ..VI Z..S .... .C.M (mmu)
+                                               @ ...I Z..S .... .... (uc)
 #if L2_CACHE_ENABLE
        orr     r0, r0, #0x04000000             @ L2 enable
 #endif
@@ -439,7 +438,7 @@ __xsc3_setup:
 
        .type   xsc3_crval, #object
 xsc3_crval:
-       crval   clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100
+       crval   clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
 
        __INITDATA
 
@@ -474,7 +473,7 @@ cpu_elf_name:
 
        .type   cpu_xsc3_name, #object
 cpu_xsc3_name:
-       .asciz  "XScale-Core3"
+       .asciz  "XScale-V3 based processor"
        .size   cpu_xsc3_name, . - cpu_xsc3_name
 
        .align
@@ -490,7 +489,7 @@ __xsc3_proc_info:
                PMD_SECT_CACHEABLE | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
-       .long   PMD_TYPE_SECT | \
+       .long   PMD_TYPE_SECT | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
        b       __xsc3_setup
index fd6adde39091ef28cadf0d4fa273d8376fbbe707..20f84bbaa9bbc7c1f5cfe1fbadf532c8f10947d1 100644 (file)
@@ -53,6 +53,8 @@ ENTRY(v6wbi_flush_user_tlb_range)
        add     r0, r0, #PAGE_SZ
        cmp     r0, r1
        blo     1b
+       mcr     p15, 0, ip, c7, c5, 6           @ flush BTAC/BTB
+       mcr     p15, 0, ip, c7, c10, 4          @ data synchronization barrier
        mov     pc, lr
 
 /*
@@ -80,7 +82,9 @@ ENTRY(v6wbi_flush_kern_tlb_range)
        add     r0, r0, #PAGE_SZ
        cmp     r0, r1
        blo     1b
+       mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
        mcr     p15, 0, r2, c7, c10, 4          @ data synchronization barrier
+       mcr     p15, 0, r2, c7, c5, 4           @ prefetch flush
        mov     pc, lr
 
        .section ".text.init", #alloc, #execinstr
index 19d37730b664a03cc441886740dc517fd7349c2c..afd93ad02febb9c07262b49648d8438a53db0c27 100644 (file)
@@ -19,5 +19,24 @@ config OPROFILE
 
          If unsure, say N.
 
+if OPROFILE
+
+config OPROFILE_ARMV6
+       bool
+       depends on CPU_V6 && !SMP
+       default y
+       select OPROFILE_ARM11_CORE
+
+config OPROFILE_MPCORE
+       bool
+       depends on CPU_V6 && SMP
+       default y
+       select OPROFILE_ARM11_CORE
+
+config OPROFILE_ARM11_CORE
+       bool
+
+endif
+
 endmenu
 
index 6a94e54848fd7a965294c1be8fc72e350878aaee..e61d0cc520b76a72419a17244d4a970579bac210 100644 (file)
@@ -8,4 +8,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
 
 oprofile-y                             := $(DRIVER_OBJS) common.o backtrace.o
 oprofile-$(CONFIG_CPU_XSCALE)          += op_model_xscale.o
-
+oprofile-$(CONFIG_OPROFILE_ARM11_CORE) += op_model_arm11_core.o
+oprofile-$(CONFIG_OPROFILE_ARMV6)      += op_model_v6.o
+oprofile-$(CONFIG_OPROFILE_MPCORE)     += op_model_mpcore.o
index 6f833358cd0612c4c13e5d59619e86ccee2749e5..0a007b931f6368f8dcb8eb3dc4b47d4c5ae17b6d 100644 (file)
@@ -135,6 +135,14 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        spec = &op_xscale_spec;
 #endif
 
+#ifdef CONFIG_OPROFILE_ARMV6
+       spec = &op_armv6_spec;
+#endif
+
+#ifdef CONFIG_OPROFILE_MPCORE
+       spec = &op_mpcore_spec;
+#endif
+
        if (spec) {
                ret = spec->init();
                if (ret < 0)
index 38c6ad158547e2e615620888c59848be57784f46..4899c629aa03473fe4a7d7fe1ad67b77b15ce9d2 100644 (file)
@@ -24,6 +24,9 @@ struct op_arm_model_spec {
 extern struct op_arm_model_spec op_xscale_spec;
 #endif
 
+extern struct op_arm_model_spec op_armv6_spec;
+extern struct op_arm_model_spec op_mpcore_spec;
+
 extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
 
 extern int __init op_arm_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c
new file mode 100644 (file)
index 0000000..ad80752
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * @file op_model_arm11_core.c
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+/*
+ * ARM11 PMU support
+ */
+static inline void arm11_write_pmnc(u32 val)
+{
+       /* upper 4bits and 7, 11 are write-as-0 */
+       val &= 0x0ffff77f;
+       asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val));
+}
+
+static inline u32 arm11_read_pmnc(void)
+{
+       u32 val;
+       asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));
+       return val;
+}
+
+static void arm11_reset_counter(unsigned int cnt)
+{
+       u32 val = -(u32)counter_config[CPU_COUNTER(smp_processor_id(), cnt)].count;
+       switch (cnt) {
+       case CCNT:
+               asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val));
+               break;
+
+       case PMN0:
+               asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val));
+               break;
+
+       case PMN1:
+               asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val));
+               break;
+       }
+}
+
+int arm11_setup_pmu(void)
+{
+       unsigned int cnt;
+       u32 pmnc;
+
+       if (arm11_read_pmnc() & PMCR_E) {
+               printk(KERN_ERR "oprofile: CPU%u PMU still enabled when setup new event counter.\n", smp_processor_id());
+               return -EBUSY;
+       }
+
+       /* initialize PMNC, reset overflow, D bit, C bit and P bit. */
+       arm11_write_pmnc(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |
+                        PMCR_C | PMCR_P);
+
+       for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
+               unsigned long event;
+
+               if (!counter_config[CPU_COUNTER(smp_processor_id(), cnt)].enabled)
+                       continue;
+
+               event = counter_config[CPU_COUNTER(smp_processor_id(), cnt)].event & 255;
+
+               /*
+                * Set event (if destined for PMNx counters)
+                */
+               if (cnt == PMN0) {
+                       pmnc |= event << 20;
+               } else if (cnt == PMN1) {
+                       pmnc |= event << 12;
+               }
+
+               /*
+                * We don't need to set the event if it's a cycle count
+                * Enable interrupt for this counter
+                */
+               pmnc |= PMCR_IEN_PMN0 << cnt;
+               arm11_reset_counter(cnt);
+       }
+       arm11_write_pmnc(pmnc);
+
+       return 0;
+}
+
+int arm11_start_pmu(void)
+{
+       arm11_write_pmnc(arm11_read_pmnc() | PMCR_E);
+       return 0;
+}
+
+int arm11_stop_pmu(void)
+{
+       unsigned int cnt;
+
+       arm11_write_pmnc(arm11_read_pmnc() & ~PMCR_E);
+
+       for (cnt = PMN0; cnt <= CCNT; cnt++)
+               arm11_reset_counter(cnt);
+
+       return 0;
+}
+
+/*
+ * CPU counters' IRQ handler (one IRQ per CPU)
+ */
+static irqreturn_t arm11_pmu_interrupt(int irq, void *arg)
+{
+       struct pt_regs *regs = get_irq_regs();
+       unsigned int cnt;
+       u32 pmnc;
+
+       pmnc = arm11_read_pmnc();
+
+       for (cnt = PMN0; cnt <= CCNT; cnt++) {
+               if ((pmnc & (PMCR_OFL_PMN0 << cnt)) && (pmnc & (PMCR_IEN_PMN0 << cnt))) {
+                       arm11_reset_counter(cnt);
+                       oprofile_add_sample(regs, CPU_COUNTER(smp_processor_id(), cnt));
+               }
+       }
+       /* Clear counter flag(s) */
+       arm11_write_pmnc(pmnc);
+       return IRQ_HANDLED;
+}
+
+int arm11_request_interrupts(int *irqs, int nr)
+{
+       unsigned int i;
+       int ret = 0;
+
+       for(i = 0; i < nr; i++) {
+               ret = request_irq(irqs[i], arm11_pmu_interrupt, IRQF_DISABLED, "CP15 PMU", NULL);
+               if (ret != 0) {
+                       printk(KERN_ERR "oprofile: unable to request IRQ%u for MPCORE-EM\n",
+                              irqs[i]);
+                       break;
+               }
+       }
+
+       if (i != nr)
+               while (i-- != 0)
+                       free_irq(irqs[i], NULL);
+
+       return ret;
+}
+
+void arm11_release_interrupts(int *irqs, int nr)
+{
+       unsigned int i;
+
+       for (i = 0; i < nr; i++)
+               free_irq(irqs[i], NULL);
+}
diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h
new file mode 100644 (file)
index 0000000..6f8538e
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * @file op_model_arm11_core.h
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_ARM11_CORE_H
+#define OP_MODEL_ARM11_CORE_H
+
+/*
+ * Per-CPU PMCR
+ */
+#define PMCR_E         (1 << 0)        /* Enable */
+#define PMCR_P         (1 << 1)        /* Count reset */
+#define PMCR_C         (1 << 2)        /* Cycle counter reset */
+#define PMCR_D         (1 << 3)        /* Cycle counter counts every 64th cpu cycle */
+#define PMCR_IEN_PMN0  (1 << 4)        /* Interrupt enable count reg 0 */
+#define PMCR_IEN_PMN1  (1 << 5)        /* Interrupt enable count reg 1 */
+#define PMCR_IEN_CCNT  (1 << 6)        /* Interrupt enable cycle counter */
+#define PMCR_OFL_PMN0  (1 << 8)        /* Count reg 0 overflow */
+#define PMCR_OFL_PMN1  (1 << 9)        /* Count reg 1 overflow */
+#define PMCR_OFL_CCNT  (1 << 10)       /* Cycle counter overflow */
+
+#define PMN0 0
+#define PMN1 1
+#define CCNT 2
+
+#define CPU_COUNTER(cpu, counter)      ((cpu) * 3 + (counter))
+
+int arm11_setup_pmu(void);
+int arm11_start_pmu(void);
+int arm11_stop_pmu(void);
+int arm11_request_interrupts(int *, int);
+void arm11_release_interrupts(int *, int);
+
+#endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
new file mode 100644 (file)
index 0000000..8985007
--- /dev/null
@@ -0,0 +1,296 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ *
+ *  Counters:
+ *    0: PMN0 on CPU0, per-cpu configurable event counter
+ *    1: PMN1 on CPU0, per-cpu configurable event counter
+ *    2: CCNT on CPU0
+ *    3: PMN0 on CPU1
+ *    4: PMN1 on CPU1
+ *    5: CCNT on CPU1
+ *    6: PMN0 on CPU1
+ *    7: PMN1 on CPU1
+ *    8: CCNT on CPU1
+ *    9: PMN0 on CPU1
+ *   10: PMN1 on CPU1
+ *   11: CCNT on CPU1
+ *   12-19: configurable SCU event counters
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+#include "op_model_mpcore.h"
+
+/*
+ * MPCore SCU event monitor support
+ */
+#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
+
+/*
+ * Bitmask of used SCU counters
+ */
+static unsigned int scu_em_used;
+
+/*
+ * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number)
+ */
+static inline void scu_reset_counter(struct eventmonitor __iomem *emc, unsigned int n)
+{
+       writel(-(u32)counter_config[SCU_COUNTER(n)].count, &emc->MC[n]);
+}
+
+static inline void scu_set_event(struct eventmonitor __iomem *emc, unsigned int n, u32 event)
+{
+       event &= 0xff;
+       writeb(event, &emc->MCEB[n]);
+}
+
+/*
+ * SCU counters' IRQ handler (one IRQ per counter => 2 IRQs per CPU)
+ */
+static irqreturn_t scu_em_interrupt(int irq, void *arg)
+{
+       struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+       unsigned int cnt;
+
+       cnt = irq - IRQ_PMU_SCU0;
+       oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
+       scu_reset_counter(emc, cnt);
+
+       /* Clear overflow flag for this counter */
+       writel(1 << (cnt + 16), &emc->PMCR);
+
+       return IRQ_HANDLED;
+}
+
+/* Configure just the SCU counters that the user has requested */
+static void scu_setup(void)
+{
+       struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+       unsigned int i;
+
+       scu_em_used = 0;
+
+       for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+               if (counter_config[SCU_COUNTER(i)].enabled &&
+                   counter_config[SCU_COUNTER(i)].event) {
+                       scu_set_event(emc, i, 0); /* disable counter for now */
+                       scu_em_used |= 1 << i;
+               }
+       }
+}
+
+static int scu_start(void)
+{
+       struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+       unsigned int temp, i;
+       unsigned long event;
+       int ret = 0;
+
+       /*
+        * request the SCU counter interrupts that we need
+        */
+       for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+               if (scu_em_used & (1 << i)) {
+                       ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+                       if (ret) {
+                               printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
+                                      IRQ_PMU_SCU0 + i);
+                               goto err_free_scu;
+                       }
+               }
+       }
+
+       /*
+        * clear overflow and enable interrupt for all used counters
+        */
+       temp = readl(&emc->PMCR);
+       for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+               if (scu_em_used & (1 << i)) {
+                       scu_reset_counter(emc, i);
+                       event = counter_config[SCU_COUNTER(i)].event;
+                       scu_set_event(emc, i, event);
+
+                       /* clear overflow/interrupt */
+                       temp |= 1 << (i + 16);
+                       /* enable interrupt*/
+                       temp |= 1 << (i + 8);
+               }
+       }
+
+       /* Enable all 8 counters */
+       temp |= PMCR_E;
+       writel(temp, &emc->PMCR);
+
+       return 0;
+
+ err_free_scu:
+       while (i--)
+               free_irq(IRQ_PMU_SCU0 + i, NULL);
+       return ret;
+}
+
+static void scu_stop(void)
+{
+       struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+       unsigned int temp, i;
+
+       /* Disable counter interrupts */
+       /* Don't disable all 8 counters (with the E bit) as they may be in use */
+       temp = readl(&emc->PMCR);
+       for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+               if (scu_em_used & (1 << i))
+                       temp &= ~(1 << (i + 8));
+       }
+       writel(temp, &emc->PMCR);
+
+       /* Free counter interrupts and reset counters */
+       for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+               if (scu_em_used & (1 << i)) {
+                       scu_reset_counter(emc, i);
+                       free_irq(IRQ_PMU_SCU0 + i, NULL);
+               }
+       }
+}
+
+struct em_function_data {
+       int (*fn)(void);
+       int ret;
+};
+
+static void em_func(void *data)
+{
+       struct em_function_data *d = data;
+       int ret = d->fn();
+       if (ret)
+               d->ret = ret;
+}
+
+static int em_call_function(int (*fn)(void))
+{
+       struct em_function_data data;
+
+       data.fn = fn;
+       data.ret = 0;
+
+       smp_call_function(em_func, &data, 1, 1);
+       em_func(&data);
+
+       return data.ret;
+}
+
+/*
+ * Glue to stick the individual ARM11 PMUs and the SCU
+ * into the oprofile framework.
+ */
+static int em_setup_ctrs(void)
+{
+       int ret;
+
+       /* Configure CPU counters by cross-calling to the other CPUs */
+       ret = em_call_function(arm11_setup_pmu);
+       if (ret == 0)
+               scu_setup();
+
+       return 0;
+}
+
+static int arm11_irqs[] = {
+       [0]     = IRQ_PMU_CPU0,
+       [1]     = IRQ_PMU_CPU1,
+       [2]     = IRQ_PMU_CPU2,
+       [3]     = IRQ_PMU_CPU3
+};
+
+static int em_start(void)
+{
+       int ret;
+
+       ret = arm11_request_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+       if (ret == 0) {
+               em_call_function(arm11_start_pmu);
+
+               ret = scu_start();
+               if (ret)
+                       arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+       }
+       return ret;
+}
+
+static void em_stop(void)
+{
+       em_call_function(arm11_stop_pmu);
+       arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+       scu_stop();
+}
+
+/*
+ * Why isn't there a function to route an IRQ to a specific CPU in
+ * genirq?
+ */
+static void em_route_irq(int irq, unsigned int cpu)
+{
+       irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+       irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+}
+
+static int em_setup(void)
+{
+       /*
+        * Send SCU PMU interrupts to the "owner" CPU.
+        */
+       em_route_irq(IRQ_PMU_SCU0, 0);
+       em_route_irq(IRQ_PMU_SCU1, 0);
+       em_route_irq(IRQ_PMU_SCU2, 1);
+       em_route_irq(IRQ_PMU_SCU3, 1);
+       em_route_irq(IRQ_PMU_SCU4, 2);
+       em_route_irq(IRQ_PMU_SCU5, 2);
+       em_route_irq(IRQ_PMU_SCU6, 3);
+       em_route_irq(IRQ_PMU_SCU7, 3);
+
+       /*
+        * Send CP15 PMU interrupts to the owner CPU.
+        */
+       em_route_irq(IRQ_PMU_CPU0, 0);
+       em_route_irq(IRQ_PMU_CPU1, 1);
+       em_route_irq(IRQ_PMU_CPU2, 2);
+       em_route_irq(IRQ_PMU_CPU3, 3);
+
+       return 0;
+}
+
+struct op_arm_model_spec op_mpcore_spec = {
+       .init           = em_setup,
+       .num_counters   = MPCORE_NUM_COUNTERS,
+       .setup_ctrs     = em_setup_ctrs,
+       .start          = em_start,
+       .stop           = em_stop,
+       .name           = "arm/mpcore",
+};
diff --git a/arch/arm/oprofile/op_model_mpcore.h b/arch/arm/oprofile/op_model_mpcore.h
new file mode 100644 (file)
index 0000000..73d8110
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_MPCORE_H
+#define OP_MODEL_MPCORE_H
+
+struct eventmonitor {
+       unsigned long PMCR;
+       unsigned char MCEB[8];
+       unsigned long MC[8];
+};
+
+/*
+ * List of userspace counter numbers: note that the structure is important.
+ * The code relies on CPUn's counters being CPU0's counters + 3n
+ * and on CPU0's counters starting at 0
+ */
+
+#define COUNTER_CPU0_PMN0 0
+#define COUNTER_CPU0_PMN1 1
+#define COUNTER_CPU0_CCNT 2
+
+#define COUNTER_CPU1_PMN0 3
+#define COUNTER_CPU1_PMN1 4
+#define COUNTER_CPU1_CCNT 5
+
+#define COUNTER_CPU2_PMN0 6
+#define COUNTER_CPU2_PMN1 7
+#define COUNTER_CPU2_CCNT 8
+
+#define COUNTER_CPU3_PMN0 9
+#define COUNTER_CPU3_PMN1 10
+#define COUNTER_CPU3_CCNT 11
+
+#define COUNTER_SCU_MN0 12
+#define COUNTER_SCU_MN1 13
+#define COUNTER_SCU_MN2 14
+#define COUNTER_SCU_MN3 15
+#define COUNTER_SCU_MN4 16
+#define COUNTER_SCU_MN5 17
+#define COUNTER_SCU_MN6 18
+#define COUNTER_SCU_MN7 19
+#define NUM_SCU_COUNTERS 8
+
+#define SCU_COUNTER(number)    ((number) + COUNTER_SCU_MN0)
+
+#define MPCORE_NUM_COUNTERS    SCU_COUNTER(NUM_SCU_COUNTERS)
+
+#endif
diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c
new file mode 100644 (file)
index 0000000..fe58138
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * @file op_model_v6.c
+ * ARM11 Performance Monitor Driver
+ *
+ * Based on op_model_xscale.c
+ *
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 OProfile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Tony Lindgren <tony@atomide.com>
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+static int irqs[] = {
+#ifdef CONFIG_ARCH_OMAP2
+       3,
+#endif
+};
+
+static void armv6_pmu_stop(void)
+{
+       arm11_stop_pmu();
+       arm11_release_interrupts(irqs, ARRAY_SIZE(irqs));
+}
+
+static int armv6_pmu_start(void)
+{
+       int ret;
+
+       ret = arm11_request_interrupts(irqs, ARRAY_SIZE(irqs));
+       if (ret >= 0)
+               ret = arm11_start_pmu();
+
+       return ret;
+}
+
+static int armv6_detect_pmu(void)
+{
+       return 0;
+}
+
+struct op_arm_model_spec op_armv6_spec = {
+       .init           = armv6_detect_pmu,
+       .num_counters   = 3,
+       .setup_ctrs     = arm11_setup_pmu,
+       .start          = armv6_pmu_start,
+       .stop           = armv6_pmu_stop,
+       .name           = "arm/armv6",
+};
index 23da00b11517768c9129a418492c8eafb0ffd3cb..3250d732a17142fec31636d18a551df97b57e1ba 100644 (file)
@@ -2,7 +2,29 @@
 # Makefile for the linux kernel.
 #
 
-obj-y                  := gpio.o i2c.o pci.o setup.o time.o
-obj-m                  :=
-obj-n                  :=
-obj-                   :=
+obj-y :=
+
+# IOP32X
+obj-$(CONFIG_ARCH_IOP32X) += gpio.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += io.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+
+# IOP33X
+obj-$(CONFIG_ARCH_IOP33X) += gpio.o
+obj-$(CONFIG_ARCH_IOP33X) += i2c.o
+obj-$(CONFIG_ARCH_IOP33X) += pci.o
+obj-$(CONFIG_ARCH_IOP33X) += setup.o
+obj-$(CONFIG_ARCH_IOP33X) += time.o
+obj-$(CONFIG_ARCH_IOP33X) += io.o
+obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+
+# IOP13XX
+obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/plat-iop/cp6.c
new file mode 100644 (file)
index 0000000..9612a87
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * IOP Coprocessor-6 access handler
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/init.h>
+#include <asm/traps.h>
+
+static int cp6_trap(struct pt_regs *regs, unsigned int instr)
+{
+       u32 temp;
+
+        /* enable cp6 access */
+        asm volatile (
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "orr    %0, %0, #(1 << 6)\n\t"
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               : "=r"(temp));
+
+       return 0;
+}
+
+/* permit kernel space cp6 access
+ * deny user space cp6 access
+ */
+static struct undef_hook cp6_hook = {
+       .instr_mask     = 0x0f000ff0,
+       .instr_val      = 0x0e000610,
+       .cpsr_mask      = MODE_MASK,
+       .cpsr_val       = SVC_MODE,
+       .fn             = cp6_trap,
+};
+
+void __init iop_init_cp6_handler(void)
+{
+       register_undef_hook(&cp6_hook);
+}
diff --git a/arch/arm/plat-iop/io.c b/arch/arm/plat-iop/io.c
new file mode 100644 (file)
index 0000000..f7eccec
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * iop3xx custom ioremap implementation
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags)
+{
+       void __iomem * retval;
+
+       switch (cookie) {
+       case IOP3XX_PCI_LOWER_IO_PA ... IOP3XX_PCI_UPPER_IO_PA:
+               retval = (void *) IOP3XX_PCI_IO_PHYS_TO_VIRT(cookie);
+               break;
+       case IOP3XX_PERIPHERAL_PHYS_BASE ... IOP3XX_PERIPHERAL_UPPER_PA:
+               retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
+               break;
+       default:
+               retval = __ioremap(cookie, size, flags);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(__iop3xx_ioremap);
+
+void __iop3xx_iounmap(void __iomem *addr)
+{
+       extern void __iounmap(volatile void __iomem *addr);
+
+       switch ((u32) addr) {
+       case IOP3XX_PCI_LOWER_IO_VA ... IOP3XX_PCI_UPPER_IO_VA:
+       case IOP3XX_PERIPHERAL_VIRT_BASE ... IOP3XX_PERIPHERAL_UPPER_VA:
+               goto skip;
+       }
+       __iounmap(addr);
+
+skip:
+       return;
+}
+EXPORT_SYMBOL(__iop3xx_iounmap);
index e647812654f2c0bcdf0b47c76c83e807419414a8..b5f6ec35aafb59e2b9fd1597e615e7000a157769 100644 (file)
@@ -196,8 +196,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
        if (!res)
                panic("PCI: unable to alloc resources");
 
-       res[0].start = IOP3XX_PCI_LOWER_IO_VA;
-       res[0].end   = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+       res[0].start = IOP3XX_PCI_LOWER_IO_PA;
+       res[0].end   = IOP3XX_PCI_LOWER_IO_PA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
        res[0].name  = "IOP3XX PCI I/O Space";
        res[0].flags = IORESOURCE_IO;
        request_resource(&ioport_resource, &res[0]);
@@ -209,7 +209,7 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
        request_resource(&iomem_resource, &res[1]);
 
        sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
-       sys->io_offset  = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+       sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
 
        sys->resource[0] = &res[0];
        sys->resource[1] = &res[1];
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
new file mode 100644 (file)
index 0000000..e223431
--- /dev/null
@@ -0,0 +1,99 @@
+# arch/arm/plat-s3c24xx/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config PLAT_S3C24XX
+       bool
+       depends on ARCH_S3C2410
+       default y if ARCH_S3C2410
+       help
+         Base platform code for any Samsung S3C device
+
+if PLAT_S3C24XX
+
+config CPU_S3C244X
+       bool
+       depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+       help
+         Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+config PM_SIMTEC
+       bool
+       help
+         Common power management code for systems that are
+         compatible with the Simtec style of power management
+
+config S3C2410_BOOT_WATCHDOG
+       bool "S3C2410 Initialisation watchdog"
+       depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+       help
+         Say y to enable the watchdog during the kernel decompression
+         stage. If the kernel fails to uncompress, then the watchdog
+         will trigger a reset and the system should restart.
+
+config S3C2410_BOOT_ERROR_RESET
+       bool "S3C2410 Reboot on decompression error"
+       depends on ARCH_S3C2410
+       help
+         Say y here to use the watchdog to reset the system if the
+         kernel decompressor detects an error during decompression.
+
+config S3C2410_PM_DEBUG
+       bool "S3C2410 PM Suspend debug"
+       depends on ARCH_S3C2410 && PM
+       help
+         Say Y here if you want verbose debugging from the PM Suspend and
+         Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+         for more information.
+
+config S3C2410_PM_CHECK
+       bool "S3C2410 PM Suspend Memory CRC"
+       depends on ARCH_S3C2410 && PM && CRC32
+       help
+         Enable the PM code's memory area checksum over sleep. This option
+         will generate CRCs of all blocks of memory, and store them before
+         going to sleep. The blocks are then checked on resume for any
+         errors.
+
+config S3C2410_PM_CHECK_CHUNKSIZE
+       int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+       depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
+       default 64
+       help
+         Set the chunksize in Kilobytes of the CRC for checking memory
+         corruption over suspend and resume. A smaller value will mean that
+         the CRC data block will take more memory, but wil identify any
+         faults with better precision.
+
+config S3C2410_LOWLEVEL_UART_PORT
+       int "S3C2410 UART to use for low-level messages"
+       default 0
+       help
+         Choice of which UART port to use for the low-level messages,
+         such as the `Uncompressing...` at start time. The value of
+         this configuration should be between zero and two. The port
+         must have been initialised by the boot-loader before use.
+
+config S3C2410_DMA
+       bool "S3C2410 DMA support"
+       depends on ARCH_S3C2410
+       help
+         S3C2410 DMA support. This is needed for drivers like sound which
+         use the S3C2410's DMA system to move data to and from the
+         peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+       bool "S3C2410 DMA support debug"
+       depends on ARCH_S3C2410 && S3C2410_DMA
+       help
+         Enable debugging output for the DMA code. This option sends info
+         to the kernel log, at priority KERN_DEBUG.
+
+config MACH_SMDK
+       bool
+       help
+         Common machine code for SMDK2410 and SMDK2440
+
+endif
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
new file mode 100644 (file)
index 0000000..8e5ccaa
--- /dev/null
@@ -0,0 +1,30 @@
+# arch/arm/plat-s3c24xx/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+
+# Core files
+
+obj-y                          += cpu.o
+obj-y                          += irq.o
+obj-y                          += devs.o
+obj-y                          += gpio.o
+obj-y                          += time.o
+obj-y                          += clock.o
+
+# Architecture dependant builds
+
+obj-$(CONFIG_CPU_S3C244X)      += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)      += s3c244x-irq.o
+obj-$(CONFIG_PM_SIMTEC)                += pm-simtec.o
+obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_PM)               += sleep.o
+obj-$(CONFIG_S3C2410_DMA)      += dma.o
+obj-$(CONFIG_MACH_SMDK)                += common-smdk.o
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
new file mode 100644 (file)
index 0000000..d3dc03a
--- /dev/null
@@ -0,0 +1,449 @@
+/* linux/arch/arm/plat-s3c24xx/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Core clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* clock information */
+
+static LIST_HEAD(clocks);
+
+DEFINE_MUTEX(clocks_mutex);
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+       return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p;
+       struct clk *clk = ERR_PTR(-ENOENT);
+       int idno;
+
+       if (dev == NULL || dev->bus != &platform_bus_type)
+               idno = -1;
+       else
+               idno = to_platform_device(dev)->id;
+
+       mutex_lock(&clocks_mutex);
+
+       list_for_each_entry(p, &clocks, list) {
+               if (p->id == idno &&
+                   strcmp(id, p->name) == 0 &&
+                   try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+
+       /* check for the case where a device was supplied, but the
+        * clock that was being searched for is not device specific */
+
+       if (IS_ERR(clk)) {
+               list_for_each_entry(p, &clocks, list) {
+                       if (p->id == -1 && strcmp(id, p->name) == 0 &&
+                           try_module_get(p->owner)) {
+                               clk = p;
+                               break;
+                       }
+               }
+       }
+
+       mutex_unlock(&clocks_mutex);
+       return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+       module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+       if (IS_ERR(clk) || clk == NULL)
+               return -EINVAL;
+
+       clk_enable(clk->parent);
+
+       mutex_lock(&clocks_mutex);
+
+       if ((clk->usage++) == 0)
+               (clk->enable)(clk, 1);
+
+       mutex_unlock(&clocks_mutex);
+       return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+       if (IS_ERR(clk) || clk == NULL)
+               return;
+
+       mutex_lock(&clocks_mutex);
+
+       if ((--clk->usage) == 0)
+               (clk->enable)(clk, 0);
+
+       mutex_unlock(&clocks_mutex);
+       clk_disable(clk->parent);
+}
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (IS_ERR(clk))
+               return 0;
+
+       if (clk->rate != 0)
+               return clk->rate;
+
+       if (clk->get_rate != NULL)
+               return (clk->get_rate)(clk);
+
+       if (clk->parent != NULL)
+               return clk_get_rate(clk->parent);
+
+       return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (!IS_ERR(clk) && clk->round_rate)
+               return (clk->round_rate)(clk, rate);
+
+       return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret;
+
+       if (IS_ERR(clk))
+               return -EINVAL;
+
+       mutex_lock(&clocks_mutex);
+       ret = (clk->set_rate)(clk, rate);
+       mutex_unlock(&clocks_mutex);
+
+       return ret;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+       return clk->parent;
+}
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = 0;
+
+       if (IS_ERR(clk))
+               return -EINVAL;
+
+       mutex_lock(&clocks_mutex);
+
+       if (clk->set_parent)
+               ret = (clk->set_parent)(clk, parent);
+
+       mutex_unlock(&clocks_mutex);
+
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+EXPORT_SYMBOL(clk_set_parent);
+
+/* base clocks */
+
+struct clk clk_xtal = {
+       .name           = "xtal",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = NULL,
+       .ctrlbit        = 0,
+};
+
+struct clk clk_mpll = {
+       .name           = "mpll",
+       .id             = -1,
+};
+
+struct clk clk_upll = {
+       .name           = "upll",
+       .id             = -1,
+       .parent         = NULL,
+       .ctrlbit        = 0,
+};
+
+struct clk clk_f = {
+       .name           = "fclk",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = &clk_mpll,
+       .ctrlbit        = 0,
+};
+
+struct clk clk_h = {
+       .name           = "hclk",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = NULL,
+       .ctrlbit        = 0,
+};
+
+struct clk clk_p = {
+       .name           = "pclk",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = NULL,
+       .ctrlbit        = 0,
+};
+
+struct clk clk_usb_bus = {
+       .name           = "usb-bus",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = &clk_upll,
+};
+
+/* clocks that could be registered by external code */
+
+static int s3c24xx_dclk_enable(struct clk *clk, int enable)
+{
+       unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+       if (enable)
+               dclkcon |= clk->ctrlbit;
+       else
+               dclkcon &= ~clk->ctrlbit;
+
+       __raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+       return 0;
+}
+
+static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+{
+       unsigned long dclkcon;
+       unsigned int uclk;
+
+       if (parent == &clk_upll)
+               uclk = 1;
+       else if (parent == &clk_p)
+               uclk = 0;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+       if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
+               if (uclk)
+                       dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
+               else
+                       dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
+       } else {
+               if (uclk)
+                       dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
+               else
+                       dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+       }
+
+       __raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+       return 0;
+}
+
+
+static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+{
+       unsigned long mask;
+       unsigned long source;
+
+       /* calculate the MISCCR setting for the clock */
+
+       if (parent == &clk_xtal)
+               source = S3C2410_MISCCR_CLK0_MPLL;
+       else if (parent == &clk_upll)
+               source = S3C2410_MISCCR_CLK0_UPLL;
+       else if (parent == &clk_f)
+               source = S3C2410_MISCCR_CLK0_FCLK;
+       else if (parent == &clk_h)
+               source = S3C2410_MISCCR_CLK0_HCLK;
+       else if (parent == &clk_p)
+               source = S3C2410_MISCCR_CLK0_PCLK;
+       else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
+               source = S3C2410_MISCCR_CLK0_DCLK0;
+       else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
+               source = S3C2410_MISCCR_CLK0_DCLK0;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       if (clk == &s3c24xx_dclk0)
+               mask = S3C2410_MISCCR_CLK0_MASK;
+       else {
+               source <<= 4;
+               mask = S3C2410_MISCCR_CLK1_MASK;
+       }
+
+       s3c2410_modify_misccr(mask, source);
+       return 0;
+}
+
+/* external clock definitions */
+
+struct clk s3c24xx_dclk0 = {
+       .name           = "dclk0",
+       .id             = -1,
+       .ctrlbit        = S3C2410_DCLKCON_DCLK0EN,
+       .enable         = s3c24xx_dclk_enable,
+       .set_parent     = s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_dclk1 = {
+       .name           = "dclk1",
+       .id             = -1,
+       .ctrlbit        = S3C2410_DCLKCON_DCLK0EN,
+       .enable         = s3c24xx_dclk_enable,
+       .set_parent     = s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_clkout0 = {
+       .name           = "clkout0",
+       .id             = -1,
+       .set_parent     = s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_clkout1 = {
+       .name           = "clkout1",
+       .id             = -1,
+       .set_parent     = s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_uclk = {
+       .name           = "uclk",
+       .id             = -1,
+};
+
+/* initialise the clock system */
+
+int s3c24xx_register_clock(struct clk *clk)
+{
+       clk->owner = THIS_MODULE;
+
+       if (clk->enable == NULL)
+               clk->enable = clk_null_enable;
+
+       /* add to the list of available clocks */
+
+       mutex_lock(&clocks_mutex);
+       list_add(&clk->list, &clocks);
+       mutex_unlock(&clocks_mutex);
+
+       return 0;
+}
+
+/* initalise all the clocks */
+
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+                               unsigned long fclk,
+                               unsigned long hclk,
+                               unsigned long pclk)
+{
+       printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+
+       /* initialise the main system clocks */
+
+       clk_xtal.rate = xtal;
+       clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+
+       clk_mpll.rate = fclk;
+       clk_h.rate = hclk;
+       clk_p.rate = pclk;
+       clk_f.rate = fclk;
+
+       /* assume uart clocks are correctly setup */
+
+       /* register our clocks */
+
+       if (s3c24xx_register_clock(&clk_xtal) < 0)
+               printk(KERN_ERR "failed to register master xtal\n");
+
+       if (s3c24xx_register_clock(&clk_mpll) < 0)
+               printk(KERN_ERR "failed to register mpll clock\n");
+
+       if (s3c24xx_register_clock(&clk_upll) < 0)
+               printk(KERN_ERR "failed to register upll clock\n");
+
+       if (s3c24xx_register_clock(&clk_f) < 0)
+               printk(KERN_ERR "failed to register cpu fclk\n");
+
+       if (s3c24xx_register_clock(&clk_h) < 0)
+               printk(KERN_ERR "failed to register cpu hclk\n");
+
+       if (s3c24xx_register_clock(&clk_p) < 0)
+               printk(KERN_ERR "failed to register cpu pclk\n");
+
+       return 0;
+}
similarity index 96%
rename from arch/arm/mach-s3c2410/common-smdk.c
rename to arch/arm/plat-s3c24xx/common-smdk.c
index a40eaa6561771bbd3c09410b9e06b6e1cc6967de..908efa7d745fbc98fea12ecd38079e3dcd41dbaf 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.c
+/* linux/arch/arm/plat-s3c24xx/common-smdk.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -38,9 +38,9 @@
 
 #include <asm/arch/nand.h>
 
-#include "common-smdk.h"
-#include "devs.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 /* LED devices */
 
similarity index 92%
rename from arch/arm/mach-s3c2410/cpu.c
rename to arch/arm/plat-s3c24xx/cpu.c
index ae1f5bb63f7a809081a31a437aa983b944c66fa1..6a2d1070e5a08825e35b2e9db24519e9578ff8a1 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/cpu.c
+/* linux/arch/arm/plat-s3c24xx/cpu.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     http://www.simtec.co.uk/products/SWLINUX/
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-serial.h>
 
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "s3c2400.h"
-#include "s3c2410.h"
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/s3c2400.h>
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
 #include "s3c244x.h"
-#include "s3c2440.h"
-#include "s3c2442.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/s3c2443.h>
 
 struct cpu_table {
        unsigned long   idcode;
@@ -67,6 +68,7 @@ static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2440[]  = "S3C2440";
 static const char name_s3c2442[]  = "S3C2442";
+static const char name_s3c2443[]  = "S3C2443";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2440a[] = "S3C2440A";
 
@@ -134,6 +136,15 @@ static struct cpu_table cpu_ids[] __initdata = {
                .init           = s3c2412_init,
                .name           = name_s3c2412,
        },
+       {
+               .idcode         = 0x32443001,
+               .idmask         = 0xffffffff,
+               .map_io         = s3c2443_map_io,
+               .init_clocks    = s3c2443_init_clocks,
+               .init_uarts     = s3c2443_init_uarts,
+               .init           = s3c2443_init,
+               .name           = name_s3c2443,
+       },
        {
                .idcode         = 0x0,   /* S3C2400 doesn't have an idcode */
                .idmask         = 0xffffffff,
similarity index 96%
rename from arch/arm/mach-s3c2410/devs.c
rename to arch/arm/plat-s3c24xx/devs.c
index faccde2092d2f353617e61893218c50a263ab22c..0fe53b39cb2f57566200a8f234cf4e64f3cefa33 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/devs.c
+/* linux/arch/arm/plat-s3c24xx/devs.c
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
 #include <asm/irq.h>
 
 #include <asm/arch/regs-serial.h>
+#include <asm/arch/udc.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* Serial port registrations */
 
@@ -230,6 +231,20 @@ struct platform_device s3c_device_usbgadget = {
 
 EXPORT_SYMBOL(s3c_device_usbgadget);
 
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+       struct s3c2410_udc_mach_info *npd;
+
+       npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+       if (npd) {
+               memcpy(npd, pd, sizeof(*npd));
+               s3c_device_usbgadget.dev.platform_data = npd;
+       } else {
+               printk(KERN_ERR "no memory for udc platform data\n");
+       }
+}
+
+
 /* Watchdog */
 
 static struct resource s3c_wdt_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
new file mode 100644 (file)
index 0000000..4540a80
--- /dev/null
@@ -0,0 +1,1499 @@
+/* linux/arch/arm/plat-s3c24xx/dma.c
+ *
+ * Copyright (c) 2003-2005,2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+
+/* io map for dma */
+static void __iomem *dma_base;
+static struct kmem_cache *dma_kmem;
+
+static int dma_channels;
+
+struct s3c24xx_dma_selection dma_sel;
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
+{
+       pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+       writel(val, dma_regaddr(chan, reg));
+}
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+       unsigned long         dcsrc;
+       unsigned long         disrc;
+       unsigned long         dstat;
+       unsigned long         dcon;
+       unsigned long         dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+{
+       regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+       regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
+       regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+       regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
+       regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
+                struct s3c2410_dma_regstate *regs)
+{
+       printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+              chan->number, fname, line,
+              regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+              regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+       struct s3c2410_dma_regstate state;
+
+       dmadbg_capture(chan, &state);
+
+       printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+              chan->number, fname, line, chan->load_state,
+              chan->curr, chan->next, chan->end);
+
+       dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+       struct s3c2410_dma_regstate state;
+
+       dmadbg_capture(chan, &state);
+       dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
+
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+       if (channel & DMACH_LOW_LEVEL)
+               return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+       else
+               return dma_chan_map[channel];
+}
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+{
+       if (stats == NULL)
+               return;
+
+       if (val > stats->timeout_longest)
+               stats->timeout_longest = val;
+       if (val < stats->timeout_shortest)
+               stats->timeout_shortest = val;
+
+       stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
+{
+       int timeout = chan->load_timeout;
+       int took;
+
+       if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+               printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+               return 0;
+       }
+
+       if (chan->stats != NULL)
+               chan->stats->loads++;
+
+       while (--timeout > 0) {
+               if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+                       took = chan->load_timeout - timeout;
+
+                       s3c2410_dma_stats_timeout(chan->stats, took);
+
+                       switch (chan->load_state) {
+                       case S3C2410_DMALOAD_1LOADED:
+                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
+                               break;
+
+                       default:
+                               printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+                       }
+
+                       return 1;
+               }
+       }
+
+       if (chan->stats != NULL) {
+               chan->stats->timeout_failed++;
+       }
+
+       return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+                      struct s3c2410_dma_buf *buf)
+{
+       unsigned long reload;
+
+       pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+                buf, (unsigned long)buf->data, buf->size);
+
+       if (buf == NULL) {
+               dmawarn("buffer is NULL\n");
+               return -EINVAL;
+       }
+
+       /* check the state of the channel before we do anything */
+
+       if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+               dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+       }
+
+       if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+               dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+       }
+
+       /* it would seem sensible if we are the last buffer to not bother
+        * with the auto-reload bit, so that the DMA engine will not try
+        * and load another transfer after this one has finished...
+        */
+       if (chan->load_state == S3C2410_DMALOAD_NONE) {
+               pr_debug("load_state is none, checking for noreload (next=%p)\n",
+                        buf->next);
+               reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+       } else {
+               //pr_debug("load_state is %d => autoreload\n", chan->load_state);
+               reload = S3C2410_DCON_AUTORELOAD;
+       }
+
+       if ((buf->data & 0xf0000000) != 0x30000000) {
+               dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+       }
+
+       writel(buf->data, chan->addr_reg);
+
+       dma_wrreg(chan, S3C2410_DMA_DCON,
+                 chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+       chan->next = buf->next;
+
+       /* update the state of the channel */
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_NONE:
+               chan->load_state = S3C2410_DMALOAD_1LOADED;
+               break;
+
+       case S3C2410_DMALOAD_1RUNNING:
+               chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+               break;
+
+       default:
+               dmawarn("dmaload: unknown state %d in loadbuffer\n",
+                       chan->load_state);
+               break;
+       }
+
+       return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
+{
+       if (chan->op_fn != NULL) {
+               (chan->op_fn)(chan, op);
+       }
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+                    enum s3c2410_dma_buffresult result)
+{
+#if 0
+       pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+                chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
+
+       if (chan->callback_fn != NULL) {
+               (chan->callback_fn)(chan, buf->id, buf->size, result);
+       }
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
+{
+       unsigned long tmp;
+       unsigned long flags;
+
+       pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+       local_irq_save(flags);
+
+       if (chan->state == S3C2410_DMA_RUNNING) {
+               pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+               local_irq_restore(flags);
+               return 0;
+       }
+
+       chan->state = S3C2410_DMA_RUNNING;
+
+       /* check wether there is anything to load, and if not, see
+        * if we can find anything to load
+        */
+
+       if (chan->load_state == S3C2410_DMALOAD_NONE) {
+               if (chan->next == NULL) {
+                       printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+                              chan->number);
+                       chan->state = S3C2410_DMA_IDLE;
+                       local_irq_restore(flags);
+                       return -EINVAL;
+               }
+
+               s3c2410_dma_loadbuffer(chan, chan->next);
+       }
+
+       dbg_showchan(chan);
+
+       /* enable the channel */
+
+       if (!chan->irq_enabled) {
+               enable_irq(chan->irq);
+               chan->irq_enabled = 1;
+       }
+
+       /* start the channel going */
+
+       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+       tmp &= ~S3C2410_DMASKTRIG_STOP;
+       tmp |= S3C2410_DMASKTRIG_ON;
+       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+       pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
+
+#if 0
+       /* the dma buffer loads should take care of clearing the AUTO
+        * reloading feature */
+       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+       tmp &= ~S3C2410_DCON_NORELOAD;
+       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+       s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+       dbg_showchan(chan);
+
+       /* if we've only loaded one buffer onto the channel, then chec
+        * to see if we have another, and if so, try and load it so when
+        * the first buffer is finished, the new one will be loaded onto
+        * the channel */
+
+       if (chan->next != NULL) {
+               if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               pr_debug("%s: buff not yet loaded, no more todo\n",
+                                        __FUNCTION__);
+                       } else {
+                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
+                               s3c2410_dma_loadbuffer(chan, chan->next);
+                       }
+
+               } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+                       s3c2410_dma_loadbuffer(chan, chan->next);
+               }
+       }
+
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
+{
+       if (chan->load_state == S3C2410_DMALOAD_NONE ||
+           chan->load_state == S3C2410_DMALOAD_1RUNNING)
+               return 1;
+
+       return 0;
+}
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+                       dma_addr_t data, int size)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+       struct s3c2410_dma_buf *buf;
+       unsigned long flags;
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: id=%p, data=%08x, size=%d\n",
+                __FUNCTION__, id, (unsigned int)data, size);
+
+       buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
+       if (buf == NULL) {
+               pr_debug("%s: out of memory (%ld alloc)\n",
+                        __FUNCTION__, (long)sizeof(*buf));
+               return -ENOMEM;
+       }
+
+       //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+       //dbg_showchan(chan);
+
+       buf->next  = NULL;
+       buf->data  = buf->ptr = data;
+       buf->size  = size;
+       buf->id    = id;
+       buf->magic = BUF_MAGIC;
+
+       local_irq_save(flags);
+
+       if (chan->curr == NULL) {
+               /* we've got nothing loaded... */
+               pr_debug("%s: buffer %p queued onto empty channel\n",
+                        __FUNCTION__, buf);
+
+               chan->curr = buf;
+               chan->end  = buf;
+               chan->next = NULL;
+       } else {
+               pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+                        chan->number, __FUNCTION__, buf);
+
+               if (chan->end == NULL)
+                       pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+                                chan->number, __FUNCTION__, chan);
+
+               chan->end->next = buf;
+               chan->end = buf;
+       }
+
+       /* if necessary, update the next buffer field */
+       if (chan->next == NULL)
+               chan->next = buf;
+
+       /* check to see if we can load a buffer */
+       if (chan->state == S3C2410_DMA_RUNNING) {
+               if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               printk(KERN_ERR "dma%d: loadbuffer:"
+                                      "timeout loading buffer\n",
+                                      chan->number);
+                               dbg_showchan(chan);
+                               local_irq_restore(flags);
+                               return -EINVAL;
+                       }
+               }
+
+               while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+                       s3c2410_dma_loadbuffer(chan, chan->next);
+               }
+       } else if (chan->state == S3C2410_DMA_IDLE) {
+               if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+               }
+       }
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+static inline void
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
+{
+       int magicok = (buf->magic == BUF_MAGIC);
+
+       buf->magic = -1;
+
+       if (magicok) {
+               kmem_cache_free(dma_kmem, buf);
+       } else {
+               printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+       }
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
+{
+#if 0
+       pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+                chan->number, chan->load_state);
+#endif
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_NONE:
+               break;
+
+       case S3C2410_DMALOAD_1LOADED:
+               if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               /* flag error? */
+                       printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+                              chan->number, __FUNCTION__);
+                       return;
+               }
+               break;
+
+       case S3C2410_DMALOAD_1LOADED_1RUNNING:
+               /* I belive in this case we do not have anything to do
+                * until the next buffer comes along, and we turn off the
+                * reload */
+               return;
+
+       default:
+               pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
+                        chan->number, chan->load_state);
+               return;
+
+       }
+
+       /* hopefully this'll shut the damned thing up after the transfer... */
+       dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw)
+{
+       struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+       struct s3c2410_dma_buf  *buf;
+
+       buf = chan->curr;
+
+       dbg_showchan(chan);
+
+       /* modify the channel state */
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_1RUNNING:
+               /* TODO - if we are running only one buffer, we probably
+                * want to reload here, and then worry about the buffer
+                * callback */
+
+               chan->load_state = S3C2410_DMALOAD_NONE;
+               break;
+
+       case S3C2410_DMALOAD_1LOADED:
+               /* iirc, we should go back to NONE loaded here, we
+                * had a buffer, and it was never verified as being
+                * loaded.
+                */
+
+               chan->load_state = S3C2410_DMALOAD_NONE;
+               break;
+
+       case S3C2410_DMALOAD_1LOADED_1RUNNING:
+               /* we'll worry about checking to see if another buffer is
+                * ready after we've called back the owner. This should
+                * ensure we do not wait around too long for the DMA
+                * engine to start the next transfer
+                */
+
+               chan->load_state = S3C2410_DMALOAD_1LOADED;
+               break;
+
+       case S3C2410_DMALOAD_NONE:
+               printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+                      chan->number);
+               break;
+
+       default:
+               printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+                      chan->number, chan->load_state);
+               break;
+       }
+
+       if (buf != NULL) {
+               /* update the chain to make sure that if we load any more
+                * buffers when we call the callback function, things should
+                * work properly */
+
+               chan->curr = buf->next;
+               buf->next  = NULL;
+
+               if (buf->magic != BUF_MAGIC) {
+                       printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+                              chan->number, __FUNCTION__, buf);
+                       return IRQ_HANDLED;
+               }
+
+               s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+               /* free resouces */
+               s3c2410_dma_freebuf(buf);
+       } else {
+       }
+
+       /* only reload if the channel is still running... our buffer done
+        * routine may have altered the state by requesting the dma channel
+        * to stop or shutdown... */
+
+       /* todo: check that when the channel is shut-down from inside this
+        * function, we cope with unsetting reload, etc */
+
+       if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
+               unsigned long flags;
+
+               switch (chan->load_state) {
+               case S3C2410_DMALOAD_1RUNNING:
+                       /* don't need to do anything for this state */
+                       break;
+
+               case S3C2410_DMALOAD_NONE:
+                       /* can load buffer immediately */
+                       break;
+
+               case S3C2410_DMALOAD_1LOADED:
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               /* flag error? */
+                               printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+                                      chan->number, __FUNCTION__);
+                               return IRQ_HANDLED;
+                       }
+
+                       break;
+
+               case S3C2410_DMALOAD_1LOADED_1RUNNING:
+                       goto no_load;
+
+               default:
+                       printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+                              chan->number, chan->load_state);
+                       return IRQ_HANDLED;
+               }
+
+               local_irq_save(flags);
+               s3c2410_dma_loadbuffer(chan, chan->next);
+               local_irq_restore(flags);
+       } else {
+               s3c2410_dma_lastxfer(chan);
+
+               /* see if we can stop this channel.. */
+               if (chan->load_state == S3C2410_DMALOAD_NONE) {
+                       pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+                                chan->number, jiffies);
+                       s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+                                        S3C2410_DMAOP_STOP);
+               }
+       }
+
+ no_load:
+       return IRQ_HANDLED;
+}
+
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+                       struct s3c2410_dma_client *client,
+                       void *dev)
+{
+       struct s3c2410_dma_chan *chan;
+       unsigned long flags;
+       int err;
+
+       pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+                channel, client->name, dev);
+
+       local_irq_save(flags);
+
+       chan = s3c2410_dma_map_channel(channel);
+       if (chan == NULL) {
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+
+       dbg_showchan(chan);
+
+       chan->client = client;
+       chan->in_use = 1;
+
+       if (!chan->irq_claimed) {
+               pr_debug("dma%d: %s : requesting irq %d\n",
+                        channel, __FUNCTION__, chan->irq);
+
+               chan->irq_claimed = 1;
+               local_irq_restore(flags);
+
+               err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
+                                 client->name, (void *)chan);
+
+               local_irq_save(flags);
+
+               if (err) {
+                       chan->in_use = 0;
+                       chan->irq_claimed = 0;
+                       local_irq_restore(flags);
+
+                       printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+                              client->name, chan->irq, chan->number);
+                       return err;
+               }
+
+               chan->irq_enabled = 1;
+       }
+
+       local_irq_restore(flags);
+
+       /* need to setup */
+
+       pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+       unsigned long flags;
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       if (chan->client != client) {
+               printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+                      channel, chan->client, client);
+       }
+
+       /* sort out stopping and freeing the channel */
+
+       if (chan->state != S3C2410_DMA_IDLE) {
+               pr_debug("%s: need to stop dma channel %p\n",
+                      __FUNCTION__, chan);
+
+               /* possibly flush the channel */
+               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+       }
+
+       chan->client = NULL;
+       chan->in_use = 0;
+
+       if (chan->irq_claimed)
+               free_irq(chan->irq, (void *)chan);
+
+       chan->irq_claimed = 0;
+
+       if (!(channel & DMACH_LOW_LEVEL))
+               dma_chan_map[channel] = NULL;
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
+{
+       unsigned long flags;
+       unsigned long tmp;
+
+       pr_debug("%s:\n", __FUNCTION__);
+
+       dbg_showchan(chan);
+
+       local_irq_save(flags);
+
+       s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+       tmp |= S3C2410_DMASKTRIG_STOP;
+       //tmp &= ~S3C2410_DMASKTRIG_ON;
+       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+       /* should also clear interrupts, according to WinCE BSP */
+       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+       tmp |= S3C2410_DCON_NORELOAD;
+       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+       /* should stop do this, or should we wait for flush? */
+       chan->state      = S3C2410_DMA_IDLE;
+       chan->load_state = S3C2410_DMALOAD_NONE;
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+       unsigned long tmp;
+       unsigned int timeout = 0x10000;
+
+       while (timeout-- > 0) {
+               tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+               if (!(tmp & S3C2410_DMASKTRIG_ON))
+                       return;
+       }
+
+       pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
+{
+       struct s3c2410_dma_buf *buf, *next;
+       unsigned long flags;
+
+       pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+       dbg_showchan(chan);
+
+       local_irq_save(flags);
+
+       if (chan->state != S3C2410_DMA_IDLE) {
+               pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+               s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+       }
+
+       buf = chan->curr;
+       if (buf == NULL)
+               buf = chan->next;
+
+       chan->curr = chan->next = chan->end = NULL;
+
+       if (buf != NULL) {
+               for ( ; buf != NULL; buf = next) {
+                       next = buf->next;
+
+                       pr_debug("%s: free buffer %p, next %p\n",
+                              __FUNCTION__, buf, buf->next);
+
+                       s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+                       s3c2410_dma_freebuf(buf);
+               }
+       }
+
+       dbg_showregs(chan);
+
+       s3c2410_dma_waitforstop(chan);
+
+#if 0
+       /* should also clear interrupts, according to WinCE BSP */
+       {
+               unsigned long tmp;
+
+               tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+               tmp |= S3C2410_DCON_NORELOAD;
+               dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+       }
+#endif
+
+       dbg_showregs(chan);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+int
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       dbg_showchan(chan);
+
+       /* if we've only loaded one buffer onto the channel, then chec
+        * to see if we have another, and if so, try and load it so when
+        * the first buffer is finished, the new one will be loaded onto
+        * the channel */
+
+       if (chan->next != NULL) {
+               if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               pr_debug("%s: buff not yet loaded, no more todo\n",
+                                        __FUNCTION__);
+                       } else {
+                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
+                               s3c2410_dma_loadbuffer(chan, chan->next);
+                       }
+
+               } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+                       s3c2410_dma_loadbuffer(chan, chan->next);
+               }
+       }
+
+
+       local_irq_restore(flags);
+
+       return 0;
+
+}
+
+int
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       switch (op) {
+       case S3C2410_DMAOP_START:
+               return s3c2410_dma_start(chan);
+
+       case S3C2410_DMAOP_STOP:
+               return s3c2410_dma_dostop(chan);
+
+       case S3C2410_DMAOP_PAUSE:
+       case S3C2410_DMAOP_RESUME:
+               return -ENOENT;
+
+       case S3C2410_DMAOP_FLUSH:
+               return s3c2410_dma_flush(chan);
+
+       case S3C2410_DMAOP_STARTED:
+               return s3c2410_dma_started(chan);
+
+       case S3C2410_DMAOP_TIMEOUT:
+               return 0;
+
+       }
+
+       return -ENOENT;      /* unknown, don't bother */
+}
+
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC  -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST  -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize:     size of unit in bytes (1,2,4)
+ * dcon:         base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+                      int xferunit,
+                      int dcon)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+                __FUNCTION__, channel, xferunit, dcon);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
+
+       dcon |= chan->dcon & dma_sel.dcon_mask;
+
+       pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
+
+       switch (xferunit) {
+       case 1:
+               dcon |= S3C2410_DCON_BYTE;
+               break;
+
+       case 2:
+               dcon |= S3C2410_DCON_HALFWORD;
+               break;
+
+       case 4:
+               dcon |= S3C2410_DCON_WORD;
+               break;
+
+       default:
+               pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+               return -EINVAL;
+       }
+
+       dcon |= S3C2410_DCON_HWTRIG;
+       dcon |= S3C2410_DCON_INTREQ;
+
+       pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+       chan->dcon = dcon;
+       chan->xfer_unit = xferunit;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+       chan->flags = flags;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_setflags);
+
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+       chan->op_fn = rtn;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+       chan->callback_fn = rtn;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source:    S3C2410_DMASRC_HW: source is hardware
+ *            S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg:     the value for xxxSTCn register,
+ *            bit 0: 0=increment pointer, 1=leave pointer
+ *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr:   physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+                         enum s3c2410_dmasrc source,
+                         int hwcfg,
+                         unsigned long devaddr)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+                __FUNCTION__, (int)source, hwcfg, devaddr);
+
+       chan->source = source;
+       chan->dev_addr = devaddr;
+
+       switch (source) {
+       case S3C2410_DMASRC_HW:
+               /* source is hardware */
+               pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+                        __FUNCTION__, devaddr, hwcfg);
+               dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+               dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
+               dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+               return 0;
+
+       case S3C2410_DMASRC_MEM:
+               /* source is memory */
+               pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+                         __FUNCTION__, devaddr, hwcfg);
+               dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+               dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
+               dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+               return 0;
+       }
+
+       printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+/* s3c2410_dma_getposition
+ *
+ * returns the current transfer points for the dma source and destination
+*/
+
+int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
+{
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+       if (chan == NULL)
+               return -EINVAL;
+
+       if (src != NULL)
+               *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+
+       if (dst != NULL)
+               *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+
+/* system device class */
+
+#ifdef CONFIG_PM
+
+static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
+
+       printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
+
+       if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
+               /* the dma channel is still working, which is probably
+                * a bad thing to do over suspend/resume. We stop the
+                * channel and assume that the client is either going to
+                * retry after resume, or that it is broken.
+                */
+
+               printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
+                      cp->number);
+
+               s3c2410_dma_dostop(cp);
+       }
+
+       return 0;
+}
+
+static int s3c2410_dma_resume(struct sys_device *dev)
+{
+       return 0;
+}
+
+#else
+#define s3c2410_dma_suspend NULL
+#define s3c2410_dma_resume  NULL
+#endif /* CONFIG_PM */
+
+struct sysdev_class dma_sysclass = {
+       set_kset_name("s3c24xx-dma"),
+       .suspend        = s3c2410_dma_suspend,
+       .resume         = s3c2410_dma_resume,
+};
+
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+{
+       memset(p, 0, sizeof(struct s3c2410_dma_buf));
+}
+
+/* initialisation code */
+
+int __init s3c24xx_dma_sysclass_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);
+
+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;
+               }
+       }
+
+       return 0;
+}
+
+late_initcall(s3c24xx_dma_sysdev_register);
+
+int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+                           unsigned int stride)
+{
+       struct s3c2410_dma_chan *cp;
+       int channel;
+       int ret;
+
+       printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
+
+       dma_channels = channels;
+
+       dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
+       if (dma_base == NULL) {
+               printk(KERN_ERR "dma failed to remap register block\n");
+               return -ENOMEM;
+       }
+
+       dma_kmem = kmem_cache_create("dma_desc",
+                                    sizeof(struct s3c2410_dma_buf), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    s3c2410_dma_cache_ctor, NULL);
+
+       if (dma_kmem == NULL) {
+               printk(KERN_ERR "dma failed to make kmem cache\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (channel = 0; channel < channels;  channel++) {
+               cp = &s3c2410_chans[channel];
+
+               memset(cp, 0, sizeof(struct s3c2410_dma_chan));
+
+               /* dma channel irqs are in order.. */
+               cp->number = channel;
+               cp->irq    = channel + irq;
+               cp->regs   = dma_base + (channel * stride);
+
+               /* point current stats somewhere */
+               cp->stats  = &cp->stats_store;
+               cp->stats_store.timeout_shortest = LONG_MAX;
+
+               /* basic channel configuration */
+
+               cp->load_timeout = 1<<18;
+
+               printk("DMA channel %d at %p, irq %d\n",
+                      cp->number, cp->regs, cp->irq);
+       }
+
+       return 0;
+
+ err:
+       kmem_cache_destroy(dma_kmem);
+       iounmap(dma_base);
+       dma_base = NULL;
+       return ret;
+}
+
+int s3c2410_dma_init(void)
+{
+       return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
+}
+
+static inline int is_channel_valid(unsigned int channel)
+{
+       return (channel & DMA_CH_VALID);
+}
+
+static struct s3c24xx_dma_order *dma_order;
+
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * first, try the dma ordering given to us by either the relevant
+ * dma code, or the board. Then just find the first usable free
+ * channel
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+       struct s3c24xx_dma_order_ch *ord = NULL;
+       struct s3c24xx_dma_map *ch_map;
+       struct s3c2410_dma_chan *dmach;
+       int ch;
+
+       if (dma_sel.map == NULL || channel > dma_sel.map_size)
+               return NULL;
+
+       ch_map = dma_sel.map + channel;
+
+       /* first, try the board mapping */
+
+       if (dma_order) {
+               ord = &dma_order->channels[channel];
+
+               for (ch = 0; ch < dma_channels; ch++) {
+                       if (!is_channel_valid(ord->list[ch]))
+                               continue;
+
+                       if (s3c2410_chans[ord->list[ch]].in_use == 0) {
+                               ch = ord->list[ch] & ~DMA_CH_VALID;
+                               goto found;
+                       }
+               }
+
+               if (ord->flags & DMA_CH_NEVER)
+                       return NULL;
+       }
+
+       /* second, search the channel map for first free */
+
+       for (ch = 0; ch < dma_channels; ch++) {
+               if (!is_channel_valid(ch_map->channels[ch]))
+                       continue;
+
+               if (s3c2410_chans[ch].in_use == 0) {
+                       printk("mapped channel %d to %d\n", channel, ch);
+                       break;
+               }
+       }
+
+       if (ch >= dma_channels)
+               return NULL;
+
+       /* update our channel mapping */
+
+ found:
+       dmach = &s3c2410_chans[ch];
+       dma_chan_map[channel] = dmach;
+
+       /* select the channel */
+
+       (dma_sel.select)(dmach, ch_map);
+
+       return dmach;
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+       return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+       struct s3c24xx_dma_map *nmap;
+       size_t map_sz = sizeof(*nmap) * sel->map_size;
+       int ptr;
+
+       nmap = kmalloc(map_sz, GFP_KERNEL);
+       if (nmap == NULL)
+               return -ENOMEM;
+
+       memcpy(nmap, sel->map, map_sz);
+       memcpy(&dma_sel, sel, sizeof(*sel));
+
+       dma_sel.map = nmap;
+
+       for (ptr = 0; ptr < sel->map_size; ptr++)
+               s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+       return 0;
+}
+
+int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
+{
+       struct s3c24xx_dma_order *nord = dma_order;
+
+       if (nord == NULL)
+               nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
+
+       if (nord == NULL) {
+               printk(KERN_ERR "no memory to store dma channel order\n");
+               return -ENOMEM;
+       }
+
+       dma_order = nord;
+       memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
+       return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
new file mode 100644 (file)
index 0000000..ec3a09c
--- /dev/null
@@ -0,0 +1,188 @@
+/* linux/arch/arm/plat-s3c24xx/gpio.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+{
+       void __iomem *base = S3C24XX_GPIO_BASE(pin);
+       unsigned long mask;
+       unsigned long con;
+       unsigned long flags;
+
+       if (pin < S3C2410_GPIO_BANKB) {
+               mask = 1 << S3C2410_GPIO_OFFSET(pin);
+       } else {
+               mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+       }
+
+       switch (function) {
+       case S3C2410_GPIO_LEAVE:
+               mask = 0;
+               function = 0;
+               break;
+
+       case S3C2410_GPIO_INPUT:
+       case S3C2410_GPIO_OUTPUT:
+       case S3C2410_GPIO_SFN2:
+       case S3C2410_GPIO_SFN3:
+               if (pin < S3C2410_GPIO_BANKB) {
+                       function -= 1;
+                       function &= 1;
+                       function <<= S3C2410_GPIO_OFFSET(pin);
+               } else {
+                       function &= 3;
+                       function <<= S3C2410_GPIO_OFFSET(pin)*2;
+               }
+       }
+
+       /* modify the specified register wwith IRQs off */
+
+       local_irq_save(flags);
+
+       con  = __raw_readl(base + 0x00);
+       con &= ~mask;
+       con |= function;
+
+       __raw_writel(con, base + 0x00);
+
+       local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
+
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+       void __iomem *base = S3C24XX_GPIO_BASE(pin);
+       unsigned long val = __raw_readl(base);
+
+       if (pin < S3C2410_GPIO_BANKB) {
+               val >>= S3C2410_GPIO_OFFSET(pin);
+               val &= 1;
+               val += 1;
+       } else {
+               val >>= S3C2410_GPIO_OFFSET(pin)*2;
+               val &= 3;
+       }
+
+       return val | S3C2410_GPIO_INPUT;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getcfg);
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+       void __iomem *base = S3C24XX_GPIO_BASE(pin);
+       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+       unsigned long flags;
+       unsigned long up;
+
+       if (pin < S3C2410_GPIO_BANKB)
+               return;
+
+       local_irq_save(flags);
+
+       up = __raw_readl(base + 0x08);
+       up &= ~(1L << offs);
+       up |= to << offs;
+       __raw_writel(up, base + 0x08);
+
+       local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+       void __iomem *base = S3C24XX_GPIO_BASE(pin);
+       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+       unsigned long flags;
+       unsigned long dat;
+
+       local_irq_save(flags);
+
+       dat = __raw_readl(base + 0x04);
+       dat &= ~(1 << offs);
+       dat |= to << offs;
+       __raw_writel(dat, base + 0x04);
+
+       local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+       void __iomem *base = S3C24XX_GPIO_BASE(pin);
+       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+       return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+       unsigned long flags;
+       unsigned long misccr;
+
+       local_irq_save(flags);
+       misccr = __raw_readl(S3C24XX_MISCCR);
+       misccr &= ~clear;
+       misccr ^= change;
+       __raw_writel(misccr, S3C24XX_MISCCR);
+       local_irq_restore(flags);
+
+       return misccr;
+}
+
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+       if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
+               return -1;      /* not valid interrupts */
+
+       if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+               return -1;      /* not valid pin */
+
+       if (pin < S3C2410_GPF4)
+               return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+       if (pin < S3C2410_GPG0)
+               return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+       return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
new file mode 100644 (file)
index 0000000..ce18639
--- /dev/null
@@ -0,0 +1,801 @@
+/* linux/arch/arm/plat-s3c24xx/irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *               Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *               Tidy up KF's patch and sort out new release
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *               Add support for power management controls
+ *
+ *   04-Nov-2004  Ben Dooks
+ *               Fix standard IRQ wake for EINT0..4 and RTC
+ *
+ *   22-Feb-2005  Ben Dooks
+ *               Fixed edge-triggering on ADC IRQ
+ *
+ *   28-Jun-2005  Ben Dooks
+ *               Mark IRQ_LCD valid
+ *
+ *   25-Jul-2005  Ben Dooks
+ *               Split the S3C2440 IRQ code to seperate file
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* wakeup irq control */
+
+#ifdef CONFIG_PM
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow     = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intmask      = 0xffffffffL;
+unsigned long s3c_irqwake_eintallow    = 0x0000fff0L;
+unsigned long s3c_irqwake_eintmask     = 0xffffffffL;
+
+int
+s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+       unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+       if (!(s3c_irqwake_intallow & irqbit))
+               return -ENOENT;
+
+       printk(KERN_INFO "wake %s for irq %d\n",
+              state ? "enabled" : "disabled", irqno);
+
+       if (!state)
+               s3c_irqwake_intmask |= irqbit;
+       else
+               s3c_irqwake_intmask &= ~irqbit;
+
+       return 0;
+}
+
+static int
+s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+       unsigned long bit = 1L << (irqno - EXTINT_OFF);
+
+       if (!(s3c_irqwake_eintallow & bit))
+               return -ENOENT;
+
+       printk(KERN_INFO "wake %s for irq %d\n",
+              state ? "enabled" : "disabled", irqno);
+
+       if (!state)
+               s3c_irqwake_eintmask |= bit;
+       else
+               s3c_irqwake_eintmask &= ~bit;
+
+       return 0;
+}
+
+#else
+#define s3c_irqext_wake NULL
+#define s3c_irq_wake NULL
+#endif
+
+
+static void
+s3c_irq_mask(unsigned int irqno)
+{
+       unsigned long mask;
+
+       irqno -= IRQ_EINT0;
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       mask |= 1UL << irqno;
+       __raw_writel(mask, S3C2410_INTMSK);
+}
+
+static inline void
+s3c_irq_ack(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+       __raw_writel(bitval, S3C2410_SRCPND);
+       __raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c_irq_maskack(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+       unsigned long mask;
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       __raw_writel(mask|bitval, S3C2410_INTMSK);
+
+       __raw_writel(bitval, S3C2410_SRCPND);
+       __raw_writel(bitval, S3C2410_INTPND);
+}
+
+
+static void
+s3c_irq_unmask(unsigned int irqno)
+{
+       unsigned long mask;
+
+       if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
+               irqdbf2("s3c_irq_unmask %d\n", irqno);
+
+       irqno -= IRQ_EINT0;
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       mask &= ~(1UL << irqno);
+       __raw_writel(mask, S3C2410_INTMSK);
+}
+
+struct irq_chip s3c_irq_level_chip = {
+       .name           = "s3c-level",
+       .ack            = s3c_irq_maskack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_chip = {
+       .name           = "s3c",
+       .ack            = s3c_irq_ack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake
+};
+
+static void
+s3c_irqext_mask(unsigned int irqno)
+{
+       unsigned long mask;
+
+       irqno -= EXTINT_OFF;
+
+       mask = __raw_readl(S3C24XX_EINTMASK);
+       mask |= ( 1UL << irqno);
+       __raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+static void
+s3c_irqext_ack(unsigned int irqno)
+{
+       unsigned long req;
+       unsigned long bit;
+       unsigned long mask;
+
+       bit = 1UL << (irqno - EXTINT_OFF);
+
+       mask = __raw_readl(S3C24XX_EINTMASK);
+
+       __raw_writel(bit, S3C24XX_EINTPEND);
+
+       req = __raw_readl(S3C24XX_EINTPEND);
+       req &= ~mask;
+
+       /* not sure if we should be acking the parent irq... */
+
+       if (irqno <= IRQ_EINT7 ) {
+               if ((req & 0xf0) == 0)
+                       s3c_irq_ack(IRQ_EINT4t7);
+       } else {
+               if ((req >> 8) == 0)
+                       s3c_irq_ack(IRQ_EINT8t23);
+       }
+}
+
+static void
+s3c_irqext_unmask(unsigned int irqno)
+{
+       unsigned long mask;
+
+       irqno -= EXTINT_OFF;
+
+       mask = __raw_readl(S3C24XX_EINTMASK);
+       mask &= ~( 1UL << irqno);
+       __raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+int
+s3c_irqext_type(unsigned int irq, unsigned int type)
+{
+       void __iomem *extint_reg;
+       void __iomem *gpcon_reg;
+       unsigned long gpcon_offset, extint_offset;
+       unsigned long newvalue = 0, value;
+
+       if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+       {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C24XX_EXTINT0;
+               gpcon_offset = (irq - IRQ_EINT0) * 2;
+               extint_offset = (irq - IRQ_EINT0) * 4;
+       }
+       else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+       {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C24XX_EXTINT0;
+               gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+               extint_offset = (irq - (EXTINT_OFF)) * 4;
+       }
+       else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+       {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C24XX_EXTINT1;
+               gpcon_offset = (irq - IRQ_EINT8) * 2;
+               extint_offset = (irq - IRQ_EINT8) * 4;
+       }
+       else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+       {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C24XX_EXTINT2;
+               gpcon_offset = (irq - IRQ_EINT8) * 2;
+               extint_offset = (irq - IRQ_EINT16) * 4;
+       } else
+               return -1;
+
+       /* Set the GPIO to external interrupt mode */
+       value = __raw_readl(gpcon_reg);
+       value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+       __raw_writel(value, gpcon_reg);
+
+       /* Set the external interrupt to pointed trigger type */
+       switch (type)
+       {
+               case IRQT_NOEDGE:
+                       printk(KERN_WARNING "No edge setting!\n");
+                       break;
+
+               case IRQT_RISING:
+                       newvalue = S3C2410_EXTINT_RISEEDGE;
+                       break;
+
+               case IRQT_FALLING:
+                       newvalue = S3C2410_EXTINT_FALLEDGE;
+                       break;
+
+               case IRQT_BOTHEDGE:
+                       newvalue = S3C2410_EXTINT_BOTHEDGE;
+                       break;
+
+               case IRQT_LOW:
+                       newvalue = S3C2410_EXTINT_LOWLEV;
+                       break;
+
+               case IRQT_HIGH:
+                       newvalue = S3C2410_EXTINT_HILEV;
+                       break;
+
+               default:
+                       printk(KERN_ERR "No such irq type %d", type);
+                       return -1;
+       }
+
+       value = __raw_readl(extint_reg);
+       value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+       __raw_writel(value, extint_reg);
+
+       return 0;
+}
+
+static struct irq_chip s3c_irqext_chip = {
+       .name           = "s3c-ext",
+       .mask           = s3c_irqext_mask,
+       .unmask         = s3c_irqext_unmask,
+       .ack            = s3c_irqext_ack,
+       .set_type       = s3c_irqext_type,
+       .set_wake       = s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+       .name           = "s3c-ext0",
+       .ack            = s3c_irq_ack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake,
+       .set_type       = s3c_irqext_type,
+};
+
+/* mask values for the parent registers for each of the interrupt types */
+
+#define INTMSK_UART0    (1UL << (IRQ_UART0 - IRQ_EINT0))
+#define INTMSK_UART1    (1UL << (IRQ_UART1 - IRQ_EINT0))
+#define INTMSK_UART2    (1UL << (IRQ_UART2 - IRQ_EINT0))
+#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
+
+
+/* UART0 */
+
+static void
+s3c_irq_uart0_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+}
+
+static void
+s3c_irq_uart0_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_UART0);
+}
+
+static void
+s3c_irq_uart0_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+}
+
+static struct irq_chip s3c_irq_uart0 = {
+       .name           = "s3c-uart0",
+       .mask           = s3c_irq_uart0_mask,
+       .unmask         = s3c_irq_uart0_unmask,
+       .ack            = s3c_irq_uart0_ack,
+};
+
+/* UART1 */
+
+static void
+s3c_irq_uart1_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static void
+s3c_irq_uart1_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_UART1);
+}
+
+static void
+s3c_irq_uart1_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static struct irq_chip s3c_irq_uart1 = {
+       .name           = "s3c-uart1",
+       .mask           = s3c_irq_uart1_mask,
+       .unmask         = s3c_irq_uart1_unmask,
+       .ack            = s3c_irq_uart1_ack,
+};
+
+/* UART2 */
+
+static void
+s3c_irq_uart2_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static void
+s3c_irq_uart2_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_UART2);
+}
+
+static void
+s3c_irq_uart2_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static struct irq_chip s3c_irq_uart2 = {
+       .name           = "s3c-uart2",
+       .mask           = s3c_irq_uart2_mask,
+       .unmask         = s3c_irq_uart2_unmask,
+       .ack            = s3c_irq_uart2_ack,
+};
+
+/* ADC and Touchscreen */
+
+static void
+s3c_irq_adc_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static void
+s3c_irq_adc_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+}
+
+static void
+s3c_irq_adc_ack(unsigned int irqno)
+{
+       s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static struct irq_chip s3c_irq_adc = {
+       .name           = "s3c-adc",
+       .mask           = s3c_irq_adc_mask,
+       .unmask         = s3c_irq_adc_unmask,
+       .ack            = s3c_irq_adc_ack,
+};
+
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+                             struct irq_desc *desc)
+{
+       unsigned int subsrc, submsk;
+       unsigned int offset = 9;
+       struct irq_desc *mydesc;
+
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
+
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+       subsrc &= ~submsk;
+       subsrc >>= offset;
+       subsrc &= 3;
+
+       if (subsrc != 0) {
+               if (subsrc & 1) {
+                       mydesc = irq_desc + IRQ_TC;
+                       desc_handle_irq(IRQ_TC, mydesc);
+               }
+               if (subsrc & 2) {
+                       mydesc = irq_desc + IRQ_ADC;
+                       desc_handle_irq(IRQ_ADC, mydesc);
+               }
+       }
+}
+
+static void s3c_irq_demux_uart(unsigned int start)
+{
+       unsigned int subsrc, submsk;
+       unsigned int offset = start - IRQ_S3CUART_RX0;
+       struct irq_desc *desc;
+
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
+
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+       irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+               start, offset, subsrc, submsk);
+
+       subsrc &= ~submsk;
+       subsrc >>= offset;
+       subsrc &= 7;
+
+       if (subsrc != 0) {
+               desc = irq_desc + start;
+
+               if (subsrc & 1)
+                       desc_handle_irq(start, desc);
+
+               desc++;
+
+               if (subsrc & 2)
+                       desc_handle_irq(start+1, desc);
+
+               desc++;
+
+               if (subsrc & 4)
+                       desc_handle_irq(start+2, desc);
+       }
+}
+
+/* uart demux entry points */
+
+static void
+s3c_irq_demux_uart0(unsigned int irq,
+                   struct irq_desc *desc)
+{
+       irq = irq;
+       s3c_irq_demux_uart(IRQ_S3CUART_RX0);
+}
+
+static void
+s3c_irq_demux_uart1(unsigned int irq,
+                   struct irq_desc *desc)
+{
+       irq = irq;
+       s3c_irq_demux_uart(IRQ_S3CUART_RX1);
+}
+
+static void
+s3c_irq_demux_uart2(unsigned int irq,
+                   struct irq_desc *desc)
+{
+       irq = irq;
+       s3c_irq_demux_uart(IRQ_S3CUART_RX2);
+}
+
+static void
+s3c_irq_demux_extint8(unsigned int irq,
+                     struct irq_desc *desc)
+{
+       unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+       unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+       eintpnd &= ~eintmsk;
+       eintpnd &= ~0xff;       /* ignore lower irqs */
+
+       /* we may as well handle all the pending IRQs here */
+
+       while (eintpnd) {
+               irq = __ffs(eintpnd);
+               eintpnd &= ~(1<<irq);
+
+               irq += (IRQ_EINT4 - 4);
+               desc_handle_irq(irq, irq_desc + irq);
+       }
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+                       struct irq_desc *desc)
+{
+       unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+       unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+       eintpnd &= ~eintmsk;
+       eintpnd &= 0xff;        /* only lower irqs */
+
+       /* we may as well handle all the pending IRQs here */
+
+       while (eintpnd) {
+               irq = __ffs(eintpnd);
+               eintpnd &= ~(1<<irq);
+
+               irq += (IRQ_EINT4 - 4);
+
+               desc_handle_irq(irq, irq_desc + irq);
+       }
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+       SAVE_ITEM(S3C2410_INTMSK),
+       SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+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)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+       save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+       return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+       __raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+       return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
+/* s3c24xx_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
+
+void __init s3c24xx_init_irq(void)
+{
+       unsigned long pend;
+       unsigned long last;
+       int irqno;
+       int i;
+
+       irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
+
+       /* first, clear all interrupts pending... */
+
+       last = 0;
+       for (i = 0; i < 4; i++) {
+               pend = __raw_readl(S3C24XX_EINTPEND);
+
+               if (pend == 0 || pend == last)
+                       break;
+
+               __raw_writel(pend, S3C24XX_EINTPEND);
+               printk("irq: clearing pending ext status %08x\n", (int)pend);
+               last = pend;
+       }
+
+       last = 0;
+       for (i = 0; i < 4; i++) {
+               pend = __raw_readl(S3C2410_INTPND);
+
+               if (pend == 0 || pend == last)
+                       break;
+
+               __raw_writel(pend, S3C2410_SRCPND);
+               __raw_writel(pend, S3C2410_INTPND);
+               printk("irq: clearing pending status %08x\n", (int)pend);
+               last = pend;
+       }
+
+       last = 0;
+       for (i = 0; i < 4; i++) {
+               pend = __raw_readl(S3C2410_SUBSRCPND);
+
+               if (pend == 0 || pend == last)
+                       break;
+
+               printk("irq: clearing subpending status %08x\n", (int)pend);
+               __raw_writel(pend, S3C2410_SUBSRCPND);
+               last = pend;
+       }
+
+       /* register the main interrupts */
+
+       irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
+
+       for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
+               /* set all the s3c2410 internal irqs */
+
+               switch (irqno) {
+                       /* deal with the special IRQs (cascaded) */
+
+               case IRQ_EINT4t7:
+               case IRQ_EINT8t23:
+               case IRQ_UART0:
+               case IRQ_UART1:
+               case IRQ_UART2:
+               case IRQ_ADCPARENT:
+                       set_irq_chip(irqno, &s3c_irq_level_chip);
+                       set_irq_handler(irqno, handle_level_irq);
+                       break;
+
+               case IRQ_RESERVED6:
+               case IRQ_RESERVED24:
+                       /* no IRQ here */
+                       break;
+
+               default:
+                       //irqdbf("registering irq %d (s3c irq)\n", irqno);
+                       set_irq_chip(irqno, &s3c_irq_chip);
+                       set_irq_handler(irqno, handle_edge_irq);
+                       set_irq_flags(irqno, IRQF_VALID);
+               }
+       }
+
+       /* setup the cascade irq handlers */
+
+       set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+       set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+
+       set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+       set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+       set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+       set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+
+       /* external interrupts */
+
+       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+               irqdbf("registering irq %d (ext int)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_eint0t4);
+               set_irq_handler(irqno, handle_edge_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
+               irqdbf("registering irq %d (extended s3c irq)\n", irqno);
+               set_irq_chip(irqno, &s3c_irqext_chip);
+               set_irq_handler(irqno, handle_edge_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       /* register the uart interrupts */
+
+       irqdbf("s3c2410: registering external interrupts\n");
+
+       for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
+               irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_uart0);
+               set_irq_handler(irqno, handle_level_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
+               irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_uart1);
+               set_irq_handler(irqno, handle_level_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
+               irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_uart2);
+               set_irq_handler(irqno, handle_level_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
+               irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_adc);
+               set_irq_handler(irqno, handle_edge_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       irqdbf("s3c2410: registered interrupt handlers\n");
+}
similarity index 95%
rename from arch/arm/mach-s3c2410/pm-simtec.c
rename to arch/arm/plat-s3c24xx/pm-simtec.c
index 619133eb716802b9002c6b44022591f44b80cddd..bd965f2feecae51e053dba07f04d697707546c31 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm-simtec.c
+/* linux/arch/arm/plat-s3c24xx/pm-simtec.c
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +32,7 @@
 
 #include <asm/mach-types.h>
 
-#include "pm.h"
+#include <asm/plat-s3c24xx/pm.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
new file mode 100644 (file)
index 0000000..ecf68d6
--- /dev/null
@@ -0,0 +1,659 @@
+/* linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004,2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Power Manager (Suspend-To-RAM) support
+ *
+ * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Parts based on arch/arm/mach-pxa/pm.c
+ *
+ * Thanks to Dimitry Andric for debugging
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/pm.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+#define PFX "s3c24xx-pm: "
+
+static struct sleep_save core_save[] = {
+       SAVE_ITEM(S3C2410_LOCKTIME),
+       SAVE_ITEM(S3C2410_CLKCON),
+
+       /* we restore the timings here, with the proviso that the board
+        * brings the system up in an slower, or equal frequency setting
+        * to the original system.
+        *
+        * if we cannot guarantee this, then things are going to go very
+        * wrong here, as we modify the refresh and both pll settings.
+        */
+
+       SAVE_ITEM(S3C2410_BWSCON),
+       SAVE_ITEM(S3C2410_BANKCON0),
+       SAVE_ITEM(S3C2410_BANKCON1),
+       SAVE_ITEM(S3C2410_BANKCON2),
+       SAVE_ITEM(S3C2410_BANKCON3),
+       SAVE_ITEM(S3C2410_BANKCON4),
+       SAVE_ITEM(S3C2410_BANKCON5),
+
+       SAVE_ITEM(S3C2410_CLKDIVN),
+       SAVE_ITEM(S3C2410_MPLLCON),
+       SAVE_ITEM(S3C2410_UPLLCON),
+       SAVE_ITEM(S3C2410_CLKSLOW),
+       SAVE_ITEM(S3C2410_REFRESH),
+};
+
+static struct sleep_save gpio_save[] = {
+       SAVE_ITEM(S3C2410_GPACON),
+       SAVE_ITEM(S3C2410_GPADAT),
+
+       SAVE_ITEM(S3C2410_GPBCON),
+       SAVE_ITEM(S3C2410_GPBDAT),
+       SAVE_ITEM(S3C2410_GPBUP),
+
+       SAVE_ITEM(S3C2410_GPCCON),
+       SAVE_ITEM(S3C2410_GPCDAT),
+       SAVE_ITEM(S3C2410_GPCUP),
+
+       SAVE_ITEM(S3C2410_GPDCON),
+       SAVE_ITEM(S3C2410_GPDDAT),
+       SAVE_ITEM(S3C2410_GPDUP),
+
+       SAVE_ITEM(S3C2410_GPECON),
+       SAVE_ITEM(S3C2410_GPEDAT),
+       SAVE_ITEM(S3C2410_GPEUP),
+
+       SAVE_ITEM(S3C2410_GPFCON),
+       SAVE_ITEM(S3C2410_GPFDAT),
+       SAVE_ITEM(S3C2410_GPFUP),
+
+       SAVE_ITEM(S3C2410_GPGCON),
+       SAVE_ITEM(S3C2410_GPGDAT),
+       SAVE_ITEM(S3C2410_GPGUP),
+
+       SAVE_ITEM(S3C2410_GPHCON),
+       SAVE_ITEM(S3C2410_GPHDAT),
+       SAVE_ITEM(S3C2410_GPHUP),
+
+       SAVE_ITEM(S3C2410_DCLKCON),
+};
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+#define SAVE_UART(va) \
+       SAVE_ITEM((va) + S3C2410_ULCON), \
+       SAVE_ITEM((va) + S3C2410_UCON), \
+       SAVE_ITEM((va) + S3C2410_UFCON), \
+       SAVE_ITEM((va) + S3C2410_UMCON), \
+       SAVE_ITEM((va) + S3C2410_UBRDIV)
+
+static struct sleep_save uart_save[] = {
+       SAVE_UART(S3C24XX_VA_UART0),
+       SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+       SAVE_UART(S3C24XX_VA_UART2),
+#endif
+};
+
+/* debug
+ *
+ * we send the debug to printascii() to allow it to be seen if the
+ * system never wakes up from the sleep
+*/
+
+extern void printascii(const char *);
+
+void pm_dbg(const char *fmt, ...)
+{
+       va_list va;
+       char buff[256];
+
+       va_start(va, fmt);
+       vsprintf(buff, fmt, va);
+       va_end(va);
+
+       printascii(buff);
+}
+
+static void s3c2410_pm_debug_init(void)
+{
+       unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+       /* re-start uart clocks */
+       tmp |= S3C2410_CLKCON_UART0;
+       tmp |= S3C2410_CLKCON_UART1;
+       tmp |= S3C2410_CLKCON_UART2;
+
+       __raw_writel(tmp, S3C2410_CLKCON);
+       udelay(10);
+}
+
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+
+#define s3c2410_pm_debug_init() do { } while(0)
+
+static struct sleep_save uart_save[] = {};
+#endif
+
+#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;   /* size needed for the crc block */
+static u32 *crcs;      /* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c2410_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+       while (ptr != NULL) {
+               if (ptr->child != NULL)
+                       s3c2410_pm_run_res(ptr->child, fn, arg);
+
+               if ((ptr->flags & IORESOURCE_MEM) &&
+                   strcmp(ptr->name, "System RAM") == 0) {
+                       DBG("Found system RAM at %08lx..%08lx\n",
+                           ptr->start, ptr->end);
+                       arg = (fn)(ptr, arg);
+               }
+
+               ptr = ptr->sibling;
+       }
+}
+
+static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+       s3c2410_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
+{
+       u32 size = (u32)(res->end - res->start)+1;
+
+       size += CHECK_CHUNKSIZE-1;
+       size /= CHECK_CHUNKSIZE;
+
+       DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+       *val += size * sizeof(u32);
+       return val;
+}
+
+/* s3c2410_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c2410_pm_check_prepare(void)
+{
+       crc_size = 0;
+
+       s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+
+       DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+
+       crcs = kmalloc(crc_size+4, GFP_KERNEL);
+       if (crcs == NULL)
+               printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
+{
+       unsigned long addr, left;
+
+       for (addr = res->start; addr < res->end;
+            addr += CHECK_CHUNKSIZE) {
+               left = res->end - addr;
+
+               if (left > CHECK_CHUNKSIZE)
+                       left = CHECK_CHUNKSIZE;
+
+               *val = crc32_le(~0, phys_to_virt(addr), left);
+               val++;
+       }
+
+       return val;
+}
+
+/* s3c2410_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c2410_pm_check_store(void)
+{
+       if (crcs != NULL)
+               s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+       if ((what+whatsz) < ptr)
+               return 0;
+
+       if (what > (ptr+size))
+               return 0;
+
+       return 1;
+}
+
+static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
+{
+       void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
+       unsigned long addr;
+       unsigned long left;
+       void *ptr;
+       u32 calc;
+
+       for (addr = res->start; addr < res->end;
+            addr += CHECK_CHUNKSIZE) {
+               left = res->end - addr;
+
+               if (left > CHECK_CHUNKSIZE)
+                       left = CHECK_CHUNKSIZE;
+
+               ptr = phys_to_virt(addr);
+
+               if (in_region(ptr, left, crcs, crc_size)) {
+                       DBG("skipping %08lx, has crc block in\n", addr);
+                       goto skip_check;
+               }
+
+               if (in_region(ptr, left, save_at, 32*4 )) {
+                       DBG("skipping %08lx, has save block in\n", addr);
+                       goto skip_check;
+               }
+
+               /* calculate and check the checksum */
+
+               calc = crc32_le(~0, ptr, left);
+               if (calc != *val) {
+                       printk(KERN_ERR PFX "Restore CRC error at "
+                              "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+                       DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+                           addr, calc, *val);
+               }
+
+       skip_check:
+               val++;
+       }
+
+       return val;
+}
+
+/* s3c2410_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c2410_pm_check_restore(void)
+{
+       if (crcs != NULL) {
+               s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
+               kfree(crcs);
+               crcs = NULL;
+       }
+}
+
+#else
+
+#define s3c2410_pm_check_prepare() do { } while(0)
+#define s3c2410_pm_check_restore() do { } while(0)
+#define s3c2410_pm_check_store()   do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+{
+       for (; count > 0; count--, ptr++) {
+               ptr->val = __raw_readl(ptr->reg);
+               DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+       }
+}
+
+/* s3c2410_pm_do_restore
+ *
+ * restore the system from the given list of saved registers
+ *
+ * Note, we do not use DBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
+{
+       for (; count > 0; count--, ptr++) {
+               printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+                      ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+               __raw_writel(ptr->val, ptr->reg);
+       }
+}
+
+/* s3c2410_pm_do_restore_core
+ *
+ * similar to s3c2410_pm_do_restore_core
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+       for (; count > 0; count--, ptr++) {
+               __raw_writel(ptr->val, ptr->reg);
+       }
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+
+static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
+                                       unsigned long mask)
+{
+       int i;
+
+       which &= ~mask;
+
+       for (i = 0; i <= 31; i++) {
+               if ((which) & (1L<<i)) {
+                       DBG("IRQ %d asserted at resume\n", start+i);
+               }
+       }
+}
+
+/* s3c2410_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+       unsigned long irqstate;
+       unsigned long pinstate;
+       int irq = s3c2410_gpio_getirq(pin);
+
+       if (irqoffs < 4)
+               irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
+       else
+               irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
+
+       pinstate = s3c2410_gpio_getcfg(pin);
+
+       if (!irqstate) {
+               if (pinstate == S3C2410_GPIO_IRQ)
+                       DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+       } else {
+               if (pinstate == S3C2410_GPIO_IRQ) {
+                       DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+                       s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+               }
+       }
+}
+
+/* s3c2410_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+static void s3c2410_pm_configure_extint(void)
+{
+       int pin;
+
+       /* for each of the external interrupts (EINT0..EINT15) we
+        * need to check wether it is an external interrupt source,
+        * and then configure it as an input if it is not
+       */
+
+       for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
+               s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+       }
+
+       for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
+               s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+       }
+}
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c2410_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c2410_pm_enter(suspend_state_t state)
+{
+       unsigned long regs_save[16];
+
+       /* ensure the debug is initialised (if enabled) */
+
+       s3c2410_pm_debug_init();
+
+       DBG("s3c2410_pm_enter(%d)\n", state);
+
+       if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+               printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+               return -EINVAL;
+       }
+
+       if (state != PM_SUSPEND_MEM) {
+               printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+               return -EINVAL;
+       }
+
+       /* check if we have anything to wake-up with... bad things seem
+        * to happen if you suspend with no wakeup (system will often
+        * require a full power-cycle)
+       */
+
+       if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+           !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+               printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
+               printk(KERN_ERR PFX "Aborting sleep\n");
+               return -EINVAL;
+       }
+
+       /* prepare check area if configured */
+
+       s3c2410_pm_check_prepare();
+
+       /* store the physical address of the register recovery block */
+
+       s3c2410_sleep_save_phys = virt_to_phys(regs_save);
+
+       DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
+
+       /* save all necessary core registers not covered by the drivers */
+
+       s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+       s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
+       s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
+
+       /* set the irq configuration for wake */
+
+       s3c2410_pm_configure_extint();
+
+       DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+           s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+       __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+       __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+       /* ack any outstanding external interrupts before we go to sleep */
+
+       __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+       __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+       __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+       /* call cpu specific preperation */
+
+       pm_cpu_prep();
+
+       /* flush cache back to ram */
+
+       flush_cache_all();
+
+       s3c2410_pm_check_store();
+
+       /* send the cpu to sleep... */
+
+       __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+
+       /* s3c2410_cpu_save will also act as our return point from when
+        * we resume as it saves its own register state, so use the return
+        * code to differentiate return from save and return from sleep */
+
+       if (s3c2410_cpu_save(regs_save) == 0) {
+               flush_cache_all();
+               pm_cpu_sleep();
+       }
+
+       /* restore the cpu state */
+
+       cpu_init();
+
+       /* restore the system state */
+
+       s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+       s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+       s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
+
+       s3c2410_pm_debug_init();
+
+       /* check what irq (if any) restored the system */
+
+       DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+           __raw_readl(S3C2410_SRCPND),
+           __raw_readl(S3C2410_EINTPEND));
+
+       s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+                                   s3c_irqwake_intmask);
+
+       s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+                                   s3c_irqwake_eintmask);
+
+       DBG("post sleep, preparing to return\n");
+
+       s3c2410_pm_check_restore();
+
+       /* ok, let's return from sleep */
+
+       DBG("S3C2410 PM Resume (post-restore)\n");
+       return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c2410_pm_prepare(suspend_state_t state)
+{
+       return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c2410_pm_finish(suspend_state_t state)
+{
+       return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c2410_pm_ops = {
+       .pm_disk_mode   = PM_DISK_FIRMWARE,
+       .prepare        = s3c2410_pm_prepare,
+       .enter          = s3c2410_pm_enter,
+       .finish         = s3c2410_pm_finish,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+       printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
+
+       pm_set_ops(&s3c2410_pm_ops);
+       return 0;
+}
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c244x-irq.c
rename to arch/arm/plat-s3c24xx/s3c244x-irq.c
index ede94636a72a94bc0be668fd102472b5975d8ca2..a0e39d894014278274d1a9b4ed2e70e70ff5d914 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x-irq.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
 
 /* camera irq */
 
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c244x.c
rename to arch/arm/plat-s3c24xx/s3c244x.c
index 23c7494ad10d57ce685de8e74da04c74da6a9261..767f2e9a3a555beff2d3e05388ad1ac9800f7590 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x.c
  *
  * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
- * Samsung S3C2440 and S3C2442 Mobile CPU support
+ * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <asm/arch/regs-gpioj.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
 #include "s3c244x.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc s3c244x_iodesc[] __initdata = {
        IODESC_ENT(CLKPWR),
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c244x.h
rename to arch/arm/plat-s3c24xx/s3c244x.h
index 1488c1eb37e67cf56c4c929d6722e1d5af3610e8..f8ed17676a355c49a7f5af03818cdc826a85df10 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c244x.h
+/* linux/arch/arm/plat-s3c24xx/s3c244x.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
new file mode 100644 (file)
index 0000000..435349d
--- /dev/null
@@ -0,0 +1,157 @@
+/* linux/arch/arm/mach-s3c2410/sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *     Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *     Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+//#define CONFIG_DEBUG_RESUME
+
+       .text
+
+       /* s3c2410_cpu_save
+        *
+        * save enough of the CPU state to allow us to re-start
+        * pm.c code. as we store items like the sp/lr, we will
+        * end up returning from this function when the cpu resumes
+        * so the return value is set to mark this.
+        *
+        * This arangement means we avoid having to flush the cache
+        * from this code.
+        *
+        * entry:
+        *      r0 = pointer to save block
+        *
+        * exit:
+        *      r0 = 0 => we stored everything
+        *           1 => resumed from sleep
+       */
+
+ENTRY(s3c2410_cpu_save)
+       stmfd   sp!, { r4 - r12, lr }
+
+       @@ store co-processor registers
+
+       mrc     p15, 0, r4, c13, c0, 0  @ PID
+       mrc     p15, 0, r5, c3, c0, 0   @ Domain ID
+       mrc     p15, 0, r6, c2, c0, 0   @ translation table base address
+       mrc     p15, 0, r7, c1, c0, 0   @ control register
+
+       stmia   r0, { r4 - r13 }
+
+       mov     r0, #0
+       ldmfd   sp, { r4 - r12, pc }
+
+       @@ return to the caller, after having the MMU
+       @@ turned on, this restores the last bits from the
+       @@ stack
+resume_with_mmu:
+       mov     r0, #1
+       ldmfd   sp!, { r4 - r12, pc }
+
+       .ltorg
+
+       @@ the next bits sit in the .data segment, even though they
+       @@ happen to be code... the s3c2410_sleep_save_phys needs to be
+       @@ accessed by the resume code before it can restore the MMU.
+       @@ This means that the variable has to be close enough for the
+       @@ code to read it... since the .text segment needs to be RO,
+       @@ the data segment can be the only place to put this code.
+
+       .data
+
+       .global s3c2410_sleep_save_phys
+s3c2410_sleep_save_phys:
+       .word   0
+
+       /* s3c2410_cpu_resume
+        *
+        * resume code entry for bootloader to call
+        *
+        * we must put this code here in the data segment as we have no
+        * other way of restoring the stack pointer after sleep, and we
+        * must not write to the code segment (code is read-only)
+       */
+
+ENTRY(s3c2410_cpu_resume)
+       mov     r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+       msr     cpsr_c, r0
+
+       @@ load UART to allow us to print the two characters for
+       @@ resume debug
+
+       mov     r2, #S3C24XX_PA_UART & 0xff000000
+       orr     r2, r2, #S3C24XX_PA_UART & 0xff000
+
+#if 0
+       /* SMDK2440 LED set */
+       mov     r14, #S3C24XX_PA_GPIO
+       ldr     r12, [ r14, #0x54 ]
+       bic     r12, r12, #3<<4
+       orr     r12, r12, #1<<7
+       str     r12, [ r14, #0x54 ]
+#endif
+
+#ifdef CONFIG_DEBUG_RESUME
+       mov     r3, #'L'
+       strb    r3, [ r2, #S3C2410_UTXH ]
+1001:
+       ldrb    r14, [ r3, #S3C2410_UTRSTAT ]
+       tst     r14, #S3C2410_UTRSTAT_TXE
+       beq     1001b
+#endif /* CONFIG_DEBUG_RESUME */
+
+       mov     r1, #0
+       mcr     p15, 0, r1, c8, c7, 0           @@ invalidate I & D TLBs
+       mcr     p15, 0, r1, c7, c7, 0           @@ invalidate I & D caches
+
+       ldr     r0, s3c2410_sleep_save_phys     @ address of restore block
+       ldmia   r0, { r4 - r13 }
+
+       mcr     p15, 0, r4, c13, c0, 0          @ PID
+       mcr     p15, 0, r5, c3, c0, 0           @ Domain ID
+       mcr     p15, 0, r6, c2, c0, 0           @ translation table base
+
+#ifdef CONFIG_DEBUG_RESUME
+       mov     r3, #'R'
+       strb    r3, [ r2, #S3C2410_UTXH ]
+#endif
+
+       ldr     r2, =resume_with_mmu
+       mcr     p15, 0, r7, c1, c0, 0           @ turn on MMU, etc
+       nop                                     @ second-to-last before mmu
+       mov     pc, r2                          @ go back to virtual address
+
+       .ltorg
similarity index 98%
rename from arch/arm/mach-s3c2410/time.c
rename to arch/arm/plat-s3c24xx/time.c
index 9910bf0f2cea63c3fab5e53e79a9a6398762b418..c523d1c9cce5e6e4c2ae0723aca5c3dc5871cd22 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/time.c
+/* linux/arch/arm/plat-s3c24xx/time.c
  *
  * Copyright (C) 2003-2005 Simtec Electronics
  *     Ben Dooks, <ben@simtec.co.uk>
@@ -37,8 +37,8 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_usec_ticks;
index d47e39f0e971925f81cba2588fa185b5829ed1a0..5974768a59e58f182b32c52626c2daed58528b24 100644 (file)
@@ -8,7 +8,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk.h>
-#include <linux/device.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -36,12 +35,11 @@ static struct eth_addr __initdata hw_addr[2];
 static struct eth_platform_data __initdata eth_data[2];
 extern struct lcdc_platform_data atstk1000_fb0_data;
 
-static struct spi_board_info spi_board_info[] __initdata = {
+static struct spi_board_info spi0_board_info[] __initdata = {
        {
+               /* QVGA display */
                .modalias       = "ltv350qv",
-               .controller_data = (void *)GPIO_PIN_PA(4),
                .max_speed_hz   = 16000000,
-               .bus_num        = 0,
                .chip_select    = 1,
        },
 };
@@ -149,8 +147,7 @@ static int __init atstk1002_init(void)
 
        set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
 
-       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-       at32_add_device_spi(0);
+       at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
        at32_add_device_lcdc(0, &atstk1000_fb0_data);
 
        return 0;
index db8f8b55ffdf2925cfc0288a045c2fc463eefa3a..7c279586fbbac96b6445adc074ec56848c213e7f 100644 (file)
@@ -8,14 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
-#define sys_nfsservctl sys_ni_syscall
-#endif
-
-#if !defined(CONFIG_SYSV_IPC)
-# define sys_ipc       sys_ni_syscall
-#endif
-
        .section .rodata,"a",@progbits
        .type   sys_call_table,@object
        .global sys_call_table
@@ -129,7 +121,7 @@ sys_call_table:
        .long   sys_getitimer           /* 105 */
        .long   sys_swapoff
        .long   sys_sysinfo
-       .long   sys_ipc
+       .long   sys_ni_syscall          /* was sys_ipc briefly */
        .long   sys_sendfile
        .long   sys_setdomainname       /* 110 */
        .long   sys_newuname
@@ -287,4 +279,16 @@ sys_call_table:
        .long   sys_tee
        .long   sys_vmsplice
        .long   __sys_epoll_pwait       /* 265 */
+       .long   sys_msgget
+       .long   sys_msgsnd
+       .long   sys_msgrcv
+       .long   sys_msgctl
+       .long   sys_semget              /* 270 */
+       .long   sys_semop
+       .long   sys_semctl
+       .long   sys_semtimedop
+       .long   sys_shmat
+       .long   sys_shmget              /* 275 */
+       .long   sys_shmdt
+       .long   sys_shmctl
        .long   sys_ni_syscall          /* r8 is saturated at nr_syscalls */
index a2f74affaa98b920729d629a71d55c796475e0e3..c10833f2ee0ce0e1dea60d255e64e07f13f14c48 100644 (file)
@@ -37,7 +37,7 @@ static struct clocksource clocksource_avr32 = {
        .read           = read_cycle_count,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 16,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
index c1e477ec7576850887591f9cc14c7d42128fa0b0..bc235507c5c7508c28a79a6219079c95d349641b 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/io.h>
 
@@ -310,8 +311,6 @@ static void genclk_mode(struct clk *clk, int enabled)
 {
        u32 control;
 
-       BUG_ON(clk->index > 7);
-
        control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
        if (enabled)
                control |= SM_BIT(CEN);
@@ -325,11 +324,6 @@ static unsigned long genclk_get_rate(struct clk *clk)
        u32 control;
        unsigned long div = 1;
 
-       BUG_ON(clk->index > 7);
-
-       if (!clk->parent)
-               return 0;
-
        control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
        if (control & SM_BIT(DIVEN))
                div = 2 * (SM_BFEXT(DIV, control) + 1);
@@ -342,11 +336,6 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
        u32 control;
        unsigned long parent_rate, actual_rate, div;
 
-       BUG_ON(clk->index > 7);
-
-       if (!clk->parent)
-               return 0;
-
        parent_rate = clk->parent->get_rate(clk->parent);
        control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 
@@ -373,11 +362,8 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
 {
        u32 control;
 
-       BUG_ON(clk->index > 7);
-
        printk("clk %s: new parent %s (was %s)\n",
-              clk->name, parent->name,
-              clk->parent ? clk->parent->name : "(null)");
+              clk->name, parent->name, clk->parent->name);
 
        control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 
@@ -399,6 +385,22 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
+static void __init genclk_init_parent(struct clk *clk)
+{
+       u32 control;
+       struct clk *parent;
+
+       BUG_ON(clk->index > 7);
+
+       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+       if (control & SM_BIT(OSCSEL))
+               parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
+       else
+               parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;
+
+       clk->parent = parent;
+}
+
 /* --------------------------------------------------------------------
  *  System peripherals
  * -------------------------------------------------------------------- */
@@ -750,8 +752,41 @@ static struct resource atmel_spi1_resource[] = {
 DEFINE_DEV(atmel_spi, 1);
 DEV_CLK(spi_clk, atmel_spi1, pba, 1);
 
-struct platform_device *__init at32_add_device_spi(unsigned int id)
+static void
+at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b,
+                     unsigned int n, const u8 *pins)
+{
+       unsigned int pin, mode;
+
+       for (; n; n--, b++) {
+               b->bus_num = bus_num;
+               if (b->chip_select >= 4)
+                       continue;
+               pin = (unsigned)b->controller_data;
+               if (!pin) {
+                       pin = pins[b->chip_select];
+                       b->controller_data = (void *)pin;
+               }
+               mode = AT32_GPIOF_OUTPUT;
+               if (!(b->mode & SPI_CS_HIGH))
+                       mode |= AT32_GPIOF_HIGH;
+               at32_select_gpio(pin, mode);
+       }
+}
+
+struct platform_device *__init
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
 {
+       /*
+        * Manage the chipselects as GPIOs, normally using the same pins
+        * the SPI controller expects; but boards can use other pins.
+        */
+       static u8 __initdata spi0_pins[] =
+               { GPIO_PIN_PA(3), GPIO_PIN_PA(4),
+                 GPIO_PIN_PA(5), GPIO_PIN_PA(20), };
+       static u8 __initdata spi1_pins[] =
+               { GPIO_PIN_PB(2), GPIO_PIN_PB(3),
+                 GPIO_PIN_PB(4), GPIO_PIN_PA(27), };
        struct platform_device *pdev;
 
        switch (id) {
@@ -760,14 +795,7 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
                select_peripheral(PA(0),  PERIPH_A, 0); /* MISO  */
                select_peripheral(PA(1),  PERIPH_A, 0); /* MOSI  */
                select_peripheral(PA(2),  PERIPH_A, 0); /* SCK   */
-
-               /* NPCS[2:0] */
-               at32_select_gpio(GPIO_PIN_PA(3),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
-               at32_select_gpio(GPIO_PIN_PA(4),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
-               at32_select_gpio(GPIO_PIN_PA(5),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+               at32_spi_setup_slaves(0, b, n, spi0_pins);
                break;
 
        case 1:
@@ -775,20 +803,14 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
                select_peripheral(PB(0),  PERIPH_B, 0); /* MISO  */
                select_peripheral(PB(1),  PERIPH_B, 0); /* MOSI  */
                select_peripheral(PB(5),  PERIPH_B, 0); /* SCK   */
-
-               /* NPCS[2:0] */
-               at32_select_gpio(GPIO_PIN_PB(2),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
-               at32_select_gpio(GPIO_PIN_PB(3),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
-               at32_select_gpio(GPIO_PIN_PB(4),
-                                AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+               at32_spi_setup_slaves(1, b, n, spi1_pins);
                break;
 
        default:
                return NULL;
        }
 
+       spi_register_board_info(b, n);
        platform_device_register(pdev);
        return pdev;
 }
@@ -872,6 +894,50 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
        return pdev;
 }
 
+/* --------------------------------------------------------------------
+ *  GCLK
+ * -------------------------------------------------------------------- */
+static struct clk gclk0 = {
+       .name           = "gclk0",
+       .mode           = genclk_mode,
+       .get_rate       = genclk_get_rate,
+       .set_rate       = genclk_set_rate,
+       .set_parent     = genclk_set_parent,
+       .index          = 0,
+};
+static struct clk gclk1 = {
+       .name           = "gclk1",
+       .mode           = genclk_mode,
+       .get_rate       = genclk_get_rate,
+       .set_rate       = genclk_set_rate,
+       .set_parent     = genclk_set_parent,
+       .index          = 1,
+};
+static struct clk gclk2 = {
+       .name           = "gclk2",
+       .mode           = genclk_mode,
+       .get_rate       = genclk_get_rate,
+       .set_rate       = genclk_set_rate,
+       .set_parent     = genclk_set_parent,
+       .index          = 2,
+};
+static struct clk gclk3 = {
+       .name           = "gclk3",
+       .mode           = genclk_mode,
+       .get_rate       = genclk_get_rate,
+       .set_rate       = genclk_set_rate,
+       .set_parent     = genclk_set_parent,
+       .index          = 3,
+};
+static struct clk gclk4 = {
+       .name           = "gclk4",
+       .mode           = genclk_mode,
+       .get_rate       = genclk_get_rate,
+       .set_rate       = genclk_set_rate,
+       .set_parent     = genclk_set_parent,
+       .index          = 4,
+};
+
 struct clk *at32_clock_list[] = {
        &osc32k,
        &osc0,
@@ -908,6 +974,11 @@ struct clk *at32_clock_list[] = {
        &atmel_spi1_spi_clk,
        &lcdc0_hclk,
        &lcdc0_pixclk,
+       &gclk0,
+       &gclk1,
+       &gclk2,
+       &gclk3,
+       &gclk4,
 };
 unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
 
@@ -936,6 +1007,13 @@ void __init at32_clock_init(void)
        if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
                pll1.parent = &osc1;
 
+       genclk_init_parent(&gclk0);
+       genclk_init_parent(&gclk1);
+       genclk_init_parent(&gclk2);
+       genclk_init_parent(&gclk3);
+       genclk_init_parent(&gclk4);
+       genclk_init_parent(&lcdc0_pixclk);
+
        /*
         * Turn on all clocks that have at least one user already, and
         * turn off everything else. We only do this for module
index 3d0d1097389f167ec48dca953e277f7b331ab5fa..00c435452d7e500e473b3cbbeb1b4f1d939d5659 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006 Atmel Corporation
  *
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
  *   Copyright (C) 2005 David Brownell
  *   Copyright (C) 2005 Ivan Kokshaysky
  *
@@ -63,7 +63,11 @@ EXPORT_SYMBOL(clk_enable);
 
 static void __clk_disable(struct clk *clk)
 {
-       BUG_ON(clk->users == 0);
+       if (clk->users == 0) {
+               printk(KERN_ERR "%s: mismatched disable\n", clk->name);
+               WARN_ON(1);
+               return;
+       }
 
        if (--clk->users == 0 && clk->mode)
                clk->mode(clk, 0);
index f953f044ba4da40afe56d45ab28d2d816210230a..bb8e1f295835e95fa306c42071a6d5c55fe4fe3b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006 Atmel Corporation
  *
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
  *   Copyright (C) 2005 David Brownell
  *   Copyright (C) 2005 Ivan Kokshaysky
  *
index 107796e501495f50a85731a6cee88c06f393528a..d47cfbf98d6e0b1487500ca2292997423f8da2e7 100644 (file)
@@ -311,7 +311,7 @@ pcf8563_register(void)
 {
        pcf8563_init();
        if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-               printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
+               printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
                       PCF8563_NAME, PCF8563_MAJOR);
                return -1;
        }
index 544ab01794110e84a250a15a3baf57053e7c40e2..24b919b3821aff88ca23be6c4bfa97d5021b4150 100644 (file)
@@ -171,7 +171,7 @@ pcf8563_init(void)
                goto err;
 
        if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-               printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
+               printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
                       PCF8563_NAME, PCF8563_MAJOR);
                return -1;
        }
index ee677ced7b68413b098e6e192815afb067c1cdf8..c57ce3f1f2e281b2c38a7de860d390cbc08e5fd0 100644 (file)
@@ -125,7 +125,6 @@ unsigned long sleep_phys_sp(void *sp)
  * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
  * when all the PM interfaces exist nicely.
  */
-#define CTL_PM 9899
 #define CTL_PM_SUSPEND 1
 #define CTL_PM_CMODE 2
 #define CTL_PM_P0 4
@@ -402,17 +401,53 @@ static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
 
 static struct ctl_table pm_table[] =
 {
-       {CTL_PM_SUSPEND, "suspend", NULL, 0, 0200, NULL, &sysctl_pm_do_suspend},
-       {CTL_PM_CMODE, "cmode", &clock_cmode_current, sizeof(int), 0644, NULL, &cmode_procctl, &cmode_sysctl, NULL},
-       {CTL_PM_P0, "p0", &clock_p0_current, sizeof(int), 0644, NULL, &p0_procctl, &p0_sysctl, NULL},
-       {CTL_PM_CM, "cm", &clock_cm_current, sizeof(int), 0644, NULL, &cm_procctl, &cm_sysctl, NULL},
-       {0}
+       {
+               .ctl_name       = CTL_PM_SUSPEND,
+               .procname       = "suspend",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0200,
+               .proc_handler   = &sysctl_pm_do_suspend,
+       },
+       {
+               .ctl_name       = CTL_PM_CMODE,
+               .procname       = "cmode",
+               .data           = &clock_cmode_current,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &cmode_procctl,
+               .strategy       = &cmode_sysctl,
+       },
+       {
+               .ctl_name       = CTL_PM_P0,
+               .procname       = "p0",
+               .data           = &clock_p0_current,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &p0_procctl,
+               .strategy       = &p0_sysctl,
+       },
+       {
+               .ctl_name       = CTL_PM_CM,
+               .procname       = "cm",
+               .data           = &clock_cm_current,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &cm_procctl,
+               .strategy       = &cm_sysctl,
+       },
+       { .ctl_name = 0}
 };
 
 static struct ctl_table pm_dir_table[] =
 {
-       {CTL_PM, "pm", NULL, 0, 0555, pm_table},
-       {0}
+       {
+               .ctl_name       = CTL_PM,
+               .procname       = "pm",
+               .mode           = 0555,
+               .child          = pm_table,
+       },
+       { .ctl_name = 0}
 };
 
 /*
@@ -420,7 +455,7 @@ static struct ctl_table pm_dir_table[] =
  */
 static int __init pm_init(void)
 {
-       register_sysctl_table(pm_dir_table, 1);
+       register_sysctl_table(pm_dir_table);
        return 0;
 }
 
index ce676803eb6f59a03e8ee36780ac009fac4cc63b..3e9d7e03fb95b35cd94bf4779b667641ea8df528 100644 (file)
@@ -175,22 +175,40 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
  */
 static struct ctl_table frv_table[] =
 {
-       { 1, "cache-mode",      NULL, 0, 0644, NULL, &procctl_frv_cachemode },
+       {
+               .ctl_name       = 1,
+               .procname       = "cache-mode",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0644,
+               .proc_handler   = &procctl_frv_cachemode,
+       },
 #ifdef CONFIG_MMU
-       { 2, "pin-cxnr",        NULL, 0, 0644, NULL, &procctl_frv_pin_cxnr },
+       {
+               .ctl_name       = 2,
+               .procname       = "pin-cxnr",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0644,
+               .proc_handler   = &procctl_frv_pin_cxnr
+       },
 #endif
-       { 0 }
+       {}
 };
 
 /*
  * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
  * when all the PM interfaces exist nicely.
  */
-#define CTL_FRV 9898
 static struct ctl_table frv_dir_table[] =
 {
-       {CTL_FRV, "frv", NULL, 0, 0555, frv_table},
-       {0}
+       {
+               .ctl_name       = CTL_FRV,
+               .procname       = "frv",
+               .mode           = 0555,
+               .child          = frv_table
+       },
+       {}
 };
 
 /*
@@ -198,7 +216,7 @@ static struct ctl_table frv_dir_table[] =
  */
 static int __init frv_sysctl_init(void)
 {
-       register_sysctl_table(frv_dir_table, 1);
+       register_sysctl_table(frv_dir_table);
        return 0;
 }
 
index 63d5e841caf5a1ce0ceb7e986c572b6b70f7f3e9..1df4a1f14289e15c1dc6292e3711f2ad64a30c57 100644 (file)
@@ -18,6 +18,18 @@ config GENERIC_TIME
        bool
        default y
 
+config CLOCKSOURCE_WATCHDOG
+       bool
+       default y
+
+config GENERIC_CLOCKEVENTS
+       bool
+       default y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+       bool
+       default y
+
 config LOCKDEP_SUPPORT
        bool
        default y
@@ -74,6 +86,8 @@ source "init/Kconfig"
 
 menu "Processor type and features"
 
+source "kernel/time/Kconfig"
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
@@ -203,6 +217,15 @@ config PARAVIRT
          However, when run without a hypervisor the kernel is
          theoretically slower.  If in doubt, say N.
 
+config VMI
+       bool "VMI Paravirt-ops support"
+       depends on PARAVIRT && !NO_HZ
+       default y
+       help
+         VMI provides a paravirtualized interface to multiple hypervisors
+         include VMware ESX server and Xen by connecting to a ROM module
+         provided by the hypervisor.
+
 config ACPI_SRAT
        bool
        default y
@@ -1263,3 +1286,12 @@ config X86_TRAMPOLINE
 config KTIME_SCALAR
        bool
        default y
+
+config NO_IDLE_HZ
+       bool
+       depends on PARAVIRT
+       default y
+       help
+         Switches the regular HZ timer off when the system is going idle.
+         This helps a hypervisor detect that the Linux system is idle,
+         reducing the overhead of idle systems.
index 2aecfba4ac4f8fe702a2c0fc279877f10ee792f8..b99c0e2a4e63a0b1726e83e10cd27b158b9a73bb 100644 (file)
@@ -226,11 +226,6 @@ config X86_CMPXCHG
        depends on !M386
        default y
 
-config X86_XADD
-       bool
-       depends on !M386
-       default y
-
 config X86_L1_CACHE_SHIFT
        int
        default "7" if MPENTIUM4 || X86_GENERIC
index f68cc6f215f8b1c9bff53c0f6668d4b792f3b30a..458bc1611933b815f16856f9b608ef217a5a0a74 100644 (file)
@@ -87,7 +87,7 @@ config DOUBLEFAULT
 
 config DEBUG_PARAVIRT
        bool "Enable some paravirtualization debugging"
-       default y
+       default n
        depends on PARAVIRT && DEBUG_KERNEL
        help
          Currently deliberately clobbers regs which are allowed to be
index 881951ca03e1cc53be63665b5c717e04adf1d47a..ce4fda261aaf35d4bb5edfc4d11799dd2cdd1cfd 100644 (file)
@@ -11,6 +11,7 @@
 #include <endian.h>
 
 #define MAX_SHDRS 100
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 static Elf32_Ehdr ehdr;
 static Elf32_Shdr shdr[MAX_SHDRS];
 static Elf32_Sym  *symtab[MAX_SHDRS];
@@ -71,7 +72,7 @@ static const char *sym_type(unsigned type)
 #undef SYM_TYPE
        };
        const char *name = "unknown sym type name";
-       if (type < sizeof(type_name)/sizeof(type_name[0])) {
+       if (type < ARRAY_SIZE(type_name)) {
                name = type_name[type];
        }
        return name;
@@ -87,7 +88,7 @@ static const char *sym_bind(unsigned bind)
 #undef SYM_BIND
        };
        const char *name = "unknown sym bind name";
-       if (bind < sizeof(bind_name)/sizeof(bind_name[0])) {
+       if (bind < ARRAY_SIZE(bind_name)) {
                name = bind_name[bind];
        }
        return name;
@@ -104,7 +105,7 @@ static const char *sym_visibility(unsigned visibility)
 #undef SYM_VISIBILITY
        };
        const char *name = "unknown sym visibility name";
-       if (visibility < sizeof(visibility_name)/sizeof(visibility_name[0])) {
+       if (visibility < ARRAY_SIZE(visibility_name)) {
                name = visibility_name[visibility];
        }
        return name;
@@ -128,7 +129,7 @@ static const char *rel_type(unsigned type)
 #undef REL_TYPE
        };
        const char *name = "unknown type rel type name";
-       if (type < sizeof(type_name)/sizeof(type_name[0])) {
+       if (type < ARRAY_SIZE(type_name)) {
                name = type_name[type];
        }
        return name;
index bb0c376b62b32fcc8ee934ce281676908b6fd150..5ae1e0bc8fd7e6ecf6a73cb6b3fa002ebd6cdf45 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc3
-# Fri Jan  5 11:54:46 2007
+# Linux kernel version: 2.6.20-git8
+# Tue Feb 13 11:25:18 2007
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -10,6 +10,7 @@ CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_X86=y
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_GENERIC_BUG=y
@@ -139,7 +140,6 @@ CONFIG_MPENTIUMIII=y
 # CONFIG_MVIAC3_2 is not set
 CONFIG_X86_GENERIC=y
 CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
 CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -198,6 +198,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 CONFIG_MTRR=y
@@ -211,6 +212,7 @@ CONFIG_HZ_250=y
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
 # CONFIG_RELOCATABLE is not set
 CONFIG_PHYSICAL_ALIGN=0x100000
 # CONFIG_HOTPLUG_CPU is not set
@@ -229,13 +231,14 @@ CONFIG_PM_SYSFS_DEPRECATED=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_AC=y
 CONFIG_ACPI_BATTERY=y
 CONFIG_ACPI_BUTTON=y
-# CONFIG_ACPI_VIDEO is not set
 # CONFIG_ACPI_HOTKEY is not set
 CONFIG_ACPI_FAN=y
 # CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_BAY is not set
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
 # CONFIG_ACPI_ASUS is not set
@@ -306,7 +309,6 @@ CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_HT_IRQ is not set
 CONFIG_ISA_DMA_API=y
@@ -347,6 +349,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -446,6 +449,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -466,8 +470,7 @@ CONFIG_FW_LOADER=y
 #
 # Plug and Play support
 #
-CONFIG_PNP=y
-CONFIG_PNPACPI=y
+# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -515,6 +518,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -547,6 +551,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -557,6 +562,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -655,6 +661,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_SVW=y
 CONFIG_ATA_PIIX=y
@@ -670,6 +677,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_SATA_ULI is not set
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
@@ -687,6 +695,7 @@ CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -739,9 +748,7 @@ CONFIG_IEEE1394=y
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
 # CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
 # Device Drivers
@@ -766,6 +773,11 @@ CONFIG_IEEE1394_RAWIO=y
 #
 # CONFIG_I2O is not set
 
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+
 #
 # Network device support
 #
@@ -833,6 +845,7 @@ CONFIG_8139TOO=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -855,11 +868,13 @@ CONFIG_SKY2=y
 CONFIG_TIGON3=y
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -1090,6 +1105,7 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+CONFIG_OBSOLETE_OSS=y
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
@@ -1103,6 +1119,7 @@ CONFIG_SOUND_ICH=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1117,10 +1134,8 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1130,9 +1145,11 @@ CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1183,6 +1200,7 @@ CONFIG_USB_HID=y
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1287,6 +1305,10 @@ CONFIG_USB_MON=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -1480,6 +1502,7 @@ CONFIG_UNUSED_SYMBOLS=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
@@ -1488,7 +1511,6 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1533,7 +1555,8 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
index 1e8988e558c54971fe08fbe9f868a72c7126a924..4ae3dcf1d2f0623f0ea3288fc8e400fdae730fb5 100644 (file)
@@ -18,7 +18,7 @@ obj-$(CONFIG_X86_MSR)         += msr.o
 obj-$(CONFIG_X86_CPUID)                += cpuid.o
 obj-$(CONFIG_MICROCODE)                += microcode.o
 obj-$(CONFIG_APM)              += apm.o
-obj-$(CONFIG_X86_SMP)          += smp.o smpboot.o
+obj-$(CONFIG_X86_SMP)          += smp.o smpboot.o tsc_sync.o
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-$(CONFIG_X86_MPPARSE)      += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
@@ -32,7 +32,6 @@ obj-$(CONFIG_KPROBES)         += kprobes.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-y                          += sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT)        += srat.o
-obj-$(CONFIG_HPET_TIMER)       += time_hpet.o
 obj-$(CONFIG_EFI)              += efi.o efi_stub.o
 obj-$(CONFIG_DOUBLEFAULT)      += doublefault.o
 obj-$(CONFIG_VM86)             += vm86.o
@@ -40,8 +39,9 @@ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
 obj-$(CONFIG_K8_NB)            += k8.o
 
-# Make sure this is linked after any other paravirt_ops structs: see head.S
+obj-$(CONFIG_VMI)              += vmi.o vmitime.o
 obj-$(CONFIG_PARAVIRT)         += paravirt.o
+obj-y                          += pcspeaker.o
 
 EXTRA_AFLAGS   := -traditional
 
index e94aff6888cab7aca553870d908aacf04526914f..e5eb97a910ed8d82f74fc67802e04321eacdc82c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_pmtmr.h>
 #include <linux/efi.h>
 #include <linux/cpumask.h>
 #include <linux/module.h>
@@ -615,6 +616,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)
 }
 
 #ifdef CONFIG_HPET_TIMER
+#include <asm/hpet.h>
 
 static int __init acpi_parse_hpet(struct acpi_table_header *table)
 {
@@ -645,24 +647,11 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
                hpet_res->end = (1 * 1024) - 1;
        }
 
-#ifdef CONFIG_X86_64
-       vxtime.hpet_address = hpet_tbl->address.address;
-
+       hpet_address = hpet_tbl->address.address;
        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-               hpet_tbl->id, vxtime.hpet_address);
-
-       res_start = vxtime.hpet_address;
-#else                          /* X86 */
-       {
-               extern unsigned long hpet_address;
+              hpet_tbl->id, hpet_address);
 
-               hpet_address = hpet_tbl->address.address;
-               printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-                       hpet_tbl->id, hpet_address);
-
-               res_start = hpet_address;
-       }
-#endif                         /* X86 */
+       res_start = hpet_address;
 
        if (hpet_res) {
                hpet_res->start = res_start;
@@ -676,10 +665,6 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
 #define        acpi_parse_hpet NULL
 #endif
 
-#ifdef CONFIG_X86_PM_TIMER
-extern u32 pmtmr_ioport;
-#endif
-
 static int __init acpi_parse_fadt(struct acpi_table_header *table)
 {
 
@@ -865,10 +850,9 @@ static inline int acpi_parse_madt_ioapic_entries(void)
 static void __init acpi_process_madt(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-       int count, error;
+       int error;
 
-       count = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt);
-       if (count >= 1) {
+       if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
 
                /*
                 * Parse MADT LAPIC entries
index 776d9be26af9ea5906bc0e04798878e69d3b51a3..9655c233e6f144804c275f9b8eada53fb27f8f8a 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
+#include <linux/clockchips.h>
+#include <linux/acpi_pmtmr.h>
 #include <linux/module.h>
 
 #include <asm/atomic.h>
@@ -36,6 +38,7 @@
 #include <asm/hpet.h>
 #include <asm/i8253.h>
 #include <asm/nmi.h>
+#include <asm/idle.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
 #include "io_ports.h"
 
 /*
- * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
- * IPIs in place of local APIC timers
+ * Sanity check
  */
-static cpumask_t timer_bcast_ipi;
+#if (SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F
+# error SPURIOUS_APIC_VECTOR definition error
+#endif
 
 /*
  * Knob to control our willingness to enable the local APIC.
+ *
+ * -1=force-disable, +1=force-enable
  */
-static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
-
-static inline void lapic_disable(void)
-{
-       enable_local_apic = -1;
-       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-}
+static int enable_local_apic __initdata = 0;
 
-static inline void lapic_enable(void)
-{
-       enable_local_apic = 1;
-}
+/* Local APIC timer verification ok */
+static int local_apic_timer_verify_ok;
 
 /*
- * Debug level
+ * Debug level, exported for io_apic.c
  */
 int apic_verbosity;
 
+static unsigned int calibration_result;
 
+static int lapic_next_event(unsigned long delta,
+                           struct clock_event_device *evt);
+static void lapic_timer_setup(enum clock_event_mode mode,
+                             struct clock_event_device *evt);
+static void lapic_timer_broadcast(cpumask_t mask);
 static void apic_pm_activate(void);
 
+/*
+ * The local apic timer can be used for any function which is CPU local.
+ */
+static struct clock_event_device lapic_clockevent = {
+       .name           = "lapic",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+                       | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+       .shift          = 32,
+       .set_mode       = lapic_timer_setup,
+       .set_next_event = lapic_next_event,
+       .broadcast      = lapic_timer_broadcast,
+       .rating         = 100,
+       .irq            = -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
+/* Local APIC was disabled by the BIOS and enabled by the kernel */
+static int enabled_via_apicbase;
+
+/*
+ * Get the LAPIC version
+ */
+static inline int lapic_get_version(void)
+{
+       return GET_APIC_VERSION(apic_read(APIC_LVR));
+}
+
+/*
+ * Check, if the APIC is integrated or a seperate chip
+ */
+static inline int lapic_is_integrated(void)
+{
+       return APIC_INTEGRATED(lapic_get_version());
+}
+
+/*
+ * Check, whether this is a modern or a first generation APIC
+ */
 static int modern_apic(void)
 {
-       unsigned int lvr, version;
        /* AMD systems use old APIC versions, so check the CPU */
        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-               boot_cpu_data.x86 >= 0xf)
+           boot_cpu_data.x86 >= 0xf)
                return 1;
-       lvr = apic_read(APIC_LVR);
-       version = GET_APIC_VERSION(lvr);
-       return version >= 0x14;
+       return lapic_get_version() >= 0x14;
+}
+
+/**
+ * enable_NMI_through_LVT0 - enable NMI through local vector table 0
+ */
+void enable_NMI_through_LVT0 (void * dummy)
+{
+       unsigned int v = APIC_DM_NMI;
+
+       /* Level triggered for 82489DX */
+       if (!lapic_is_integrated())
+               v |= APIC_LVT_LEVEL_TRIGGER;
+       apic_write_around(APIC_LVT0, v);
+}
+
+/**
+ * get_physical_broadcast - Get number of physical broadcast IDs
+ */
+int get_physical_broadcast(void)
+{
+       return modern_apic() ? 0xff : 0xf;
+}
+
+/**
+ * lapic_get_maxlvt - get the maximum number of local vector table entries
+ */
+int lapic_get_maxlvt(void)
+{
+       unsigned int v = apic_read(APIC_LVR);
+
+       /* 82489DXs do not report # of LVT entries. */
+       return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2;
 }
 
 /*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
+ * Local APIC timer
  */
-void ack_bad_irq(unsigned int irq)
+
+/* Clock divisor is set to 16 */
+#define APIC_DIVISOR 16
+
+/*
+ * This function sets up the local APIC timer, with a timeout of
+ * 'clocks' APIC bus clock. During calibration we actually call
+ * this function twice on the boot CPU, once with a bogus timeout
+ * value, second time for real. The other (noncalibrating) CPUs
+ * call this function only once, with the real, calibrated value.
+ *
+ * We do reads before writes even if unnecessary, to get around the
+ * P5 APIC double write bug.
+ */
+static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 {
-       printk("unexpected IRQ trap at vector %02x\n", irq);
+       unsigned int lvtt_value, tmp_value;
+
+       lvtt_value = LOCAL_TIMER_VECTOR;
+       if (!oneshot)
+               lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+       if (!lapic_is_integrated())
+               lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
+
+       if (!irqen)
+               lvtt_value |= APIC_LVT_MASKED;
+
+       apic_write_around(APIC_LVTT, lvtt_value);
+
        /*
-        * Currently unexpected vectors happen only on SMP and APIC.
-        * We _must_ ack these because every local APIC has only N
-        * irq slots per priority level, and a 'hanging, unacked' IRQ
-        * holds up an irq slot - in excessive cases (when multiple
-        * unexpected vectors occur) that might lock up the APIC
-        * completely.
-        * But only ack when the APIC is enabled -AK
+        * Divide PICLK by 16
         */
-       if (cpu_has_apic)
-               ack_APIC_irq();
+       tmp_value = apic_read(APIC_TDCR);
+       apic_write_around(APIC_TDCR, (tmp_value
+                               & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
+                               | APIC_TDR_DIV_16);
+
+       if (!oneshot)
+               apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
 }
 
-void __init apic_intr_init(void)
+/*
+ * Program the next event, relative to now
+ */
+static int lapic_next_event(unsigned long delta,
+                           struct clock_event_device *evt)
+{
+       apic_write_around(APIC_TMICT, delta);
+       return 0;
+}
+
+/*
+ * Setup the lapic timer in periodic or oneshot mode
+ */
+static void lapic_timer_setup(enum clock_event_mode mode,
+                             struct clock_event_device *evt)
+{
+       unsigned long flags;
+       unsigned int v;
+
+       /* Lapic used for broadcast ? */
+       if (!local_apic_timer_verify_ok)
+               return;
+
+       local_irq_save(flags);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+       case CLOCK_EVT_MODE_ONESHOT:
+               __setup_APIC_LVTT(calibration_result,
+                                 mode != CLOCK_EVT_MODE_PERIODIC, 1);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               v = apic_read(APIC_LVTT);
+               v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+               apic_write_around(APIC_LVTT, v);
+               break;
+       }
+
+       local_irq_restore(flags);
+}
+
+/*
+ * Local APIC timer broadcast function
+ */
+static void lapic_timer_broadcast(cpumask_t mask)
 {
 #ifdef CONFIG_SMP
-       smp_intr_init();
+       send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
 #endif
-       /* self generated IPI for local APIC timer */
-       set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+}
 
-       /* IPI vectors for APIC spurious and error interrupts */
-       set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-       set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+/*
+ * Setup the local APIC timer for this CPU. Copy the initilized values
+ * of the boot CPU and register the clock event in the framework.
+ */
+static void __devinit setup_APIC_timer(void)
+{
+       struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
-       /* thermal monitor LVT interrupt */
-#ifdef CONFIG_X86_MCE_P4THERMAL
-       set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
+       memcpy(levt, &lapic_clockevent, sizeof(*levt));
+       levt->cpumask = cpumask_of_cpu(smp_processor_id());
+
+       clockevents_register_device(levt);
 }
 
-/* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer __read_mostly = 0;
+/*
+ * In this functions we calibrate APIC bus clocks to the external timer.
+ *
+ * We want to do the calibration only once since we want to have local timer
+ * irqs syncron. CPUs connected by the same APIC bus have the very same bus
+ * frequency.
+ *
+ * This was previously done by reading the PIT/HPET and waiting for a wrap
+ * around to find out, that a tick has elapsed. I have a box, where the PIT
+ * readout is broken, so it never gets out of the wait loop again. This was
+ * also reported by others.
+ *
+ * Monitoring the jiffies value is inaccurate and the clockevents
+ * infrastructure allows us to do a simple substitution of the interrupt
+ * handler.
+ *
+ * The calibration routine also uses the pm_timer when possible, as the PIT
+ * happens to run way too slow (factor 2.3 on my VAIO CoreDuo, which goes
+ * back to normal later in the boot process).
+ */
+
+#define LAPIC_CAL_LOOPS                (HZ/10)
 
-static int enabled_via_apicbase;
+static __initdata volatile int lapic_cal_loops = -1;
+static __initdata long lapic_cal_t1, lapic_cal_t2;
+static __initdata unsigned long long lapic_cal_tsc1, lapic_cal_tsc2;
+static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
+static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
 
-void enable_NMI_through_LVT0 (void * dummy)
+/*
+ * Temporary interrupt handler.
+ */
+static void __init lapic_cal_handler(struct clock_event_device *dev)
 {
-       unsigned int v, ver;
+       unsigned long long tsc = 0;
+       long tapic = apic_read(APIC_TMCCT);
+       unsigned long pm = acpi_pm_read_early();
 
-       ver = apic_read(APIC_LVR);
-       ver = GET_APIC_VERSION(ver);
-       v = APIC_DM_NMI;                        /* unmask and set to NMI */
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
-               v |= APIC_LVT_LEVEL_TRIGGER;
-       apic_write_around(APIC_LVT0, v);
+       if (cpu_has_tsc)
+               rdtscll(tsc);
+
+       switch (lapic_cal_loops++) {
+       case 0:
+               lapic_cal_t1 = tapic;
+               lapic_cal_tsc1 = tsc;
+               lapic_cal_pm1 = pm;
+               lapic_cal_j1 = jiffies;
+               break;
+
+       case LAPIC_CAL_LOOPS:
+               lapic_cal_t2 = tapic;
+               lapic_cal_tsc2 = tsc;
+               if (pm < lapic_cal_pm1)
+                       pm += ACPI_PM_OVRRUN;
+               lapic_cal_pm2 = pm;
+               lapic_cal_j2 = jiffies;
+               break;
+       }
 }
 
-int get_physical_broadcast(void)
+/*
+ * Setup the boot APIC
+ *
+ * Calibrate and verify the result.
+ */
+void __init setup_boot_APIC_clock(void)
 {
-       if (modern_apic())
-               return 0xff;
-       else
-               return 0xf;
+       struct clock_event_device *levt = &__get_cpu_var(lapic_events);
+       const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
+       const long pm_thresh = pm_100ms/100;
+       void (*real_handler)(struct clock_event_device *dev);
+       unsigned long deltaj;
+       long delta, deltapm;
+
+       apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
+                   "calibrating APIC timer ...\n");
+
+       local_irq_disable();
+
+       /* Replace the global interrupt handler */
+       real_handler = global_clock_event->event_handler;
+       global_clock_event->event_handler = lapic_cal_handler;
+
+       /*
+        * Setup the APIC counter to 1e9. There is no way the lapic
+        * can underflow in the 100ms detection time frame
+        */
+       __setup_APIC_LVTT(1000000000, 0, 0);
+
+       /* Let the interrupts run */
+       local_irq_enable();
+
+       while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+
+       local_irq_disable();
+
+       /* Restore the real event handler */
+       global_clock_event->event_handler = real_handler;
+
+       /* Build delta t1-t2 as apic timer counts down */
+       delta = lapic_cal_t1 - lapic_cal_t2;
+       apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
+
+       /* Check, if the PM timer is available */
+       deltapm = lapic_cal_pm2 - lapic_cal_pm1;
+       apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+
+       if (deltapm) {
+               unsigned long mult;
+               u64 res;
+
+               mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, 22);
+
+               if (deltapm > (pm_100ms - pm_thresh) &&
+                   deltapm < (pm_100ms + pm_thresh)) {
+                       apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
+               } else {
+                       res = (((u64) deltapm) *  mult) >> 22;
+                       do_div(res, 1000000);
+                       printk(KERN_WARNING "APIC calibration not consistent "
+                              "with PM Timer: %ldms instead of 100ms\n",
+                              (long)res);
+                       /* Correct the lapic counter value */
+                       res = (((u64) delta ) * pm_100ms);
+                       do_div(res, deltapm);
+                       printk(KERN_INFO "APIC delta adjusted to PM-Timer: "
+                              "%lu (%ld)\n", (unsigned long) res, delta);
+                       delta = (long) res;
+               }
+       }
+
+       /* Calculate the scaled math multiplication factor */
+       lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
+       lapic_clockevent.max_delta_ns =
+               clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+       lapic_clockevent.min_delta_ns =
+               clockevent_delta2ns(0xF, &lapic_clockevent);
+
+       calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+
+       apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
+       apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult);
+       apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
+                   calibration_result);
+
+       if (cpu_has_tsc) {
+               delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
+               apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
+                           "%ld.%04ld MHz.\n",
+                           (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ),
+                           (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ));
+       }
+
+       apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
+                   "%u.%04u MHz.\n",
+                   calibration_result / (1000000 / HZ),
+                   calibration_result % (1000000 / HZ));
+
+
+       apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
+
+       /*
+        * Setup the apic timer manually
+        */
+       local_apic_timer_verify_ok = 1;
+       levt->event_handler = lapic_cal_handler;
+       lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
+       lapic_cal_loops = -1;
+
+       /* Let the interrupts run */
+       local_irq_enable();
+
+       while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+
+       local_irq_disable();
+
+       /* Stop the lapic timer */
+       lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
+
+       local_irq_enable();
+
+       /* Jiffies delta */
+       deltaj = lapic_cal_j2 - lapic_cal_j1;
+       apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
+
+       /* Check, if the PM timer is available */
+       deltapm = lapic_cal_pm2 - lapic_cal_pm1;
+       apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+
+       local_apic_timer_verify_ok = 0;
+
+       if (deltapm) {
+               if (deltapm > (pm_100ms - pm_thresh) &&
+                   deltapm < (pm_100ms + pm_thresh)) {
+                       apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
+                       /* Check, if the jiffies result is consistent */
+                       if (deltaj < LAPIC_CAL_LOOPS-2 ||
+                           deltaj > LAPIC_CAL_LOOPS+2) {
+                               /*
+                                * Not sure, what we can do about this one.
+                                * When high resultion timers are active
+                                * and the lapic timer does not stop in C3
+                                * we are fine. Otherwise more trouble might
+                                * be waiting. -- tglx
+                                */
+                               printk(KERN_WARNING "Global event device %s "
+                                      "has wrong frequency "
+                                      "(%lu ticks instead of %d)\n",
+                                      global_clock_event->name, deltaj,
+                                      LAPIC_CAL_LOOPS);
+                       }
+                       local_apic_timer_verify_ok = 1;
+               }
+       } else {
+               /* Check, if the jiffies result is consistent */
+               if (deltaj >= LAPIC_CAL_LOOPS-2 &&
+                   deltaj <= LAPIC_CAL_LOOPS+2) {
+                       apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
+                       local_apic_timer_verify_ok = 1;
+               }
+       }
+
+       if (!local_apic_timer_verify_ok) {
+               printk(KERN_WARNING
+                      "APIC timer disabled due to verification failure.\n");
+               /* No broadcast on UP ! */
+               if (num_possible_cpus() == 1)
+                       return;
+       } else
+               lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+
+       /* Setup the lapic or request the broadcast */
+       setup_APIC_timer();
+}
+
+void __devinit setup_secondary_APIC_clock(void)
+{
+       setup_APIC_timer();
 }
 
-int get_maxlvt(void)
+/*
+ * The guts of the apic timer interrupt
+ */
+static void local_apic_timer_interrupt(void)
 {
-       unsigned int v, ver, maxlvt;
+       int cpu = smp_processor_id();
+       struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
 
-       v = apic_read(APIC_LVR);
-       ver = GET_APIC_VERSION(v);
-       /* 82489DXs do not report # of LVT entries. */
-       maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
-       return maxlvt;
+       /*
+        * Normally we should not be here till LAPIC has been initialized but
+        * in some cases like kdump, its possible that there is a pending LAPIC
+        * timer interrupt from previous kernel's context and is delivered in
+        * new kernel the moment interrupts are enabled.
+        *
+        * Interrupts are enabled early and LAPIC is setup much later, hence
+        * its possible that when we get here evt->event_handler is NULL.
+        * Check for event_handler being NULL and discard the interrupt as
+        * spurious.
+        */
+       if (!evt->event_handler) {
+               printk(KERN_WARNING
+                      "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
+               /* Switch it off */
+               lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
+               return;
+       }
+
+       per_cpu(irq_stat, cpu).apic_timer_irqs++;
+
+       evt->event_handler(evt);
+}
+
+/*
+ * Local APIC timer interrupt. This is the most natural way for doing
+ * local interrupts, but local timer interrupts can be emulated by
+ * broadcast interrupts too. [in case the hw doesn't support APIC timers]
+ *
+ * [ if a single-CPU system runs an SMP kernel then we call the local
+ *   interrupt as well. Thus we cannot inline the local irq ... ]
+ */
+
+void fastcall smp_apic_timer_interrupt(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+
+       /*
+        * NOTE! We'd better ACK the irq immediately,
+        * because timer handling can be slow.
+        */
+       ack_APIC_irq();
+       /*
+        * update_process_times() expects us to have done irq_enter().
+        * Besides, if we don't timer interrupts ignore the global
+        * interrupt lock, which is the WrongThing (tm) to do.
+        */
+       exit_idle();
+       irq_enter();
+       local_apic_timer_interrupt();
+       irq_exit();
+
+       set_irq_regs(old_regs);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+       return -EINVAL;
 }
 
+/*
+ * Local APIC start and shutdown
+ */
+
+/**
+ * clear_local_APIC - shutdown the local APIC
+ *
+ * This is called, when a CPU is disabled and before rebooting, so the state of
+ * the local APIC has no dangling leftovers. Also used to cleanout any BIOS
+ * leftovers during boot.
+ */
 void clear_local_APIC(void)
 {
-       int maxlvt;
+       int maxlvt = lapic_get_maxlvt();
        unsigned long v;
 
-       maxlvt = get_maxlvt();
-
        /*
         * Masking an LVT entry can trigger a local APIC error
         * if the vector is zero. Mask LVTERR first to prevent this.
@@ -189,7 +613,7 @@ void clear_local_APIC(void)
                apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
        }
 
-/* lets not touch this if we didn't frob it */
+       /* lets not touch this if we didn't frob it */
 #ifdef CONFIG_X86_MCE_P4THERMAL
        if (maxlvt >= 5) {
                v = apic_read(APIC_LVTTHMR);
@@ -211,90 +635,23 @@ void clear_local_APIC(void)
        if (maxlvt >= 5)
                apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
 #endif
-       v = GET_APIC_VERSION(apic_read(APIC_LVR));
-       if (APIC_INTEGRATED(v)) {       /* !82489DX */
-               if (maxlvt > 3)         /* Due to Pentium errata 3AP and 11AP. */
+       /* Integrated APIC (!82489DX) ? */
+       if (lapic_is_integrated()) {
+               if (maxlvt > 3)
+                       /* Clear ESR due to Pentium errata 3AP and 11AP */
                        apic_write(APIC_ESR, 0);
                apic_read(APIC_ESR);
        }
 }
 
-void __init connect_bsp_APIC(void)
+/**
+ * disable_local_APIC - clear and disable the local APIC
+ */
+void disable_local_APIC(void)
 {
-       if (pic_mode) {
-               /*
-                * Do not trust the local APIC being empty at bootup.
-                */
-               clear_local_APIC();
-               /*
-                * PIC mode, enable APIC mode in the IMCR, i.e.
-                * connect BSP's local APIC to INT and NMI lines.
-                */
-               apic_printk(APIC_VERBOSE, "leaving PIC mode, "
-                               "enabling APIC mode.\n");
-               outb(0x70, 0x22);
-               outb(0x01, 0x23);
-       }
-       enable_apic_mode();
-}
+       unsigned long value;
 
-void disconnect_bsp_APIC(int virt_wire_setup)
-{
-       if (pic_mode) {
-               /*
-                * Put the board back into PIC mode (has an effect
-                * only on certain older boards).  Note that APIC
-                * interrupts, including IPIs, won't work beyond
-                * this point!  The only exception are INIT IPIs.
-                */
-               apic_printk(APIC_VERBOSE, "disabling APIC mode, "
-                               "entering PIC mode.\n");
-               outb(0x70, 0x22);
-               outb(0x00, 0x23);
-       }
-       else {
-               /* Go back to Virtual Wire compatibility mode */
-               unsigned long value;
-
-               /* For the spurious interrupt use vector F, and enable it */
-               value = apic_read(APIC_SPIV);
-               value &= ~APIC_VECTOR_MASK;
-               value |= APIC_SPIV_APIC_ENABLED;
-               value |= 0xf;
-               apic_write_around(APIC_SPIV, value);
-
-               if (!virt_wire_setup) {
-                       /* For LVT0 make it edge triggered, active high, external and enabled */
-                       value = apic_read(APIC_LVT0);
-                       value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
-                               APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
-                               APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
-                       value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
-                       value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
-                       apic_write_around(APIC_LVT0, value);
-               }
-               else {
-                       /* Disable LVT0 */
-                       apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
-               }
-
-               /* For LVT1 make it edge triggered, active high, nmi and enabled */
-               value = apic_read(APIC_LVT1);
-               value &= ~(
-                       APIC_MODE_MASK | APIC_SEND_PENDING |
-                       APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
-                       APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
-               value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
-               value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
-               apic_write_around(APIC_LVT1, value);
-       }
-}
-
-void disable_local_APIC(void)
-{
-       unsigned long value;
-
-       clear_local_APIC();
+       clear_local_APIC();
 
        /*
         * Disable APIC (implies clearing of registers
@@ -304,14 +661,41 @@ void disable_local_APIC(void)
        value &= ~APIC_SPIV_APIC_ENABLED;
        apic_write_around(APIC_SPIV, value);
 
+       /*
+        * When LAPIC was disabled by the BIOS and enabled by the kernel,
+        * restore the disabled state.
+        */
        if (enabled_via_apicbase) {
                unsigned int l, h;
+
                rdmsr(MSR_IA32_APICBASE, l, h);
                l &= ~MSR_IA32_APICBASE_ENABLE;
                wrmsr(MSR_IA32_APICBASE, l, h);
        }
 }
 
+/*
+ * If Linux enabled the LAPIC against the BIOS default disable it down before
+ * re-entering the BIOS on shutdown.  Otherwise the BIOS may get confused and
+ * not power-off.  Additionally clear all LVT entries before disable_local_APIC
+ * for the case where Linux didn't enable the LAPIC.
+ */
+void lapic_shutdown(void)
+{
+       unsigned long flags;
+
+       if (!cpu_has_apic)
+               return;
+
+       local_irq_save(flags);
+       clear_local_APIC();
+
+       if (enabled_via_apicbase)
+               disable_local_APIC();
+
+       local_irq_restore(flags);
+}
+
 /*
  * This is to verify that we're looking at a real local APIC.
  * Check these against your board if the CPUs aren't getting
@@ -344,7 +728,7 @@ int __init verify_local_APIC(void)
        reg1 = GET_APIC_VERSION(reg0);
        if (reg1 == 0x00 || reg1 == 0xff)
                return 0;
-       reg1 = get_maxlvt();
+       reg1 = lapic_get_maxlvt();
        if (reg1 < 0x02 || reg1 == 0xff)
                return 0;
 
@@ -367,10 +751,15 @@ int __init verify_local_APIC(void)
        return 1;
 }
 
+/**
+ * sync_Arb_IDs - synchronize APIC bus arbitration IDs
+ */
 void __init sync_Arb_IDs(void)
 {
-       /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
-          And not needed on AMD */
+       /*
+        * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not
+        * needed on AMD.
+        */
        if (modern_apic())
                return;
        /*
@@ -383,14 +772,12 @@ void __init sync_Arb_IDs(void)
                                | APIC_DM_INIT);
 }
 
-extern void __error_in_apic_c (void);
-
 /*
  * An initial setup of the virtual wire mode.
  */
 void __init init_bsp_APIC(void)
 {
-       unsigned long value, ver;
+       unsigned long value;
 
        /*
         * Don't do the setup now if we have a SMP BIOS as the
@@ -399,9 +786,6 @@ void __init init_bsp_APIC(void)
        if (smp_found_config || !cpu_has_apic)
                return;
 
-       value = apic_read(APIC_LVR);
-       ver = GET_APIC_VERSION(value);
-
        /*
         * Do not trust the local APIC being empty at bootup.
         */
@@ -413,9 +797,10 @@ void __init init_bsp_APIC(void)
        value = apic_read(APIC_SPIV);
        value &= ~APIC_VECTOR_MASK;
        value |= APIC_SPIV_APIC_ENABLED;
-       
+
        /* This bit is reserved on P4/Xeon and should be cleared */
-       if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
+       if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+           (boot_cpu_data.x86 == 15))
                value &= ~APIC_SPIV_FOCUS_DISABLED;
        else
                value |= APIC_SPIV_FOCUS_DISABLED;
@@ -427,14 +812,17 @@ void __init init_bsp_APIC(void)
         */
        apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
        value = APIC_DM_NMI;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
+       if (!lapic_is_integrated())             /* 82489DX */
                value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 }
 
+/**
+ * setup_local_APIC - setup the local APIC
+ */
 void __devinit setup_local_APIC(void)
 {
-       unsigned long oldvalue, value, ver, maxlvt;
+       unsigned long oldvalue, value, maxlvt, integrated;
        int i, j;
 
        /* Pound the ESR really hard over the head with a big hammer - mbligh */
@@ -445,11 +833,7 @@ void __devinit setup_local_APIC(void)
                apic_write(APIC_ESR, 0);
        }
 
-       value = apic_read(APIC_LVR);
-       ver = GET_APIC_VERSION(value);
-
-       if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
-               __error_in_apic_c();
+       integrated = lapic_is_integrated();
 
        /*
         * Double-check whether this APIC is really registered.
@@ -520,13 +904,10 @@ void __devinit setup_local_APIC(void)
         * like LRU than MRU (the short-term load is more even across CPUs).
         * See also the comment in end_level_ioapic_irq().  --macro
         */
-#if 1
+
        /* Enable focus processor (bit==0) */
        value &= ~APIC_SPIV_FOCUS_DISABLED;
-#else
-       /* Disable focus processor (bit==1) */
-       value |= APIC_SPIV_FOCUS_DISABLED;
-#endif
+
        /*
         * Set spurious IRQ vector
         */
@@ -562,17 +943,18 @@ void __devinit setup_local_APIC(void)
                value = APIC_DM_NMI;
        else
                value = APIC_DM_NMI | APIC_LVT_MASKED;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
+       if (!integrated)                /* 82489DX */
                value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 
-       if (APIC_INTEGRATED(ver) && !esr_disable) {             /* !82489DX */
-               maxlvt = get_maxlvt();
+       if (integrated && !esr_disable) {               /* !82489DX */
+               maxlvt = lapic_get_maxlvt();
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
                        apic_write(APIC_ESR, 0);
                oldvalue = apic_read(APIC_ESR);
 
-               value = ERROR_APIC_VECTOR;      // enables sending errors
+               /* enables sending errors */
+               value = ERROR_APIC_VECTOR;
                apic_write_around(APIC_LVTERR, value);
                /*
                 * spec says clear errors after enabling vector.
@@ -585,207 +967,30 @@ void __devinit setup_local_APIC(void)
                                "vector: 0x%08lx  after: 0x%08lx\n",
                                oldvalue, value);
        } else {
-               if (esr_disable)        
-                       /* 
-                        * Something untraceble is creating bad interrupts on 
+               if (esr_disable)
+                       /*
+                        * Something untraceble is creating bad interrupts on
                         * secondary quads ... for the moment, just leave the
                         * ESR disabled - we can't do anything useful with the
                         * errors anyway - mbligh
                         */
-                       printk("Leaving ESR disabled.\n");
-               else 
-                       printk("No ESR for 82489DX.\n");
+                       printk(KERN_INFO "Leaving ESR disabled.\n");
+               else
+                       printk(KERN_INFO "No ESR for 82489DX.\n");
        }
 
+       /* Disable the local apic timer */
+       value = apic_read(APIC_LVTT);
+       value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+       apic_write_around(APIC_LVTT, value);
+
        setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
 }
 
 /*
- * If Linux enabled the LAPIC against the BIOS default
- * disable it down before re-entering the BIOS on shutdown.
- * Otherwise the BIOS may get confused and not power-off.
- * Additionally clear all LVT entries before disable_local_APIC
- * for the case where Linux didn't enable the LAPIC.
- */
-void lapic_shutdown(void)
-{
-       unsigned long flags;
-
-       if (!cpu_has_apic)
-               return;
-
-       local_irq_save(flags);
-       clear_local_APIC();
-
-       if (enabled_via_apicbase)
-               disable_local_APIC();
-
-       local_irq_restore(flags);
-}
-
-#ifdef CONFIG_PM
-
-static struct {
-       int active;
-       /* r/w apic fields */
-       unsigned int apic_id;
-       unsigned int apic_taskpri;
-       unsigned int apic_ldr;
-       unsigned int apic_dfr;
-       unsigned int apic_spiv;
-       unsigned int apic_lvtt;
-       unsigned int apic_lvtpc;
-       unsigned int apic_lvt0;
-       unsigned int apic_lvt1;
-       unsigned int apic_lvterr;
-       unsigned int apic_tmict;
-       unsigned int apic_tdcr;
-       unsigned int apic_thmr;
-} apic_pm_state;
-
-static int lapic_suspend(struct sys_device *dev, pm_message_t state)
-{
-       unsigned long flags;
-       int maxlvt;
-
-       if (!apic_pm_state.active)
-               return 0;
-
-       maxlvt = get_maxlvt();
-
-       apic_pm_state.apic_id = apic_read(APIC_ID);
-       apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
-       apic_pm_state.apic_ldr = apic_read(APIC_LDR);
-       apic_pm_state.apic_dfr = apic_read(APIC_DFR);
-       apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
-       apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
-       if (maxlvt >= 4)
-               apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
-       apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
-       apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
-       apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
-       apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
-       apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-#ifdef CONFIG_X86_MCE_P4THERMAL
-       if (maxlvt >= 5)
-               apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
-#endif
-       
-       local_irq_save(flags);
-       disable_local_APIC();
-       local_irq_restore(flags);
-       return 0;
-}
-
-static int lapic_resume(struct sys_device *dev)
-{
-       unsigned int l, h;
-       unsigned long flags;
-       int maxlvt;
-
-       if (!apic_pm_state.active)
-               return 0;
-
-       maxlvt = get_maxlvt();
-
-       local_irq_save(flags);
-
-       /*
-        * Make sure the APICBASE points to the right address
-        *
-        * FIXME! This will be wrong if we ever support suspend on
-        * SMP! We'll need to do this as part of the CPU restore!
-        */
-       rdmsr(MSR_IA32_APICBASE, l, h);
-       l &= ~MSR_IA32_APICBASE_BASE;
-       l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
-       wrmsr(MSR_IA32_APICBASE, l, h);
-
-       apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
-       apic_write(APIC_ID, apic_pm_state.apic_id);
-       apic_write(APIC_DFR, apic_pm_state.apic_dfr);
-       apic_write(APIC_LDR, apic_pm_state.apic_ldr);
-       apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);
-       apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
-       apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
-       apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
-#ifdef CONFIG_X86_MCE_P4THERMAL
-       if (maxlvt >= 5)
-               apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
-#endif
-       if (maxlvt >= 4)
-               apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
-       apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
-       apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
-       apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
-       apic_write(APIC_ESR, 0);
-       apic_read(APIC_ESR);
-       apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
-       apic_write(APIC_ESR, 0);
-       apic_read(APIC_ESR);
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*
- * This device has no shutdown method - fully functioning local APICs
- * are needed on every CPU up until machine_halt/restart/poweroff.
- */
-
-static struct sysdev_class lapic_sysclass = {
-       set_kset_name("lapic"),
-       .resume         = lapic_resume,
-       .suspend        = lapic_suspend,
-};
-
-static struct sys_device device_lapic = {
-       .id     = 0,
-       .cls    = &lapic_sysclass,
-};
-
-static void __devinit apic_pm_activate(void)
-{
-       apic_pm_state.active = 1;
-}
-
-static int __init init_lapic_sysfs(void)
-{
-       int error;
-
-       if (!cpu_has_apic)
-               return 0;
-       /* XXX: remove suspend/resume procs if !apic_pm_state.active? */
-
-       error = sysdev_class_register(&lapic_sysclass);
-       if (!error)
-               error = sysdev_register(&device_lapic);
-       return error;
-}
-device_initcall(init_lapic_sysfs);
-
-#else  /* CONFIG_PM */
-
-static void apic_pm_activate(void) { }
-
-#endif /* CONFIG_PM */
-
-/*
- * Detect and enable local APICs on non-SMP boards.
- * Original code written by Keir Fraser.
+ * Detect and initialize APIC
  */
-
-static int __init apic_set_verbosity(char *str)
-{
-       if (strcmp("debug", str) == 0)
-               apic_verbosity = APIC_DEBUG;
-       else if (strcmp("verbose", str) == 0)
-               apic_verbosity = APIC_VERBOSE;
-       return 1;
-}
-
-__setup("apic=", apic_set_verbosity);
-
 static int __init detect_init_APIC (void)
 {
        u32 h, l, features;
@@ -797,7 +1002,7 @@ static int __init detect_init_APIC (void)
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
                if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
-                   (boot_cpu_data.x86 == 15))      
+                   (boot_cpu_data.x86 == 15))
                        break;
                goto no_apic;
        case X86_VENDOR_INTEL:
@@ -811,23 +1016,23 @@ static int __init detect_init_APIC (void)
 
        if (!cpu_has_apic) {
                /*
-                * Over-ride BIOS and try to enable the local
-                * APIC only if "lapic" specified.
+                * Over-ride BIOS and try to enable the local APIC only if
+                * "lapic" specified.
                 */
                if (enable_local_apic <= 0) {
-                       printk("Local APIC disabled by BIOS -- "
+                       printk(KERN_INFO "Local APIC disabled by BIOS -- "
                               "you can enable it with \"lapic\"\n");
                        return -1;
                }
                /*
-                * Some BIOSes disable the local APIC in the
-                * APIC_BASE MSR. This can only be done in
-                * software for Intel P6 or later and AMD K7
-                * (Model > 1) or later.
+                * Some BIOSes disable the local APIC in the APIC_BASE
+                * MSR. This can only be done in software for Intel P6 or later
+                * and AMD K7 (Model > 1) or later.
                 */
                rdmsr(MSR_IA32_APICBASE, l, h);
                if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-                       printk("Local APIC disabled by BIOS -- reenabling.\n");
+                       printk(KERN_INFO
+                              "Local APIC disabled by BIOS -- reenabling.\n");
                        l &= ~MSR_IA32_APICBASE_BASE;
                        l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
                        wrmsr(MSR_IA32_APICBASE, l, h);
@@ -840,7 +1045,7 @@ static int __init detect_init_APIC (void)
         */
        features = cpuid_edx(1);
        if (!(features & (1 << X86_FEATURE_APIC))) {
-               printk("Could not enable APIC!\n");
+               printk(KERN_WARNING "Could not enable APIC!\n");
                return -1;
        }
        set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
@@ -854,17 +1059,20 @@ static int __init detect_init_APIC (void)
        if (nmi_watchdog != NMI_NONE)
                nmi_watchdog = NMI_LOCAL_APIC;
 
-       printk("Found and enabled local APIC!\n");
+       printk(KERN_INFO "Found and enabled local APIC!\n");
 
        apic_pm_activate();
 
        return 0;
 
 no_apic:
-       printk("No local APIC present or hardware disabled\n");
+       printk(KERN_INFO "No local APIC present or hardware disabled\n");
        return -1;
 }
 
+/**
+ * init_apic_mappings - initialize APIC mappings
+ */
 void __init init_apic_mappings(void)
 {
        unsigned long apic_phys;
@@ -924,387 +1132,96 @@ fake_ioapic_page:
 }
 
 /*
- * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
- * per second. We assume that the caller has already set up the local
- * APIC.
- *
- * The APIC timer is not exactly sync with the external timer chip, it
- * closely follows bus clocks.
- */
-
-/*
- * The timer chip is already set up at HZ interrupts per second here,
- * but we do not accept timer interrupts yet. We only allow the BP
- * to calibrate.
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
  */
-static unsigned int __devinit get_8254_timer_count(void)
+int __init APIC_init_uniprocessor (void)
 {
-       unsigned long flags;
+       if (enable_local_apic < 0)
+               clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
 
-       unsigned int count;
-
-       spin_lock_irqsave(&i8253_lock, flags);
-
-       outb_p(0x00, PIT_MODE);
-       count = inb_p(PIT_CH0);
-       count |= inb_p(PIT_CH0) << 8;
-
-       spin_unlock_irqrestore(&i8253_lock, flags);
-
-       return count;
-}
-
-/* next tick in 8254 can be caught by catching timer wraparound */
-static void __devinit wait_8254_wraparound(void)
-{
-       unsigned int curr_count, prev_count;
-
-       curr_count = get_8254_timer_count();
-       do {
-               prev_count = curr_count;
-               curr_count = get_8254_timer_count();
-
-               /* workaround for broken Mercury/Neptune */
-               if (prev_count >= curr_count + 0x100)
-                       curr_count = get_8254_timer_count();
-
-       } while (prev_count >= curr_count);
-}
-
-/*
- * Default initialization for 8254 timers. If we use other timers like HPET,
- * we override this later
- */
-void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
-
-/*
- * This function sets up the local APIC timer, with a timeout of
- * 'clocks' APIC bus clock. During calibration we actually call
- * this function twice on the boot CPU, once with a bogus timeout
- * value, second time for real. The other (noncalibrating) CPUs
- * call this function only once, with the real, calibrated value.
- *
- * We do reads before writes even if unnecessary, to get around the
- * P5 APIC double write bug.
- */
-
-#define APIC_DIVISOR 16
-
-static void __setup_APIC_LVTT(unsigned int clocks)
-{
-       unsigned int lvtt_value, tmp_value, ver;
-       int cpu = smp_processor_id();
-
-       ver = GET_APIC_VERSION(apic_read(APIC_LVR));
-       lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-       if (!APIC_INTEGRATED(ver))
-               lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
-
-       if (cpu_isset(cpu, timer_bcast_ipi))
-               lvtt_value |= APIC_LVT_MASKED;
-
-       apic_write_around(APIC_LVTT, lvtt_value);
+       if (!smp_found_config && !cpu_has_apic)
+               return -1;
 
        /*
-        * Divide PICLK by 16
+        * Complain if the BIOS pretends there is one.
         */
-       tmp_value = apic_read(APIC_TDCR);
-       apic_write_around(APIC_TDCR, (tmp_value
-                               & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
-                               | APIC_TDR_DIV_16);
-
-       apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
-}
+       if (!cpu_has_apic &&
+           APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
+               printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+                      boot_cpu_physical_apicid);
+               clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+               return -1;
+       }
 
-static void __devinit setup_APIC_timer(unsigned int clocks)
-{
-       unsigned long flags;
+       verify_local_APIC();
 
-       local_irq_save(flags);
+       connect_bsp_APIC();
 
        /*
-        * Wait for IRQ0's slice:
+        * Hack: In case of kdump, after a crash, kernel might be booting
+        * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
+        * might be zero if read from MP tables. Get it from LAPIC.
         */
-       wait_timer_tick();
+#ifdef CONFIG_CRASH_DUMP
+       boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+#endif
+       phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
 
-       __setup_APIC_LVTT(clocks);
+       setup_local_APIC();
 
-       local_irq_restore(flags);
+#ifdef CONFIG_X86_IO_APIC
+       if (smp_found_config)
+               if (!skip_ioapic_setup && nr_ioapics)
+                       setup_IO_APIC();
+#endif
+       setup_boot_clock();
+
+       return 0;
 }
 
 /*
- * In this function we calibrate APIC bus clocks to the external
- * timer. Unfortunately we cannot use jiffies and the timer irq
- * to calibrate, since some later bootup code depends on getting
- * the first irq? Ugh.
- *
- * We want to do the calibration only once since we
- * want to have local timer irqs syncron. CPUs connected
- * by the same APIC bus have the very same bus frequency.
- * And we want to have irqs off anyways, no accidental
- * APIC irq that way.
+ * APIC command line parameters
  */
-
-static int __init calibrate_APIC_clock(void)
-{
-       unsigned long long t1 = 0, t2 = 0;
-       long tt1, tt2;
-       long result;
-       int i;
-       const int LOOPS = HZ/10;
-
-       apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
-
-       /*
-        * Put whatever arbitrary (but long enough) timeout
-        * value into the APIC clock, we just want to get the
-        * counter running for calibration.
-        */
-       __setup_APIC_LVTT(1000000000);
-
-       /*
-        * The timer chip counts down to zero. Let's wait
-        * for a wraparound to start exact measurement:
-        * (the current tick might have been already half done)
-        */
-
-       wait_timer_tick();
-
-       /*
-        * We wrapped around just now. Let's start:
-        */
-       if (cpu_has_tsc)
-               rdtscll(t1);
-       tt1 = apic_read(APIC_TMCCT);
-
-       /*
-        * Let's wait LOOPS wraprounds:
-        */
-       for (i = 0; i < LOOPS; i++)
-               wait_timer_tick();
-
-       tt2 = apic_read(APIC_TMCCT);
-       if (cpu_has_tsc)
-               rdtscll(t2);
-
-       /*
-        * The APIC bus clock counter is 32 bits only, it
-        * might have overflown, but note that we use signed
-        * longs, thus no extra care needed.
-        *
-        * underflown to be exact, as the timer counts down ;)
-        */
-
-       result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
-
-       if (cpu_has_tsc)
-               apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
-                       "%ld.%04ld MHz.\n",
-                       ((long)(t2-t1)/LOOPS)/(1000000/HZ),
-                       ((long)(t2-t1)/LOOPS)%(1000000/HZ));
-
-       apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
-               "%ld.%04ld MHz.\n",
-               result/(1000000/HZ),
-               result%(1000000/HZ));
-
-       return result;
-}
-
-static unsigned int calibration_result;
-
-void __init setup_boot_APIC_clock(void)
-{
-       unsigned long flags;
-       apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
-       using_apic_timer = 1;
-
-       local_irq_save(flags);
-
-       calibration_result = calibrate_APIC_clock();
-       /*
-        * Now set up the timer for real.
-        */
-       setup_APIC_timer(calibration_result);
-
-       local_irq_restore(flags);
-}
-
-void __devinit setup_secondary_APIC_clock(void)
-{
-       setup_APIC_timer(calibration_result);
-}
-
-void disable_APIC_timer(void)
+static int __init parse_lapic(char *arg)
 {
-       if (using_apic_timer) {
-               unsigned long v;
-
-               v = apic_read(APIC_LVTT);
-               /*
-                * When an illegal vector value (0-15) is written to an LVT
-                * entry and delivery mode is Fixed, the APIC may signal an
-                * illegal vector error, with out regard to whether the mask
-                * bit is set or whether an interrupt is actually seen on input.
-                *
-                * Boot sequence might call this function when the LVTT has
-                * '0' vector value. So make sure vector field is set to
-                * valid value.
-                */
-               v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-               apic_write_around(APIC_LVTT, v);
-       }
+       enable_local_apic = 1;
+       return 0;
 }
+early_param("lapic", parse_lapic);
 
-void enable_APIC_timer(void)
+static int __init parse_nolapic(char *arg)
 {
-       int cpu = smp_processor_id();
-
-       if (using_apic_timer &&
-           !cpu_isset(cpu, timer_bcast_ipi)) {
-               unsigned long v;
-
-               v = apic_read(APIC_LVTT);
-               apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
-       }
+       enable_local_apic = -1;
+       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+       return 0;
 }
+early_param("nolapic", parse_nolapic);
 
-void switch_APIC_timer_to_ipi(void *cpumask)
+static int __init apic_set_verbosity(char *str)
 {
-       cpumask_t mask = *(cpumask_t *)cpumask;
-       int cpu = smp_processor_id();
-
-       if (cpu_isset(cpu, mask) &&
-           !cpu_isset(cpu, timer_bcast_ipi)) {
-               disable_APIC_timer();
-               cpu_set(cpu, timer_bcast_ipi);
-       }
+       if (strcmp("debug", str) == 0)
+               apic_verbosity = APIC_DEBUG;
+       else if (strcmp("verbose", str) == 0)
+               apic_verbosity = APIC_VERBOSE;
+       return 1;
 }
-EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
-
-void switch_ipi_to_APIC_timer(void *cpumask)
-{
-       cpumask_t mask = *(cpumask_t *)cpumask;
-       int cpu = smp_processor_id();
 
-       if (cpu_isset(cpu, mask) &&
-           cpu_isset(cpu, timer_bcast_ipi)) {
-               cpu_clear(cpu, timer_bcast_ipi);
-               enable_APIC_timer();
-       }
-}
-EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
+__setup("apic=", apic_set_verbosity);
 
-#undef APIC_DIVISOR
 
 /*
- * Local timer interrupt handler. It does both profiling and
- * process statistics/rescheduling.
- *
- * We do profiling in every local tick, statistics/rescheduling
- * happen only every 'profiling multiplier' ticks. The default
- * multiplier is 1 and it can be changed by writing the new multiplier
- * value into /proc/profile.
+ * Local APIC interrupts
  */
 
-inline void smp_local_timer_interrupt(void)
-{
-       profile_tick(CPU_PROFILING);
-#ifdef CONFIG_SMP
-       update_process_times(user_mode_vm(get_irq_regs()));
-#endif
-
-       /*
-        * We take the 'long' return path, and there every subsystem
-        * grabs the apropriate locks (kernel lock/ irq lock).
-        *
-        * we might want to decouple profiling from the 'long path',
-        * and do the profiling totally in assembly.
-        *
-        * Currently this isn't too much of an issue (performance wise),
-        * we can take more than 100K local irqs per second on a 100 MHz P5.
-        */
-}
-
-/*
- * Local APIC timer interrupt. This is the most natural way for doing
- * local interrupts, but local timer interrupts can be emulated by
- * broadcast interrupts too. [in case the hw doesn't support APIC timers]
- *
- * [ if a single-CPU system runs an SMP kernel then we call the local
- *   interrupt as well. Thus we cannot inline the local irq ... ]
- */
-
-fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
-{
-       struct pt_regs *old_regs = set_irq_regs(regs);
-       int cpu = smp_processor_id();
-
-       /*
-        * the NMI deadlock-detector uses this.
-        */
-       per_cpu(irq_stat, cpu).apic_timer_irqs++;
-
-       /*
-        * NOTE! We'd better ACK the irq immediately,
-        * because timer handling can be slow.
-        */
-       ack_APIC_irq();
-       /*
-        * update_process_times() expects us to have done irq_enter().
-        * Besides, if we don't timer interrupts ignore the global
-        * interrupt lock, which is the WrongThing (tm) to do.
-        */
-       irq_enter();
-       smp_local_timer_interrupt();
-       irq_exit();
-       set_irq_regs(old_regs);
-}
-
-#ifndef CONFIG_SMP
-static void up_apic_timer_interrupt_call(void)
-{
-       int cpu = smp_processor_id();
-
-       /*
-        * the NMI deadlock-detector uses this.
-        */
-       per_cpu(irq_stat, cpu).apic_timer_irqs++;
-
-       smp_local_timer_interrupt();
-}
-#endif
-
-void smp_send_timer_broadcast_ipi(void)
-{
-       cpumask_t mask;
-
-       cpus_and(mask, cpu_online_map, timer_bcast_ipi);
-       if (!cpus_empty(mask)) {
-#ifdef CONFIG_SMP
-               send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
-#else
-               /*
-                * We can directly call the apic timer interrupt handler
-                * in UP case. Minus all irq related functions
-                */
-               up_apic_timer_interrupt_call();
-#endif
-       }
-}
-
-int setup_profiling_timer(unsigned int multiplier)
-{
-       return -EINVAL;
-}
-
 /*
  * This interrupt should _never_ happen with our APIC/SMP architecture
  */
-fastcall void smp_spurious_interrupt(struct pt_regs *regs)
+void smp_spurious_interrupt(struct pt_regs *regs)
 {
        unsigned long v;
 
+       exit_idle();
        irq_enter();
        /*
         * Check if this really is a spurious interrupt and ACK it
@@ -1316,19 +1233,19 @@ fastcall void smp_spurious_interrupt(struct pt_regs *regs)
                ack_APIC_irq();
 
        /* see sw-dev-man vol 3, chapter 7.4.13.5 */
-       printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n",
-                       smp_processor_id());
+       printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
+              "should never happen.\n", smp_processor_id());
        irq_exit();
 }
 
 /*
  * This interrupt should never happen with our APIC/SMP architecture
  */
-
-fastcall void smp_error_interrupt(struct pt_regs *regs)
+void smp_error_interrupt(struct pt_regs *regs)
 {
        unsigned long v, v1;
 
+       exit_idle();
        irq_enter();
        /* First tickle the hardware, only then report what went on. -- REW */
        v = apic_read(APIC_ESR);
@@ -1348,69 +1265,261 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
           7: Illegal register address
        */
        printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
-               smp_processor_id(), v , v1);
+               smp_processor_id(), v , v1);
        irq_exit();
 }
 
 /*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
+ * Initialize APIC interrupts
  */
-int __init APIC_init_uniprocessor (void)
+void __init apic_intr_init(void)
 {
-       if (enable_local_apic < 0)
-               clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+#ifdef CONFIG_SMP
+       smp_intr_init();
+#endif
+       /* self generated IPI for local APIC timer */
+       set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
-       if (!smp_found_config && !cpu_has_apic)
-               return -1;
+       /* IPI vectors for APIC spurious and error interrupts */
+       set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+       set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 
-       /*
-        * Complain if the BIOS pretends there is one.
-        */
-       if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
-               printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
-                       boot_cpu_physical_apicid);
-               clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-               return -1;
+       /* thermal monitor LVT interrupt */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+}
+
+/**
+ * connect_bsp_APIC - attach the APIC to the interrupt system
+ */
+void __init connect_bsp_APIC(void)
+{
+       if (pic_mode) {
+               /*
+                * Do not trust the local APIC being empty at bootup.
+                */
+               clear_local_APIC();
+               /*
+                * PIC mode, enable APIC mode in the IMCR, i.e.  connect BSP's
+                * local APIC to INT and NMI lines.
+                */
+               apic_printk(APIC_VERBOSE, "leaving PIC mode, "
+                               "enabling APIC mode.\n");
+               outb(0x70, 0x22);
+               outb(0x01, 0x23);
        }
+       enable_apic_mode();
+}
 
-       verify_local_APIC();
+/**
+ * disconnect_bsp_APIC - detach the APIC from the interrupt system
+ * @virt_wire_setup:   indicates, whether virtual wire mode is selected
+ *
+ * Virtual wire mode is necessary to deliver legacy interrupts even when the
+ * APIC is disabled.
+ */
+void disconnect_bsp_APIC(int virt_wire_setup)
+{
+       if (pic_mode) {
+               /*
+                * Put the board back into PIC mode (has an effect only on
+                * certain older boards).  Note that APIC interrupts, including
+                * IPIs, won't work beyond this point!  The only exception are
+                * INIT IPIs.
+                */
+               apic_printk(APIC_VERBOSE, "disabling APIC mode, "
+                               "entering PIC mode.\n");
+               outb(0x70, 0x22);
+               outb(0x00, 0x23);
+       } else {
+               /* Go back to Virtual Wire compatibility mode */
+               unsigned long value;
 
-       connect_bsp_APIC();
+               /* For the spurious interrupt use vector F, and enable it */
+               value = apic_read(APIC_SPIV);
+               value &= ~APIC_VECTOR_MASK;
+               value |= APIC_SPIV_APIC_ENABLED;
+               value |= 0xf;
+               apic_write_around(APIC_SPIV, value);
 
-       /*
-        * Hack: In case of kdump, after a crash, kernel might be booting
-        * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
-        * might be zero if read from MP tables. Get it from LAPIC.
-        */
-#ifdef CONFIG_CRASH_DUMP
-       boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
-#endif
-       phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+               if (!virt_wire_setup) {
+                       /*
+                        * For LVT0 make it edge triggered, active high,
+                        * external and enabled
+                        */
+                       value = apic_read(APIC_LVT0);
+                       value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+                               APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+                               APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+                       value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+                       value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+                       apic_write_around(APIC_LVT0, value);
+               } else {
+                       /* Disable LVT0 */
+                       apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+               }
 
-       setup_local_APIC();
+               /*
+                * For LVT1 make it edge triggered, active high, nmi and
+                * enabled
+                */
+               value = apic_read(APIC_LVT1);
+               value &= ~(
+                       APIC_MODE_MASK | APIC_SEND_PENDING |
+                       APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+                       APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+               value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+               value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+               apic_write_around(APIC_LVT1, value);
+       }
+}
 
-#ifdef CONFIG_X86_IO_APIC
-       if (smp_found_config)
-               if (!skip_ioapic_setup && nr_ioapics)
-                       setup_IO_APIC();
+/*
+ * Power management
+ */
+#ifdef CONFIG_PM
+
+static struct {
+       int active;
+       /* r/w apic fields */
+       unsigned int apic_id;
+       unsigned int apic_taskpri;
+       unsigned int apic_ldr;
+       unsigned int apic_dfr;
+       unsigned int apic_spiv;
+       unsigned int apic_lvtt;
+       unsigned int apic_lvtpc;
+       unsigned int apic_lvt0;
+       unsigned int apic_lvt1;
+       unsigned int apic_lvterr;
+       unsigned int apic_tmict;
+       unsigned int apic_tdcr;
+       unsigned int apic_thmr;
+} apic_pm_state;
+
+static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+{
+       unsigned long flags;
+       int maxlvt;
+
+       if (!apic_pm_state.active)
+               return 0;
+
+       maxlvt = lapic_get_maxlvt();
+
+       apic_pm_state.apic_id = apic_read(APIC_ID);
+       apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
+       apic_pm_state.apic_ldr = apic_read(APIC_LDR);
+       apic_pm_state.apic_dfr = apic_read(APIC_DFR);
+       apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
+       apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
+       if (maxlvt >= 4)
+               apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+       apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
+       apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
+       apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
+       apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
+       apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 #endif
-       setup_boot_APIC_clock();
 
+       local_irq_save(flags);
+       disable_local_APIC();
+       local_irq_restore(flags);
        return 0;
 }
 
-static int __init parse_lapic(char *arg)
+static int lapic_resume(struct sys_device *dev)
 {
-       lapic_enable();
+       unsigned int l, h;
+       unsigned long flags;
+       int maxlvt;
+
+       if (!apic_pm_state.active)
+               return 0;
+
+       maxlvt = lapic_get_maxlvt();
+
+       local_irq_save(flags);
+
+       /*
+        * Make sure the APICBASE points to the right address
+        *
+        * FIXME! This will be wrong if we ever support suspend on
+        * SMP! We'll need to do this as part of the CPU restore!
+        */
+       rdmsr(MSR_IA32_APICBASE, l, h);
+       l &= ~MSR_IA32_APICBASE_BASE;
+       l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+       wrmsr(MSR_IA32_APICBASE, l, h);
+
+       apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
+       apic_write(APIC_ID, apic_pm_state.apic_id);
+       apic_write(APIC_DFR, apic_pm_state.apic_dfr);
+       apic_write(APIC_LDR, apic_pm_state.apic_ldr);
+       apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);
+       apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
+       apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
+       apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
+#endif
+       if (maxlvt >= 4)
+               apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+       apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
+       apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
+       apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
+       apic_write(APIC_ESR, 0);
+       apic_read(APIC_ESR);
+       apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
+       apic_write(APIC_ESR, 0);
+       apic_read(APIC_ESR);
+       local_irq_restore(flags);
        return 0;
 }
-early_param("lapic", parse_lapic);
 
-static int __init parse_nolapic(char *arg)
+/*
+ * This device has no shutdown method - fully functioning local APICs
+ * are needed on every CPU up until machine_halt/restart/poweroff.
+ */
+
+static struct sysdev_class lapic_sysclass = {
+       set_kset_name("lapic"),
+       .resume         = lapic_resume,
+       .suspend        = lapic_suspend,
+};
+
+static struct sys_device device_lapic = {
+       .id     = 0,
+       .cls    = &lapic_sysclass,
+};
+
+static void __devinit apic_pm_activate(void)
 {
-       lapic_disable();
-       return 0;
+       apic_pm_state.active = 1;
 }
-early_param("nolapic", parse_nolapic);
 
+static int __init init_lapic_sysfs(void)
+{
+       int error;
+
+       if (!cpu_has_apic)
+               return 0;
+       /* XXX: remove suspend/resume procs if !apic_pm_state.active? */
+
+       error = sysdev_class_register(&lapic_sysclass);
+       if (!error)
+               error = sysdev_register(&device_lapic);
+       return error;
+}
+device_initcall(init_lapic_sysfs);
+
+#else  /* CONFIG_PM */
+
+static void apic_pm_activate(void) { }
+
+#endif /* CONFIG_PM */
index db99a8948dae1abad5b16357841b54efe969c9d7..064bbf2861f40fc4e96ed1ebfb9916b2c4731334 100644 (file)
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
 #include <linux/init.h>
 
 #include "io_ports.h"
 
-extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
 
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
@@ -1175,28 +1175,6 @@ out:
        spin_unlock(&user_list_lock);
 }
 
-static void set_time(void)
-{
-       struct timespec ts;
-       if (got_clock_diff) {   /* Must know time zone in order to set clock */
-               ts.tv_sec = get_cmos_time() + clock_cmos_diff;
-               ts.tv_nsec = 0;
-               do_settimeofday(&ts);
-       } 
-}
-
-static void get_time_diff(void)
-{
-#ifndef CONFIG_APM_RTC_IS_GMT
-       /*
-        * Estimate time zone so that set_time can update the clock
-        */
-       clock_cmos_diff = -get_cmos_time();
-       clock_cmos_diff += get_seconds();
-       got_clock_diff = 1;
-#endif
-}
-
 static void reinit_timer(void)
 {
 #ifdef INIT_TIMER_AFTER_SUSPEND
@@ -1236,19 +1214,6 @@ static int suspend(int vetoable)
        local_irq_disable();
        device_power_down(PMSG_SUSPEND);
 
-       /* serialize with the timer interrupt */
-       write_seqlock(&xtime_lock);
-
-       /* protect against access to timer chip registers */
-       spin_lock(&i8253_lock);
-
-       get_time_diff();
-       /*
-        * Irq spinlock must be dropped around set_system_power_state.
-        * We'll undo any timer changes due to interrupts below.
-        */
-       spin_unlock(&i8253_lock);
-       write_sequnlock(&xtime_lock);
        local_irq_enable();
 
        save_processor_state();
@@ -1257,7 +1222,6 @@ static int suspend(int vetoable)
        restore_processor_state();
 
        local_irq_disable();
-       set_time();
        reinit_timer();
 
        if (err == APM_NO_ERROR)
@@ -1287,11 +1251,6 @@ static void standby(void)
 
        local_irq_disable();
        device_power_down(PMSG_SUSPEND);
-       /* serialize with the timer interrupt */
-       write_seqlock(&xtime_lock);
-       /* If needed, notify drivers here */
-       get_time_diff();
-       write_sequnlock(&xtime_lock);
        local_irq_enable();
 
        err = set_system_power_state(APM_STATE_STANDBY);
@@ -1385,7 +1344,6 @@ static void check_events(void)
                        ignore_bounce = 1;
                        if ((event != APM_NORMAL_RESUME)
                            || (ignore_normal_resume == 0)) {
-                               set_time();
                                device_resume();
                                pm_send_all(PM_RESUME, (void *)0);
                                queue_event(event, NULL);
@@ -1401,7 +1359,6 @@ static void check_events(void)
                        break;
 
                case APM_UPDATE_TIME:
-                       set_time();
                        break;
 
                case APM_CRITICAL_SUSPEND:
@@ -1636,9 +1593,8 @@ static int do_open(struct inode * inode, struct file * filp)
        return 0;
 }
 
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+static int proc_apm_show(struct seq_file *m, void *v)
 {
-       char *          p;
        unsigned short  bx;
        unsigned short  cx;
        unsigned short  dx;
@@ -1650,8 +1606,6 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
        int             time_units     = -1;
        char            *units         = "?";
 
-       p = buf;
-
        if ((num_online_cpus() == 1) &&
            !(error = apm_get_power_status(&bx, &cx, &dx))) {
                ac_line_status = (bx >> 8) & 0xff;
@@ -1705,7 +1659,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
              -1: Unknown
           8) min = minutes; sec = seconds */
 
-       p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+       seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
                     driver_version,
                     (apm_info.bios.version >> 8) & 0xff,
                     apm_info.bios.version & 0xff,
@@ -1716,10 +1670,22 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
                     percentage,
                     time_units,
                     units);
+       return 0;
+}
 
-       return p - buf;
+static int proc_apm_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_apm_show, NULL);
 }
 
+static const struct file_operations apm_file_ops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_apm_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int apm(void *unused)
 {
        unsigned short  bx;
@@ -2341,9 +2307,9 @@ static int __init apm_init(void)
        set_base(gdt[APM_DS >> 3],
                 __va((unsigned long)apm_info.bios.dseg << 4));
 
-       apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
+       apm_proc = create_proc_entry("apm", 0, NULL);
        if (apm_proc)
-               apm_proc->owner = THIS_MODULE;
+               apm_proc->proc_fops = &apm_file_ops;
 
        kapmd_task = kthread_create(apm, NULL, "kapmd");
        if (IS_ERR(kapmd_task)) {
index 1b2f3cd332707f7fd6beb0e6fdf7b0a4149eb5ad..c37535163bfc1624bb069f85743a87211972b202 100644 (file)
@@ -72,7 +72,7 @@ void foo(void)
        OFFSET(PT_EAX, pt_regs, eax);
        OFFSET(PT_DS,  pt_regs, xds);
        OFFSET(PT_ES,  pt_regs, xes);
-       OFFSET(PT_GS,  pt_regs, xgs);
+       OFFSET(PT_FS,  pt_regs, xfs);
        OFFSET(PT_ORIG_EAX, pt_regs, orig_eax);
        OFFSET(PT_EIP, pt_regs, eip);
        OFFSET(PT_CS,  pt_regs, xcs);
index 8a8bbdaaf38aba279fa3df1672f05a0cdc5253cb..dcbbd0a8bfc2b8b5aa29ce1b7d4b1b78dd47b4e2 100644 (file)
@@ -605,7 +605,7 @@ void __init early_cpu_init(void)
 struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
-       regs->xgs = __KERNEL_PDA;
+       regs->xfs = __KERNEL_PDA;
        return regs;
 }
 
@@ -662,12 +662,12 @@ struct i386_pda boot_pda = {
        .pcurrent = &init_task,
 };
 
-static inline void set_kernel_gs(void)
+static inline void set_kernel_fs(void)
 {
-       /* Set %gs for this CPU's PDA.  Memory clobber is to create a
+       /* Set %fs for this CPU's PDA.  Memory clobber is to create a
           barrier with respect to any PDA operations, so the compiler
           doesn't move any before here. */
-       asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
+       asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
 }
 
 /* Initialize the CPU's GDT and PDA.  The boot CPU does this for
@@ -718,7 +718,7 @@ void __cpuinit cpu_set_gdt(int cpu)
           the boot CPU, this will transition from the boot gdt+pda to
           the real ones). */
        load_gdt(cpu_gdt_descr);
-       set_kernel_gs();
+       set_kernel_fs();
 }
 
 /* Common CPU init for both boot and secondary CPUs */
@@ -764,8 +764,8 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
        __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 #endif
 
-       /* Clear %fs. */
-       asm volatile ("mov %0, %%fs" : : "r" (0));
+       /* Clear %gs. */
+       asm volatile ("mov %0, %%gs" : : "r" (0));
 
        /* Clear all 6 debug registers: */
        set_debugreg(0, 0);
index 5299c5bf445484c26ea5ade60eb3b0ecbcdb71ee..6c52182ca323c7e874a35f30092da909449f8b19 100644 (file)
@@ -217,6 +217,15 @@ config X86_LONGHAUL
 
          If in doubt, say N.
 
+config X86_E_POWERSAVER
+       tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)"
+       select CPU_FREQ_TABLE
+       depends on EXPERIMENTAL
+       help
+         This adds the CPUFreq driver for VIA C7 processors.
+
+         If in doubt, say N.
+
 comment "shared options"
 
 config X86_ACPI_CPUFREQ_PROC_INTF
index 8de3abe322a946aec2b1c6a3ec49a72fb3ad1438..560f7760dae5c3dd18fa4b85845531bca0d30db4 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_X86_POWERNOW_K6)           += powernow-k6.o
 obj-$(CONFIG_X86_POWERNOW_K7)          += powernow-k7.o
 obj-$(CONFIG_X86_POWERNOW_K8)          += powernow-k8.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  
diff --git a/arch/i386/kernel/cpu/cpufreq/e_powersaver.c b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
new file mode 100644 (file)
index 0000000..f43d98e
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ *  Based on documentation provided by Dave Jones. Thanks!
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include <asm/msr.h>
+#include <asm/tsc.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#define EPS_BRAND_C7M  0
+#define EPS_BRAND_C7   1
+#define EPS_BRAND_EDEN 2
+#define EPS_BRAND_C3   3
+
+struct eps_cpu_data {
+       u32 fsb;
+       struct cpufreq_frequency_table freq_table[];
+};
+
+static struct eps_cpu_data *eps_cpu[NR_CPUS];
+
+
+static unsigned int eps_get(unsigned int cpu)
+{
+       struct eps_cpu_data *centaur;
+       u32 lo, hi;
+
+       if (cpu)
+               return 0;
+       centaur = eps_cpu[cpu];
+       if (centaur == NULL)
+               return 0;
+
+       /* Return current frequency */
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       return centaur->fsb * ((lo >> 8) & 0xff);
+}
+
+static int eps_set_state(struct eps_cpu_data *centaur,
+                        unsigned int cpu,
+                        u32 dest_state)
+{
+       struct cpufreq_freqs freqs;
+       u32 lo, hi;
+       int err = 0;
+       int i;
+
+       freqs.old = eps_get(cpu);
+       freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
+       freqs.cpu = cpu;
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       /* Wait while CPU is busy */
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       i = 0;
+       while (lo & ((1 << 16) | (1 << 17))) {
+               udelay(16);
+               rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+               i++;
+               if (unlikely(i > 64)) {
+                       err = -ENODEV;
+                       goto postchange;
+               }
+       }
+       /* Set new multiplier and voltage */
+       wrmsr(MSR_IA32_PERF_CTL, dest_state & 0xffff, 0);
+       /* Wait until transition end */
+       i = 0;
+       do {
+               udelay(16);
+               rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+               i++;
+               if (unlikely(i > 64)) {
+                       err = -ENODEV;
+                       goto postchange;
+               }
+       } while (lo & ((1 << 16) | (1 << 17)));
+
+       /* Return current frequency */
+postchange:
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       return err;
+}
+
+static int eps_target(struct cpufreq_policy *policy,
+                              unsigned int target_freq,
+                              unsigned int relation)
+{
+       struct eps_cpu_data *centaur;
+       unsigned int newstate = 0;
+       unsigned int cpu = policy->cpu;
+       unsigned int dest_state;
+       int ret;
+
+       if (unlikely(eps_cpu[cpu] == NULL))
+               return -ENODEV;
+       centaur = eps_cpu[cpu];
+
+       if (unlikely(cpufreq_frequency_table_target(policy,
+                       &eps_cpu[cpu]->freq_table[0],
+                       target_freq,
+                       relation,
+                       &newstate))) {
+               return -EINVAL;
+       }
+
+       /* Make frequency transition */
+       dest_state = centaur->freq_table[newstate].index & 0xffff;
+       ret = eps_set_state(centaur, cpu, dest_state);
+       if (ret)
+               printk(KERN_ERR "eps: Timeout!\n");
+       return ret;
+}
+
+static int eps_verify(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy,
+                       &eps_cpu[policy->cpu]->freq_table[0]);
+}
+
+static int eps_cpu_init(struct cpufreq_policy *policy)
+{
+       unsigned int i;
+       u32 lo, hi;
+       u64 val;
+       u8 current_multiplier, current_voltage;
+       u8 max_multiplier, max_voltage;
+       u8 min_multiplier, min_voltage;
+       u8 brand;
+       u32 fsb;
+       struct eps_cpu_data *centaur;
+       struct cpufreq_frequency_table *f_table;
+       int k, step, voltage;
+       int ret;
+       int states;
+
+       if (policy->cpu != 0)
+               return -ENODEV;
+
+       /* Check brand */
+       printk("eps: Detected VIA ");
+       rdmsr(0x1153, lo, hi);
+       brand = (((lo >> 2) ^ lo) >> 18) & 3;
+       switch(brand) {
+       case EPS_BRAND_C7M:
+               printk("C7-M\n");
+               break;
+       case EPS_BRAND_C7:
+               printk("C7\n");
+               break;
+       case EPS_BRAND_EDEN:
+               printk("Eden\n");
+               break;
+       case EPS_BRAND_C3:
+               printk("C3\n");
+               return -ENODEV;
+               break;
+       }
+       /* Enable Enhanced PowerSaver */
+       rdmsrl(MSR_IA32_MISC_ENABLE, val);
+       if (!(val & 1 << 16)) {
+               val |= 1 << 16;
+               wrmsrl(MSR_IA32_MISC_ENABLE, val);
+               /* Can be locked at 0 */
+               rdmsrl(MSR_IA32_MISC_ENABLE, val);
+               if (!(val & 1 << 16)) {
+                       printk("eps: Can't enable Enhanced PowerSaver\n");
+                       return -ENODEV;
+               }
+       }
+
+       /* Print voltage and multiplier */
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       current_voltage = lo & 0xff;
+       printk("eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
+       current_multiplier = (lo >> 8) & 0xff;
+       printk("eps: Current multiplier = %d\n", current_multiplier);
+
+       /* Print limits */
+       max_voltage = hi & 0xff;
+       printk("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
+       max_multiplier = (hi >> 8) & 0xff;
+       printk("eps: Highest multiplier = %d\n", max_multiplier);
+       min_voltage = (hi >> 16) & 0xff;
+       printk("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
+       min_multiplier = (hi >> 24) & 0xff;
+       printk("eps: Lowest multiplier = %d\n", min_multiplier);
+
+       /* Sanity checks */
+       if (current_multiplier == 0 || max_multiplier == 0
+           || min_multiplier == 0)
+               return -EINVAL;
+       if (current_multiplier > max_multiplier
+           || max_multiplier <= min_multiplier)
+               return -EINVAL;
+       if (current_voltage > 0x1c || max_voltage > 0x1c)
+               return -EINVAL;
+       if (max_voltage < min_voltage)
+               return -EINVAL;
+
+       /* Calc FSB speed */
+       fsb = cpu_khz / current_multiplier;
+       /* Calc number of p-states supported */
+       if (brand == EPS_BRAND_C7M)
+               states = max_multiplier - min_multiplier + 1;
+       else
+               states = 2;
+
+       /* Allocate private data and frequency table for current cpu */
+       centaur = kzalloc(sizeof(struct eps_cpu_data)
+                   + (states + 1) * sizeof(struct cpufreq_frequency_table),
+                   GFP_KERNEL);
+       if (!centaur)
+               return -ENOMEM;
+       eps_cpu[0] = centaur;
+
+       /* Copy basic values */
+       centaur->fsb = fsb;
+
+       /* Fill frequency and MSR value table */
+       f_table = &centaur->freq_table[0];
+       if (brand != EPS_BRAND_C7M) {
+               f_table[0].frequency = fsb * min_multiplier;
+               f_table[0].index = (min_multiplier << 8) | min_voltage;
+               f_table[1].frequency = fsb * max_multiplier;
+               f_table[1].index = (max_multiplier << 8) | max_voltage;
+               f_table[2].frequency = CPUFREQ_TABLE_END;
+       } else {
+               k = 0;
+               step = ((max_voltage - min_voltage) * 256)
+                       / (max_multiplier - min_multiplier);
+               for (i = min_multiplier; i <= max_multiplier; i++) {
+                       voltage = (k * step) / 256 + min_voltage;
+                       f_table[k].frequency = fsb * i;
+                       f_table[k].index = (i << 8) | voltage;
+                       k++;
+               }
+               f_table[k].frequency = CPUFREQ_TABLE_END;
+       }
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+       policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
+       policy->cur = fsb * current_multiplier;
+
+       ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
+       if (ret) {
+               kfree(centaur);
+               return ret;
+       }
+
+       cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
+       return 0;
+}
+
+static int eps_cpu_exit(struct cpufreq_policy *policy)
+{
+       unsigned int cpu = policy->cpu;
+       struct eps_cpu_data *centaur;
+       u32 lo, hi;
+
+       if (eps_cpu[cpu] == NULL)
+               return -ENODEV;
+       centaur = eps_cpu[cpu];
+
+       /* Get max frequency */
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       /* Set max frequency */
+       eps_set_state(centaur, cpu, hi & 0xffff);
+       /* Bye */
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       kfree(eps_cpu[cpu]);
+       eps_cpu[cpu] = NULL;
+       return 0;
+}
+
+static struct freq_attr* eps_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver eps_driver = {
+       .verify         = eps_verify,
+       .target         = eps_target,
+       .init           = eps_cpu_init,
+       .exit           = eps_cpu_exit,
+       .get            = eps_get,
+       .name           = "e_powersaver",
+       .owner          = THIS_MODULE,
+       .attr           = eps_attr,
+};
+
+static int __init eps_init(void)
+{
+       struct cpuinfo_x86 *c = cpu_data;
+
+       /* This driver will work only on Centaur C7 processors with
+        * Enhanced SpeedStep/PowerSaver registers */
+       if (c->x86_vendor != X86_VENDOR_CENTAUR
+           || c->x86 != 6 || c->x86_model != 10)
+               return -ENODEV;
+       if (!cpu_has(c, X86_FEATURE_EST))
+               return -ENODEV;
+
+       if (cpufreq_register_driver(&eps_driver))
+               return -EINVAL;
+       return 0;
+}
+
+static void __exit eps_exit(void)
+{
+       cpufreq_unregister_driver(&eps_driver);
+}
+
+MODULE_AUTHOR("Rafa³ Bilski <rafalbilski@interia.pl>");
+MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
+MODULE_LICENSE("GPL");
+
+module_init(eps_init);
+module_exit(eps_exit);
index a3db9332d652eccbc9c3745b55aaf309c4eebbe7..b59878a0d9b31a6f58b939f64bebadc656c55752 100644 (file)
@@ -8,12 +8,11 @@
  *  VIA have currently 3 different versions of Longhaul.
  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
  *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
- *  Version 2 of longhaul is the same as v1, but adds voltage scaling.
- *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
- *   voltage scaling support has currently been disabled in this driver
- *   until we have code that gets it right.
+ *  Version 2 of longhaul is backward compatible with v1, but adds
+ *   LONGHAUL MSR for purpose of both frequency and voltage scaling.
+ *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
  *  Version 3 of longhaul got renamed to Powersaver and redesigned
- *   to use the POWERSAVER MSR at 0x110a.
+ *   to use only the POWERSAVER MSR at 0x110a.
  *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
  *   It's pretty much the same feature wise to longhaul v2, though
  *   there is provision for scaling FSB too, but this doesn't work
 #define        CPU_EZRA        3
 #define        CPU_EZRA_T      4
 #define        CPU_NEHEMIAH    5
+#define        CPU_NEHEMIAH_C  6
 
 /* Flags */
 #define USE_ACPI_C3            (1 << 1)
 #define USE_NORTHBRIDGE                (1 << 2)
+#define USE_VT8235             (1 << 3)
 
 static int cpu_model;
 static unsigned int numscales=16;
@@ -63,7 +64,8 @@ static unsigned int fsb;
 static struct mV_pos *vrm_mV_table;
 static unsigned char *mV_vrm_table;
 struct f_msr {
-       unsigned char vrm;
+       u8 vrm;
+       u8 pos;
 };
 static struct f_msr f_msr_table[32];
 
@@ -73,10 +75,10 @@ static int can_scale_voltage;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
 static u8 longhaul_flags;
+static u8 longhaul_pos;
 
 /* Module parameters */
 static int scale_voltage;
-static int ignore_latency;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
@@ -164,26 +166,47 @@ static void do_longhaul1(unsigned int clock_ratio_index)
 static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
 {
        union msr_longhaul longhaul;
+       u8 dest_pos;
        u32 t;
 
+       dest_pos = f_msr_table[clock_ratio_index].pos;
+
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+       /* Setup new frequency */
        longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
        longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
        longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-       longhaul.bits.EnableSoftBusRatio = 1;
-
-       if (can_scale_voltage) {
+       /* Setup new voltage */
+       if (can_scale_voltage)
                longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
+       /* Sync to timer tick */
+       safe_halt();
+       /* Raise voltage if necessary */
+       if (can_scale_voltage && longhaul_pos < dest_pos) {
                longhaul.bits.EnableSoftVID = 1;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               /* Change voltage */
+               if (!cx_address) {
+                       ACPI_FLUSH_CPU_CACHE();
+                       halt();
+               } else {
+                       ACPI_FLUSH_CPU_CACHE();
+                       /* Invoke C3 */
+                       inb(cx_address);
+                       /* Dummy op - must do something useless after P_LVL3
+                        * read */
+                       t = inl(acpi_gbl_FADT.xpm_timer_block.address);
+               }
+               longhaul.bits.EnableSoftVID = 0;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               longhaul_pos = dest_pos;
        }
 
-       /* Sync to timer tick */
-       safe_halt();
        /* Change frequency on next halt or sleep */
+       longhaul.bits.EnableSoftBusRatio = 1;
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        if (!cx_address) {
                ACPI_FLUSH_CPU_CACHE();
-               /* Invoke C1 */
                halt();
        } else {
                ACPI_FLUSH_CPU_CACHE();
@@ -193,12 +216,29 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
                t = inl(acpi_gbl_FADT.xpm_timer_block.address);
        }
        /* Disable bus ratio bit */
-       local_irq_disable();
-       longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
        longhaul.bits.EnableSoftBusRatio = 0;
-       longhaul.bits.EnableSoftBSEL = 0;
-       longhaul.bits.EnableSoftVID = 0;
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+
+       /* Reduce voltage if necessary */
+       if (can_scale_voltage && longhaul_pos > dest_pos) {
+               longhaul.bits.EnableSoftVID = 1;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               /* Change voltage */
+               if (!cx_address) {
+                       ACPI_FLUSH_CPU_CACHE();
+                       halt();
+               } else {
+                       ACPI_FLUSH_CPU_CACHE();
+                       /* Invoke C3 */
+                       inb(cx_address);
+                       /* Dummy op - must do something useless after P_LVL3
+                        * read */
+                       t = inl(acpi_gbl_FADT.xpm_timer_block.address);
+               }
+               longhaul.bits.EnableSoftVID = 0;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               longhaul_pos = dest_pos;
+       }
 }
 
 /**
@@ -257,26 +297,19 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
        /*
         * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
         * Software controlled multipliers only.
-        *
-        * *NB* Until we get voltage scaling working v1 & v2 are the same code.
-        * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
         */
        case TYPE_LONGHAUL_V1:
-       case TYPE_LONGHAUL_V2:
                do_longhaul1(clock_ratio_index);
                break;
 
        /*
+        * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
+        *
         * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
-        * We can scale voltage with this too, but that's currently
-        * disabled until we come up with a decent 'match freq to voltage'
-        * algorithm.
-        * When we add voltage scaling, we will also need to do the
-        * voltage/freq setting in order depending on the direction
-        * of scaling (like we do in powernow-k7.c)
         * Nehemiah can do FSB scaling too, but this has never been proven
         * to work in practice.
         */
+       case TYPE_LONGHAUL_V2:
        case TYPE_POWERSAVER:
                if (longhaul_flags & USE_ACPI_C3) {
                        /* Don't allow wakeup */
@@ -301,6 +334,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
        local_irq_restore(flags);
        preempt_enable();
 
+       freqs.new = calc_speed(longhaul_get_cpu_mult());
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 }
 
@@ -315,31 +349,19 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 
 #define ROUNDING       0xf
 
-static int _guess(int guess, int mult)
-{
-       int target;
-
-       target = ((mult/10)*guess);
-       if (mult%10 != 0)
-               target += (guess/2);
-       target += ROUNDING/2;
-       target &= ~ROUNDING;
-       return target;
-}
-
-
 static int guess_fsb(int mult)
 {
-       int speed = (cpu_khz/1000);
+       int speed = cpu_khz / 1000;
        int i;
-       int speeds[] = { 66, 100, 133, 200 };
-
-       speed += ROUNDING/2;
-       speed &= ~ROUNDING;
-
-       for (i=0; i<4; i++) {
-               if (_guess(speeds[i], mult) == speed)
-                       return speeds[i];
+       int speeds[] = { 666, 1000, 1333, 2000 };
+       int f_max, f_min;
+
+       for (i = 0; i < 4; i++) {
+               f_max = ((speeds[i] * mult) + 50) / 100;
+               f_max += (ROUNDING / 2);
+               f_min = f_max - ROUNDING;
+               if ((speed <= f_max) && (speed >= f_min))
+                       return speeds[i] / 10;
        }
        return 0;
 }
@@ -347,67 +369,40 @@ static int guess_fsb(int mult)
 
 static int __init longhaul_get_ranges(void)
 {
-       unsigned long invalue;
-       unsigned int ezra_t_multipliers[32]= {
-                       90,  30,  40, 100,  55,  35,  45,  95,
-                       50,  70,  80,  60, 120,  75,  85,  65,
-                       -1, 110, 120,  -1, 135, 115, 125, 105,
-                       130, 150, 160, 140,  -1, 155,  -1, 145 };
        unsigned int j, k = 0;
-       union msr_longhaul longhaul;
-       int mult = 0;
+       int mult;
 
-       switch (longhaul_version) {
-       case TYPE_LONGHAUL_V1:
-       case TYPE_LONGHAUL_V2:
-               /* Ugh, Longhaul v1 didn't have the min/max MSRs.
-                  Assume min=3.0x & max = whatever we booted at. */
+       /* Get current frequency */
+       mult = longhaul_get_cpu_mult();
+       if (mult == -1) {
+               printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
+               return -EINVAL;
+       }
+       fsb = guess_fsb(mult);
+       if (fsb == 0) {
+               printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
+               return -EINVAL;
+       }
+       /* Get max multiplier - as we always did.
+        * Longhaul MSR is usefull only when voltage scaling is enabled.
+        * C3 is booting at max anyway. */
+       maxmult = mult;
+       /* Get min multiplier */
+       switch (cpu_model) {
+       case CPU_NEHEMIAH:
+               minmult = 50;
+               break;
+       case CPU_NEHEMIAH_C:
+               minmult = 40;
+               break;
+       default:
                minmult = 30;
-               maxmult = mult = longhaul_get_cpu_mult();
                break;
-
-       case TYPE_POWERSAVER:
-               /* Ezra-T */
-               if (cpu_model==CPU_EZRA_T) {
-                       minmult = 30;
-                       rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-                       invalue = longhaul.bits.MaxMHzBR;
-                       if (longhaul.bits.MaxMHzBR4)
-                               invalue += 16;
-                       maxmult = mult = ezra_t_multipliers[invalue];
-                       break;
-               }
-
-               /* Nehemiah */
-               if (cpu_model==CPU_NEHEMIAH) {
-                       rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-                       /*
-                        * TODO: This code works, but raises a lot of questions.
-                        * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
-                        *   We get around this by using a hardcoded multiplier of 4.0x
-                        *   for the minimimum speed, and the speed we booted up at for the max.
-                        *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
-                        * - According to some VIA documentation EBLCR is only
-                        *   in pre-Nehemiah C3s. How this still works is a mystery.
-                        *   We're possibly using something undocumented and unsupported,
-                        *   But it works, so we don't grumble.
-                        */
-                       minmult=40;
-                       maxmult = mult = longhaul_get_cpu_mult();
-                       break;
-               }
        }
-       fsb = guess_fsb(mult);
 
        dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
                 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
-       if (fsb == 0) {
-               printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
-               return -EINVAL;
-       }
-
        highest_speed = calc_speed(maxmult);
        lowest_speed = calc_speed(minmult);
        dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
@@ -455,6 +450,7 @@ static void __init longhaul_setup_voltagescaling(void)
        union msr_longhaul longhaul;
        struct mV_pos minvid, maxvid;
        unsigned int j, speed, pos, kHz_step, numvscales;
+       int min_vid_speed;
 
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        if (!(longhaul.bits.RevisionID & 1)) {
@@ -468,14 +464,14 @@ static void __init longhaul_setup_voltagescaling(void)
                mV_vrm_table = &mV_vrm85[0];
        } else {
                printk (KERN_INFO PFX "Mobile VRM\n");
+               if (cpu_model < CPU_NEHEMIAH)
+                       return;
                vrm_mV_table = &mobilevrm_mV[0];
                mV_vrm_table = &mV_mobilevrm[0];
        }
 
        minvid = vrm_mV_table[longhaul.bits.MinimumVID];
        maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
-       numvscales = maxvid.pos - minvid.pos + 1;
-       kHz_step = (highest_speed - lowest_speed) / numvscales;
 
        if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
                printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
@@ -491,20 +487,59 @@ static void __init longhaul_setup_voltagescaling(void)
                return;
        }
 
-       printk(KERN_INFO PFX "Max VID=%d.%03d  Min VID=%d.%03d, %d possible voltage scales\n",
+       /* How many voltage steps */
+       numvscales = maxvid.pos - minvid.pos + 1;
+       printk(KERN_INFO PFX
+               "Max VID=%d.%03d  "
+               "Min VID=%d.%03d, "
+               "%d possible voltage scales\n",
                maxvid.mV/1000, maxvid.mV%1000,
                minvid.mV/1000, minvid.mV%1000,
                numvscales);
 
+       /* Calculate max frequency at min voltage */
+       j = longhaul.bits.MinMHzBR;
+       if (longhaul.bits.MinMHzBR4)
+               j += 16;
+       min_vid_speed = eblcr_table[j];
+       if (min_vid_speed == -1)
+               return;
+       switch (longhaul.bits.MinMHzFSB) {
+       case 0:
+               min_vid_speed *= 13333;
+               break;
+       case 1:
+               min_vid_speed *= 10000;
+               break;
+       case 3:
+               min_vid_speed *= 6666;
+               break;
+       default:
+               return;
+               break;
+       }
+       if (min_vid_speed >= highest_speed)
+               return;
+       /* Calculate kHz for one voltage step */
+       kHz_step = (highest_speed - min_vid_speed) / numvscales;
+
+
        j = 0;
        while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
                speed = longhaul_table[j].frequency;
-               pos = (speed - lowest_speed) / kHz_step + minvid.pos;
+               if (speed > min_vid_speed)
+                       pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
+               else
+                       pos = minvid.pos;
                f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
+               f_msr_table[longhaul_table[j].index].pos = pos;
                j++;
        }
 
+       longhaul_pos = maxvid.pos;
        can_scale_voltage = 1;
+       printk(KERN_INFO PFX "Voltage scaling enabled. "
+               "Use of \"conservative\" governor is highly recommended.\n");
 }
 
 
@@ -573,20 +608,51 @@ static int enable_arbiter_disable(void)
        if (dev != NULL) {
                /* Enable access to port 0x22 */
                pci_read_config_byte(dev, reg, &pci_cmd);
-               if ( !(pci_cmd & 1<<7) ) {
+               if (!(pci_cmd & 1<<7)) {
                        pci_cmd |= 1<<7;
                        pci_write_config_byte(dev, reg, pci_cmd);
+                       pci_read_config_byte(dev, reg, &pci_cmd);
+                       if (!(pci_cmd & 1<<7)) {
+                               printk(KERN_ERR PFX
+                                       "Can't enable access to port 0x22.\n");
+                               return 0;
+                       }
                }
                return 1;
        }
        return 0;
 }
 
+static int longhaul_setup_vt8235(void)
+{
+       struct pci_dev *dev;
+       u8 pci_cmd;
+
+       /* Find VT8235 southbridge */
+       dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+       if (dev != NULL) {
+               /* Set transition time to max */
+               pci_read_config_byte(dev, 0xec, &pci_cmd);
+               pci_cmd &= ~(1 << 2);
+               pci_write_config_byte(dev, 0xec, pci_cmd);
+               pci_read_config_byte(dev, 0xe4, &pci_cmd);
+               pci_cmd &= ~(1 << 7);
+               pci_write_config_byte(dev, 0xe4, pci_cmd);
+               pci_read_config_byte(dev, 0xe5, &pci_cmd);
+               pci_cmd |= 1 << 7;
+               pci_write_config_byte(dev, 0xe5, pci_cmd);
+               return 1;
+       }
+       return 0;
+}
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = cpu_data;
        char *cpuname=NULL;
        int ret;
+       u32 lo, hi;
+       int vt8235_present;
 
        /* Check what we have on this motherboard */
        switch (c->x86_model) {
@@ -599,16 +665,20 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                break;
 
        case 7:
-               longhaul_version = TYPE_LONGHAUL_V1;
                switch (c->x86_mask) {
                case 0:
+                       longhaul_version = TYPE_LONGHAUL_V1;
                        cpu_model = CPU_SAMUEL2;
                        cpuname = "C3 'Samuel 2' [C5B]";
-                       /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
-                       memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
-                       memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
+                       /* Note, this is not a typo, early Samuel2's had
+                        * Samuel1 ratios. */
+                       memcpy(clock_ratio, samuel1_clock_ratio,
+                               sizeof(samuel1_clock_ratio));
+                       memcpy(eblcr_table, samuel2_eblcr,
+                               sizeof(samuel2_eblcr));
                        break;
                case 1 ... 15:
+                       longhaul_version = TYPE_LONGHAUL_V2;
                        if (c->x86_mask < 8) {
                                cpu_model = CPU_SAMUEL2;
                                cpuname = "C3 'Samuel 2' [C5B]";
@@ -616,8 +686,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                                cpu_model = CPU_EZRA;
                                cpuname = "C3 'Ezra' [C5C]";
                        }
-                       memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
-                       memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
+                       memcpy(clock_ratio, ezra_clock_ratio,
+                               sizeof(ezra_clock_ratio));
+                       memcpy(eblcr_table, ezra_eblcr,
+                               sizeof(ezra_eblcr));
                        break;
                }
                break;
@@ -632,24 +704,24 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                break;
 
        case 9:
-               cpu_model = CPU_NEHEMIAH;
                longhaul_version = TYPE_POWERSAVER;
-               numscales=32;
+               numscales = 32;
+               memcpy(clock_ratio,
+                      nehemiah_clock_ratio,
+                      sizeof(nehemiah_clock_ratio));
+               memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
                switch (c->x86_mask) {
                case 0 ... 1:
-                       cpuname = "C3 'Nehemiah A' [C5N]";
-                       memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
+                       cpu_model = CPU_NEHEMIAH;
+                       cpuname = "C3 'Nehemiah A' [C5XLOE]";
                        break;
                case 2 ... 4:
-                       cpuname = "C3 'Nehemiah B' [C5N]";
-                       memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
+                       cpu_model = CPU_NEHEMIAH;
+                       cpuname = "C3 'Nehemiah B' [C5XLOH]";
                        break;
                case 5 ... 15:
-                       cpuname = "C3 'Nehemiah C' [C5N]";
-                       memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
+                       cpu_model = CPU_NEHEMIAH_C;
+                       cpuname = "C3 'Nehemiah C' [C5P]";
                        break;
                }
                break;
@@ -658,6 +730,13 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                cpuname = "Unknown";
                break;
        }
+       /* Check Longhaul ver. 2 */
+       if (longhaul_version == TYPE_LONGHAUL_V2) {
+               rdmsr(MSR_VIA_LONGHAUL, lo, hi);
+               if (lo == 0 && hi == 0)
+                       /* Looks like MSR isn't present */
+                       longhaul_version = TYPE_LONGHAUL_V1;
+       }
 
        printk (KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
        switch (longhaul_version) {
@@ -670,15 +749,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                break;
        };
 
+       /* Doesn't hurt */
+       vt8235_present = longhaul_setup_vt8235();
+
        /* Find ACPI data for processor */
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
-                           &longhaul_walk_callback, NULL, (void *)&pr);
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+                               ACPI_UINT32_MAX, &longhaul_walk_callback,
+                               NULL, (void *)&pr);
 
        /* Check ACPI support for C3 state */
-       if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
+       if (pr != NULL && longhaul_version != TYPE_LONGHAUL_V1) {
                cx = &pr->power.states[ACPI_STATE_C3];
-               if (cx->address > 0 &&
-                  (cx->latency <= 1000 || ignore_latency != 0) ) {
+               if (cx->address > 0 && cx->latency <= 1000) {
                        longhaul_flags |= USE_ACPI_C3;
                        goto print_support_type;
                }
@@ -688,8 +770,11 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_flags |= USE_NORTHBRIDGE;
                goto print_support_type;
        }
-
-       /* No ACPI C3 or we can't use it */
+       /* Use VT8235 southbridge if present */
+       if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
+               longhaul_flags |= USE_VT8235;
+               goto print_support_type;
+       }
        /* Check ACPI support for bus master arbiter disable */
        if ((pr == NULL) || !(pr->flags.bm_control)) {
                printk(KERN_ERR PFX
@@ -698,18 +783,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        }
 
 print_support_type:
-       if (!(longhaul_flags & USE_NORTHBRIDGE)) {
-               printk (KERN_INFO PFX "Using ACPI support.\n");
-       } else {
+       if (longhaul_flags & USE_NORTHBRIDGE)
                printk (KERN_INFO PFX "Using northbridge support.\n");
-       }
+       else if (longhaul_flags & USE_VT8235)
+               printk (KERN_INFO PFX "Using VT8235 support.\n");
+       else
+               printk (KERN_INFO PFX "Using ACPI support.\n");
 
        ret = longhaul_get_ranges();
        if (ret != 0)
                return ret;
 
-       if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
-                (scale_voltage != 0))
+       if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
                longhaul_setup_voltagescaling();
 
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
@@ -797,8 +882,6 @@ static void __exit longhaul_exit(void)
 
 module_param (scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
-module_param(ignore_latency, int, 0644);
-MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
 
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
index bc4682aad69b506acd909307ef6eba787013fd64..bb0a04b1d1abe5af709ce624397c838013d0bd46 100644 (file)
@@ -235,84 +235,14 @@ static int __initdata ezrat_eblcr[32] = {
 /*
  * VIA C3 Nehemiah */
 
-static int __initdata nehemiah_a_clock_ratio[32] = {
+static int __initdata  nehemiah_clock_ratio[32] = {
        100, /* 0000 -> 10.0x */
        160, /* 0001 -> 16.0x */
-       -1,  /* 0010 ->  RESERVED */
-       90,  /* 0011 ->  9.0x */
-       95,  /* 0100 ->  9.5x */
-       -1,  /* 0101 ->  RESERVED */
-       -1,  /* 0110 ->  RESERVED */
-       55,  /* 0111 ->  5.5x */
-       60,  /* 1000 ->  6.0x */
-       70,  /* 1001 ->  7.0x */
-       80,  /* 1010 ->  8.0x */
-       50,  /* 1011 ->  5.0x */
-       65,  /* 1100 ->  6.5x */
-       75,  /* 1101 ->  7.5x */
-       85,  /* 1110 ->  8.5x */
-       120, /* 1111 -> 12.0x */
-       100, /* 0000 -> 10.0x */
-       -1,  /* 0001 -> RESERVED */
-       120, /* 0010 -> 12.0x */
-       90,  /* 0011 ->  9.0x */
-       105, /* 0100 -> 10.5x */
-       115, /* 0101 -> 11.5x */
-       125, /* 0110 -> 12.5x */
-       135, /* 0111 -> 13.5x */
-       140, /* 1000 -> 14.0x */
-       150, /* 1001 -> 15.0x */
-       160, /* 1010 -> 16.0x */
-       130, /* 1011 -> 13.0x */
-       145, /* 1100 -> 14.5x */
-       155, /* 1101 -> 15.5x */
-       -1,  /* 1110 -> RESERVED (13.0x) */
-       120, /* 1111 -> 12.0x */
-};
-
-static int __initdata  nehemiah_b_clock_ratio[32] = {
-       100, /* 0000 -> 10.0x */
-       160, /* 0001 -> 16.0x */
-       -1,  /* 0010 ->  RESERVED */
-       90,  /* 0011 ->  9.0x */
-       95,  /* 0100 ->  9.5x */
-       -1,  /* 0101 ->  RESERVED */
-       -1,  /* 0110 ->  RESERVED */
-       55,  /* 0111 ->  5.5x */
-       60,  /* 1000 ->  6.0x */
-       70,  /* 1001 ->  7.0x */
-       80,  /* 1010 ->  8.0x */
-       50,  /* 1011 ->  5.0x */
-       65,  /* 1100 ->  6.5x */
-       75,  /* 1101 ->  7.5x */
-       85,  /* 1110 ->  8.5x */
-       120, /* 1111 -> 12.0x */
-       100, /* 0000 -> 10.0x */
-       110, /* 0001 -> 11.0x */
-       120, /* 0010 -> 12.0x */
-       90,  /* 0011 ->  9.0x */
-       105, /* 0100 -> 10.5x */
-       115, /* 0101 -> 11.5x */
-       125, /* 0110 -> 12.5x */
-       135, /* 0111 -> 13.5x */
-       140, /* 1000 -> 14.0x */
-       150, /* 1001 -> 15.0x */
-       160, /* 1010 -> 16.0x */
-       130, /* 1011 -> 13.0x */
-       145, /* 1100 -> 14.5x */
-       155, /* 1101 -> 15.5x */
-       -1,  /* 1110 -> RESERVED (13.0x) */
-       120, /* 1111 -> 12.0x */
-};
-
-static int __initdata  nehemiah_c_clock_ratio[32] = {
-       100, /* 0000 -> 10.0x */
-       160, /* 0001 -> 16.0x */
-       40,  /* 0010 ->  RESERVED */
+       40,  /* 0010 ->  4.0x */
        90,  /* 0011 ->  9.0x */
        95,  /* 0100 ->  9.5x */
        -1,  /* 0101 ->  RESERVED */
-       45,  /* 0110 ->  RESERVED */
+       45,  /* 0110 ->  4.5x */
        55,  /* 0111 ->  5.5x */
        60,  /* 1000 ->  6.0x */
        70,  /* 1001 ->  7.0x */
@@ -340,84 +270,14 @@ static int __initdata  nehemiah_c_clock_ratio[32] = {
        120, /* 1111 -> 12.0x */
 };
 
-static int __initdata nehemiah_a_eblcr[32] = {
-       50,  /* 0000 ->  5.0x */
-       160, /* 0001 -> 16.0x */
-       -1,  /* 0010 ->  RESERVED */
-       100, /* 0011 -> 10.0x */
-       55,  /* 0100 ->  5.5x */
-       -1,  /* 0101 ->  RESERVED */
-       -1,  /* 0110 ->  RESERVED */
-       95,  /* 0111 ->  9.5x */
-       90,  /* 1000 ->  9.0x */
-       70,  /* 1001 ->  7.0x */
-       80,  /* 1010 ->  8.0x */
-       60,  /* 1011 ->  6.0x */
-       120, /* 1100 -> 12.0x */
-       75,  /* 1101 ->  7.5x */
-       85,  /* 1110 ->  8.5x */
-       65,  /* 1111 ->  6.5x */
-       90,  /* 0000 ->  9.0x */
-       -1,  /* 0001 -> RESERVED */
-       120, /* 0010 -> 12.0x */
-       100, /* 0011 -> 10.0x */
-       135, /* 0100 -> 13.5x */
-       115, /* 0101 -> 11.5x */
-       125, /* 0110 -> 12.5x */
-       105, /* 0111 -> 10.5x */
-       130, /* 1000 -> 13.0x */
-       150, /* 1001 -> 15.0x */
-       160, /* 1010 -> 16.0x */
-       140, /* 1011 -> 14.0x */
-       120, /* 1100 -> 12.0x */
-       155, /* 1101 -> 15.5x */
-       -1,  /* 1110 -> RESERVED (13.0x) */
-       145 /* 1111 -> 14.5x */
-   /* end of table  */
-};
-static int __initdata nehemiah_b_eblcr[32] = {
-       50,  /* 0000 ->  5.0x */
-       160, /* 0001 -> 16.0x */
-       -1,  /* 0010 ->  RESERVED */
-       100, /* 0011 -> 10.0x */
-       55,  /* 0100 ->  5.5x */
-       -1,  /* 0101 ->  RESERVED */
-       -1,  /* 0110 ->  RESERVED */
-       95,  /* 0111 ->  9.5x */
-       90,  /* 1000 ->  9.0x */
-       70,  /* 1001 ->  7.0x */
-       80,  /* 1010 ->  8.0x */
-       60,  /* 1011 ->  6.0x */
-       120, /* 1100 -> 12.0x */
-       75,  /* 1101 ->  7.5x */
-       85,  /* 1110 ->  8.5x */
-       65,  /* 1111 ->  6.5x */
-       90,  /* 0000 ->  9.0x */
-       110, /* 0001 -> 11.0x */
-       120, /* 0010 -> 12.0x */
-       100, /* 0011 -> 10.0x */
-       135, /* 0100 -> 13.5x */
-       115, /* 0101 -> 11.5x */
-       125, /* 0110 -> 12.5x */
-       105, /* 0111 -> 10.5x */
-       130, /* 1000 -> 13.0x */
-       150, /* 1001 -> 15.0x */
-       160, /* 1010 -> 16.0x */
-       140, /* 1011 -> 14.0x */
-       120, /* 1100 -> 12.0x */
-       155, /* 1101 -> 15.5x */
-       -1,  /* 1110 -> RESERVED (13.0x) */
-       145 /* 1111 -> 14.5x */
-          /* end of table  */
-};
-static int __initdata nehemiah_c_eblcr[32] = {
+static int __initdata nehemiah_eblcr[32] = {
        50,  /* 0000 ->  5.0x */
        160, /* 0001 -> 16.0x */
-       40,  /* 0010 ->  RESERVED */
+       40,  /* 0010 ->  4.0x */
        100, /* 0011 -> 10.0x */
        55,  /* 0100 ->  5.5x */
        -1,  /* 0101 ->  RESERVED */
-       45,  /* 0110 ->  RESERVED */
+       45,  /* 0110 ->  4.5x */
        95,  /* 0111 ->  9.5x */
        90,  /* 1000 ->  9.0x */
        70,  /* 1001 ->  7.0x */
@@ -443,7 +303,6 @@ static int __initdata nehemiah_c_eblcr[32] = {
        155, /* 1101 -> 15.5x */
        -1,  /* 1110 -> RESERVED (13.0x) */
        145 /* 1111 -> 14.5x */
-         /* end of table  */
 };
 
 /*
index 2d64916725592dd98d69faf36df2d6bd14d284f3..fe3b67005ebbb1d04ea17c20e804b47cf8cede7e 100644 (file)
@@ -1289,7 +1289,11 @@ static unsigned int powernowk8_get (unsigned int cpu)
        if (query_current_values_with_pending_wait(data))
                goto out;
 
-       khz = find_khz_freq_from_fid(data->currfid);
+       if (cpu_family == CPU_HW_PSTATE)
+               khz = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+       else
+               khz = find_khz_freq_from_fid(data->currfid);
+
 
 out:
        set_cpus_allowed(current, oldmask);
index c0c3b59de32c4d183b677e843ffacffa5aa2f1bb..de27bd07bc9c853c36ee21cdd4ddfaa9ea455663 100644 (file)
@@ -6,6 +6,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/pci-direct.h>
 
 #include "cpu.h"
 
@@ -161,19 +162,19 @@ static void __cpuinit set_cx86_inc(void)
 static void __cpuinit geode_configure(void)
 {
        unsigned long flags;
-       u8 ccr3, ccr4;
+       u8 ccr3;
        local_irq_save(flags);
 
        /* Suspend on halt power saving and enable #SUSP pin */
        setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
 
        ccr3 = getCx86(CX86_CCR3);
-       setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* Enable */
-       
-       ccr4 = getCx86(CX86_CCR4);
-       ccr4 |= 0x38;           /* FPU fast, DTE cache, Mem bypass */
+       setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN */
        
-       setCx86(CX86_CCR3, ccr3);
+
+       /* FPU fast, DTE cache, Mem bypass */
+       setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
+       setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
        
        set_cx86_memwb();
        set_cx86_reorder();     
@@ -183,14 +184,6 @@ static void __cpuinit geode_configure(void)
 }
 
 
-#ifdef CONFIG_PCI
-static struct pci_device_id __cpuinitdata cyrix_55x0[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
-       { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
-       { },
-};
-#endif
-
 static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 {
        unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
@@ -258,6 +251,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 
        case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
 #ifdef CONFIG_PCI
+       {
+               u32 vendor, device;
                /* It isn't really a PCI quirk directly, but the cure is the
                   same. The MediaGX has deep magic SMM stuff that handles the
                   SB emulation. It thows away the fifo on disable_dma() which
@@ -273,22 +268,34 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
                printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
                isa_dma_bridge_buggy = 2;
 
+               /* We do this before the PCI layer is running. However we
+                  are safe here as we know the bridge must be a Cyrix
+                  companion and must be present */
+               vendor = read_pci_config_16(0, 0, 0x12, PCI_VENDOR_ID);
+               device = read_pci_config_16(0, 0, 0x12, PCI_DEVICE_ID);
 
                /*
                 *  The 5510/5520 companion chips have a funky PIT.
                 */  
-               if (pci_dev_present(cyrix_55x0))
+               if (vendor == PCI_VENDOR_ID_CYRIX &&
+        (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
                        pit_latch_buggy = 1;
+       }
 #endif
                c->x86_cache_size=16;   /* Yep 16K integrated cache thats it */
 
                /* GXm supports extended cpuid levels 'ala' AMD */
                if (c->cpuid_level == 2) {
                        /* Enable cxMMX extensions (GX1 Datasheet 54) */
-                       setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
+                       setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
                        
-                       /* GXlv/GXm/GX1 */
-                       if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
+                       /*
+                        * GXm : 0x30 ... 0x5f GXm  datasheet 51
+                        * GXlv: 0x6x          GXlv datasheet 54
+                        *  ?  : 0x7x
+                        * GX1 : 0x8x          GX1  datasheet 56
+                        */
+                       if((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <=dir1 && dir1 <= 0x8f))
                                geode_configure();
                        get_model_name(c);  /* get CPU marketing name */
                        return;
@@ -415,15 +422,14 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
                
                if (dir0 == 5 || dir0 == 3)
                {
-                       unsigned char ccr3, ccr4;
+                       unsigned char ccr3;
                        unsigned long flags;
                        printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
                        local_irq_save(flags);
                        ccr3 = getCx86(CX86_CCR3);
-                       setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
-                       ccr4 = getCx86(CX86_CCR4);
-                       setCx86(CX86_CCR4, ccr4 | 0x80);          /* enable cpuid  */
-                       setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
+                       setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN  */
+                       setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80);  /* enable cpuid  */
+                       setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
                        local_irq_restore(flags);
                }
        }
index d555bec0db99d0c0cfa1f3d910a3a17403e7709d..4f10c62d180c1521b26fa5007ca8120e12e4d409 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/processor.h> 
 #include <asm/system.h>
+#include <asm/mce.h>
 
 #include "mce.h"
 
index 84fd4cf7d0fb11e4396c981f0319af9d85b4dc5f..81fb6e2d35f37e2109d02a0e5b98fb1335261e4f 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/init.h>
+#include <asm/mce.h>
 
 void amd_mcheck_init(struct cpuinfo_x86 *c);
 void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
@@ -9,6 +10,5 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c);
 /* Call the installed machine check handler for this CPU setup. */
 extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code);
 
-extern int mce_disabled;
 extern int nr_mce_banks;
 
index 504434a46011e2ca553a7e6f67ccfad3c5ec7fc1..8359c19d3a23d1c531a543a766d00d7ca5842b61 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/system.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
+#include <asm/idle.h>
 
 #include <asm/therm_throt.h>
 
@@ -59,6 +60,7 @@ static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_therm
 
 fastcall void smp_thermal_interrupt(struct pt_regs *regs)
 {
+       exit_idle();
        irq_enter();
        vendor_thermal_interrupt(regs);
        irq_exit();
index ee771f305f960c13f01feb2dad718828a9081d08..c7d8f175674525543baa11f712b1241eeb364d67 100644 (file)
@@ -211,6 +211,9 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
        default:
                return -ENOTTY;
        case MTRRIOC_ADD_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_ADD_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err =
@@ -218,21 +221,33 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
                                  file, 0);
                break;
        case MTRRIOC_SET_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_SET_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_add(sentry.base, sentry.size, sentry.type, 0);
                break;
        case MTRRIOC_DEL_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_DEL_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_file_del(sentry.base, sentry.size, file, 0);
                break;
        case MTRRIOC_KILL_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_KILL_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_del(-1, sentry.base, sentry.size);
                break;
        case MTRRIOC_GET_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_GET_ENTRY:
+#endif
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
                mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
@@ -249,6 +264,9 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 
                break;
        case MTRRIOC_ADD_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_ADD_PAGE_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err =
@@ -256,21 +274,33 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
                                  file, 1);
                break;
        case MTRRIOC_SET_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_SET_PAGE_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0);
                break;
        case MTRRIOC_DEL_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_DEL_PAGE_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_file_del(sentry.base, sentry.size, file, 1);
                break;
        case MTRRIOC_KILL_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_KILL_PAGE_ENTRY:
+#endif
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                err = mtrr_del_page(-1, sentry.base, sentry.size);
                break;
        case MTRRIOC_GET_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+       case MTRRIOC32_GET_PAGE_ENTRY:
+#endif
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
                mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
index 16bb7ea87145411e9ee63f1dd31b982a4f7ed816..0acfb6a5a220839deeba89f0f1766cf703c94332 100644 (file)
@@ -50,7 +50,7 @@ u32 num_var_ranges = 0;
 unsigned int *usage_table;
 static DEFINE_MUTEX(mtrr_mutex);
 
-u32 size_or_mask, size_and_mask;
+u64 size_or_mask, size_and_mask;
 
 static struct mtrr_ops * mtrr_ops[X86_VENDOR_NUM] = {};
 
@@ -662,8 +662,8 @@ void __init mtrr_bp_init(void)
                             boot_cpu_data.x86_mask == 0x4))
                                phys_addr = 36;
 
-                       size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
-                       size_and_mask = ~size_or_mask & 0xfff00000;
+                       size_or_mask = ~((1ULL << (phys_addr - PAGE_SHIFT)) - 1);
+                       size_and_mask = ~size_or_mask & 0xfffff00000ULL;
                } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
                           boot_cpu_data.x86 == 6) {
                        /* VIA C* family have Intel style MTRRs, but
index d61ea9db6cfebfd908ca2184621979bc2faf82ab..289dfe6030e3a4b89d8615bfd89ff2abd52fc7fa 100644 (file)
@@ -84,7 +84,7 @@ void get_mtrr_state(void);
 
 extern void set_mtrr_ops(struct mtrr_ops * ops);
 
-extern u32 size_or_mask, size_and_mask;
+extern u64 size_or_mask, size_and_mask;
 extern struct mtrr_ops * mtrr_if;
 
 #define is_cpu(vnd)    (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd)
index 6624d8583c428a20694641aabba7f0ec6ce9308c..47e3ebbfb28df3755ab08e7c129363561192c88b 100644 (file)
@@ -29,7 +29,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
-               NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
+               NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
 
                /* Transmeta-defined */
                "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -47,7 +47,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                /* Intel-defined (#2) */
                "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
                "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
-               NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* VIA/Cyrix/Centaur-defined */
@@ -57,8 +57,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* AMD-defined (#2) */
-               "lahf_lm", "cmp_legacy", "svm", NULL, "cr8legacy", NULL, NULL, NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
+               "sse4a", "misalignsse",
+               "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        };
@@ -69,8 +70,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "ttp",  /* thermal trip */
                "tm",
                "stc",
+               "100mhzsteps",
+               "hwpstate",
                NULL,
-               /* nothing */   /* constant_tsc - moved to flags */
+               NULL,   /* constant_tsc - moved to flags */
+               /* nothing */
        };
        struct cpuinfo_x86 *c = v;
        int i, n = c - cpu_data;
index 4056fb7d2cdfdbb137f4b1e40ddab1a908d6ca0b..5678d46863c614f2c942ef6397eca9e627fd7a22 100644 (file)
@@ -9,7 +9,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
 {
        unsigned int cap_mask, uk, max, dummy;
        unsigned int cms_rev1, cms_rev2;
-       unsigned int cpu_rev, cpu_freq, cpu_flags, new_cpu_rev;
+       unsigned int cpu_rev, cpu_freq = 0, cpu_flags, new_cpu_rev;
        char cpu_info[65];
 
        get_model_name(c);      /* Same as AMD/Cyrix */
@@ -72,6 +72,9 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
        wrmsr(0x80860004, ~0, uk);
        c->x86_capability[0] = cpuid_edx(0x00000001);
        wrmsr(0x80860004, cap_mask, uk);
+
+       /* All Transmeta CPUs have a constant TSC */
+       set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
        
        /* If we can run i686 user-space code, call us an i686 */
 #define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
index 4da75fa3208d8842f92255d82678331183215c72..eeae0d992337dd3e7c543e683adcc45233abb697 100644 (file)
@@ -48,7 +48,6 @@ static struct class *cpuid_class;
 #ifdef CONFIG_SMP
 
 struct cpuid_command {
-       int cpu;
        u32 reg;
        u32 *data;
 };
@@ -57,8 +56,7 @@ static void cpuid_smp_cpuid(void *cmd_block)
 {
        struct cpuid_command *cmd = (struct cpuid_command *)cmd_block;
 
-       if (cmd->cpu == smp_processor_id())
-               cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
+       cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
                      &cmd->data[3]);
 }
 
@@ -70,11 +68,10 @@ static inline void do_cpuid(int cpu, u32 reg, u32 * data)
        if (cpu == smp_processor_id()) {
                cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
        } else {
-               cmd.cpu = cpu;
                cmd.reg = reg;
                cmd.data = data;
 
-               smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1);
+               smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
        }
        preempt_enable();
 }
index f391abcf7da901d2b4320eb2618dc53feddf63c1..70f39560846aa3bcd27bb52fe426a766a441479e 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/e820.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_EFI
 int efi_enabled = 0;
@@ -156,21 +157,22 @@ static struct resource standard_io_resources[] = { {
        .flags  = IORESOURCE_BUSY | IORESOURCE_IO
 } };
 
-static int romsignature(const unsigned char *x)
+#define ROMSIGNATURE 0xaa55
+
+static int __init romsignature(const unsigned char *rom)
 {
        unsigned short sig;
-       int ret = 0;
-       if (probe_kernel_address((const unsigned short *)x, sig) == 0)
-               ret = (sig == 0xaa55);
-       return ret;
+
+       return probe_kernel_address((const unsigned short *)rom, sig) == 0 &&
+              sig == ROMSIGNATURE;
 }
 
 static int __init romchecksum(unsigned char *rom, unsigned long length)
 {
-       unsigned char *p, sum = 0;
+       unsigned char sum;
 
-       for (p = rom; p < rom + length; p++)
-               sum += *p;
+       for (sum = 0; length; length--)
+               sum += *rom++;
        return sum == 0;
 }
 
index 5e47683fc63ae736e25d30e83aef093965cdc17d..18bddcb8e9e82757042d4813568120257b9bb25f 100644 (file)
@@ -30,7 +30,7 @@
  *     18(%esp) - %eax
  *     1C(%esp) - %ds
  *     20(%esp) - %es
- *     24(%esp) - %gs
+ *     24(%esp) - %fs
  *     28(%esp) - orig_eax
  *     2C(%esp) - %eip
  *     30(%esp) - %cs
@@ -99,9 +99,9 @@ VM_MASK               = 0x00020000
 
 #define SAVE_ALL \
        cld; \
-       pushl %gs; \
+       pushl %fs; \
        CFI_ADJUST_CFA_OFFSET 4;\
-       /*CFI_REL_OFFSET gs, 0;*/\
+       /*CFI_REL_OFFSET fs, 0;*/\
        pushl %es; \
        CFI_ADJUST_CFA_OFFSET 4;\
        /*CFI_REL_OFFSET es, 0;*/\
@@ -133,7 +133,7 @@ VM_MASK             = 0x00020000
        movl %edx, %ds; \
        movl %edx, %es; \
        movl $(__KERNEL_PDA), %edx; \
-       movl %edx, %gs
+       movl %edx, %fs
 
 #define RESTORE_INT_REGS \
        popl %ebx;      \
@@ -166,9 +166,9 @@ VM_MASK             = 0x00020000
 2:     popl %es;       \
        CFI_ADJUST_CFA_OFFSET -4;\
        /*CFI_RESTORE es;*/\
-3:     popl %gs;       \
+3:     popl %fs;       \
        CFI_ADJUST_CFA_OFFSET -4;\
-       /*CFI_RESTORE gs;*/\
+       /*CFI_RESTORE fs;*/\
 .pushsection .fixup,"ax";      \
 4:     movl $0,(%esp); \
        jmp 1b;         \
@@ -227,6 +227,7 @@ ENTRY(ret_from_fork)
        CFI_ADJUST_CFA_OFFSET -4
        jmp syscall_exit
        CFI_ENDPROC
+END(ret_from_fork)
 
 /*
  * Return to user mode is not as complex as all this looks,
@@ -258,6 +259,7 @@ ENTRY(resume_userspace)
                                        # int/exception return?
        jne work_pending
        jmp restore_all
+END(ret_from_exception)
 
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
@@ -272,6 +274,7 @@ need_resched:
        jz restore_all
        call preempt_schedule_irq
        jmp need_resched
+END(resume_kernel)
 #endif
        CFI_ENDPROC
 
@@ -349,16 +352,17 @@ sysenter_past_esp:
        movl PT_OLDESP(%esp), %ecx
        xorl %ebp,%ebp
        TRACE_IRQS_ON
-1:     mov  PT_GS(%esp), %gs
+1:     mov  PT_FS(%esp), %fs
        ENABLE_INTERRUPTS_SYSEXIT
        CFI_ENDPROC
 .pushsection .fixup,"ax"
-2:     movl $0,PT_GS(%esp)
+2:     movl $0,PT_FS(%esp)
        jmp 1b
 .section __ex_table,"a"
        .align 4
        .long 1b,2b
 .popsection
+ENDPROC(sysenter_entry)
 
        # system call handler stub
 ENTRY(system_call)
@@ -459,6 +463,7 @@ ldt_ss:
        CFI_ADJUST_CFA_OFFSET -8
        jmp restore_nocheck
        CFI_ENDPROC
+ENDPROC(system_call)
 
        # perform work that needs to be done immediately before resumption
        ALIGN
@@ -504,6 +509,7 @@ work_notifysig_v86:
        xorl %edx, %edx
        call do_notify_resume
        jmp resume_userspace_sig
+END(work_pending)
 
        # perform syscall exit tracing
        ALIGN
@@ -519,6 +525,7 @@ syscall_trace_entry:
        cmpl $(nr_syscalls), %eax
        jnae syscall_call
        jmp syscall_exit
+END(syscall_trace_entry)
 
        # perform syscall exit tracing
        ALIGN
@@ -532,6 +539,7 @@ syscall_exit_work:
        movl $1, %edx
        call do_syscall_trace
        jmp resume_userspace
+END(syscall_exit_work)
        CFI_ENDPROC
 
        RING0_INT_FRAME                 # can't unwind into user space anyway
@@ -542,15 +550,17 @@ syscall_fault:
        GET_THREAD_INFO(%ebp)
        movl $-EFAULT,PT_EAX(%esp)
        jmp resume_userspace
+END(syscall_fault)
 
 syscall_badsys:
        movl $-ENOSYS,PT_EAX(%esp)
        jmp resume_userspace
+END(syscall_badsys)
        CFI_ENDPROC
 
 #define FIXUP_ESPFIX_STACK \
        /* since we are on a wrong stack, we cant make it a C code :( */ \
-       movl %gs:PDA_cpu, %ebx; \
+       movl %fs:PDA_cpu, %ebx; \
        PER_CPU(cpu_gdt_descr, %ebx); \
        movl GDS_address(%ebx), %ebx; \
        GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
@@ -581,9 +591,9 @@ syscall_badsys:
 ENTRY(interrupt)
 .text
 
-vector=0
 ENTRY(irq_entries_start)
        RING0_INT_FRAME
+vector=0
 .rept NR_IRQS
        ALIGN
  .if vector
@@ -592,11 +602,16 @@ ENTRY(irq_entries_start)
 1:     pushl $~(vector)
        CFI_ADJUST_CFA_OFFSET 4
        jmp common_interrupt
-.data
+ .previous
        .long 1b
-.text
+ .text
 vector=vector+1
 .endr
+END(irq_entries_start)
+
+.previous
+END(interrupt)
+.previous
 
 /*
  * the CPU automatically disables interrupts when executing an IRQ vector,
@@ -609,6 +624,7 @@ common_interrupt:
        movl %esp,%eax
        call do_IRQ
        jmp ret_from_intr
+ENDPROC(common_interrupt)
        CFI_ENDPROC
 
 #define BUILD_INTERRUPT(name, nr)      \
@@ -621,18 +637,24 @@ ENTRY(name)                               \
        movl %esp,%eax;                 \
        call smp_/**/name;              \
        jmp ret_from_intr;              \
-       CFI_ENDPROC
+       CFI_ENDPROC;                    \
+ENDPROC(name)
 
 /* The include is where all of the SMP etc. interrupts come from */
 #include "entry_arch.h"
 
+/* This alternate entry is needed because we hijack the apic LVTT */
+#if defined(CONFIG_VMI) && defined(CONFIG_X86_LOCAL_APIC)
+BUILD_INTERRUPT(apic_vmi_timer_interrupt,LOCAL_TIMER_VECTOR)
+#endif
+
 KPROBE_ENTRY(page_fault)
        RING0_EC_FRAME
        pushl $do_page_fault
        CFI_ADJUST_CFA_OFFSET 4
        ALIGN
 error_code:
-       /* the function address is in %gs's slot on the stack */
+       /* the function address is in %fs's slot on the stack */
        pushl %es
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET es, 0*/
@@ -661,20 +683,20 @@ error_code:
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET ebx, 0
        cld
-       pushl %gs
+       pushl %fs
        CFI_ADJUST_CFA_OFFSET 4
-       /*CFI_REL_OFFSET gs, 0*/
+       /*CFI_REL_OFFSET fs, 0*/
        movl $(__KERNEL_PDA), %ecx
-       movl %ecx, %gs
+       movl %ecx, %fs
        UNWIND_ESPFIX_STACK
        popl %ecx
        CFI_ADJUST_CFA_OFFSET -4
        /*CFI_REGISTER es, ecx*/
-       movl PT_GS(%esp), %edi          # get the function address
+       movl PT_FS(%esp), %edi          # get the function address
        movl PT_ORIG_EAX(%esp), %edx    # get the error code
        movl $-1, PT_ORIG_EAX(%esp)     # no syscall to restart
-       mov  %ecx, PT_GS(%esp)
-       /*CFI_REL_OFFSET gs, ES*/
+       mov  %ecx, PT_FS(%esp)
+       /*CFI_REL_OFFSET fs, ES*/
        movl $(__USER_DS), %ecx
        movl %ecx, %ds
        movl %ecx, %es
@@ -692,6 +714,7 @@ ENTRY(coprocessor_error)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
        RING0_INT_FRAME
@@ -701,6 +724,7 @@ ENTRY(simd_coprocessor_error)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
        RING0_INT_FRAME
@@ -721,6 +745,7 @@ device_not_available_emulate:
        CFI_ADJUST_CFA_OFFSET -4
        jmp ret_from_exception
        CFI_ENDPROC
+END(device_not_available)
 
 /*
  * Debug traps and NMI can happen at the one SYSENTER instruction
@@ -864,10 +889,12 @@ ENTRY(native_iret)
        .align 4
        .long 1b,iret_exc
 .previous
+END(native_iret)
 
 ENTRY(native_irq_enable_sysexit)
        sti
        sysexit
+END(native_irq_enable_sysexit)
 #endif
 
 KPROBE_ENTRY(int3)
@@ -890,6 +917,7 @@ ENTRY(overflow)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(overflow)
 
 ENTRY(bounds)
        RING0_INT_FRAME
@@ -899,6 +927,7 @@ ENTRY(bounds)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(bounds)
 
 ENTRY(invalid_op)
        RING0_INT_FRAME
@@ -908,6 +937,7 @@ ENTRY(invalid_op)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
        RING0_INT_FRAME
@@ -917,6 +947,7 @@ ENTRY(coprocessor_segment_overrun)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
        RING0_EC_FRAME
@@ -924,6 +955,7 @@ ENTRY(invalid_TSS)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(invalid_TSS)
 
 ENTRY(segment_not_present)
        RING0_EC_FRAME
@@ -931,6 +963,7 @@ ENTRY(segment_not_present)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(segment_not_present)
 
 ENTRY(stack_segment)
        RING0_EC_FRAME
@@ -938,6 +971,7 @@ ENTRY(stack_segment)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(stack_segment)
 
 KPROBE_ENTRY(general_protection)
        RING0_EC_FRAME
@@ -953,6 +987,7 @@ ENTRY(alignment_check)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(alignment_check)
 
 ENTRY(divide_error)
        RING0_INT_FRAME
@@ -962,6 +997,7 @@ ENTRY(divide_error)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(divide_error)
 
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
@@ -972,6 +1008,7 @@ ENTRY(machine_check)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(machine_check)
 #endif
 
 ENTRY(spurious_interrupt_bug)
@@ -982,6 +1019,7 @@ ENTRY(spurious_interrupt_bug)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
+END(spurious_interrupt_bug)
 
 ENTRY(kernel_thread_helper)
        pushl $0                # fake return address for unwinder
index cb9abdfced9bbf8ba8f0b6d6858a384d957bdfaa..3fa7f9389afe7a39ce327ed5e4cf8493dfe7cf8e 100644 (file)
@@ -53,6 +53,7 @@
  * any particular GDT layout, because we load our own as soon as we
  * can.
  */
+.section .text.head,"ax",@progbits
 ENTRY(startup_32)
 
 #ifdef CONFIG_PARAVIRT
@@ -141,16 +142,25 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
        jb 10b
        movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
 
-#ifdef CONFIG_SMP
        xorl %ebx,%ebx                          /* This is the boot CPU (BSP) */
        jmp 3f
-
 /*
  * Non-boot CPU entry point; entered from trampoline.S
  * We can't lgdt here, because lgdt itself uses a data segment, but
  * we know the trampoline has already loaded the boot_gdt_table GDT
  * for us.
+ *
+ * If cpu hotplug is not supported then this code can go in init section
+ * which will be freed later
  */
+
+#ifdef CONFIG_HOTPLUG_CPU
+.section .text,"ax",@progbits
+#else
+.section .init.text,"ax",@progbits
+#endif
+
+#ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
        cld
        movl $(__BOOT_DS),%eax
@@ -208,8 +218,8 @@ ENTRY(startup_32_smp)
        xorl %ebx,%ebx
        incl %ebx
 
-3:
 #endif /* CONFIG_SMP */
+3:
 
 /*
  * Enable paging
@@ -309,7 +319,7 @@ is386:      movl $2,%ecx            # set MP
 
        call check_x87
        call setup_pda
-       lgdt cpu_gdt_descr
+       lgdt early_gdt_descr
        lidt idt_descr
        ljmp $(__KERNEL_CS),$1f
 1:     movl $(__KERNEL_DS),%eax        # reload all the segment registers
@@ -319,12 +329,12 @@ is386:    movl $2,%ecx            # set MP
        movl %eax,%ds
        movl %eax,%es
 
-       xorl %eax,%eax                  # Clear FS and LDT
-       movl %eax,%fs
+       xorl %eax,%eax                  # Clear GS and LDT
+       movl %eax,%gs
        lldt %ax
 
        movl $(__KERNEL_PDA),%eax
-       mov  %eax,%gs
+       mov  %eax,%fs
 
        cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
@@ -360,12 +370,12 @@ check_x87:
  * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
  * that CPU's GDT and PDA.
  */
-setup_pda:
+ENTRY(setup_pda)
        /* get the PDA pointer */
        movl start_pda, %eax
 
        /* slot the PDA address into the GDT */
-       mov cpu_gdt_descr+2, %ecx
+       mov early_gdt_descr+2, %ecx
        mov %ax, (__KERNEL_PDA+0+2)(%ecx)               /* base & 0x0000ffff */
        shr $16, %eax
        mov %al, (__KERNEL_PDA+4+0)(%ecx)               /* base & 0x00ff0000 */
@@ -492,6 +502,7 @@ ignore_int:
 #endif
        iret
 
+.section .text
 #ifdef CONFIG_PARAVIRT
 startup_paravirt:
        cld
@@ -502,10 +513,11 @@ startup_paravirt:
        pushl   %ecx
        pushl   %eax
 
-       /* paravirt.o is last in link, and that probe fn never returns */
        pushl   $__start_paravirtprobe
 1:
        movl    0(%esp), %eax
+       cmpl    $__stop_paravirtprobe, %eax
+       je      unhandled_paravirt
        pushl   (%eax)
        movl    8(%esp), %eax
        call    *(%esp)
@@ -517,6 +529,10 @@ startup_paravirt:
 
        addl    $4, (%esp)
        jmp     1b
+
+unhandled_paravirt:
+       /* Nothing wanted us: we're screwed. */
+       ud2
 #endif
 
 /*
@@ -581,7 +597,7 @@ idt_descr:
 
 # boot GDT descriptor (later on used by CPU#0):
        .word 0                         # 32 bit align gdt_desc.address
-ENTRY(cpu_gdt_descr)
+ENTRY(early_gdt_descr)
        .word GDT_ENTRIES*8-1
        .long cpu_gdt_table
 
index 0b29d41322a2620c50a0bdc98fa1ec314d397ac9..e1006b7acc9e56d5be196599cd997d9cd364be8b 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/errno.h>
 #include <linux/hpet.h>
 #include <linux/init.h>
 #include <asm/hpet.h>
 #include <asm/io.h>
 
+extern struct clock_event_device *global_clock_event;
+
 #define HPET_MASK      CLOCKSOURCE_MASK(32)
 #define HPET_SHIFT     22
 
 /* FSEC = 10^-15 NSEC = 10^-9 */
 #define FSEC_PER_NSEC  1000000
 
-static void __iomem *hpet_ptr;
+/*
+ * HPET address is set in acpi/boot.c, when an ACPI entry exists
+ */
+unsigned long hpet_address;
+static void __iomem * hpet_virt_address;
+
+static inline unsigned long hpet_readl(unsigned long a)
+{
+       return readl(hpet_virt_address + a);
+}
+
+static inline void hpet_writel(unsigned long d, unsigned long a)
+{
+       writel(d, hpet_virt_address + a);
+}
+
+/*
+ * HPET command line enable / disable
+ */
+static int boot_hpet_disable;
+
+static int __init hpet_setup(char* str)
+{
+       if (str) {
+               if (!strncmp("disable", str, 7))
+                       boot_hpet_disable = 1;
+       }
+       return 1;
+}
+__setup("hpet=", hpet_setup);
+
+static inline int is_hpet_capable(void)
+{
+       return (!boot_hpet_disable && hpet_address);
+}
+
+/*
+ * HPET timer interrupt enable / disable
+ */
+static int hpet_legacy_int_enabled;
+
+/**
+ * is_hpet_enabled - check whether the hpet timer interrupt is enabled
+ */
+int is_hpet_enabled(void)
+{
+       return is_hpet_capable() && hpet_legacy_int_enabled;
+}
+
+/*
+ * When the hpet driver (/dev/hpet) is enabled, we need to reserve
+ * timer 0 and timer 1 in case of RTC emulation.
+ */
+#ifdef CONFIG_HPET
+static void hpet_reserve_platform_timers(unsigned long id)
+{
+       struct hpet __iomem *hpet = hpet_virt_address;
+       struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
+       unsigned int nrtimers, i;
+       struct hpet_data hd;
+
+       nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+
+       memset(&hd, 0, sizeof (hd));
+       hd.hd_phys_address = hpet_address;
+       hd.hd_address = hpet_virt_address;
+       hd.hd_nirqs = nrtimers;
+       hd.hd_flags = HPET_DATA_PLATFORM;
+       hpet_reserve_timer(&hd, 0);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+       hpet_reserve_timer(&hd, 1);
+#endif
+
+       hd.hd_irq[0] = HPET_LEGACY_8254;
+       hd.hd_irq[1] = HPET_LEGACY_RTC;
+
+       for (i = 2; i < nrtimers; timer++, i++)
+               hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >>
+                       Tn_INT_ROUTE_CNF_SHIFT;
+
+       hpet_alloc(&hd);
+
+}
+#else
+static void hpet_reserve_platform_timers(unsigned long id) { }
+#endif
+
+/*
+ * Common hpet info
+ */
+static unsigned long hpet_period;
+
+static void hpet_set_mode(enum clock_event_mode mode,
+                         struct clock_event_device *evt);
+static int hpet_next_event(unsigned long delta,
+                          struct clock_event_device *evt);
+
+/*
+ * The hpet clock event device
+ */
+static struct clock_event_device hpet_clockevent = {
+       .name           = "hpet",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = hpet_set_mode,
+       .set_next_event = hpet_next_event,
+       .shift          = 32,
+       .irq            = 0,
+};
+
+static void hpet_start_counter(void)
+{
+       unsigned long cfg = hpet_readl(HPET_CFG);
+
+       cfg &= ~HPET_CFG_ENABLE;
+       hpet_writel(cfg, HPET_CFG);
+       hpet_writel(0, HPET_COUNTER);
+       hpet_writel(0, HPET_COUNTER + 4);
+       cfg |= HPET_CFG_ENABLE;
+       hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_enable_int(void)
+{
+       unsigned long cfg = hpet_readl(HPET_CFG);
+
+       cfg |= HPET_CFG_LEGACY;
+       hpet_writel(cfg, HPET_CFG);
+       hpet_legacy_int_enabled = 1;
+}
+
+static void hpet_set_mode(enum clock_event_mode mode,
+                         struct clock_event_device *evt)
+{
+       unsigned long cfg, cmp, now;
+       uint64_t delta;
+
+       switch(mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * hpet_clockevent.mult;
+               delta >>= hpet_clockevent.shift;
+               now = hpet_readl(HPET_COUNTER);
+               cmp = now + (unsigned long) delta;
+               cfg = hpet_readl(HPET_T0_CFG);
+               cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+                      HPET_TN_SETVAL | HPET_TN_32BIT;
+               hpet_writel(cfg, HPET_T0_CFG);
+               /*
+                * The first write after writing TN_SETVAL to the
+                * config register sets the counter value, the second
+                * write sets the period.
+                */
+               hpet_writel(cmp, HPET_T0_CMP);
+               udelay(1);
+               hpet_writel((unsigned long) delta, HPET_T0_CMP);
+               break;
+
+       case CLOCK_EVT_MODE_ONESHOT:
+               cfg = hpet_readl(HPET_T0_CFG);
+               cfg &= ~HPET_TN_PERIODIC;
+               cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+               hpet_writel(cfg, HPET_T0_CFG);
+               break;
+
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               cfg = hpet_readl(HPET_T0_CFG);
+               cfg &= ~HPET_TN_ENABLE;
+               hpet_writel(cfg, HPET_T0_CFG);
+               break;
+       }
+}
+
+static int hpet_next_event(unsigned long delta,
+                          struct clock_event_device *evt)
+{
+       unsigned long cnt;
+
+       cnt = hpet_readl(HPET_COUNTER);
+       cnt += delta;
+       hpet_writel(cnt, HPET_T0_CMP);
+
+       return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0);
+}
+
+/*
+ * Try to setup the HPET timer
+ */
+int __init hpet_enable(void)
+{
+       unsigned long id;
+       uint64_t hpet_freq;
+
+       if (!is_hpet_capable())
+               return 0;
+
+       hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+
+       /*
+        * Read the period and check for a sane value:
+        */
+       hpet_period = hpet_readl(HPET_PERIOD);
+       if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
+               goto out_nohpet;
+
+       /*
+        * The period is a femto seconds value. We need to calculate the
+        * scaled math multiplication factor for nanosecond to hpet tick
+        * conversion.
+        */
+       hpet_freq = 1000000000000000ULL;
+       do_div(hpet_freq, hpet_period);
+       hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
+                                     NSEC_PER_SEC, 32);
+       /* Calculate the min / max delta */
+       hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+                                                          &hpet_clockevent);
+       hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
+                                                          &hpet_clockevent);
+
+       /*
+        * Read the HPET ID register to retrieve the IRQ routing
+        * information and the number of channels
+        */
+       id = hpet_readl(HPET_ID);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+       /*
+        * The legacy routing mode needs at least two channels, tick timer
+        * and the rtc emulation channel.
+        */
+       if (!(id & HPET_ID_NUMBER))
+               goto out_nohpet;
+#endif
+
+       /* Start the counter */
+       hpet_start_counter();
+
+       if (id & HPET_ID_LEGSUP) {
+               hpet_enable_int();
+               hpet_reserve_platform_timers(id);
+               /*
+                * Start hpet with the boot cpu mask and make it
+                * global after the IO_APIC has been initialized.
+                */
+               hpet_clockevent.cpumask =cpumask_of_cpu(0);
+               clockevents_register_device(&hpet_clockevent);
+               global_clock_event = &hpet_clockevent;
+               return 1;
+       }
+       return 0;
 
+out_nohpet:
+       iounmap(hpet_virt_address);
+       hpet_virt_address = NULL;
+       return 0;
+}
+
+/*
+ * Clock source related code
+ */
 static cycle_t read_hpet(void)
 {
-       return (cycle_t)readl(hpet_ptr);
+       return (cycle_t)hpet_readl(HPET_COUNTER);
 }
 
 static struct clocksource clocksource_hpet = {
@@ -24,28 +286,17 @@ static struct clocksource clocksource_hpet = {
        .rating         = 250,
        .read           = read_hpet,
        .mask           = HPET_MASK,
-       .mult           = 0, /* set below */
        .shift          = HPET_SHIFT,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_hpet_clocksource(void)
 {
-       unsigned long hpet_period;
-       void __iomem* hpet_base;
        u64 tmp;
-       int err;
 
-       if (!is_hpet_enabled())
+       if (!hpet_virt_address)
                return -ENODEV;
 
-       /* calculate the hpet address: */
-       hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
-       hpet_ptr = hpet_base + HPET_COUNTER;
-
-       /* calculate the frequency: */
-       hpet_period = readl(hpet_base + HPET_PERIOD);
-
        /*
         * hpet period is in femto seconds per cycle
         * so we need to convert this to ns/cyc units
@@ -61,11 +312,218 @@ static int __init init_hpet_clocksource(void)
        do_div(tmp, FSEC_PER_NSEC);
        clocksource_hpet.mult = (u32)tmp;
 
-       err = clocksource_register(&clocksource_hpet);
-       if (err)
-               iounmap(hpet_base);
-
-       return err;
+       return clocksource_register(&clocksource_hpet);
 }
 
 module_init(init_hpet_clocksource);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+
+/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+ * is enabled, we support RTC interrupt functionality in software.
+ * RTC has 3 kinds of interrupts:
+ * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
+ *    is updated
+ * 2) Alarm Interrupt - generate an interrupt at a specific time of day
+ * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
+ * (1) and (2) above are implemented using polling at a frequency of
+ * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
+ * overhead. (DEFAULT_RTC_INT_FREQ)
+ * For (3), we use interrupts at 64Hz or user specified periodic
+ * frequency, whichever is higher.
+ */
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+#define DEFAULT_RTC_INT_FREQ   64
+#define DEFAULT_RTC_SHIFT      6
+#define RTC_NUM_INTS           1
+
+static unsigned long hpet_rtc_flags;
+static unsigned long hpet_prev_update_sec;
+static struct rtc_time hpet_alarm_time;
+static unsigned long hpet_pie_count;
+static unsigned long hpet_t1_cmp;
+static unsigned long hpet_default_delta;
+static unsigned long hpet_pie_delta;
+static unsigned long hpet_pie_limit;
+
+/*
+ * Timer 1 for RTC emulation. We use one shot mode, as periodic mode
+ * is not supported by all HPET implementations for timer 1.
+ *
+ * hpet_rtc_timer_init() is called when the rtc is initialized.
+ */
+int hpet_rtc_timer_init(void)
+{
+       unsigned long cfg, cnt, delta, flags;
+
+       if (!is_hpet_enabled())
+               return 0;
+
+       if (!hpet_default_delta) {
+               uint64_t clc;
+
+               clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+               clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT;
+               hpet_default_delta = (unsigned long) clc;
+       }
+
+       if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
+               delta = hpet_default_delta;
+       else
+               delta = hpet_pie_delta;
+
+       local_irq_save(flags);
+
+       cnt = delta + hpet_readl(HPET_COUNTER);
+       hpet_writel(cnt, HPET_T1_CMP);
+       hpet_t1_cmp = cnt;
+
+       cfg = hpet_readl(HPET_T1_CFG);
+       cfg &= ~HPET_TN_PERIODIC;
+       cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+       hpet_writel(cfg, HPET_T1_CFG);
+
+       local_irq_restore(flags);
+
+       return 1;
+}
+
+/*
+ * The functions below are called from rtc driver.
+ * Return 0 if HPET is not being used.
+ * Otherwise do the necessary changes and return 1.
+ */
+int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
+{
+       if (!is_hpet_enabled())
+               return 0;
+
+       hpet_rtc_flags &= ~bit_mask;
+       return 1;
+}
+
+int hpet_set_rtc_irq_bit(unsigned long bit_mask)
+{
+       unsigned long oldbits = hpet_rtc_flags;
+
+       if (!is_hpet_enabled())
+               return 0;
+
+       hpet_rtc_flags |= bit_mask;
+
+       if (!oldbits)
+               hpet_rtc_timer_init();
+
+       return 1;
+}
+
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min,
+                       unsigned char sec)
+{
+       if (!is_hpet_enabled())
+               return 0;
+
+       hpet_alarm_time.tm_hour = hrs;
+       hpet_alarm_time.tm_min = min;
+       hpet_alarm_time.tm_sec = sec;
+
+       return 1;
+}
+
+int hpet_set_periodic_freq(unsigned long freq)
+{
+       uint64_t clc;
+
+       if (!is_hpet_enabled())
+               return 0;
+
+       if (freq <= DEFAULT_RTC_INT_FREQ)
+               hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
+       else {
+               clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+               do_div(clc, freq);
+               clc >>= hpet_clockevent.shift;
+               hpet_pie_delta = (unsigned long) clc;
+       }
+       return 1;
+}
+
+int hpet_rtc_dropped_irq(void)
+{
+       return is_hpet_enabled();
+}
+
+static void hpet_rtc_timer_reinit(void)
+{
+       unsigned long cfg, delta;
+       int lost_ints = -1;
+
+       if (unlikely(!hpet_rtc_flags)) {
+               cfg = hpet_readl(HPET_T1_CFG);
+               cfg &= ~HPET_TN_ENABLE;
+               hpet_writel(cfg, HPET_T1_CFG);
+               return;
+       }
+
+       if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
+               delta = hpet_default_delta;
+       else
+               delta = hpet_pie_delta;
+
+       /*
+        * Increment the comparator value until we are ahead of the
+        * current count.
+        */
+       do {
+               hpet_t1_cmp += delta;
+               hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+               lost_ints++;
+       } while ((long)(hpet_readl(HPET_COUNTER) - hpet_t1_cmp) > 0);
+
+       if (lost_ints) {
+               if (hpet_rtc_flags & RTC_PIE)
+                       hpet_pie_count += lost_ints;
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "rtc: lost %d interrupts\n",
+                               lost_ints);
+       }
+}
+
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+{
+       struct rtc_time curr_time;
+       unsigned long rtc_int_flag = 0;
+
+       hpet_rtc_timer_reinit();
+
+       if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
+               rtc_get_rtc_time(&curr_time);
+
+       if (hpet_rtc_flags & RTC_UIE &&
+           curr_time.tm_sec != hpet_prev_update_sec) {
+               rtc_int_flag = RTC_UF;
+               hpet_prev_update_sec = curr_time.tm_sec;
+       }
+
+       if (hpet_rtc_flags & RTC_PIE &&
+           ++hpet_pie_count >= hpet_pie_limit) {
+               rtc_int_flag |= RTC_PF;
+               hpet_pie_count = 0;
+       }
+
+       if (hpet_rtc_flags & RTC_PIE &&
+           (curr_time.tm_sec == hpet_alarm_time.tm_sec) &&
+           (curr_time.tm_min == hpet_alarm_time.tm_min) &&
+           (curr_time.tm_hour == hpet_alarm_time.tm_hour))
+                       rtc_int_flag |= RTC_AF;
+
+       if (rtc_int_flag) {
+               rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
+               rtc_interrupt(rtc_int_flag, dev_id);
+       }
+       return IRQ_HANDLED;
+}
+#endif
index 9a0060b92e32ace2911ae839a9d8b710e7458ec4..a6bc7bb38834282239bba67631b6ae2041b14e2b 100644 (file)
@@ -2,7 +2,7 @@
  * i8253.c  8253/PIT functions
  *
  */
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysdev.h>
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
-void setup_pit_timer(void)
+/*
+ * HPET replaces the PIT, when enabled. So we need to know, which of
+ * the two timers is used
+ */
+struct clock_event_device *global_clock_event;
+
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+static void init_pit_timer(enum clock_event_mode mode,
+                          struct clock_event_device *evt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8253_lock, flags);
+
+       switch(mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               /* binary, mode 2, LSB/MSB, ch 0 */
+               outb_p(0x34, PIT_MODE);
+               udelay(10);
+               outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
+               udelay(10);
+               outb(LATCH >> 8 , PIT_CH0);     /* MSB */
+               break;
+
+       case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               /* One shot setup */
+               outb_p(0x38, PIT_MODE);
+               udelay(10);
+               break;
+       }
+       spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&i8253_lock, flags);
-       outb_p(0x34,PIT_MODE);          /* binary, mode 2, LSB/MSB, ch 0 */
-       udelay(10);
-       outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
-       udelay(10);
-       outb(LATCH >> 8 , PIT_CH0);     /* MSB */
+       outb_p(delta & 0xff , PIT_CH0); /* LSB */
+       outb(delta >> 8 , PIT_CH0);     /* MSB */
        spin_unlock_irqrestore(&i8253_lock, flags);
+
+       return 0;
+}
+
+/*
+ * On UP the PIT can serve all of the possible timer functions. On SMP systems
+ * it can be solely used for the global tick.
+ *
+ * The profiling and update capabilites are switched off once the local apic is
+ * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
+ * !using_apic_timer decisions in do_timer_interrupt_hook()
+ */
+struct clock_event_device pit_clockevent = {
+       .name           = "pit",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = init_pit_timer,
+       .set_next_event = pit_next_event,
+       .shift          = 32,
+       .irq            = 0,
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init setup_pit_timer(void)
+{
+       /*
+        * Start pit with the boot cpu mask and make it global after the
+        * IO_APIC has been initialized.
+        */
+       pit_clockevent.cpumask = cpumask_of_cpu(0);
+       pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
+       pit_clockevent.max_delta_ns =
+               clockevent_delta2ns(0x7FFF, &pit_clockevent);
+       pit_clockevent.min_delta_ns =
+               clockevent_delta2ns(0xF, &pit_clockevent);
+       clockevents_register_device(&pit_clockevent);
+       global_clock_event = &pit_clockevent;
 }
 
 /*
@@ -46,7 +126,7 @@ static cycle_t pit_read(void)
        static u32 old_jifs;
 
        spin_lock_irqsave(&i8253_lock, flags);
-        /*
+       /*
         * Although our caller may have the read side of xtime_lock,
         * this is now a seqlock, and we are cheating in this routine
         * by having side effects on state that we cannot undo if
index c8d45821c788f77467535569816d820d395f8a4b..03abfdb1a6e4c5cb8e4c7e407f0a19e3763de2df 100644 (file)
@@ -41,6 +41,7 @@ static void mask_and_ack_8259A(unsigned int);
 static struct irq_chip i8259A_chip = {
        .name           = "XT-PIC",
        .mask           = disable_8259A_irq,
+       .disable        = disable_8259A_irq,
        .unmask         = enable_8259A_irq,
        .mask_ack       = mask_and_ack_8259A,
 };
@@ -409,12 +410,6 @@ void __init native_init_IRQ(void)
         */
        intr_init_hook();
 
-       /*
-        * Set the clock to HZ Hz, we already have a valid
-        * vector now:
-        */
-       setup_pit_timer();
-
        /*
         * External FPU? Set up irq13 if so, for
         * original braindamaged IBM FERR coupling.
index ba8d302a0b728718d099f5254a8e463d45b1853d..4ccebd454e256786d0e8e32fc9e540bf97ab5b72 100644 (file)
@@ -482,8 +482,8 @@ static void do_irq_balance(void)
                package_index = CPU_TO_PACKAGEINDEX(i);
                for (j = 0; j < NR_IRQS; j++) {
                        unsigned long value_now, delta;
-                       /* Is this an active IRQ? */
-                       if (!irq_desc[j].action)
+                       /* Is this an active IRQ or balancing disabled ? */
+                       if (!irq_desc[j].action || irq_balancing_disabled(j))
                                continue;
                        if ( package_index == i )
                                IRQ_DELTA(package_index,j) = 0;
@@ -1281,11 +1281,9 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
                        trigger == IOAPIC_LEVEL)
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                         handle_fasteoi_irq, "fasteoi");
-       else {
-               irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
+       else
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                         handle_edge_irq, "edge");
-       }
        set_intr_gate(vector, interrupt[irq]);
 }
 
@@ -1588,7 +1586,7 @@ void /*__init*/ print_local_APIC(void * dummy)
        v = apic_read(APIC_LVR);
        printk(KERN_INFO "... APIC VERSION: %08x\n", v);
        ver = GET_APIC_VERSION(v);
-       maxlvt = get_maxlvt();
+       maxlvt = lapic_get_maxlvt();
 
        v = apic_read(APIC_TASKPRI);
        printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
@@ -1920,7 +1918,7 @@ static void __init setup_ioapic_ids_from_mpc(void)
 static void __init setup_ioapic_ids_from_mpc(void) { }
 #endif
 
-static int no_timer_check __initdata;
+int no_timer_check __initdata;
 
 static int __init notimercheck(char *s)
 {
@@ -2310,7 +2308,7 @@ static inline void __init check_timer(void)
 
        disable_8259A_irq(0);
        set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
-                                     "fasteio");
+                                     "fasteoi");
        apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);   /* Fixed mode */
        enable_8259A_irq(0);
 
index 3201d421090a0d2cf5237f4d55ef070d41bc48b9..0f2ca590bf2306411c58a149a091c5941dae7113 100644 (file)
@@ -10,7 +10,6 @@
  * io_apic.c.)
  */
 
-#include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 
+#include <asm/idle.h>
+
+#include <asm/apic.h>
+#include <asm/uaccess.h>
+
 DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
 EXPORT_PER_CPU_SYMBOL(irq_stat);
 
-#ifndef CONFIG_X86_LOCAL_APIC
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
  */
 void ack_bad_irq(unsigned int irq)
 {
-       printk("unexpected IRQ trap at vector %02x\n", irq);
-}
+       printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       /*
+        * Currently unexpected vectors happen only on SMP and APIC.
+        * We _must_ ack these because every local APIC has only N
+        * irq slots per priority level, and a 'hanging, unacked' IRQ
+        * holds up an irq slot - in excessive cases (when multiple
+        * unexpected vectors occur) that might lock up the APIC
+        * completely.
+        * But only ack when the APIC is enabled -AK
+        */
+       if (cpu_has_apic)
+               ack_APIC_irq();
 #endif
+}
 
 #ifdef CONFIG_4KSTACKS
 /*
@@ -61,6 +77,7 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
        union irq_ctx *curctx, *irqctx;
        u32 *isp;
 #endif
+       exit_idle();
 
        if (unlikely((unsigned)irq >= NR_IRQS)) {
                printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
index af1d53344993cac32221d7209bf853bed4f5febc..b545bc746fceb2a9f6f192778c6dbca784395553 100644 (file)
@@ -363,7 +363,7 @@ no_kprobe:
                        "       pushf\n"
                        /* skip cs, eip, orig_eax */
                        "       subl $12, %esp\n"
-                       "       pushl %gs\n"
+                       "       pushl %fs\n"
                        "       pushl %ds\n"
                        "       pushl %es\n"
                        "       pushl %eax\n"
@@ -387,7 +387,7 @@ no_kprobe:
                        "       popl %edi\n"
                        "       popl %ebp\n"
                        "       popl %eax\n"
-                       /* skip eip, orig_eax, es, ds, gs */
+                       /* skip eip, orig_eax, es, ds, fs */
                        "       addl $20, %esp\n"
                        "       popf\n"
                        "       ret\n");
@@ -408,7 +408,7 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
        spin_lock_irqsave(&kretprobe_lock, flags);
        head = kretprobe_inst_table_head(current);
        /* fixup registers */
-       regs->xcs = __KERNEL_CS;
+       regs->xcs = __KERNEL_CS | get_kernel_rpl();
        regs->eip = trampoline_address;
        regs->orig_eax = 0xffffffff;
 
index 381252bae3d817c1509a7c3fcd98d304f831da29..b8f16633a6ece6380cd8396c702c2ac75937a6a1 100644 (file)
@@ -384,7 +384,7 @@ static int do_microcode_update (void)
 {
        long cursor = 0;
        int error = 0;
-       void *new_mc;
+       void *new_mc = NULL;
        int cpu;
        cpumask_t old;
 
index 4e14264f392a93678ad9a0ef906f6d3a4def45bd..bcaa6e9b6197a4466972153fb812f783f82c13a7 100644 (file)
@@ -68,7 +68,6 @@ static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
 #ifdef CONFIG_SMP
 
 struct msr_command {
-       int cpu;
        int err;
        u32 reg;
        u32 data[2];
@@ -78,16 +77,14 @@ static void msr_smp_wrmsr(void *cmd_block)
 {
        struct msr_command *cmd = (struct msr_command *)cmd_block;
 
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
+       cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
 }
 
 static void msr_smp_rdmsr(void *cmd_block)
 {
        struct msr_command *cmd = (struct msr_command *)cmd_block;
 
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
+       cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
 }
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
@@ -99,12 +96,11 @@ static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
        if (cpu == smp_processor_id()) {
                ret = wrmsr_eio(reg, eax, edx);
        } else {
-               cmd.cpu = cpu;
                cmd.reg = reg;
                cmd.data[0] = eax;
                cmd.data[1] = edx;
 
-               smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
+               smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1);
                ret = cmd.err;
        }
        preempt_enable();
@@ -120,10 +116,9 @@ static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
        if (cpu == smp_processor_id()) {
                ret = rdmsr_eio(reg, eax, edx);
        } else {
-               cmd.cpu = cpu;
                cmd.reg = reg;
 
-               smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
+               smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1);
 
                *eax = cmd.data[0];
                *edx = cmd.data[1];
index 1a6f8bb8881ce72fa99909914beb70141b4a519f..821df34d2b3a3a1b8a71ada0a77b64229e0f0200 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/dmi.h>
 #include <linux/kprobes.h>
 #include <linux/cpumask.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
@@ -185,7 +186,8 @@ static __cpuinit inline int nmi_known_cpu(void)
 {
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
-               return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
+               return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6)
+                       || (boot_cpu_data.x86 == 16));
        case X86_VENDOR_INTEL:
                if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
                        return 1;
@@ -216,6 +218,28 @@ static __init void nmi_cpu_busy(void *data)
 }
 #endif
 
+static unsigned int adjust_for_32bit_ctr(unsigned int hz)
+{
+       u64 counter_val;
+       unsigned int retval = hz;
+
+       /*
+        * On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter
+        * are writable, with higher bits sign extending from bit 31.
+        * So, we can only program the counter with 31 bit values and
+        * 32nd bit should be 1, for 33.. to be 1.
+        * Find the appropriate nmi_hz
+        */
+       counter_val = (u64)cpu_khz * 1000;
+       do_div(counter_val, retval);
+       if (counter_val > 0x7fffffffULL) {
+               u64 count = (u64)cpu_khz * 1000;
+               do_div(count, 0x7fffffffUL);
+               retval = count + 1;
+       }
+       return retval;
+}
+
 static int __init check_nmi_watchdog(void)
 {
        unsigned int *prev_nmi_count;
@@ -281,18 +305,10 @@ static int __init check_nmi_watchdog(void)
                struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
                nmi_hz = 1;
-               /*
-                * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
-                * are writable, with higher bits sign extending from bit 31.
-                * So, we can only program the counter with 31 bit values and
-                * 32nd bit should be 1, for 33.. to be 1.
-                * Find the appropriate nmi_hz
-                */
-               if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
-                       ((u64)cpu_khz * 1000) > 0x7fffffffULL) {
-                       u64 count = (u64)cpu_khz * 1000;
-                       do_div(count, 0x7fffffffUL);
-                       nmi_hz = count + 1;
+
+               if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
+                   wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+                       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
                }
        }
 
@@ -369,6 +385,34 @@ void enable_timer_nmi_watchdog(void)
        }
 }
 
+static void __acpi_nmi_disable(void *__unused)
+{
+       apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
+}
+
+/*
+ * Disable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_disable(void)
+{
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
+}
+
+static void __acpi_nmi_enable(void *__unused)
+{
+       apic_write_around(APIC_LVT0, APIC_DM_NMI);
+}
+
+/*
+ * Enable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_enable(void)
+{
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
+}
+
 #ifdef CONFIG_PM
 
 static int nmi_pm_active; /* nmi_active before suspend */
@@ -442,6 +486,17 @@ static void write_watchdog_counter(unsigned int perfctr_msr, const char *descr)
        wrmsrl(perfctr_msr, 0 - count);
 }
 
+static void write_watchdog_counter32(unsigned int perfctr_msr,
+               const char *descr)
+{
+       u64 count = (u64)cpu_khz * 1000;
+
+       do_div(count, nmi_hz);
+       if(descr)
+               Dprintk("setting %s to -0x%08Lx\n", descr, count);
+       wrmsr(perfctr_msr, (u32)(-count), 0);
+}
+
 /* Note that these events don't tick when the CPU idles. This means
    the frequency varies with CPU load. */
 
@@ -531,7 +586,8 @@ static int setup_p6_watchdog(void)
 
        /* setup the timer */
        wrmsr(evntsel_msr, evntsel, 0);
-       write_watchdog_counter(perfctr_msr, "P6_PERFCTR0");
+       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+       write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= P6_EVNTSEL0_ENABLE;
        wrmsr(evntsel_msr, evntsel, 0);
@@ -704,7 +760,8 @@ static int setup_intel_arch_watchdog(void)
 
        /* setup the timer */
        wrmsr(evntsel_msr, evntsel, 0);
-       write_watchdog_counter(perfctr_msr, "INTEL_ARCH_PERFCTR0");
+       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+       write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
        wrmsr(evntsel_msr, evntsel, 0);
@@ -762,7 +819,8 @@ void setup_apic_nmi_watchdog (void *unused)
        if (nmi_watchdog == NMI_LOCAL_APIC) {
                switch (boot_cpu_data.x86_vendor) {
                case X86_VENDOR_AMD:
-                       if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
+                       if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
+                               boot_cpu_data.x86 != 16)
                                return;
                        if (!setup_k7_watchdog())
                                return;
@@ -916,9 +974,13 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                cpu_clear(cpu, backtrace_mask);
        }
 
-       sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
+       /*
+        * Take the local apic timer and PIT/HPET into account. We don't
+        * know which one is active, when we have highres/dyntick on
+        */
+       sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_irqs(0);
 
-       /* if the apic timer isn't firing, this cpu isn't doing much */
+       /* if the none of the timers isn't firing, this cpu isn't doing much */
        if (!touched && last_irq_sums[cpu] == sum) {
                /*
                 * Ayiee, looks like this CPU is stuck ...
@@ -956,6 +1018,8 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                                dummy &= ~P4_CCCR_OVF;
                                wrmsrl(wd->cccr_msr, dummy);
                                apic_write(APIC_LVTPC, APIC_DM_NMI);
+                               /* start the cycle over again */
+                               write_watchdog_counter(wd->perfctr_msr, NULL);
                        }
                        else if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
                                 wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
@@ -964,9 +1028,12 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                                 * other P6 variant.
                                 * ArchPerfom/Core Duo also needs this */
                                apic_write(APIC_LVTPC, APIC_DM_NMI);
+                               /* P6/ARCH_PERFMON has 32 bit counter write */
+                               write_watchdog_counter32(wd->perfctr_msr, NULL);
+                       } else {
+                               /* start the cycle over again */
+                               write_watchdog_counter(wd->perfctr_msr, NULL);
                        }
-                       /* start the cycle over again */
-                       write_watchdog_counter(wd->perfctr_msr, NULL);
                        rc = 1;
                } else if (nmi_watchdog == NMI_IO_APIC) {
                        /* don't know how to accurately check for this.
index e55fd05da0f521048c03bf68206f336e1cb6f94f..c156ecfa38727c2133ec4f3994ba8f4f9e82fc9f 100644 (file)
@@ -92,7 +92,7 @@ static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len)
        return insn_len;
 }
 
-static fastcall unsigned long native_get_debugreg(int regno)
+static unsigned long native_get_debugreg(int regno)
 {
        unsigned long val = 0;  /* Damn you, gcc! */
 
@@ -115,7 +115,7 @@ static fastcall unsigned long native_get_debugreg(int regno)
        return val;
 }
 
-static fastcall void native_set_debugreg(int regno, unsigned long value)
+static void native_set_debugreg(int regno, unsigned long value)
 {
        switch (regno) {
        case 0:
@@ -146,55 +146,55 @@ void init_IRQ(void)
        paravirt_ops.init_IRQ();
 }
 
-static fastcall void native_clts(void)
+static void native_clts(void)
 {
        asm volatile ("clts");
 }
 
-static fastcall unsigned long native_read_cr0(void)
+static unsigned long native_read_cr0(void)
 {
        unsigned long val;
        asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
        return val;
 }
 
-static fastcall void native_write_cr0(unsigned long val)
+static void native_write_cr0(unsigned long val)
 {
        asm volatile("movl %0,%%cr0": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr2(void)
+static unsigned long native_read_cr2(void)
 {
        unsigned long val;
        asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
        return val;
 }
 
-static fastcall void native_write_cr2(unsigned long val)
+static void native_write_cr2(unsigned long val)
 {
        asm volatile("movl %0,%%cr2": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr3(void)
+static unsigned long native_read_cr3(void)
 {
        unsigned long val;
        asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
        return val;
 }
 
-static fastcall void native_write_cr3(unsigned long val)
+static void native_write_cr3(unsigned long val)
 {
        asm volatile("movl %0,%%cr3": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr4(void)
+static unsigned long native_read_cr4(void)
 {
        unsigned long val;
        asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
        return val;
 }
 
-static fastcall unsigned long native_read_cr4_safe(void)
+static unsigned long native_read_cr4_safe(void)
 {
        unsigned long val;
        /* This could fault if %cr4 does not exist */
@@ -207,51 +207,51 @@ static fastcall unsigned long native_read_cr4_safe(void)
        return val;
 }
 
-static fastcall void native_write_cr4(unsigned long val)
+static void native_write_cr4(unsigned long val)
 {
        asm volatile("movl %0,%%cr4": :"r" (val));
 }
 
-static fastcall unsigned long native_save_fl(void)
+static unsigned long native_save_fl(void)
 {
        unsigned long f;
        asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
        return f;
 }
 
-static fastcall void native_restore_fl(unsigned long f)
+static void native_restore_fl(unsigned long f)
 {
        asm volatile("pushl %0 ; popfl": /* no output */
                             :"g" (f)
                             :"memory", "cc");
 }
 
-static fastcall void native_irq_disable(void)
+static void native_irq_disable(void)
 {
        asm volatile("cli": : :"memory");
 }
 
-static fastcall void native_irq_enable(void)
+static void native_irq_enable(void)
 {
        asm volatile("sti": : :"memory");
 }
 
-static fastcall void native_safe_halt(void)
+static void native_safe_halt(void)
 {
        asm volatile("sti; hlt": : :"memory");
 }
 
-static fastcall void native_halt(void)
+static void native_halt(void)
 {
        asm volatile("hlt": : :"memory");
 }
 
-static fastcall void native_wbinvd(void)
+static void native_wbinvd(void)
 {
        asm volatile("wbinvd": : :"memory");
 }
 
-static fastcall unsigned long long native_read_msr(unsigned int msr, int *err)
+static unsigned long long native_read_msr(unsigned int msr, int *err)
 {
        unsigned long long val;
 
@@ -270,7 +270,7 @@ static fastcall unsigned long long native_read_msr(unsigned int msr, int *err)
        return val;
 }
 
-static fastcall int native_write_msr(unsigned int msr, unsigned long long val)
+static int native_write_msr(unsigned int msr, unsigned long long val)
 {
        int err;
        asm volatile("2: wrmsr ; xorl %0,%0\n"
@@ -288,53 +288,53 @@ static fastcall int native_write_msr(unsigned int msr, unsigned long long val)
        return err;
 }
 
-static fastcall unsigned long long native_read_tsc(void)
+static unsigned long long native_read_tsc(void)
 {
        unsigned long long val;
        asm volatile("rdtsc" : "=A" (val));
        return val;
 }
 
-static fastcall unsigned long long native_read_pmc(void)
+static unsigned long long native_read_pmc(void)
 {
        unsigned long long val;
        asm volatile("rdpmc" : "=A" (val));
        return val;
 }
 
-static fastcall void native_load_tr_desc(void)
+static void native_load_tr_desc(void)
 {
        asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
 }
 
-static fastcall void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static void native_load_gdt(const struct Xgt_desc_struct *dtr)
 {
        asm volatile("lgdt %0"::"m" (*dtr));
 }
 
-static fastcall void native_load_idt(const struct Xgt_desc_struct *dtr)
+static void native_load_idt(const struct Xgt_desc_struct *dtr)
 {
        asm volatile("lidt %0"::"m" (*dtr));
 }
 
-static fastcall void native_store_gdt(struct Xgt_desc_struct *dtr)
+static void native_store_gdt(struct Xgt_desc_struct *dtr)
 {
        asm ("sgdt %0":"=m" (*dtr));
 }
 
-static fastcall void native_store_idt(struct Xgt_desc_struct *dtr)
+static void native_store_idt(struct Xgt_desc_struct *dtr)
 {
        asm ("sidt %0":"=m" (*dtr));
 }
 
-static fastcall unsigned long native_store_tr(void)
+static unsigned long native_store_tr(void)
 {
        unsigned long tr;
        asm ("str %0":"=r" (tr));
        return tr;
 }
 
-static fastcall void native_load_tls(struct thread_struct *t, unsigned int cpu)
+static void native_load_tls(struct thread_struct *t, unsigned int cpu)
 {
 #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
        C(0); C(1); C(2);
@@ -348,22 +348,22 @@ static inline void native_write_dt_entry(void *dt, int entry, u32 entry_low, u32
        lp[1] = entry_high;
 }
 
-static fastcall void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
        native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
        native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
        native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_load_esp0(struct tss_struct *tss,
+static void native_load_esp0(struct tss_struct *tss,
                                      struct thread_struct *thread)
 {
        tss->esp0 = thread->esp0;
@@ -375,12 +375,12 @@ static fastcall void native_load_esp0(struct tss_struct *tss,
        }
 }
 
-static fastcall void native_io_delay(void)
+static void native_io_delay(void)
 {
        asm volatile("outb %al,$0x80");
 }
 
-static fastcall void native_flush_tlb(void)
+static void native_flush_tlb(void)
 {
        __native_flush_tlb();
 }
@@ -389,49 +389,49 @@ static fastcall void native_flush_tlb(void)
  * Global pages have to be flushed a bit differently. Not a real
  * performance problem because this does not happen often.
  */
-static fastcall void native_flush_tlb_global(void)
+static void native_flush_tlb_global(void)
 {
        __native_flush_tlb_global();
 }
 
-static fastcall void native_flush_tlb_single(u32 addr)
+static void native_flush_tlb_single(u32 addr)
 {
        __native_flush_tlb_single(addr);
 }
 
 #ifndef CONFIG_X86_PAE
-static fastcall void native_set_pte(pte_t *ptep, pte_t pteval)
+static void native_set_pte(pte_t *ptep, pte_t pteval)
 {
        *ptep = pteval;
 }
 
-static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
+static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
 {
        *ptep = pteval;
 }
 
-static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
        *pmdp = pmdval;
 }
 
 #else /* CONFIG_X86_PAE */
 
-static fastcall void native_set_pte(pte_t *ptep, pte_t pte)
+static void native_set_pte(pte_t *ptep, pte_t pte)
 {
        ptep->pte_high = pte.pte_high;
        smp_wmb();
        ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
 {
        ptep->pte_high = pte.pte_high;
        smp_wmb();
        ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+static void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
 {
        ptep->pte_low = 0;
        smp_wmb();
@@ -440,29 +440,29 @@ static fastcall void native_set_pte_present(struct mm_struct *mm, unsigned long
        ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
+static void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
 {
        set_64bit((unsigned long long *)ptep,pte_val(pteval));
 }
 
-static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
        set_64bit((unsigned long long *)pmdp,pmd_val(pmdval));
 }
 
-static fastcall void native_set_pud(pud_t *pudp, pud_t pudval)
+static void native_set_pud(pud_t *pudp, pud_t pudval)
 {
        *pudp = pudval;
 }
 
-static fastcall void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+static void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        ptep->pte_low = 0;
        smp_wmb();
        ptep->pte_high = 0;
 }
 
-static fastcall void native_pmd_clear(pmd_t *pmd)
+static void native_pmd_clear(pmd_t *pmd)
 {
        u32 *tmp = (u32 *)pmd;
        *tmp = 0;
@@ -472,8 +472,8 @@ static fastcall void native_pmd_clear(pmd_t *pmd)
 #endif /* CONFIG_X86_PAE */
 
 /* These are in entry.S */
-extern fastcall void native_iret(void);
-extern fastcall void native_irq_enable_sysexit(void);
+extern void native_iret(void);
+extern void native_irq_enable_sysexit(void);
 
 static int __init print_banner(void)
 {
@@ -482,9 +482,6 @@ static int __init print_banner(void)
 }
 core_initcall(print_banner);
 
-/* We simply declare start_kernel to be the paravirt probe of last resort. */
-paravirt_probe(start_kernel);
-
 struct paravirt_ops paravirt_ops = {
        .name = "bare hardware",
        .paravirt_enabled = 0,
@@ -544,12 +541,21 @@ struct paravirt_ops paravirt_ops = {
        .apic_write = native_apic_write,
        .apic_write_atomic = native_apic_write_atomic,
        .apic_read = native_apic_read,
+       .setup_boot_clock = setup_boot_APIC_clock,
+       .setup_secondary_clock = setup_secondary_APIC_clock,
 #endif
+       .set_lazy_mode = (void *)native_nop,
 
        .flush_tlb_user = native_flush_tlb,
        .flush_tlb_kernel = native_flush_tlb_global,
        .flush_tlb_single = native_flush_tlb_single,
 
+       .alloc_pt = (void *)native_nop,
+       .alloc_pd = (void *)native_nop,
+       .alloc_pd_clone = (void *)native_nop,
+       .release_pt = (void *)native_nop,
+       .release_pd = (void *)native_nop,
+
        .set_pte = native_set_pte,
        .set_pte_at = native_set_pte_at,
        .set_pmd = native_set_pmd,
@@ -565,6 +571,8 @@ struct paravirt_ops paravirt_ops = {
 
        .irq_enable_sysexit = native_irq_enable_sysexit,
        .iret = native_iret,
+
+       .startup_ipi_hook = (void *)native_nop,
 };
 
 /*
diff --git a/arch/i386/kernel/pcspeaker.c b/arch/i386/kernel/pcspeaker.c
new file mode 100644 (file)
index 0000000..bc1f2d3
--- /dev/null
@@ -0,0 +1,20 @@
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static __init int add_pcspkr(void)
+{
+       struct platform_device *pd;
+       int ret;
+
+       pd = platform_device_alloc("pcspkr", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               platform_device_put(pd);
+
+       return ret;
+}
+device_initcall(add_pcspkr);
index c641056233a60a2bffaff12edae8773018019945..bea304d48cdbb8fdc150e9033ad0e53a3961c439 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/ptrace.h>
 #include <linux/random.h>
 #include <linux/personality.h>
+#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -48,6 +49,7 @@
 #include <asm/i387.h>
 #include <asm/desc.h>
 #include <asm/vm86.h>
+#include <asm/idle.h>
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
@@ -80,6 +82,42 @@ void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
 static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+       atomic_notifier_chain_register(&idle_notifier, n);
+}
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+       atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+
+static DEFINE_PER_CPU(volatile unsigned long, idle_state);
+
+void enter_idle(void)
+{
+       /* needs to be atomic w.r.t. interrupts, not against other CPUs */
+       __set_bit(0, &__get_cpu_var(idle_state));
+       atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+}
+
+static void __exit_idle(void)
+{
+       /* needs to be atomic w.r.t. interrupts, not against other CPUs */
+       if (__test_and_clear_bit(0, &__get_cpu_var(idle_state)) == 0)
+               return;
+       atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+}
+
+void exit_idle(void)
+{
+       if (current->pid)
+               return;
+       __exit_idle();
+}
+
 void disable_hlt(void)
 {
        hlt_counter++;
@@ -130,6 +168,7 @@ EXPORT_SYMBOL(default_idle);
  */
 static void poll_idle (void)
 {
+       local_irq_enable();
        cpu_relax();
 }
 
@@ -173,6 +212,7 @@ void cpu_idle(void)
 
        /* endless idle loop with no priority at all */
        while (1) {
+               tick_nohz_stop_sched_tick();
                while (!need_resched()) {
                        void (*idle)(void);
 
@@ -189,8 +229,18 @@ void cpu_idle(void)
                                play_dead();
 
                        __get_cpu_var(irq_stat).idle_timestamp = jiffies;
+
+                       /*
+                        * Idle routines should keep interrupts disabled
+                        * from here on, until they go to idle.
+                        * Otherwise, idle callbacks can misfire.
+                        */
+                       local_irq_disable();
+                       enter_idle();
                        idle();
+                       __exit_idle();
                }
+               tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
@@ -243,7 +293,11 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
-                       __mwait(eax, ecx);
+                       __sti_mwait(eax, ecx);
+               else
+                       local_irq_enable();
+       } else {
+               local_irq_enable();
        }
 }
 
@@ -308,8 +362,8 @@ void show_regs(struct pt_regs * regs)
                regs->eax,regs->ebx,regs->ecx,regs->edx);
        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
                regs->esi, regs->edi, regs->ebp);
-       printk(" DS: %04x ES: %04x GS: %04x\n",
-              0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
+       printk(" DS: %04x ES: %04x FS: %04x\n",
+              0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs);
 
        cr0 = read_cr0();
        cr2 = read_cr2();
@@ -340,7 +394,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 
        regs.xds = __USER_DS;
        regs.xes = __USER_DS;
-       regs.xgs = __KERNEL_PDA;
+       regs.xfs = __KERNEL_PDA;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
        regs.xcs = __KERNEL_CS | get_kernel_rpl();
@@ -425,7 +479,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 
        p->thread.eip = (unsigned long) ret_from_fork;
 
-       savesegment(fs,p->thread.fs);
+       savesegment(gs,p->thread.gs);
 
        tsk = current;
        if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
@@ -501,8 +555,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        dump->regs.eax = regs->eax;
        dump->regs.ds = regs->xds;
        dump->regs.es = regs->xes;
-       savesegment(fs,dump->regs.fs);
-       dump->regs.gs = regs->xgs;
+       dump->regs.fs = regs->xfs;
+       savesegment(gs,dump->regs.gs);
        dump->regs.orig_eax = regs->orig_eax;
        dump->regs.eip = regs->eip;
        dump->regs.cs = regs->xcs;
@@ -653,7 +707,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        load_esp0(tss, next);
 
        /*
-        * Save away %fs. No need to save %gs, as it was saved on the
+        * Save away %gs. No need to save %fs, as it was saved on the
         * stack on entry.  No need to save %es and %ds, as those are
         * always kernel segments while inside the kernel.  Doing this
         * before setting the new TLS descriptors avoids the situation
@@ -662,7 +716,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
         * used %fs or %gs (it does not today), or if the kernel is
         * running inside of a hypervisor layer.
         */
-       savesegment(fs, prev->fs);
+       savesegment(gs, prev->gs);
 
        /*
         * Load the per-thread Thread-Local Storage descriptor.
@@ -670,14 +724,13 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        load_TLS(next, cpu);
 
        /*
-        * Restore %fs if needed.
-        *
-        * Glibc normally makes %fs be zero.
+        * Restore IOPL if needed.  In normal use, the flags restore
+        * in the switch assembly will handle this.  But if the kernel
+        * is running virtualized at a non-zero CPL, the popf will
+        * not restore flags, so it must be done in a separate step.
         */
-       if (unlikely(prev->fs | next->fs))
-               loadsegment(fs, next->fs);
-
-       write_pda(pcurrent, next_p);
+       if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
+               set_iopl_mask(next->iopl);
 
        /*
         * Now maybe handle debug registers and/or IO bitmaps
@@ -688,6 +741,15 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 
        disable_tsc(prev_p, next_p);
 
+       /*
+        * Leave lazy mode, flushing any hypercalls made here.
+        * This must be done before restoring TLS segments so
+        * the GDT and LDT are properly updated, and must be
+        * done before math_state_restore, so the TS bit is up
+        * to date.
+        */
+       arch_leave_lazy_cpu_mode();
+
        /* If the task has used fpu the last 5 timeslices, just do a full
         * restore of the math state immediately to avoid the trap; the
         * chances of needing FPU soon are obviously high now
@@ -695,6 +757,14 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        if (next_p->fpu_counter > 5)
                math_state_restore();
 
+       /*
+        * Restore %gs if needed (which is common)
+        */
+       if (prev->gs | next->gs)
+               loadsegment(gs, next->gs);
+
+       write_pda(pcurrent, next_p);
+
        return prev_p;
 }
 
index af8aabe8580034970071a8ddb57630fbc619ace9..4a8f8a2597233d06316afa6463d9e1eabdd9592e 100644 (file)
@@ -89,14 +89,14 @@ static int putreg(struct task_struct *child,
        unsigned long regno, unsigned long value)
 {
        switch (regno >> 2) {
-               case FS:
+               case GS:
                        if (value && (value & 3) != 3)
                                return -EIO;
-                       child->thread.fs = value;
+                       child->thread.gs = value;
                        return 0;
                case DS:
                case ES:
-               case GS:
+               case FS:
                        if (value && (value & 3) != 3)
                                return -EIO;
                        value &= 0xffff;
@@ -112,7 +112,7 @@ static int putreg(struct task_struct *child,
                        value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
                        break;
        }
-       if (regno > ES*4)
+       if (regno > FS*4)
                regno -= 1*4;
        put_stack_long(child, regno, value);
        return 0;
@@ -124,18 +124,18 @@ static unsigned long getreg(struct task_struct *child,
        unsigned long retval = ~0UL;
 
        switch (regno >> 2) {
-               case FS:
-                       retval = child->thread.fs;
+               case GS:
+                       retval = child->thread.gs;
                        break;
                case DS:
                case ES:
-               case GS:
+               case FS:
                case SS:
                case CS:
                        retval = 0xffff;
                        /* fall through */
                default:
-                       if (regno > ES*4)
+                       if (regno > FS*4)
                                regno -= 1*4;
                        retval &= get_stack_long(child, regno);
        }
index 4694ac980cd201c2b53bea98ae03299b816bc999..122623dcc6e1bc94543f0d343d0fe4a19e90cef7 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/mca.h>
 #include <linux/root_dev.h>
@@ -60,6 +59,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
+#include <asm/vmi.h>
 #include <setup_arch.h>
 #include <bios_ebda.h>
 
@@ -581,6 +581,14 @@ void __init setup_arch(char **cmdline_p)
 
        max_low_pfn = setup_memory();
 
+#ifdef CONFIG_VMI
+       /*
+        * Must be after max_low_pfn is determined, and before kernel
+        * pagetables are setup.
+        */
+       vmi_init();
+#endif
+
        /*
         * NOTE: before this point _nobody_ is allowed to allocate
         * any memory using the bootmem allocator.  Although the
@@ -651,28 +659,3 @@ void __init setup_arch(char **cmdline_p)
 #endif
        tsc_init();
 }
-
-static __init int add_pcspkr(void)
-{
-       struct platform_device *pd;
-       int ret;
-
-       pd = platform_device_alloc("pcspkr", -1);
-       if (!pd)
-               return -ENOMEM;
-
-       ret = platform_device_add(pd);
-       if (ret)
-               platform_device_put(pd);
-
-       return ret;
-}
-device_initcall(add_pcspkr);
-
-/*
- * Local Variables:
- * mode:c
- * c-file-style:"k&r"
- * c-basic-offset:8
- * End:
- */
index 65d7620eaa093756e083ed5d0f9786ccfc1bd917..4f99e870c986f41b72168b3dd44fbfc1e075bbe6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
+#include <linux/binfmts.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -128,8 +129,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
                         X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
                         X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
 
-       COPY_SEG(gs);
-       GET_SEG(fs);
+       GET_SEG(gs);
+       COPY_SEG(fs);
        COPY_SEG(es);
        COPY_SEG(ds);
        COPY(edi);
@@ -244,9 +245,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
 {
        int tmp, err = 0;
 
-       err |= __put_user(regs->xgs, (unsigned int __user *)&sc->gs);
-       savesegment(fs, tmp);
-       err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
+       err |= __put_user(regs->xfs, (unsigned int __user *)&sc->fs);
+       savesegment(gs, tmp);
+       err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
 
        err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
        err |= __put_user(regs->xds, (unsigned int __user *)&sc->ds);
@@ -349,7 +350,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
                        goto give_sigsegv;
        }
 
-       restorer = (void *)VDSO_SYM(&__kernel_sigreturn);
+       if (current->binfmt->hasvdso)
+               restorer = (void *)VDSO_SYM(&__kernel_sigreturn);
+       else
+               restorer = (void *)&frame->retcode;
        if (ka->sa.sa_flags & SA_RESTORER)
                restorer = ka->sa.sa_restorer;
 
index 5285aff8367fec481d33a7ed94c0278815202286..9bd9637ae692fb731e08c836b562b5ad069eecb3 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
+#include <asm/idle.h>
 #include <mach_apic.h>
 
 /*
@@ -374,8 +375,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
        /*
         * i'm not happy about this global shared spinlock in the
         * MM hot path, but we'll see how contended it is.
-        * Temporarily this turns IRQs off, so that lockups are
-        * detected by the NMI watchdog.
+        * AK: x86-64 has a faster method that could be ported.
         */
        spin_lock(&tlbstate_lock);
        
@@ -400,7 +400,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
 
        while (!cpus_empty(flush_cpumask))
                /* nothing. lockup detection does not belong here */
-               mb();
+               cpu_relax();
 
        flush_mm = NULL;
        flush_va = 0;
@@ -624,6 +624,7 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
        /*
         * At this point the info structure may be out of scope unless wait==1
         */
+       exit_idle();
        irq_enter();
        (*func)(info);
        irq_exit();
index 8c6c8c52b95c0b574b837c279f84647d3b4ba867..48bfcaa13ecca45c79503f791814c75ed4a5ba54 100644 (file)
@@ -63,6 +63,7 @@
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
+#include <asm/vmi.h>
 
 /* Set if we find a B stepping CPU */
 static int __devinitdata smp_b_stepping;
@@ -93,12 +94,6 @@ cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
-/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
- * is no way to resync one AP against BP. TBD: for prescott and above, we
- * should use IA64's algorithm
- */
-static int __devinitdata tsc_sync_disabled;
-
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 EXPORT_SYMBOL(cpu_data);
@@ -215,151 +210,6 @@ valid_k7:
        ;
 }
 
-/*
- * TSC synchronization.
- *
- * We first check whether all CPUs have their TSC's synchronized,
- * then we print a warning if not, and always resync.
- */
-
-static struct {
-       atomic_t start_flag;
-       atomic_t count_start;
-       atomic_t count_stop;
-       unsigned long long values[NR_CPUS];
-} tsc __cpuinitdata = {
-       .start_flag = ATOMIC_INIT(0),
-       .count_start = ATOMIC_INIT(0),
-       .count_stop = ATOMIC_INIT(0),
-};
-
-#define NR_LOOPS 5
-
-static void __init synchronize_tsc_bp(void)
-{
-       int i;
-       unsigned long long t0;
-       unsigned long long sum, avg;
-       long long delta;
-       unsigned int one_usec;
-       int buggy = 0;
-
-       printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
-
-       /* convert from kcyc/sec to cyc/usec */
-       one_usec = cpu_khz / 1000;
-
-       atomic_set(&tsc.start_flag, 1);
-       wmb();
-
-       /*
-        * We loop a few times to get a primed instruction cache,
-        * then the last pass is more or less synchronized and
-        * the BP and APs set their cycle counters to zero all at
-        * once. This reduces the chance of having random offsets
-        * between the processors, and guarantees that the maximum
-        * delay between the cycle counters is never bigger than
-        * the latency of information-passing (cachelines) between
-        * two CPUs.
-        */
-       for (i = 0; i < NR_LOOPS; i++) {
-               /*
-                * all APs synchronize but they loop on '== num_cpus'
-                */
-               while (atomic_read(&tsc.count_start) != num_booting_cpus()-1)
-                       cpu_relax();
-               atomic_set(&tsc.count_stop, 0);
-               wmb();
-               /*
-                * this lets the APs save their current TSC:
-                */
-               atomic_inc(&tsc.count_start);
-
-               rdtscll(tsc.values[smp_processor_id()]);
-               /*
-                * We clear the TSC in the last loop:
-                */
-               if (i == NR_LOOPS-1)
-                       write_tsc(0, 0);
-
-               /*
-                * Wait for all APs to leave the synchronization point:
-                */
-               while (atomic_read(&tsc.count_stop) != num_booting_cpus()-1)
-                       cpu_relax();
-               atomic_set(&tsc.count_start, 0);
-               wmb();
-               atomic_inc(&tsc.count_stop);
-       }
-
-       sum = 0;
-       for (i = 0; i < NR_CPUS; i++) {
-               if (cpu_isset(i, cpu_callout_map)) {
-                       t0 = tsc.values[i];
-                       sum += t0;
-               }
-       }
-       avg = sum;
-       do_div(avg, num_booting_cpus());
-
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_isset(i, cpu_callout_map))
-                       continue;
-               delta = tsc.values[i] - avg;
-               if (delta < 0)
-                       delta = -delta;
-               /*
-                * We report bigger than 2 microseconds clock differences.
-                */
-               if (delta > 2*one_usec) {
-                       long long realdelta;
-
-                       if (!buggy) {
-                               buggy = 1;
-                               printk("\n");
-                       }
-                       realdelta = delta;
-                       do_div(realdelta, one_usec);
-                       if (tsc.values[i] < avg)
-                               realdelta = -realdelta;
-
-                       if (realdelta)
-                               printk(KERN_INFO "CPU#%d had %Ld usecs TSC "
-                                       "skew, fixed it up.\n", i, realdelta);
-               }
-       }
-       if (!buggy)
-               printk("passed.\n");
-}
-
-static void __cpuinit synchronize_tsc_ap(void)
-{
-       int i;
-
-       /*
-        * Not every cpu is online at the time
-        * this gets called, so we first wait for the BP to
-        * finish SMP initialization:
-        */
-       while (!atomic_read(&tsc.start_flag))
-               cpu_relax();
-
-       for (i = 0; i < NR_LOOPS; i++) {
-               atomic_inc(&tsc.count_start);
-               while (atomic_read(&tsc.count_start) != num_booting_cpus())
-                       cpu_relax();
-
-               rdtscll(tsc.values[smp_processor_id()]);
-               if (i == NR_LOOPS-1)
-                       write_tsc(0, 0);
-
-               atomic_inc(&tsc.count_stop);
-               while (atomic_read(&tsc.count_stop) != num_booting_cpus())
-                       cpu_relax();
-       }
-}
-#undef NR_LOOPS
-
 extern void calibrate_delay(void);
 
 static atomic_t init_deasserted;
@@ -437,20 +287,12 @@ static void __cpuinit smp_callin(void)
        /*
         * Save our processor parameters
         */
-       smp_store_cpu_info(cpuid);
-
-       disable_APIC_timer();
+       smp_store_cpu_info(cpuid);
 
        /*
         * Allow the master to continue.
         */
        cpu_set(cpuid, cpu_callin_map);
-
-       /*
-        *      Synchronize the TSC with the BP
-        */
-       if (cpu_has_tsc && cpu_khz && !tsc_sync_disabled)
-               synchronize_tsc_ap();
 }
 
 static int cpucount;
@@ -545,18 +387,25 @@ static void __cpuinit start_secondary(void *unused)
         * booting is too fragile that we want to limit the
         * things done here to the most necessary things.
         */
+#ifdef CONFIG_VMI
+       vmi_bringup();
+#endif
        secondary_cpu_init();
        preempt_disable();
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
                rep_nop();
-       setup_secondary_APIC_clock();
+       /*
+        * Check TSC synchronization with the BP:
+        */
+       check_tsc_sync_target();
+
+       setup_secondary_clock();
        if (nmi_watchdog == NMI_IO_APIC) {
                disable_8259A_irq(0);
                enable_NMI_through_LVT0(NULL);
                enable_8259A_irq(0);
        }
-       enable_APIC_timer();
        /*
         * low-memory mappings have been cleared, flush them from
         * the local TLBs too.
@@ -619,7 +468,6 @@ extern struct {
        unsigned short ss;
 } stack_start;
 extern struct i386_pda *start_pda;
-extern struct Xgt_desc_struct cpu_gdt_descr;
 
 #ifdef CONFIG_NUMA
 
@@ -749,7 +597,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
        /*
         * Due to the Pentium erratum 3AP.
         */
-       maxlvt = get_maxlvt();
+       maxlvt = lapic_get_maxlvt();
        if (maxlvt > 3) {
                apic_read_around(APIC_SPIV);
                apic_write(APIC_ESR, 0);
@@ -834,12 +682,19 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
        else
                num_starts = 0;
 
+       /*
+        * Paravirt / VMI wants a startup IPI hook here to set up the
+        * target processor state.
+        */
+       startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
+                        (unsigned long) stack_start.esp);
+
        /*
         * Run STARTUP IPI loop.
         */
        Dprintk("#startup loops: %d.\n", num_starts);
 
-       maxlvt = get_maxlvt();
+       maxlvt = lapic_get_maxlvt();
 
        for (j = 1; j <= num_starts; j++) {
                Dprintk("Sending STARTUP #%d.\n",j);
@@ -1115,8 +970,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
        info.cpu = cpu;
        INIT_WORK(&info.task, do_warm_boot_cpu);
 
-       tsc_sync_disabled = 1;
-
        /* init low mem mapping */
        clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
                        min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
@@ -1124,7 +977,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
        schedule_work(&info.task);
        wait_for_completion(&done);
 
-       tsc_sync_disabled = 0;
        zap_low_mappings();
        ret = 0;
 exit:
@@ -1320,13 +1172,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 
        smpboot_setup_io_apic();
 
-       setup_boot_APIC_clock();
-
-       /*
-        * Synchronize the TSC with the AP
-        */
-       if (cpu_has_tsc && cpucount && cpu_khz)
-               synchronize_tsc_bp();
+       setup_boot_clock();
 }
 
 /* These are wrappers to interface to the new boot process.  Someone
@@ -1461,9 +1307,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
        }
 
        local_irq_enable();
+
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
        /* Unleash the CPU! */
        cpu_set(cpu, smp_commenced_mask);
+
+       /*
+        * Check TSC synchronization with the AP:
+        */
+       check_tsc_sync_source(cpu);
+
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
 
index bc882a2b1db6f4fda8f80976d968ae48e804f0e8..13ca54a85a1ca2220e1f521441307e7d558946b7 100644 (file)
@@ -78,7 +78,7 @@ int __init sysenter_setup(void)
        syscall_pages[0] = virt_to_page(syscall_page);
 
 #ifdef CONFIG_COMPAT_VDSO
-       __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
+       __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY_EXEC);
        printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
 #endif
 
index c505b16c099038381efc87791d37e49c0aeb158c..a5350059557a6541c0c96b8f8ba6933073999d05 100644 (file)
@@ -131,15 +131,13 @@ unsigned long profile_pc(struct pt_regs *regs)
        unsigned long pc = instruction_pointer(regs);
 
 #ifdef CONFIG_SMP
-       if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+       if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs) &&
+           in_lock_functions(pc)) {
 #ifdef CONFIG_FRAME_POINTER
                return *(unsigned long *)(regs->ebp + 4);
 #else
-               unsigned long *sp;
-               if ((regs->xcs & 3) == 0)
-                       sp = (unsigned long *)&regs->esp;
-               else
-                       sp = (unsigned long *)regs->esp;
+               unsigned long *sp = (unsigned long *)&regs->esp;
+
                /* Return address is either directly at stack pointer
                   or above a saved eflags. Eflags has bits 22-31 zero,
                   kernel addresses don't. */
@@ -161,15 +159,6 @@ EXPORT_SYMBOL(profile_pc);
  */
 irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-       /*
-        * Here we are in the timer irq handler. We just have irqs locally
-        * disabled but we don't know if the timer_bh is running on the other
-        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-        * the irq version of write_lock because as just said we have irq
-        * locally disabled. -arca
-        */
-       write_seqlock(&xtime_lock);
-
 #ifdef CONFIG_X86_IO_APIC
        if (timer_ack) {
                /*
@@ -188,7 +177,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
 
        do_timer_interrupt_hook();
 
-
        if (MCA_bus) {
                /* The PS/2 uses level-triggered interrupts.  You can't
                turn them off, nor would you want to (any attempt to
@@ -203,18 +191,11 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
                outb_p( irq_v|0x80, 0x61 );     /* reset the IRQ */
        }
 
-       write_sequnlock(&xtime_lock);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-       if (using_apic_timer)
-               smp_send_timer_broadcast_ipi();
-#endif
-
        return IRQ_HANDLED;
 }
 
 /* not static: needed by APM */
-unsigned long get_cmos_time(void)
+unsigned long read_persistent_clock(void)
 {
        unsigned long retval;
        unsigned long flags;
@@ -227,11 +208,11 @@ unsigned long get_cmos_time(void)
 
        return retval;
 }
-EXPORT_SYMBOL(get_cmos_time);
 
 static void sync_cmos_clock(unsigned long dummy);
 
 static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
+int no_sync_cmos_clock;
 
 static void sync_cmos_clock(unsigned long dummy)
 {
@@ -275,117 +256,20 @@ static void sync_cmos_clock(unsigned long dummy)
 
 void notify_arch_cmos_timer(void)
 {
-       mod_timer(&sync_cmos_timer, jiffies + 1);
-}
-
-static long clock_cmos_diff;
-static unsigned long sleep_start;
-
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
-       /*
-        * Estimate time zone so that set_time can update the clock
-        */
-       unsigned long ctime =  get_cmos_time();
-
-       clock_cmos_diff = -ctime;
-       clock_cmos_diff += get_seconds();
-       sleep_start = ctime;
-       return 0;
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-       unsigned long flags;
-       unsigned long sec;
-       unsigned long ctime = get_cmos_time();
-       long sleep_length = (ctime - sleep_start) * HZ;
-       struct timespec ts;
-
-       if (sleep_length < 0) {
-               printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
-               /* The time after the resume must not be earlier than the time
-                * before the suspend or some nasty things will happen
-                */
-               sleep_length = 0;
-               ctime = sleep_start;
-       }
-#ifdef CONFIG_HPET_TIMER
-       if (is_hpet_enabled())
-               hpet_reenable();
-#endif
-       setup_pit_timer();
-
-       sec = ctime + clock_cmos_diff;
-       ts.tv_sec = sec;
-       ts.tv_nsec = 0;
-       do_settimeofday(&ts);
-       write_seqlock_irqsave(&xtime_lock, flags);
-       jiffies_64 += sleep_length;
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-       touch_softlockup_watchdog();
-       return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
-       .resume = timer_resume,
-       .suspend = timer_suspend,
-       set_kset_name("timer"),
-};
-
-
-/* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_timer = {
-       .id     = 0,
-       .cls    = &timer_sysclass,
-};
-
-static int time_init_device(void)
-{
-       int error = sysdev_class_register(&timer_sysclass);
-       if (!error)
-               error = sysdev_register(&device_timer);
-       return error;
+       if (!no_sync_cmos_clock)
+               mod_timer(&sync_cmos_timer, jiffies + 1);
 }
 
-device_initcall(time_init_device);
-
-#ifdef CONFIG_HPET_TIMER
 extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
 static void __init hpet_time_init(void)
 {
-       struct timespec ts;
-       ts.tv_sec = get_cmos_time();
-       ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-
-       do_settimeofday(&ts);
-
-       if ((hpet_enable() >= 0) && hpet_use_timer) {
-               printk("Using HPET for base-timer\n");
-       }
-
+       if (!hpet_enable())
+               setup_pit_timer();
        do_time_init();
 }
-#endif
 
 void __init time_init(void)
 {
-       struct timespec ts;
-#ifdef CONFIG_HPET_TIMER
-       if (is_hpet_capable()) {
-               /*
-                * HPET initialization needs to do memory-mapped io. So, let
-                * us do a late initialization after mem_init().
-                */
-               late_time_init = hpet_time_init;
-               return;
-       }
-#endif
-       ts.tv_sec = get_cmos_time();
-       ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-
-       do_settimeofday(&ts);
-
-       do_time_init();
+       late_time_init = hpet_time_init;
 }
index 79cf608e14ca16254db381dcba319979047745fc..45782356a618d27432f2b8648ef914d4442771d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/i386/kernel/topology.c - Populate driverfs with topology information
+ * arch/i386/kernel/topology.c - Populate sysfs with topology information
  *
  * Written by: Matthew Dobson, IBM Corporation
  * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
index 0efad8aeb41af86849ac3b8e6b667d6603f4f594..af0d3f70a8174d6b0a3b284dd46495e64c4deb34 100644 (file)
@@ -94,6 +94,7 @@ asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
 int kstack_depth_to_print = 24;
+static unsigned int code_bytes = 64;
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
@@ -291,10 +292,11 @@ void show_registers(struct pt_regs *regs)
        int i;
        int in_kernel = 1;
        unsigned long esp;
-       unsigned short ss;
+       unsigned short ss, gs;
 
        esp = (unsigned long) (&regs->esp);
        savesegment(ss, ss);
+       savesegment(gs, gs);
        if (user_mode_vm(regs)) {
                in_kernel = 0;
                esp = regs->esp;
@@ -313,8 +315,8 @@ void show_registers(struct pt_regs *regs)
                regs->eax, regs->ebx, regs->ecx, regs->edx);
        printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
                regs->esi, regs->edi, regs->ebp, esp);
-       printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
-               regs->xds & 0xffff, regs->xes & 0xffff, ss);
+       printk(KERN_EMERG "ds: %04x   es: %04x   fs: %04x  gs: %04x  ss: %04x\n",
+              regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
        printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
                TASK_COMM_LEN, current->comm, current->pid,
                current_thread_info(), current, current->thread_info);
@@ -324,7 +326,8 @@ void show_registers(struct pt_regs *regs)
         */
        if (in_kernel) {
                u8 *eip;
-               int code_bytes = 64;
+               unsigned int code_prologue = code_bytes * 43 / 64;
+               unsigned int code_len = code_bytes;
                unsigned char c;
 
                printk("\n" KERN_EMERG "Stack: ");
@@ -332,14 +335,14 @@ void show_registers(struct pt_regs *regs)
 
                printk(KERN_EMERG "Code: ");
 
-               eip = (u8 *)regs->eip - 43;
+               eip = (u8 *)regs->eip - code_prologue;
                if (eip < (u8 *)PAGE_OFFSET ||
                        probe_kernel_address(eip, c)) {
                        /* try starting at EIP */
                        eip = (u8 *)regs->eip;
-                       code_bytes = 32;
+                       code_len = code_len - code_prologue + 1;
                }
-               for (i = 0; i < code_bytes; i++, eip++) {
+               for (i = 0; i < code_len; i++, eip++) {
                        if (eip < (u8 *)PAGE_OFFSET ||
                                probe_kernel_address(eip, c)) {
                                printk(" Bad EIP value.");
@@ -1191,3 +1194,13 @@ static int __init kstack_setup(char *s)
        return 1;
 }
 __setup("kstack=", kstack_setup);
+
+static int __init code_bytes_setup(char *s)
+{
+       code_bytes = simple_strtoul(s, NULL, 0);
+       if (code_bytes > 8192)
+               code_bytes = 8192;
+
+       return 1;
+}
+__setup("code_bytes=", code_bytes_setup);
index 2cfc7b09b925cd8147e7f54aa809ce3f58a592f6..3082a418635c11d6f3cdce2b53d3499a3124c075 100644 (file)
@@ -23,6 +23,7 @@
  * an extra value to store the TSC freq
  */
 unsigned int tsc_khz;
+unsigned long long (*custom_sched_clock)(void);
 
 int tsc_disable;
 
@@ -59,12 +60,6 @@ static inline int check_tsc_unstable(void)
        return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-       tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
-
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -107,14 +102,14 @@ unsigned long long sched_clock(void)
 {
        unsigned long long this_offset;
 
+       if (unlikely(custom_sched_clock))
+               return (*custom_sched_clock)();
+
        /*
-        * in the NUMA case we dont use the TSC as they are not
-        * synchronized across all CPUs.
+        * Fall back to jiffies if there's no TSC available:
         */
-#ifndef CONFIG_NUMA
-       if (!cpu_khz || check_tsc_unstable())
-#endif
-               /* no locking but a rare wrong value is not a big deal */
+       if (unlikely(tsc_disable))
+               /* No locking but a rare wrong value is not a big deal: */
                return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
        /* read the Time Stamp Counter: */
@@ -194,13 +189,13 @@ EXPORT_SYMBOL(recalibrate_cpu_khz);
 void __init tsc_init(void)
 {
        if (!cpu_has_tsc || tsc_disable)
-               return;
+               goto out_no_tsc;
 
        cpu_khz = calculate_cpu_khz();
        tsc_khz = cpu_khz;
 
        if (!cpu_khz)
-               return;
+               goto out_no_tsc;
 
        printk("Detected %lu.%03lu MHz processor.\n",
                                (unsigned long)cpu_khz / 1000,
@@ -208,37 +203,18 @@ void __init tsc_init(void)
 
        set_cyc2ns_scale(cpu_khz);
        use_tsc_delay();
-}
+       return;
 
-#ifdef CONFIG_CPU_FREQ
-
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(struct work_struct *work)
-{
-       unsigned int cpu;
-
-       for_each_online_cpu(cpu)
-               cpufreq_get(cpu);
-
-       cpufreq_delayed_issched = 0;
+out_no_tsc:
+       /*
+        * Set the tsc_disable flag if there's no TSC support, this
+        * makes it a fast flag for the kernel to see whether it
+        * should be using the TSC.
+        */
+       tsc_disable = 1;
 }
 
-/*
- * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries
- * to verify the CPU frequency the timing core thinks the CPU is running
- * at is still correct.
- */
-static inline void cpufreq_delayed_get(void)
-{
-       if (cpufreq_init && !cpufreq_delayed_issched) {
-               cpufreq_delayed_issched = 1;
-               printk(KERN_DEBUG "Checking if CPU frequency changed.\n");
-               schedule_work(&cpufreq_delayed_get_work);
-       }
-}
+#ifdef CONFIG_CPU_FREQ
 
 /*
  * if the CPU frequency is scaled, TSC-based delays will need a different
@@ -303,17 +279,9 @@ static struct notifier_block time_cpufreq_notifier_block = {
 
 static int __init cpufreq_tsc(void)
 {
-       int ret;
-
-       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
-       ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
-       if (!ret)
-               cpufreq_init = 1;
-
-       return ret;
+       return cpufreq_register_notifier(&time_cpufreq_notifier_block,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
 }
-
 core_initcall(cpufreq_tsc);
 
 #endif
@@ -321,7 +289,6 @@ core_initcall(cpufreq_tsc);
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
-static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -339,37 +306,28 @@ static struct clocksource clocksource_tsc = {
        .mask                   = CLOCKSOURCE_MASK(64),
        .mult                   = 0, /* to be set */
        .shift                  = 22,
-       .update_callback        = tsc_update_callback,
-       .is_continuous          = 1,
+       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
+                                 CLOCK_SOURCE_MUST_VERIFY,
 };
 
-static int tsc_update_callback(void)
+void mark_tsc_unstable(void)
 {
-       int change = 0;
-
-       /* check to see if we should switch to the safe clocksource: */
-       if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
-               clocksource_tsc.rating = 0;
-               clocksource_reselect();
-               change = 1;
-       }
-
-       /* only update if tsc_khz has changed: */
-       if (current_tsc_khz != tsc_khz) {
-               current_tsc_khz = tsc_khz;
-               clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
-                                                       clocksource_tsc.shift);
-               change = 1;
+       if (!tsc_unstable) {
+               tsc_unstable = 1;
+               /* Can be called before registration */
+               if (clocksource_tsc.mult)
+                       clocksource_change_rating(&clocksource_tsc, 0);
+               else
+                       clocksource_tsc.rating = 0;
        }
-
-       return change;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
        printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
                       d->ident);
-       mark_tsc_unstable();
+       tsc_unstable = 1;
        return 0;
 }
 
@@ -386,65 +344,44 @@ static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
         {}
 };
 
-#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
-static struct timer_list verify_tsc_freq_timer;
-
-/* XXX - Probably should add locking */
-static void verify_tsc_freq(unsigned long unused)
-{
-       static u64 last_tsc;
-       static unsigned long last_jiffies;
-
-       u64 now_tsc, interval_tsc;
-       unsigned long now_jiffies, interval_jiffies;
-
-
-       if (check_tsc_unstable())
-               return;
-
-       rdtscll(now_tsc);
-       now_jiffies = jiffies;
-
-       if (!last_jiffies) {
-               goto out;
-       }
-
-       interval_jiffies = now_jiffies - last_jiffies;
-       interval_tsc = now_tsc - last_tsc;
-       interval_tsc *= HZ;
-       do_div(interval_tsc, cpu_khz*1000);
-
-       if (interval_tsc < (interval_jiffies * 3 / 4)) {
-               printk("TSC appears to be running slowly. "
-                       "Marking it as unstable\n");
-               mark_tsc_unstable();
-               return;
-       }
-
-out:
-       last_tsc = now_tsc;
-       last_jiffies = now_jiffies;
-       /* set us up to go off on the next interval: */
-       mod_timer(&verify_tsc_freq_timer,
-               jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
-}
-
 /*
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
  */
-static __init int unsynchronized_tsc(void)
+__cpuinit int unsynchronized_tsc(void)
 {
+       if (!cpu_has_tsc || tsc_unstable)
+               return 1;
        /*
         * Intel systems are normally all synchronized.
         * Exceptions must mark TSC as unstable:
         */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-               return 0;
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
+               /* assume multi socket systems are not synchronized: */
+               if (num_possible_cpus() > 1)
+                       tsc_unstable = 1;
+       }
+       return tsc_unstable;
+}
+
+/*
+ * Geode_LX - the OLPC CPU has a possibly a very reliable TSC
+ */
+#ifdef CONFIG_MGEODE_LX
+/* RTSC counts during suspend */
+#define RTSC_SUSP 0x100
+
+static void __init check_geode_tsc_reliable(void)
+{
+       unsigned long val;
 
-       /* assume multi socket systems are not synchronized: */
-       return num_possible_cpus() > 1;
+       rdmsrl(MSR_GEODE_BUSCONT_CONF0, val);
+       if ((val & RTSC_SUSP))
+               clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
 }
+#else
+static inline void check_geode_tsc_reliable(void) { }
+#endif
 
 static int __init init_tsc_clocksource(void)
 {
@@ -453,20 +390,16 @@ static int __init init_tsc_clocksource(void)
                /* check blacklist */
                dmi_check_system(bad_tsc_dmi_table);
 
-               if (unsynchronized_tsc()) /* mark unstable if unsynced */
-                       mark_tsc_unstable();
+               unsynchronized_tsc();
+               check_geode_tsc_reliable();
                current_tsc_khz = tsc_khz;
                clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
                                                        clocksource_tsc.shift);
                /* lower the rating if we already know its unstable: */
-               if (check_tsc_unstable())
+               if (check_tsc_unstable()) {
                        clocksource_tsc.rating = 0;
-
-               init_timer(&verify_tsc_freq_timer);
-               verify_tsc_freq_timer.function = verify_tsc_freq;
-               verify_tsc_freq_timer.expires =
-                       jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL);
-               add_timer(&verify_tsc_freq_timer);
+                       clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
+               }
 
                return clocksource_register(&clocksource_tsc);
        }
diff --git a/arch/i386/kernel/tsc_sync.c b/arch/i386/kernel/tsc_sync.c
new file mode 100644 (file)
index 0000000..1242462
--- /dev/null
@@ -0,0 +1 @@
+#include "../../x86_64/kernel/tsc_sync.c"
index be2f96e67f78d80c51ba6c1b9a5fde49563ff415..d1b8f2b7aea616c1902bfe616071f586c76f5bbd 100644 (file)
@@ -96,12 +96,12 @@ static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
 {
        int ret = 0;
 
-       /* kernel_vm86_regs is missing xfs, so copy everything up to
-          (but not including) xgs, and then rest after xgs. */
-       ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.xgs));
-       ret += copy_to_user(&user->__null_gs, &regs->pt.xgs,
+       /* kernel_vm86_regs is missing xgs, so copy everything up to
+          (but not including) orig_eax, and then rest including orig_eax. */
+       ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.orig_eax));
+       ret += copy_to_user(&user->orig_eax, &regs->pt.orig_eax,
                            sizeof(struct kernel_vm86_regs) -
-                           offsetof(struct kernel_vm86_regs, pt.xgs));
+                           offsetof(struct kernel_vm86_regs, pt.orig_eax));
 
        return ret;
 }
@@ -113,12 +113,13 @@ static int copy_vm86_regs_from_user(struct kernel_vm86_regs *regs,
 {
        int ret = 0;
 
-       ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.xgs));
-       ret += copy_from_user(&regs->pt.xgs, &user->__null_gs,
+       /* copy eax-xfs inclusive */
+       ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.orig_eax));
+       /* copy orig_eax-__gsh+extra */
+       ret += copy_from_user(&regs->pt.orig_eax, &user->orig_eax,
                              sizeof(struct kernel_vm86_regs) -
-                             offsetof(struct kernel_vm86_regs, pt.xgs) +
+                             offsetof(struct kernel_vm86_regs, pt.orig_eax) +
                              extra);
-
        return ret;
 }
 
@@ -157,8 +158,8 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
 
        ret = KVM86->regs32;
 
-       loadsegment(fs, current->thread.saved_fs);
-       ret->xgs = current->thread.saved_gs;
+       ret->xfs = current->thread.saved_fs;
+       loadsegment(gs, current->thread.saved_gs);
 
        return ret;
 }
@@ -285,9 +286,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
  */
        info->regs.pt.xds = 0;
        info->regs.pt.xes = 0;
-       info->regs.pt.xgs = 0;
+       info->regs.pt.xfs = 0;
 
-/* we are clearing fs later just before "jmp resume_userspace",
+/* we are clearing gs later just before "jmp resume_userspace",
  * because it is not saved/restored.
  */
 
@@ -321,8 +322,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
  */
        info->regs32->eax = 0;
        tsk->thread.saved_esp0 = tsk->thread.esp0;
-       savesegment(fs, tsk->thread.saved_fs);
-       tsk->thread.saved_gs = info->regs32->xgs;
+       tsk->thread.saved_fs = info->regs32->xfs;
+       savesegment(gs, tsk->thread.saved_gs);
 
        tss = &per_cpu(init_tss, get_cpu());
        tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -342,7 +343,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        __asm__ __volatile__(
                "movl %0,%%esp\n\t"
                "movl %1,%%ebp\n\t"
-               "mov  %2, %%fs\n\t"
+               "mov  %2, %%gs\n\t"
                "jmp resume_userspace"
                : /* no outputs */
                :"r" (&info->regs), "r" (task_thread_info(tsk)), "r" (0));
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c
new file mode 100644 (file)
index 0000000..bb5a7ab
--- /dev/null
@@ -0,0 +1,949 @@
+/*
+ * VMI specific paravirt-ops implementation
+ *
+ * Copyright (C) 2005, VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to zach@vmware.com
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/license.h>
+#include <linux/cpu.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <asm/vmi.h>
+#include <asm/io.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <asm/apic.h>
+#include <asm/processor.h>
+#include <asm/timer.h>
+#include <asm/vmi_time.h>
+
+/* Convenient for calling VMI functions indirectly in the ROM */
+typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
+typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
+
+#define call_vrom_func(rom,func) \
+   (((VROMFUNC *)(rom->func))())
+
+#define call_vrom_long_func(rom,func,arg) \
+   (((VROMLONGFUNC *)(rom->func)) (arg))
+
+static struct vrom_header *vmi_rom;
+static int license_gplok;
+static int disable_nodelay;
+static int disable_pge;
+static int disable_pse;
+static int disable_sep;
+static int disable_tsc;
+static int disable_mtrr;
+
+/* Cached VMI operations */
+struct {
+       void (*cpuid)(void /* non-c */);
+       void (*_set_ldt)(u32 selector);
+       void (*set_tr)(u32 selector);
+       void (*set_kernel_stack)(u32 selector, u32 esp0);
+       void (*allocate_page)(u32, u32, u32, u32, u32);
+       void (*release_page)(u32, u32);
+       void (*set_pte)(pte_t, pte_t *, unsigned);
+       void (*update_pte)(pte_t *, unsigned);
+       void (*set_linear_mapping)(int, u32, u32, u32);
+       void (*flush_tlb)(int);
+       void (*set_initial_ap_state)(int, int);
+       void (*halt)(void);
+} vmi_ops;
+
+/* XXX move this to alternative.h */
+extern struct paravirt_patch __start_parainstructions[],
+       __stop_parainstructions[];
+
+/*
+ * VMI patching routines.
+ */
+#define MNEM_CALL 0xe8
+#define MNEM_JMP  0xe9
+#define MNEM_RET  0xc3
+
+static char irq_save_disable_callout[] = {
+       MNEM_CALL, 0, 0, 0, 0,
+       MNEM_CALL, 0, 0, 0, 0,
+       MNEM_RET
+};
+#define IRQ_PATCH_INT_MASK 0
+#define IRQ_PATCH_DISABLE  5
+
+static inline void patch_offset(unsigned char *eip, unsigned char *dest)
+{
+        *(unsigned long *)(eip+1) = dest-eip-5;
+}
+
+static unsigned patch_internal(int call, unsigned len, void *insns)
+{
+       u64 reloc;
+       struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc;
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, call);
+       switch(rel->type) {
+               case VMI_RELOCATION_CALL_REL:
+                       BUG_ON(len < 5);
+                       *(char *)insns = MNEM_CALL;
+                       patch_offset(insns, rel->eip);
+                       return 5;
+
+               case VMI_RELOCATION_JUMP_REL:
+                       BUG_ON(len < 5);
+                       *(char *)insns = MNEM_JMP;
+                       patch_offset(insns, rel->eip);
+                       return 5;
+
+               case VMI_RELOCATION_NOP:
+                       /* obliterate the whole thing */
+                       return 0;
+
+               case VMI_RELOCATION_NONE:
+                       /* leave native code in place */
+                       break;
+
+               default:
+                       BUG();
+       }
+       return len;
+}
+
+/*
+ * Apply patch if appropriate, return length of new instruction
+ * sequence.  The callee does nop padding for us.
+ */
+static unsigned vmi_patch(u8 type, u16 clobbers, void *insns, unsigned len)
+{
+       switch (type) {
+               case PARAVIRT_IRQ_DISABLE:
+                       return patch_internal(VMI_CALL_DisableInterrupts, len, insns);
+               case PARAVIRT_IRQ_ENABLE:
+                       return patch_internal(VMI_CALL_EnableInterrupts, len, insns);
+               case PARAVIRT_RESTORE_FLAGS:
+                       return patch_internal(VMI_CALL_SetInterruptMask, len, insns);
+               case PARAVIRT_SAVE_FLAGS:
+                       return patch_internal(VMI_CALL_GetInterruptMask, len, insns);
+               case PARAVIRT_SAVE_FLAGS_IRQ_DISABLE:
+                       if (len >= 10) {
+                               patch_internal(VMI_CALL_GetInterruptMask, len, insns);
+                               patch_internal(VMI_CALL_DisableInterrupts, len-5, insns+5);
+                               return 10;
+                       } else {
+                               /*
+                                * You bastards didn't leave enough room to
+                                * patch save_flags_irq_disable inline.  Patch
+                                * to a helper
+                                */
+                               BUG_ON(len < 5);
+                               *(char *)insns = MNEM_CALL;
+                               patch_offset(insns, irq_save_disable_callout);
+                               return 5;
+                       }
+               case PARAVIRT_INTERRUPT_RETURN:
+                       return patch_internal(VMI_CALL_IRET, len, insns);
+               case PARAVIRT_STI_SYSEXIT:
+                       return patch_internal(VMI_CALL_SYSEXIT, len, insns);
+               default:
+                       break;
+       }
+       return len;
+}
+
+/* CPUID has non-C semantics, and paravirt-ops API doesn't match hardware ISA */
+static void vmi_cpuid(unsigned int *eax, unsigned int *ebx,
+                               unsigned int *ecx, unsigned int *edx)
+{
+       int override = 0;
+       if (*eax == 1)
+               override = 1;
+        asm volatile ("call *%6"
+                      : "=a" (*eax),
+                        "=b" (*ebx),
+                        "=c" (*ecx),
+                        "=d" (*edx)
+                      : "0" (*eax), "2" (*ecx), "r" (vmi_ops.cpuid));
+       if (override) {
+               if (disable_pse)
+                       *edx &= ~X86_FEATURE_PSE;
+               if (disable_pge)
+                       *edx &= ~X86_FEATURE_PGE;
+               if (disable_sep)
+                       *edx &= ~X86_FEATURE_SEP;
+               if (disable_tsc)
+                       *edx &= ~X86_FEATURE_TSC;
+               if (disable_mtrr)
+                       *edx &= ~X86_FEATURE_MTRR;
+       }
+}
+
+static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
+{
+       if (gdt[nr].a != new->a || gdt[nr].b != new->b)
+               write_gdt_entry(gdt, nr, new->a, new->b);
+}
+
+static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+       struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0]);
+       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1]);
+       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2]);
+}
+
+static void vmi_set_ldt(const void *addr, unsigned entries)
+{
+       unsigned cpu = smp_processor_id();
+       u32 low, high;
+
+       pack_descriptor(&low, &high, (unsigned long)addr,
+                       entries * sizeof(struct desc_struct) - 1,
+                       DESCTYPE_LDT, 0);
+       write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, low, high);
+       vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
+}
+
+static void vmi_set_tr(void)
+{
+       vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
+}
+
+static void vmi_load_esp0(struct tss_struct *tss,
+                                  struct thread_struct *thread)
+{
+       tss->esp0 = thread->esp0;
+
+       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
+       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+               tss->ss1 = thread->sysenter_cs;
+               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+       }
+       vmi_ops.set_kernel_stack(__KERNEL_DS, tss->esp0);
+}
+
+static void vmi_flush_tlb_user(void)
+{
+       vmi_ops.flush_tlb(VMI_FLUSH_TLB);
+}
+
+static void vmi_flush_tlb_kernel(void)
+{
+       vmi_ops.flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
+}
+
+/* Stub to do nothing at all; used for delays and unimplemented calls */
+static void vmi_nop(void)
+{
+}
+
+/* For NO_IDLE_HZ, we stop the clock when halting the kernel */
+#ifdef CONFIG_NO_IDLE_HZ
+static fastcall void vmi_safe_halt(void)
+{
+       int idle = vmi_stop_hz_timer();
+       vmi_ops.halt();
+       if (idle) {
+               local_irq_disable();
+               vmi_account_time_restart_hz_timer();
+               local_irq_enable();
+       }
+}
+#endif
+
+#ifdef CONFIG_DEBUG_PAGE_TYPE
+
+#ifdef CONFIG_X86_PAE
+#define MAX_BOOT_PTS (2048+4+1)
+#else
+#define MAX_BOOT_PTS (1024+1)
+#endif
+
+/*
+ * During boot, mem_map is not yet available in paging_init, so stash
+ * all the boot page allocations here.
+ */
+static struct {
+       u32 pfn;
+       int type;
+} boot_page_allocations[MAX_BOOT_PTS];
+static int num_boot_page_allocations;
+static int boot_allocations_applied;
+
+void vmi_apply_boot_page_allocations(void)
+{
+       int i;
+       BUG_ON(!mem_map);
+       for (i = 0; i < num_boot_page_allocations; i++) {
+               struct page *page = pfn_to_page(boot_page_allocations[i].pfn);
+               page->type = boot_page_allocations[i].type;
+               page->type = boot_page_allocations[i].type &
+                               ~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+       }
+       boot_allocations_applied = 1;
+}
+
+static void record_page_type(u32 pfn, int type)
+{
+       BUG_ON(num_boot_page_allocations >= MAX_BOOT_PTS);
+       boot_page_allocations[num_boot_page_allocations].pfn = pfn;
+       boot_page_allocations[num_boot_page_allocations].type = type;
+       num_boot_page_allocations++;
+}
+
+static void check_zeroed_page(u32 pfn, int type, struct page *page)
+{
+       u32 *ptr;
+       int i;
+       int limit = PAGE_SIZE / sizeof(int);
+
+       if (page_address(page))
+               ptr = (u32 *)page_address(page);
+       else
+               ptr = (u32 *)__va(pfn << PAGE_SHIFT);
+       /*
+        * When cloning the root in non-PAE mode, only the userspace
+        * pdes need to be zeroed.
+        */
+       if (type & VMI_PAGE_CLONE)
+               limit = USER_PTRS_PER_PGD;
+       for (i = 0; i < limit; i++)
+               BUG_ON(ptr[i]);
+}
+
+/*
+ * We stash the page type into struct page so we can verify the page
+ * types are used properly.
+ */
+static void vmi_set_page_type(u32 pfn, int type)
+{
+       /* PAE can have multiple roots per page - don't track */
+       if (PTRS_PER_PMD > 1 && (type & VMI_PAGE_PDP))
+               return;
+
+       if (boot_allocations_applied) {
+               struct page *page = pfn_to_page(pfn);
+               if (type != VMI_PAGE_NORMAL)
+                       BUG_ON(page->type);
+               else
+                       BUG_ON(page->type == VMI_PAGE_NORMAL);
+               page->type = type & ~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+               if (type & VMI_PAGE_ZEROED)
+                       check_zeroed_page(pfn, type, page);
+       } else {
+               record_page_type(pfn, type);
+       }
+}
+
+static void vmi_check_page_type(u32 pfn, int type)
+{
+       /* PAE can have multiple roots per page - skip checks */
+       if (PTRS_PER_PMD > 1 && (type & VMI_PAGE_PDP))
+               return;
+
+       type &= ~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+       if (boot_allocations_applied) {
+               struct page *page = pfn_to_page(pfn);
+               BUG_ON((page->type ^ type) & VMI_PAGE_PAE);
+               BUG_ON(type == VMI_PAGE_NORMAL && page->type);
+               BUG_ON((type & page->type) == 0);
+       }
+}
+#else
+#define vmi_set_page_type(p,t) do { } while (0)
+#define vmi_check_page_type(p,t) do { } while (0)
+#endif
+
+static void vmi_allocate_pt(u32 pfn)
+{
+       vmi_set_page_type(pfn, VMI_PAGE_L1);
+       vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
+}
+
+static void vmi_allocate_pd(u32 pfn)
+{
+       /*
+        * This call comes in very early, before mem_map is setup.
+        * It is called only for swapper_pg_dir, which already has
+        * data on it.
+        */
+       vmi_set_page_type(pfn, VMI_PAGE_L2);
+       vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
+}
+
+static void vmi_allocate_pd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
+{
+       vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
+       vmi_check_page_type(clonepfn, VMI_PAGE_L2);
+       vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
+}
+
+static void vmi_release_pt(u32 pfn)
+{
+       vmi_ops.release_page(pfn, VMI_PAGE_L1);
+       vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+}
+
+static void vmi_release_pd(u32 pfn)
+{
+       vmi_ops.release_page(pfn, VMI_PAGE_L2);
+       vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+}
+
+/*
+ * Helper macros for MMU update flags.  We can defer updates until a flush
+ * or page invalidation only if the update is to the current address space
+ * (otherwise, there is no flush).  We must check against init_mm, since
+ * this could be a kernel update, which usually passes init_mm, although
+ * sometimes this check can be skipped if we know the particular function
+ * is only called on user mode PTEs.  We could change the kernel to pass
+ * current->active_mm here, but in particular, I was unsure if changing
+ * mm/highmem.c to do this would still be correct on other architectures.
+ */
+#define is_current_as(mm, mustbeuser) ((mm) == current->active_mm ||    \
+                                       (!mustbeuser && (mm) == &init_mm))
+#define vmi_flags_addr(mm, addr, level, user)                           \
+        ((level) | (is_current_as(mm, user) ?                           \
+                (VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
+#define vmi_flags_addr_defer(mm, addr, level, user)                     \
+        ((level) | (is_current_as(mm, user) ?                           \
+                (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
+
+static void vmi_update_pte(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+       vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_update_pte_defer(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+       vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_set_pte(pte_t *ptep, pte_t pte)
+{
+       /* XXX because of set_pmd_pte, this can be called on PT or PD layers */
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE | VMI_PAGE_PD);
+       vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
+}
+
+static void vmi_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+{
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+       vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+#ifdef CONFIG_X86_PAE
+       const pte_t pte = { pmdval.pmd, pmdval.pmd >> 32 };
+       vmi_check_page_type(__pa(pmdp) >> PAGE_SHIFT, VMI_PAGE_PMD);
+#else
+       const pte_t pte = { pmdval.pud.pgd.pgd };
+       vmi_check_page_type(__pa(pmdp) >> PAGE_SHIFT, VMI_PAGE_PGD);
+#endif
+       vmi_ops.set_pte(pte, (pte_t *)pmdp, VMI_PAGE_PD);
+}
+
+#ifdef CONFIG_X86_PAE
+
+static void vmi_set_pte_atomic(pte_t *ptep, pte_t pteval)
+{
+       /*
+        * XXX This is called from set_pmd_pte, but at both PT
+        * and PD layers so the VMI_PAGE_PT flag is wrong.  But
+        * it is only called for large page mapping changes,
+        * the Xen backend, doesn't support large pages, and the
+        * ESX backend doesn't depend on the flag.
+        */
+       set_64bit((unsigned long long *)ptep,pte_val(pteval));
+       vmi_ops.update_pte(ptep, VMI_PAGE_PT);
+}
+
+static void vmi_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+       vmi_ops.set_pte(pte, ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 1));
+}
+
+static void vmi_set_pud(pud_t *pudp, pud_t pudval)
+{
+       /* Um, eww */
+       const pte_t pte = { pudval.pgd.pgd, pudval.pgd.pgd >> 32 };
+       vmi_check_page_type(__pa(pudp) >> PAGE_SHIFT, VMI_PAGE_PGD);
+       vmi_ops.set_pte(pte, (pte_t *)pudp, VMI_PAGE_PDP);
+}
+
+static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       const pte_t pte = { 0 };
+       vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+       vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+void vmi_pmd_clear(pmd_t *pmd)
+{
+       const pte_t pte = { 0 };
+       vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD);
+       vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
+}
+#endif
+
+#ifdef CONFIG_SMP
+struct vmi_ap_state ap;
+extern void setup_pda(void);
+
+static void __init /* XXX cpu hotplug */
+vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
+                    unsigned long start_esp)
+{
+       /* Default everything to zero.  This is fine for most GPRs. */
+       memset(&ap, 0, sizeof(struct vmi_ap_state));
+
+       ap.gdtr_limit = GDT_SIZE - 1;
+       ap.gdtr_base = (unsigned long) get_cpu_gdt_table(phys_apicid);
+
+       ap.idtr_limit = IDT_ENTRIES * 8 - 1;
+       ap.idtr_base = (unsigned long) idt_table;
+
+       ap.ldtr = 0;
+
+       ap.cs = __KERNEL_CS;
+       ap.eip = (unsigned long) start_eip;
+       ap.ss = __KERNEL_DS;
+       ap.esp = (unsigned long) start_esp;
+
+       ap.ds = __USER_DS;
+       ap.es = __USER_DS;
+       ap.fs = __KERNEL_PDA;
+       ap.gs = 0;
+
+       ap.eflags = 0;
+
+       setup_pda();
+
+#ifdef CONFIG_X86_PAE
+       /* efer should match BSP efer. */
+       if (cpu_has_nx) {
+               unsigned l, h;
+               rdmsr(MSR_EFER, l, h);
+               ap.efer = (unsigned long long) h << 32 | l;
+       }
+#endif
+
+       ap.cr3 = __pa(swapper_pg_dir);
+       /* Protected mode, paging, AM, WP, NE, MP. */
+       ap.cr0 = 0x80050023;
+       ap.cr4 = mmu_cr4_features;
+       vmi_ops.set_initial_ap_state(__pa(&ap), phys_apicid);
+}
+#endif
+
+static inline int __init check_vmi_rom(struct vrom_header *rom)
+{
+       struct pci_header *pci;
+       struct pnp_header *pnp;
+       const char *manufacturer = "UNKNOWN";
+       const char *product = "UNKNOWN";
+       const char *license = "unspecified";
+
+       if (rom->rom_signature != 0xaa55)
+               return 0;
+       if (rom->vrom_signature != VMI_SIGNATURE)
+               return 0;
+       if (rom->api_version_maj != VMI_API_REV_MAJOR ||
+           rom->api_version_min+1 < VMI_API_REV_MINOR+1) {
+               printk(KERN_WARNING "VMI: Found mismatched rom version %d.%d\n",
+                               rom->api_version_maj,
+                               rom->api_version_min);
+               return 0;
+       }
+
+       /*
+        * Relying on the VMI_SIGNATURE field is not 100% safe, so check
+        * the PCI header and device type to make sure this is really a
+        * VMI device.
+        */
+       if (!rom->pci_header_offs) {
+               printk(KERN_WARNING "VMI: ROM does not contain PCI header.\n");
+               return 0;
+       }
+
+       pci = (struct pci_header *)((char *)rom+rom->pci_header_offs);
+       if (pci->vendorID != PCI_VENDOR_ID_VMWARE ||
+           pci->deviceID != PCI_DEVICE_ID_VMWARE_VMI) {
+               /* Allow it to run... anyways, but warn */
+               printk(KERN_WARNING "VMI: ROM from unknown manufacturer\n");
+       }
+
+       if (rom->pnp_header_offs) {
+               pnp = (struct pnp_header *)((char *)rom+rom->pnp_header_offs);
+               if (pnp->manufacturer_offset)
+                       manufacturer = (const char *)rom+pnp->manufacturer_offset;
+               if (pnp->product_offset)
+                       product = (const char *)rom+pnp->product_offset;
+       }
+
+       if (rom->license_offs)
+               license = (char *)rom+rom->license_offs;
+
+       printk(KERN_INFO "VMI: Found %s %s, API version %d.%d, ROM version %d.%d\n",
+               manufacturer, product,
+               rom->api_version_maj, rom->api_version_min,
+               pci->rom_version_maj, pci->rom_version_min);
+
+        license_gplok = license_is_gpl_compatible(license);
+        if (!license_gplok) {
+                printk(KERN_WARNING "VMI: ROM license '%s' taints kernel... "
+                      "inlining disabled\n",
+                       license);
+                add_taint(TAINT_PROPRIETARY_MODULE);
+        }
+       return 1;
+}
+
+/*
+ * Probe for the VMI option ROM
+ */
+static inline int __init probe_vmi_rom(void)
+{
+       unsigned long base;
+
+       /* VMI ROM is in option ROM area, check signature */
+       for (base = 0xC0000; base < 0xE0000; base += 2048) {
+               struct vrom_header *romstart;
+               romstart = (struct vrom_header *)isa_bus_to_virt(base);
+               if (check_vmi_rom(romstart)) {
+                       vmi_rom = romstart;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * VMI setup common to all processors
+ */
+void vmi_bringup(void)
+{
+       /* We must establish the lowmem mapping for MMU ops to work */
+       if (vmi_rom)
+               vmi_ops.set_linear_mapping(0, __PAGE_OFFSET, max_low_pfn, 0);
+}
+
+/*
+ * Return a pointer to the VMI function or a NOP stub
+ */
+static void *vmi_get_function(int vmicall)
+{
+       u64 reloc;
+       const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, vmicall);
+       BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);
+       if (rel->type == VMI_RELOCATION_CALL_REL)
+               return (void *)rel->eip;
+       else
+               return (void *)vmi_nop;
+}
+
+/*
+ * Helper macro for making the VMI paravirt-ops fill code readable.
+ * For unimplemented operations, fall back to default.
+ */
+#define para_fill(opname, vmicall)                             \
+do {                                                           \
+       reloc = call_vrom_long_func(vmi_rom, get_reloc,         \
+                                   VMI_CALL_##vmicall);        \
+       if (rel->type != VMI_RELOCATION_NONE) {                 \
+               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);   \
+               paravirt_ops.opname = (void *)rel->eip;         \
+       }                                                       \
+} while (0)
+
+/*
+ * Activate the VMI interface and switch into paravirtualized mode
+ */
+static inline int __init activate_vmi(void)
+{
+       short kernel_cs;
+       u64 reloc;
+       const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
+
+       if (call_vrom_func(vmi_rom, vmi_init) != 0) {
+               printk(KERN_ERR "VMI ROM failed to initialize!");
+               return 0;
+       }
+       savesegment(cs, kernel_cs);
+
+       paravirt_ops.paravirt_enabled = 1;
+       paravirt_ops.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
+
+       paravirt_ops.patch = vmi_patch;
+       paravirt_ops.name = "vmi";
+
+       /*
+        * Many of these operations are ABI compatible with VMI.
+        * This means we can fill in the paravirt-ops with direct
+        * pointers into the VMI ROM.  If the calling convention for
+        * these operations changes, this code needs to be updated.
+        *
+        * Exceptions
+        *  CPUID paravirt-op uses pointers, not the native ISA
+        *  halt has no VMI equivalent; all VMI halts are "safe"
+        *  no MSR support yet - just trap and emulate.  VMI uses the
+        *    same ABI as the native ISA, but Linux wants exceptions
+        *    from bogus MSR read / write handled
+        *  rdpmc is not yet used in Linux
+        */
+
+       /* CPUID is special, so very special */
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_CPUID);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+               vmi_ops.cpuid = (void *)rel->eip;
+               paravirt_ops.cpuid = vmi_cpuid;
+       }
+
+       para_fill(clts, CLTS);
+       para_fill(get_debugreg, GetDR);
+       para_fill(set_debugreg, SetDR);
+       para_fill(read_cr0, GetCR0);
+       para_fill(read_cr2, GetCR2);
+       para_fill(read_cr3, GetCR3);
+       para_fill(read_cr4, GetCR4);
+       para_fill(write_cr0, SetCR0);
+       para_fill(write_cr2, SetCR2);
+       para_fill(write_cr3, SetCR3);
+       para_fill(write_cr4, SetCR4);
+       para_fill(save_fl, GetInterruptMask);
+       para_fill(restore_fl, SetInterruptMask);
+       para_fill(irq_disable, DisableInterrupts);
+       para_fill(irq_enable, EnableInterrupts);
+       /* irq_save_disable !!! sheer pain */
+       patch_offset(&irq_save_disable_callout[IRQ_PATCH_INT_MASK],
+                    (char *)paravirt_ops.save_fl);
+       patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE],
+                    (char *)paravirt_ops.irq_disable);
+#ifndef CONFIG_NO_IDLE_HZ
+       para_fill(safe_halt, Halt);
+#else
+       vmi_ops.halt = vmi_get_function(VMI_CALL_Halt);
+       paravirt_ops.safe_halt = vmi_safe_halt;
+#endif
+       para_fill(wbinvd, WBINVD);
+       /* paravirt_ops.read_msr = vmi_rdmsr */
+       /* paravirt_ops.write_msr = vmi_wrmsr */
+       para_fill(read_tsc, RDTSC);
+       /* paravirt_ops.rdpmc = vmi_rdpmc */
+
+       /* TR interface doesn't pass TR value */
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_SetTR);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+               vmi_ops.set_tr = (void *)rel->eip;
+               paravirt_ops.load_tr_desc = vmi_set_tr;
+       }
+
+       /* LDT is special, too */
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_SetLDT);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+               vmi_ops._set_ldt = (void *)rel->eip;
+               paravirt_ops.set_ldt = vmi_set_ldt;
+       }
+
+       para_fill(load_gdt, SetGDT);
+       para_fill(load_idt, SetIDT);
+       para_fill(store_gdt, GetGDT);
+       para_fill(store_idt, GetIDT);
+       para_fill(store_tr, GetTR);
+       paravirt_ops.load_tls = vmi_load_tls;
+       para_fill(write_ldt_entry, WriteLDTEntry);
+       para_fill(write_gdt_entry, WriteGDTEntry);
+       para_fill(write_idt_entry, WriteIDTEntry);
+       reloc = call_vrom_long_func(vmi_rom, get_reloc,
+                                   VMI_CALL_UpdateKernelStack);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+               vmi_ops.set_kernel_stack = (void *)rel->eip;
+               paravirt_ops.load_esp0 = vmi_load_esp0;
+       }
+
+       para_fill(set_iopl_mask, SetIOPLMask);
+       paravirt_ops.io_delay = (void *)vmi_nop;
+       if (!disable_nodelay) {
+               paravirt_ops.const_udelay = (void *)vmi_nop;
+       }
+
+       para_fill(set_lazy_mode, SetLazyMode);
+
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_FlushTLB);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               vmi_ops.flush_tlb = (void *)rel->eip;
+               paravirt_ops.flush_tlb_user = vmi_flush_tlb_user;
+               paravirt_ops.flush_tlb_kernel = vmi_flush_tlb_kernel;
+       }
+       para_fill(flush_tlb_single, InvalPage);
+
+       /*
+        * Until a standard flag format can be agreed on, we need to
+        * implement these as wrappers in Linux.  Get the VMI ROM
+        * function pointers for the two backend calls.
+        */
+#ifdef CONFIG_X86_PAE
+       vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxELong);
+       vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxELong);
+#else
+       vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
+       vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
+#endif
+       vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
+       vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
+       vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
+
+       paravirt_ops.alloc_pt = vmi_allocate_pt;
+       paravirt_ops.alloc_pd = vmi_allocate_pd;
+       paravirt_ops.alloc_pd_clone = vmi_allocate_pd_clone;
+       paravirt_ops.release_pt = vmi_release_pt;
+       paravirt_ops.release_pd = vmi_release_pd;
+       paravirt_ops.set_pte = vmi_set_pte;
+       paravirt_ops.set_pte_at = vmi_set_pte_at;
+       paravirt_ops.set_pmd = vmi_set_pmd;
+       paravirt_ops.pte_update = vmi_update_pte;
+       paravirt_ops.pte_update_defer = vmi_update_pte_defer;
+#ifdef CONFIG_X86_PAE
+       paravirt_ops.set_pte_atomic = vmi_set_pte_atomic;
+       paravirt_ops.set_pte_present = vmi_set_pte_present;
+       paravirt_ops.set_pud = vmi_set_pud;
+       paravirt_ops.pte_clear = vmi_pte_clear;
+       paravirt_ops.pmd_clear = vmi_pmd_clear;
+#endif
+       /*
+        * These MUST always be patched.  Don't support indirect jumps
+        * through these operations, as the VMI interface may use either
+        * a jump or a call to get to these operations, depending on
+        * the backend.  They are performance critical anyway, so requiring
+        * a patch is not a big problem.
+        */
+       paravirt_ops.irq_enable_sysexit = (void *)0xfeedbab0;
+       paravirt_ops.iret = (void *)0xbadbab0;
+
+#ifdef CONFIG_SMP
+       paravirt_ops.startup_ipi_hook = vmi_startup_ipi_hook;
+       vmi_ops.set_initial_ap_state = vmi_get_function(VMI_CALL_SetInitialAPState);
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       paravirt_ops.apic_read = vmi_get_function(VMI_CALL_APICRead);
+       paravirt_ops.apic_write = vmi_get_function(VMI_CALL_APICWrite);
+       paravirt_ops.apic_write_atomic = vmi_get_function(VMI_CALL_APICWrite);
+#endif
+
+       /*
+        * Check for VMI timer functionality by probing for a cycle frequency method
+        */
+       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
+       if (rel->type != VMI_RELOCATION_NONE) {
+               vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
+               vmi_timer_ops.get_cycle_counter =
+                       vmi_get_function(VMI_CALL_GetCycleCounter);
+               vmi_timer_ops.get_wallclock =
+                       vmi_get_function(VMI_CALL_GetWallclockTime);
+               vmi_timer_ops.wallclock_updated =
+                       vmi_get_function(VMI_CALL_WallclockUpdated);
+               vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
+               vmi_timer_ops.cancel_alarm =
+                        vmi_get_function(VMI_CALL_CancelAlarm);
+               paravirt_ops.time_init = vmi_time_init;
+               paravirt_ops.get_wallclock = vmi_get_wallclock;
+               paravirt_ops.set_wallclock = vmi_set_wallclock;
+#ifdef CONFIG_X86_LOCAL_APIC
+               paravirt_ops.setup_boot_clock = vmi_timer_setup_boot_alarm;
+               paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm;
+#endif
+               custom_sched_clock = vmi_sched_clock;
+       }
+
+       /*
+        * Alternative instruction rewriting doesn't happen soon enough
+        * to convert VMI_IRET to a call instead of a jump; so we have
+        * to do this before IRQs get reenabled.  Fortunately, it is
+        * idempotent.
+        */
+       apply_paravirt(__start_parainstructions, __stop_parainstructions);
+
+       vmi_bringup();
+
+       return 1;
+}
+
+#undef para_fill
+
+void __init vmi_init(void)
+{
+       unsigned long flags;
+
+       if (!vmi_rom)
+               probe_vmi_rom();
+       else
+               check_vmi_rom(vmi_rom);
+
+       /* In case probing for or validating the ROM failed, basil */
+       if (!vmi_rom)
+               return;
+
+       reserve_top_address(-vmi_rom->virtual_top);
+
+       local_irq_save(flags);
+       activate_vmi();
+#ifdef CONFIG_SMP
+       no_timer_check = 1;
+#endif
+       local_irq_restore(flags & X86_EFLAGS_IF);
+}
+
+static int __init parse_vmi(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcmp(arg, "disable_nodelay"))
+               disable_nodelay = 1;
+       else if (!strcmp(arg, "disable_pge")) {
+               clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+               disable_pge = 1;
+       } else if (!strcmp(arg, "disable_pse")) {
+               clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+               disable_pse = 1;
+       } else if (!strcmp(arg, "disable_sep")) {
+               clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
+               disable_sep = 1;
+       } else if (!strcmp(arg, "disable_tsc")) {
+               clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+               disable_tsc = 1;
+       } else if (!strcmp(arg, "disable_mtrr")) {
+               clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability);
+               disable_mtrr = 1;
+       }
+       return 0;
+}
+
+early_param("vmi", parse_vmi);
diff --git a/arch/i386/kernel/vmitime.c b/arch/i386/kernel/vmitime.c
new file mode 100644 (file)
index 0000000..76d2adc
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * VMI paravirtual timer support routines.
+ *
+ * Copyright (C) 2005, VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to dhecht@vmware.com
+ *
+ */
+
+/*
+ * Portions of this code from arch/i386/kernel/timers/timer_tsc.c.
+ * Portions of the CONFIG_NO_IDLE_HZ code from arch/s390/kernel/time.c.
+ * See comments there for proper credits.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/rcupdate.h>
+#include <linux/clocksource.h>
+
+#include <asm/timer.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/div64.h>
+#include <asm/timer.h>
+#include <asm/desc.h>
+
+#include <asm/vmi.h>
+#include <asm/vmi_time.h>
+
+#include <mach_timer.h>
+#include <io_ports.h>
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#define VMI_ALARM_WIRING VMI_ALARM_WIRED_LVTT
+#else
+#define VMI_ALARM_WIRING VMI_ALARM_WIRED_IRQ0
+#endif
+
+/* Cached VMI operations */
+struct vmi_timer_ops vmi_timer_ops;
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+/* /proc/sys/kernel/hz_timer state. */
+int sysctl_hz_timer;
+
+/* Some stats */
+static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_irqs);
+static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_jiffies);
+static DEFINE_PER_CPU(unsigned long, idle_start_jiffies);
+
+#endif /* CONFIG_NO_IDLE_HZ */
+
+/* Number of alarms per second. By default this is CONFIG_VMI_ALARM_HZ. */
+static int alarm_hz = CONFIG_VMI_ALARM_HZ;
+
+/* Cache of the value get_cycle_frequency / HZ. */
+static signed long long cycles_per_jiffy;
+
+/* Cache of the value get_cycle_frequency / alarm_hz. */
+static signed long long cycles_per_alarm;
+
+/* The number of cycles accounted for by the 'jiffies'/'xtime' count.
+ * Protected by xtime_lock. */
+static unsigned long long real_cycles_accounted_system;
+
+/* The number of cycles accounted for by update_process_times(), per cpu. */
+static DEFINE_PER_CPU(unsigned long long, process_times_cycles_accounted_cpu);
+
+/* The number of stolen cycles accounted, per cpu. */
+static DEFINE_PER_CPU(unsigned long long, stolen_cycles_accounted_cpu);
+
+/* Clock source. */
+static cycle_t read_real_cycles(void)
+{
+       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+}
+
+static cycle_t read_available_cycles(void)
+{
+       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE);
+}
+
+#if 0
+static cycle_t read_stolen_cycles(void)
+{
+       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_STOLEN);
+}
+#endif  /*  0  */
+
+static struct clocksource clocksource_vmi = {
+       .name                   = "vmi-timer",
+       .rating                 = 450,
+       .read                   = read_real_cycles,
+       .mask                   = CLOCKSOURCE_MASK(64),
+       .mult                   = 0, /* to be set */
+       .shift                  = 22,
+       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/* Timer interrupt handler. */
+static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id);
+
+static struct irqaction vmi_timer_irq  = {
+       vmi_timer_interrupt,
+       SA_INTERRUPT,
+       CPU_MASK_NONE,
+       "VMI-alarm",
+       NULL,
+       NULL
+};
+
+/* Alarm rate */
+static int __init vmi_timer_alarm_rate_setup(char* str)
+{
+       int alarm_rate;
+       if (get_option(&str, &alarm_rate) == 1 && alarm_rate > 0) {
+               alarm_hz = alarm_rate;
+               printk(KERN_WARNING "VMI timer alarm HZ set to %d\n", alarm_hz);
+       }
+       return 1;
+}
+__setup("vmi_timer_alarm_hz=", vmi_timer_alarm_rate_setup);
+
+
+/* Initialization */
+static void vmi_get_wallclock_ts(struct timespec *ts)
+{
+       unsigned long long wallclock;
+       wallclock = vmi_timer_ops.get_wallclock(); // nsec units
+       ts->tv_nsec = do_div(wallclock, 1000000000);
+       ts->tv_sec = wallclock;
+}
+
+static void update_xtime_from_wallclock(void)
+{
+       struct timespec ts;
+       vmi_get_wallclock_ts(&ts);
+       do_settimeofday(&ts);
+}
+
+unsigned long vmi_get_wallclock(void)
+{
+       struct timespec ts;
+       vmi_get_wallclock_ts(&ts);
+       return ts.tv_sec;
+}
+
+int vmi_set_wallclock(unsigned long now)
+{
+       return -1;
+}
+
+unsigned long long vmi_sched_clock(void)
+{
+       return read_available_cycles();
+}
+
+void __init vmi_time_init(void)
+{
+       unsigned long long cycles_per_sec, cycles_per_msec;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       setup_irq(0, &vmi_timer_irq);
+#ifdef CONFIG_X86_LOCAL_APIC
+       set_intr_gate(LOCAL_TIMER_VECTOR, apic_vmi_timer_interrupt);
+#endif
+
+       no_sync_cmos_clock = 1;
+
+       vmi_get_wallclock_ts(&xtime);
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+
+       real_cycles_accounted_system = read_real_cycles();
+       update_xtime_from_wallclock();
+       per_cpu(process_times_cycles_accounted_cpu, 0) = read_available_cycles();
+
+       cycles_per_sec = vmi_timer_ops.get_cycle_frequency();
+
+       cycles_per_jiffy = cycles_per_sec;
+       (void)do_div(cycles_per_jiffy, HZ);
+       cycles_per_alarm = cycles_per_sec;
+       (void)do_div(cycles_per_alarm, alarm_hz);
+       cycles_per_msec = cycles_per_sec;
+       (void)do_div(cycles_per_msec, 1000);
+       cpu_khz = cycles_per_msec;
+
+       printk(KERN_WARNING "VMI timer cycles/sec = %llu ; cycles/jiffy = %llu ;"
+              "cycles/alarm = %llu\n", cycles_per_sec, cycles_per_jiffy,
+              cycles_per_alarm);
+
+       clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
+                                                   clocksource_vmi.shift);
+       if (clocksource_register(&clocksource_vmi))
+               printk(KERN_WARNING "Error registering VMITIME clocksource.");
+
+       /* Disable PIT. */
+       outb_p(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
+
+       /* schedule the alarm. do this in phase with process_times_cycles_accounted_cpu
+        * reduce the latency calling update_process_times. */
+       vmi_timer_ops.set_alarm(
+                     VMI_ALARM_WIRED_IRQ0 | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+                     per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
+                     cycles_per_alarm);
+
+       local_irq_restore(flags);
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+void __init vmi_timer_setup_boot_alarm(void)
+{
+       local_irq_disable();
+
+       /* Route the interrupt to the correct vector. */
+       apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
+
+       /* Cancel the IRQ0 wired alarm, and setup the LVTT alarm. */
+       vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
+       vmi_timer_ops.set_alarm(
+                     VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+                     per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
+                     cycles_per_alarm);
+       local_irq_enable();
+}
+
+/* Initialize the time accounting variables for an AP on an SMP system.
+ * Also, set the local alarm for the AP. */
+void __init vmi_timer_setup_secondary_alarm(void)
+{
+       int cpu = smp_processor_id();
+
+       /* Route the interrupt to the correct vector. */
+       apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
+
+       per_cpu(process_times_cycles_accounted_cpu, cpu) = read_available_cycles();
+
+       vmi_timer_ops.set_alarm(
+                     VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+                     per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
+                     cycles_per_alarm);
+}
+
+#endif
+
+/* Update system wide (real) time accounting (e.g. jiffies, xtime). */
+static void vmi_account_real_cycles(unsigned long long cur_real_cycles)
+{
+       long long cycles_not_accounted;
+
+       write_seqlock(&xtime_lock);
+
+       cycles_not_accounted = cur_real_cycles - real_cycles_accounted_system;
+       while (cycles_not_accounted >= cycles_per_jiffy) {
+               /* systems wide jiffies and wallclock. */
+               do_timer(1);
+
+               cycles_not_accounted -= cycles_per_jiffy;
+               real_cycles_accounted_system += cycles_per_jiffy;
+       }
+
+       if (vmi_timer_ops.wallclock_updated())
+               update_xtime_from_wallclock();
+
+       write_sequnlock(&xtime_lock);
+}
+
+/* Update per-cpu process times. */
+static void vmi_account_process_times_cycles(struct pt_regs *regs, int cpu,
+                                            unsigned long long cur_process_times_cycles)
+{
+       long long cycles_not_accounted;
+       cycles_not_accounted = cur_process_times_cycles -
+               per_cpu(process_times_cycles_accounted_cpu, cpu);
+
+       while (cycles_not_accounted >= cycles_per_jiffy) {
+               /* Account time to the current process.  This includes
+                * calling into the scheduler to decrement the timeslice
+                * and possibly reschedule.*/
+               update_process_times(user_mode(regs));
+               /* XXX handle /proc/profile multiplier.  */
+               profile_tick(CPU_PROFILING);
+
+               cycles_not_accounted -= cycles_per_jiffy;
+               per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+       }
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/* Update per-cpu idle times.  Used when a no-hz halt is ended. */
+static void vmi_account_no_hz_idle_cycles(int cpu,
+                                         unsigned long long cur_process_times_cycles)
+{
+       long long cycles_not_accounted;
+       unsigned long no_idle_hz_jiffies = 0;
+
+       cycles_not_accounted = cur_process_times_cycles -
+               per_cpu(process_times_cycles_accounted_cpu, cpu);
+
+       while (cycles_not_accounted >= cycles_per_jiffy) {
+               no_idle_hz_jiffies++;
+               cycles_not_accounted -= cycles_per_jiffy;
+               per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+       }
+       /* Account time to the idle process. */
+       account_steal_time(idle_task(cpu), jiffies_to_cputime(no_idle_hz_jiffies));
+}
+#endif
+
+/* Update per-cpu stolen time. */
+static void vmi_account_stolen_cycles(int cpu,
+                                     unsigned long long cur_real_cycles,
+                                     unsigned long long cur_avail_cycles)
+{
+       long long stolen_cycles_not_accounted;
+       unsigned long stolen_jiffies = 0;
+
+       if (cur_real_cycles < cur_avail_cycles)
+               return;
+
+       stolen_cycles_not_accounted = cur_real_cycles - cur_avail_cycles -
+               per_cpu(stolen_cycles_accounted_cpu, cpu);
+
+       while (stolen_cycles_not_accounted >= cycles_per_jiffy) {
+               stolen_jiffies++;
+               stolen_cycles_not_accounted -= cycles_per_jiffy;
+               per_cpu(stolen_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+       }
+       /* HACK: pass NULL to force time onto cpustat->steal. */
+       account_steal_time(NULL, jiffies_to_cputime(stolen_jiffies));
+}
+
+/* Body of either IRQ0 interrupt handler (UP no local-APIC) or
+ * local-APIC LVTT interrupt handler (UP & local-APIC or SMP). */
+static void vmi_local_timer_interrupt(int cpu)
+{
+       unsigned long long cur_real_cycles, cur_process_times_cycles;
+
+       cur_real_cycles = read_real_cycles();
+       cur_process_times_cycles = read_available_cycles();
+       /* Update system wide (real) time state (xtime, jiffies). */
+       vmi_account_real_cycles(cur_real_cycles);
+       /* Update per-cpu process times. */
+       vmi_account_process_times_cycles(get_irq_regs(), cpu, cur_process_times_cycles);
+        /* Update time stolen from this cpu by the hypervisor. */
+       vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+/* Must be called only from idle loop, with interrupts disabled. */
+int vmi_stop_hz_timer(void)
+{
+       /* Note that cpu_set, cpu_clear are (SMP safe) atomic on x86. */
+
+       unsigned long seq, next;
+       unsigned long long real_cycles_expiry;
+       int cpu = smp_processor_id();
+       int idle;
+
+       BUG_ON(!irqs_disabled());
+       if (sysctl_hz_timer != 0)
+               return 0;
+
+       cpu_set(cpu, nohz_cpu_mask);
+       smp_mb();
+       if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
+           (next = next_timer_interrupt(), time_before_eq(next, jiffies))) {
+               cpu_clear(cpu, nohz_cpu_mask);
+               next = jiffies;
+               idle = 0;
+       } else
+               idle = 1;
+
+       /* Convert jiffies to the real cycle counter. */
+       do {
+               seq = read_seqbegin(&xtime_lock);
+               real_cycles_expiry = real_cycles_accounted_system +
+                       (long)(next - jiffies) * cycles_per_jiffy;
+       } while (read_seqretry(&xtime_lock, seq));
+
+       /* This cpu is going idle. Disable the periodic alarm. */
+       if (idle) {
+               vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
+               per_cpu(idle_start_jiffies, cpu) = jiffies;
+       }
+
+       /* Set the real time alarm to expire at the next event. */
+       vmi_timer_ops.set_alarm(
+                     VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL,
+                     real_cycles_expiry, 0);
+
+       return idle;
+}
+
+static void vmi_reenable_hz_timer(int cpu)
+{
+       /* For /proc/vmi/info idle_hz stat. */
+       per_cpu(vmi_idle_no_hz_jiffies, cpu) += jiffies - per_cpu(idle_start_jiffies, cpu);
+       per_cpu(vmi_idle_no_hz_irqs, cpu)++;
+
+       /* Don't bother explicitly cancelling the one-shot alarm -- at
+        * worse we will receive a spurious timer interrupt. */
+       vmi_timer_ops.set_alarm(
+                     VMI_ALARM_WIRING | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+                     per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
+                     cycles_per_alarm);
+       /* Indicate this cpu is no longer nohz idle. */
+       cpu_clear(cpu, nohz_cpu_mask);
+}
+
+/* Called from interrupt handlers when (local) HZ timer is disabled. */
+void vmi_account_time_restart_hz_timer(void)
+{
+       unsigned long long cur_real_cycles, cur_process_times_cycles;
+       int cpu = smp_processor_id();
+
+       BUG_ON(!irqs_disabled());
+       /* Account the time during which the HZ timer was disabled. */
+       cur_real_cycles = read_real_cycles();
+       cur_process_times_cycles = read_available_cycles();
+       /* Update system wide (real) time state (xtime, jiffies). */
+       vmi_account_real_cycles(cur_real_cycles);
+       /* Update per-cpu idle times. */
+       vmi_account_no_hz_idle_cycles(cpu, cur_process_times_cycles);
+        /* Update time stolen from this cpu by the hypervisor. */
+       vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
+       /* Reenable the hz timer. */
+       vmi_reenable_hz_timer(cpu);
+}
+
+#endif /* CONFIG_NO_IDLE_HZ */
+
+/* UP (and no local-APIC) VMI-timer alarm interrupt handler.
+ * Handler for IRQ0. Not used when SMP or X86_LOCAL_APIC after
+ * APIC setup and setup_boot_vmi_alarm() is called.  */
+static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
+{
+       vmi_local_timer_interrupt(smp_processor_id());
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+/* SMP VMI-timer alarm interrupt handler. Handler for LVTT vector.
+ * Also used in UP when CONFIG_X86_LOCAL_APIC.
+ * The wrapper code is from arch/i386/kernel/apic.c#smp_apic_timer_interrupt. */
+void smp_apic_vmi_timer_interrupt(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       int cpu = smp_processor_id();
+
+       /*
+        * the NMI deadlock-detector uses this.
+        */
+        per_cpu(irq_stat,cpu).apic_timer_irqs++;
+
+       /*
+        * NOTE! We'd better ACK the irq immediately,
+        * because timer handling can be slow.
+        */
+       ack_APIC_irq();
+
+       /*
+        * update_process_times() expects us to have done irq_enter().
+        * Besides, if we don't timer interrupts ignore the global
+        * interrupt lock, which is the WrongThing (tm) to do.
+        */
+       irq_enter();
+       vmi_local_timer_interrupt(cpu);
+       irq_exit();
+       set_irq_regs(old_regs);
+}
+
+#endif  /* CONFIG_X86_LOCAL_APIC */
index 5038a73d554e18df68cc097c5f77431ddf50a5b5..ca51610955df34f56e83b323db66a8208366dc00 100644 (file)
@@ -37,9 +37,14 @@ SECTIONS
 {
   . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
   phys_startup_32 = startup_32 - LOAD_OFFSET;
+
+  .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
+       _text = .;                      /* Text and read-only data */
+       *(.text.head)
+  } :text = 0x9090
+
   /* read-only */
   .text : AT(ADDR(.text) - LOAD_OFFSET) {
-       _text = .;                      /* Text and read-only data */
        *(.text)
        SCHED_TEXT
        LOCK_TEXT
index cc2f519b2f7f6c41a5b6ff5fdbe082fa730b5734..c7881621070630abd4b7c0c25ec28b1534c163c0 100644 (file)
@@ -79,7 +79,12 @@ void __init trap_init_hook(void)
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = {
+       .handler = timer_interrupt,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .mask = CPU_MASK_NONE,
+       .name = "timer"
+};
 
 /**
  * time_init_hook - do any specific initialisations for the system timer.
@@ -90,6 +95,7 @@ static struct irqaction irq0  = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE,
  **/
 void __init time_init_hook(void)
 {
+       irq0.mask = cpumask_of_cpu(0);
        setup_irq(0, &irq0);
 }
 
index 9819b705efa422af8c3f1ee5652fa0649f606811..2e2c51a8bd3ae6d921167607977d9f25d2f75ae0 100644 (file)
@@ -56,15 +56,14 @@ static int reg_offset_vm86[] = {
 #define VM86_REG_(x) (*(unsigned short *) \
                      (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info))
 
-/* These are dummy, fs and gs are not saved on the stack. */
-#define ___FS ___ds
+/* This dummy, gs is not saved on the stack. */
 #define ___GS ___ds
 
 static int reg_offset_pm[] = {
        offsetof(struct info,___cs),
        offsetof(struct info,___ds),
        offsetof(struct info,___es),
-       offsetof(struct info,___FS),
+       offsetof(struct info,___fs),
        offsetof(struct info,___GS),
        offsetof(struct info,___ss),
        offsetof(struct info,___ds)
@@ -169,13 +168,10 @@ static long pm_address(u_char FPU_modrm, u_char segment,
 
   switch ( segment )
     {
-      /* fs and gs aren't used by the kernel, so they still have their
-        user-space values. */
-    case PREFIX_FS_-1:
-      /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
-      savesegment(fs, addr->selector);
-      break;
+      /* gs isn't used by the kernel, so it still has its
+        user-space value. */
     case PREFIX_GS_-1:
+      /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
       savesegment(gs, addr->selector);
       break;
     default:
index 78d7b7689dd6b414ae6f25fb7ca61bb3c1c91028..59e73302aa60c599c6f5609d2e81a2bf49e3c9df 100644 (file)
 
 #define status_word() \
   ((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top))
-#define setcc(cc) ({ \
-  partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
-  partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); })
+static inline void setcc(int cc)
+{
+       partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
+       partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3);
+}
 
 #ifdef PECULIAR_486
    /* Default, this conveys no information, but an 80486 does it. */
index e0c390d6ceb526464d3c3b220e0fdc59f138ec8e..aa58720f68711ab5fd61c019b4862de89b6c5c35 100644 (file)
@@ -101,7 +101,6 @@ extern void find_max_pfn(void);
 extern void add_one_highpage_init(struct page *, int, int);
 
 extern struct e820map e820;
-extern unsigned long init_pg_tables_end;
 extern unsigned long highend_pfn, highstart_pfn;
 extern unsigned long max_low_pfn;
 extern unsigned long totalram_pages;
index cba9b3894a3325c0490ab1f8475a851cea25ba2f..b8c4e259fc8b7929e5ebeb1ea028c9d25a033646 100644 (file)
@@ -46,17 +46,17 @@ int unregister_page_fault_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
 
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
        struct die_args args = {
                .regs = regs,
-               .str = str,
+               .str = "page fault",
                .err = err,
-               .trapnr = trap,
-               .signr = sig
+               .trapnr = 14,
+               .signr = SIGSEGV
        };
-       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+       return atomic_notifier_call_chain(&notify_page_fault_chain,
+                                         DIE_PAGE_FAULT, &args);
 }
 
 /*
@@ -327,8 +327,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
        if (unlikely(address >= TASK_SIZE)) {
                if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
                        return;
-               if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-                                               SIGSEGV) == NOTIFY_STOP)
+               if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
                        return;
                /*
                 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -337,8 +336,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
                goto bad_area_nosemaphore;
        }
 
-       if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-                                       SIGSEGV) == NOTIFY_STOP)
+       if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
                return;
 
        /* It's safe to allow irq's after cr2 has been saved and the vmalloc
index c5c5ea700cc708ae0e08388bfc492da509f173eb..ae436882af7a11dce76b34ee711fa6ce80c0502e 100644 (file)
@@ -62,6 +62,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
                
 #ifdef CONFIG_X86_PAE
        pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+       paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
        set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
        pud = pud_offset(pgd, 0);
        if (pmd_table != pmd_offset(pud, 0)) 
@@ -82,6 +83,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
 {
        if (pmd_none(*pmd)) {
                pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+               paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
                set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
                if (page_table != pte_offset_kernel(pmd, 0))
                        BUG();  
@@ -345,6 +347,8 @@ static void __init pagetable_init (void)
        /* Init entries of the first-level page table to the zero page */
        for (i = 0; i < PTRS_PER_PGD; i++)
                set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+#else
+       paravirt_alloc_pd(__pa(swapper_pg_dir) >> PAGE_SHIFT);
 #endif
 
        /* Enable PSE if available */
index e223b1d4981c2ee845f65d5337606862c57f0213..412ebbd8adb06f12c6f31093a43c1815f55fe8e9 100644 (file)
@@ -60,6 +60,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        address = __pa(address);
        addr = address & LARGE_PAGE_MASK; 
        pbase = (pte_t *)page_address(base);
+       paravirt_alloc_pt(page_to_pfn(base));
        for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
                set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
                                           addr == address ? prot : ref_prot));
@@ -172,6 +173,7 @@ __change_page_attr(struct page *page, pgprot_t prot)
        if (!PageReserved(kpte_page)) {
                if (cpu_has_pse && (page_private(kpte_page) == 0)) {
                        ClearPagePrivate(kpte_page);
+                       paravirt_release_pt(page_to_pfn(kpte_page));
                        list_add(&kpte_page->lru, &df_list);
                        revert_page(kpte_page, address);
                }
index f349eaf450b0db542c5c3e56c3b598da94562a66..fa0cfbd551e185f83f75adecd7a0ecd6a03788cc 100644 (file)
@@ -171,6 +171,8 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
 void reserve_top_address(unsigned long reserve)
 {
        BUG_ON(fixmaps > 0);
+       printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+              (int)-reserve);
 #ifdef CONFIG_COMPAT_VDSO
        BUG_ON(reserve != 0);
 #else
@@ -248,9 +250,15 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
        clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
                        swapper_pg_dir + USER_PTRS_PER_PGD,
                        KERNEL_PGD_PTRS);
+
        if (PTRS_PER_PMD > 1)
                return;
 
+       /* must happen under lock */
+       paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+                       __pa(swapper_pg_dir) >> PAGE_SHIFT,
+                       USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
+
        pgd_list_add(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
 }
@@ -260,6 +268,7 @@ void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
 
+       paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
        spin_lock_irqsave(&pgd_lock, flags);
        pgd_list_del(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
@@ -277,13 +286,18 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
                if (!pmd)
                        goto out_oom;
+               paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
                set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
        }
        return pgd;
 
 out_oom:
-       for (i--; i >= 0; i--)
-               kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+       for (i--; i >= 0; i--) {
+               pgd_t pgdent = pgd[i];
+               void* pmd = (void *)__va(pgd_val(pgdent)-1);
+               paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+               kmem_cache_free(pmd_cache, pmd);
+       }
        kmem_cache_free(pgd_cache, pgd);
        return NULL;
 }
@@ -294,8 +308,12 @@ void pgd_free(pgd_t *pgd)
 
        /* in the PAE case user pgd entries are overwritten before usage */
        if (PTRS_PER_PMD > 1)
-               for (i = 0; i < USER_PTRS_PER_PGD; ++i)
-                       kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+               for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+                       pgd_t pgdent = pgd[i];
+                       void* pmd = (void *)__va(pgd_val(pgdent)-1);
+                       paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+                       kmem_cache_free(pmd_cache, pmd);
+               }
        /* in the non-PAE case, free_pgtables() clears user pgd entries */
        kmem_cache_free(pgd_cache, pgd);
 }
index 3700eef78743160787de152444c95eeaa03d93a9..8fda7be9dd4dc728c81dbd9d1d0f4d41907a83ae 100644 (file)
@@ -63,7 +63,7 @@ static struct sys_device device_oprofile = {
 };
 
 
-static int __init init_driverfs(void)
+static int __init init_sysfs(void)
 {
        int error;
        if (!(error = sysdev_class_register(&oprofile_sysclass)))
@@ -72,15 +72,15 @@ static int __init init_driverfs(void)
 }
 
 
-static void exit_driverfs(void)
+static void exit_sysfs(void)
 {
        sysdev_unregister(&device_oprofile);
        sysdev_class_unregister(&oprofile_sysclass);
 }
 
 #else
-#define init_driverfs() do { } while (0)
-#define exit_driverfs() do { } while (0)
+#define init_sysfs() do { } while (0)
+#define exit_sysfs() do { } while (0)
 #endif /* CONFIG_PM */
 
 static int profile_exceptions_notify(struct notifier_block *self,
@@ -385,7 +385,7 @@ static int __init ppro_init(char ** cpu_type)
        return 1;
 }
 
-/* in order to get driverfs right */
+/* in order to get sysfs right */
 static int using_nmi;
 
 int __init op_nmi_init(struct oprofile_operations *ops)
@@ -440,7 +440,7 @@ int __init op_nmi_init(struct oprofile_operations *ops)
                        return -ENODEV;
        }
 
-       init_driverfs();
+       init_sysfs();
        using_nmi = 1;
        ops->create_files = nmi_create_files;
        ops->setup = nmi_setup;
@@ -456,5 +456,5 @@ int __init op_nmi_init(struct oprofile_operations *ops)
 void op_nmi_exit(void)
 {
        if (using_nmi)
-               exit_driverfs();
+               exit_sysfs();
 }
index ca2447e05e15d90a70012e4d2b725c8fa9a47e78..c554f52cb80825b8fc85cd72fd91cb1e1612c00a 100644 (file)
@@ -24,7 +24,8 @@
 
 #define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
 #define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
-#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), -1);} while (0)
+#define CTR_32BIT_WRITE(l,msrs,c)      \
+       do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0);} while (0)
 #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
 
 #define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
@@ -79,7 +80,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
        for (i = 0; i < NUM_COUNTERS; ++i) {
                if (unlikely(!CTR_IS_RESERVED(msrs,i)))
                        continue;
-               CTR_WRITE(1, msrs, i);
+               CTR_32BIT_WRITE(1, msrs, i);
        }
 
        /* enable active counters */
@@ -87,7 +88,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
                if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
                        reset_value[i] = counter_config[i].count;
 
-                       CTR_WRITE(counter_config[i].count, msrs, i);
+                       CTR_32BIT_WRITE(counter_config[i].count, msrs, i);
 
                        CTRL_READ(low, high, msrs, i);
                        CTRL_CLEAR(low);
@@ -116,7 +117,7 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
                CTR_READ(low, high, msrs, i);
                if (CTR_OVERFLOWED(low)) {
                        oprofile_add_sample(regs, i);
-                       CTR_WRITE(reset_value[i], msrs, i);
+                       CTR_32BIT_WRITE(reset_value[i], msrs, i);
                }
        }
 
index 1594d2f55c8f13e5fc4b22389456957d8bacefb1..44650e03308b0ad6d849abc0dcc0645800292be5 100644 (file)
@@ -1,7 +1,7 @@
 obj-y                          := i386.o init.o
 
 obj-$(CONFIG_PCI_BIOS)         += pcbios.o
-obj-$(CONFIG_PCI_MMCONFIG)     += mmconfig.o direct.o
+obj-$(CONFIG_PCI_MMCONFIG)     += mmconfig.o direct.o mmconfig-shared.o
 obj-$(CONFIG_PCI_DIRECT)       += direct.o
 
 pci-y                          := fixup.o
index 53ca6e897984a669e4a36ef23295bb0f9e30d561..1bb069372143caa99c30f33c7f4484e5c1d930e6 100644 (file)
@@ -191,6 +191,94 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
                },
        },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G3",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G4",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL30p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL25p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL35p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL460c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL465c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL480c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL685c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
+               },
+       },
        {}
 };
 
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c
new file mode 100644 (file)
index 0000000..747d8c6
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * mmconfig-shared.c - Low-level direct PCI config space access via
+ *                     MMCONFIG - common code between i386 and x86-64.
+ *
+ * This code does:
+ * - known chipset handling
+ * - ACPI decoding and validation
+ *
+ * Per-architecture code takes care of the mappings and accesses
+ * themselves.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <asm/e820.h>
+
+#include "pci.h"
+
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN      (2 * 1024*1024)
+#define MMCONFIG_APER_MAX      (256 * 1024*1024)
+
+DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+/* K8 systems have some devices (typically in the builtin northbridge)
+   that are only accessible using type1
+   Normally this can be expressed in the MCFG by not listing them
+   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+   Instead try to discover all devices on bus 0 that are unreachable using MM
+   and fallback for them. */
+static void __init unreachable_devices(void)
+{
+       int i, bus;
+       /* Use the max bus number from ACPI here? */
+       for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
+               for (i = 0; i < 32; i++) {
+                       unsigned int devfn = PCI_DEVFN(i, 0);
+                       u32 val1, val2;
+
+                       pci_conf1_read(0, bus, devfn, 0, 4, &val1);
+                       if (val1 == 0xffffffff)
+                               continue;
+
+                       if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
+                               raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
+                               if (val1 == val2)
+                                       continue;
+                       }
+                       set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
+                       printk(KERN_NOTICE "PCI: No mmconfig possible on device"
+                              " %02x:%02x\n", bus, i);
+               }
+       }
+}
+
+static const char __init *pci_mmcfg_e7520(void)
+{
+       u32 win;
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+
+       pci_mmcfg_config_num = 1;
+       pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+       if (!pci_mmcfg_config)
+               return NULL;
+       pci_mmcfg_config[0].address = (win & 0xf000) << 16;
+       pci_mmcfg_config[0].pci_segment = 0;
+       pci_mmcfg_config[0].start_bus_number = 0;
+       pci_mmcfg_config[0].end_bus_number = 255;
+
+       return "Intel Corporation E7520 Memory Controller Hub";
+}
+
+static const char __init *pci_mmcfg_intel_945(void)
+{
+       u32 pciexbar, mask = 0, len = 0;
+
+       pci_mmcfg_config_num = 1;
+
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+
+       /* Enable bit */
+       if (!(pciexbar & 1))
+               pci_mmcfg_config_num = 0;
+
+       /* Size bits */
+       switch ((pciexbar >> 1) & 3) {
+       case 0:
+               mask = 0xf0000000U;
+               len  = 0x10000000U;
+               break;
+       case 1:
+               mask = 0xf8000000U;
+               len  = 0x08000000U;
+               break;
+       case 2:
+               mask = 0xfc000000U;
+               len  = 0x04000000U;
+               break;
+       default:
+               pci_mmcfg_config_num = 0;
+       }
+
+       /* Errata #2, things break when not aligned on a 256Mb boundary */
+       /* Can only happen in 64M/128M mode */
+
+       if ((pciexbar & mask) & 0x0fffffffU)
+               pci_mmcfg_config_num = 0;
+
+       if (pci_mmcfg_config_num) {
+               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+               if (!pci_mmcfg_config)
+                       return NULL;
+               pci_mmcfg_config[0].address = pciexbar & mask;
+               pci_mmcfg_config[0].pci_segment = 0;
+               pci_mmcfg_config[0].start_bus_number = 0;
+               pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
+       }
+
+       return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
+}
+
+struct pci_mmcfg_hostbridge_probe {
+       u32 vendor;
+       u32 device;
+       const char *(*probe)(void);
+};
+
+static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+};
+
+static int __init pci_mmcfg_check_hostbridge(void)
+{
+       u32 l;
+       u16 vendor, device;
+       int i;
+       const char *name;
+
+       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+       vendor = l & 0xffff;
+       device = (l >> 16) & 0xffff;
+
+       pci_mmcfg_config_num = 0;
+       pci_mmcfg_config = NULL;
+       name = NULL;
+
+       for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+               if (pci_mmcfg_probes[i].vendor == vendor &&
+                   pci_mmcfg_probes[i].device == device)
+                       name = pci_mmcfg_probes[i].probe();
+       }
+
+       if (name) {
+               printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
+                      name, pci_mmcfg_config_num ? "with" : "without");
+       }
+
+       return name != NULL;
+}
+
+static void __init pci_mmcfg_insert_resources(void)
+{
+#define PCI_MMCFG_RESOURCE_NAME_LEN 19
+       int i;
+       struct resource *res;
+       char *names;
+       unsigned num_buses;
+
+       res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
+                       pci_mmcfg_config_num, GFP_KERNEL);
+       if (!res) {
+               printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
+               return;
+       }
+
+       names = (void *)&res[pci_mmcfg_config_num];
+       for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
+               struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
+               num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
+               res->name = names;
+               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+                        cfg->pci_segment);
+               res->start = cfg->address;
+               res->end = res->start + (num_buses << 20) - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               insert_resource(&iomem_resource, res);
+               names += PCI_MMCFG_RESOURCE_NAME_LEN;
+       }
+}
+
+static void __init pci_mmcfg_reject_broken(int type)
+{
+       typeof(pci_mmcfg_config[0]) *cfg;
+
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].address == 0))
+               return;
+
+       cfg = &pci_mmcfg_config[0];
+
+       /*
+        * Handle more broken MCFG tables on Asus etc.
+        * They only contain a single entry for bus 0-0.
+        */
+       if (pci_mmcfg_config_num == 1 &&
+           cfg->pci_segment == 0 &&
+           (cfg->start_bus_number | cfg->end_bus_number) == 0) {
+               printk(KERN_ERR "PCI: start and end of bus number is 0. "
+                      "Rejected as broken MCFG.\n");
+               goto reject;
+       }
+
+       /*
+        * Only do this check when type 1 works. If it doesn't work
+        * assume we run on a Mac and always use MCFG
+        */
+       if (type == 1 && !e820_all_mapped(cfg->address,
+                                         cfg->address + MMCONFIG_APER_MIN,
+                                         E820_RESERVED)) {
+               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
+                      " E820-reserved\n", cfg->address);
+               goto reject;
+       }
+       return;
+
+reject:
+       printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+       kfree(pci_mmcfg_config);
+       pci_mmcfg_config = NULL;
+       pci_mmcfg_config_num = 0;
+}
+
+void __init pci_mmcfg_init(int type)
+{
+       int known_bridge = 0;
+
+       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+               return;
+
+       if (type == 1 && pci_mmcfg_check_hostbridge())
+               known_bridge = 1;
+
+       if (!known_bridge) {
+               acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+               pci_mmcfg_reject_broken(type);
+       }
+
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].address == 0))
+               return;
+
+       if (pci_mmcfg_arch_init()) {
+               if (type == 1)
+                       unreachable_devices();
+               if (known_bridge)
+                       pci_mmcfg_insert_resources();
+               pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+       }
+}
index 5700220dcf5fa15a4c0984128ce0c8e95735bd60..bb1afd9e589d5bdf27a5bfe91b2c4cd78107e8f1 100644 (file)
 #include <asm/e820.h>
 #include "pci.h"
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN      (2 * 1024*1024)
-#define MMCONFIG_APER_MAX      (256 * 1024*1024)
-
 /* Assume systems with more busses have correct MCFG */
-#define MAX_CHECK_BUS 16
-
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
 static int mmcfg_last_accessed_cpu;
 
-static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
-
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
  */
 static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
 {
-       int cfg_num = -1;
        struct acpi_mcfg_allocation *cfg;
+       int cfg_num;
 
-       if (seg == 0 && bus < MAX_CHECK_BUS &&
-           test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
+       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
+           test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
                return 0;
 
-       while (1) {
-               ++cfg_num;
-               if (cfg_num >= pci_mmcfg_config_num) {
-                       break;
-               }
+       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
                cfg = &pci_mmcfg_config[cfg_num];
-               if (cfg->pci_segment != seg)
-                       continue;
-               if ((cfg->start_bus_number <= bus) &&
+               if (cfg->pci_segment == seg &&
+                   (cfg->start_bus_number <= bus) &&
                    (cfg->end_bus_number >= bus))
                        return cfg->address;
        }
 
-       /* Handle more broken MCFG tables on Asus etc.
-          They only contain a single entry for bus 0-0. Assume
-          this applies to all busses. */
-       cfg = &pci_mmcfg_config[0];
-       if (pci_mmcfg_config_num == 1 &&
-               cfg->pci_segment == 0 &&
-               (cfg->start_bus_number | cfg->end_bus_number) == 0)
-               return cfg->address;
-
        /* Fall back to type 0 */
        return 0;
 }
@@ -158,67 +136,15 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   Normally this can be expressed in the MCFG by not listing them
-   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
-   Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them. */
-static __init void unreachable_devices(void)
+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+                                   unsigned int devfn)
 {
-       int i, k;
-       unsigned long flags;
-
-       for (k = 0; k < MAX_CHECK_BUS; k++) {
-               for (i = 0; i < 32; i++) {
-                       u32 val1;
-                       u32 addr;
-
-                       pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-
-                       /* Locking probably not needed, but safer */
-                       spin_lock_irqsave(&pci_config_lock, flags);
-                       addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
-                       if (addr != 0)
-                               pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
-                       if (addr == 0 ||
-                           readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
-                               set_bit(i + 32*k, fallback_slots);
-                               printk(KERN_NOTICE
-                       "PCI: No mmconfig possible on %x:%x\n", k, i);
-                       }
-                       spin_unlock_irqrestore(&pci_config_lock, flags);
-               }
-       }
+       return get_base_addr(seg, bus, devfn) != 0;
 }
 
-void __init pci_mmcfg_init(int type)
+int __init pci_mmcfg_arch_init(void)
 {
-       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-               return;
-
-       acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return;
-
-       /* Only do this check when type 1 works. If it doesn't work
-          assume we run on a Mac and always use MCFG */
-       if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
-                       pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
-                       E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
-                               (unsigned long)pci_mmcfg_config[0].address);
-               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-               return;
-       }
-
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
-       pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
-
-       unreachable_devices();
+       return 1;
 }
index a0a25180b61a93b974d4e5918d85960a4093dd9d..e58bae2076ad50b96a0e2fb78493e198e44816ec 100644 (file)
@@ -94,3 +94,13 @@ extern void pci_pcbios_init(void);
 extern void pci_mmcfg_init(int type);
 extern void pcibios_sort(void);
 
+/* pci-mmconfig.c */
+
+/* Verify the first 16 busses. We assume that systems with more busses
+   get MCFG right. */
+#define PCI_MMCFG_MAX_CHECK_BUS 16
+extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+                                          unsigned int devfn);
+extern int __init pci_mmcfg_arch_init(void);
index db185f34e34117ddca100abf49df37d1af5bfed4..d51f0f11f7f95169f424cd99768928635be92dd3 100644 (file)
@@ -22,6 +22,7 @@ config IA64
 
 config 64BIT
        bool
+       select ATA_NONSTANDARD if ATA
        default y
 
 config ZONE_DMA
index 9197d7b361b33da914744bff7a2a393a799c9ba9..3549c94467b8a2ceea285af768f5a3a6da2dbc32 100644 (file)
@@ -651,7 +651,7 @@ int __init acpi_boot_init(void)
         * information -- the successor to MPS tables.
         */
 
-       if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) < 1) {
+       if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
                printk(KERN_ERR PREFIX "Can't find MADT\n");
                goto skip_madt;
        }
@@ -702,7 +702,7 @@ int __init acpi_boot_init(void)
         * gets interrupts such as power and sleep buttons.  If it's not
         * on a Legacy interrupt, it needs to be setup.
         */
-       if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt) < 1)
+       if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
                printk(KERN_ERR PREFIX "Can't find FADT\n");
 
 #ifdef CONFIG_SMP
index 37bb16f07fc3f2fd2b7a3ca8112f0d6a0a6af2e0..5cdd2f5fa064acbcd5ab266526545a5b4e77f3fd 100644 (file)
@@ -222,7 +222,7 @@ machine_crash_setup(void)
        if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
                return ret;
 #ifdef CONFIG_SYSCTL
-       register_sysctl_table(sys_table, 0);
+       register_sysctl_table(sys_table);
 #endif
        return 0;
 }
index ba3ba8bc50bef1aa77758256ec818e000eb88ff4..456f57b087ca78c9b3ddbc7244b125a6657ef8fa 100644 (file)
@@ -275,7 +275,7 @@ static struct irqaction ipi_irqaction = {
 
 static struct irqaction resched_irqaction = {
        .handler =      dummy_handler,
-       .flags =        SA_INTERRUPT,
+       .flags =        IRQF_DISABLED,
        .name =         "resched"
 };
 #endif
index 9860794a68fb520d9b387c9c093f7e1faf72ae2c..9ddf896a137a6033509739e4453b6963c116516d 100644 (file)
  * in UP:
  *     - we need to protect against PMU overflow interrupts (local_irq_disable)
  *
- * spin_lock_irqsave()/spin_lock_irqrestore():
+ * spin_lock_irqsave()/spin_unlock_irqrestore():
  *     in SMP: local_irq_disable + spin_lock
  *     in UP : local_irq_disable
  *
@@ -521,19 +521,57 @@ pfm_sysctl_t pfm_sysctl;
 EXPORT_SYMBOL(pfm_sysctl);
 
 static ctl_table pfm_ctl_table[]={
-       {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
-       {2, "debug_ovfl", &pfm_sysctl.debug_ovfl, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
-       {3, "fastctxsw", &pfm_sysctl.fastctxsw, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
-       {4, "expert_mode", &pfm_sysctl.expert_mode, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
-       { 0, },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "debug",
+               .data           = &pfm_sysctl.debug,
+               .maxlen         = sizeof(int),
+               .mode           = 0666,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "debug_ovfl",
+               .data           = &pfm_sysctl.debug_ovfl,
+               .maxlen         = sizeof(int),
+               .mode           = 0666,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "fastctxsw",
+               .data           = &pfm_sysctl.fastctxsw,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   =  &proc_dointvec,
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "expert_mode",
+               .data           = &pfm_sysctl.expert_mode,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = &proc_dointvec,
+       },
+       {}
 };
 static ctl_table pfm_sysctl_dir[] = {
-       {1, "perfmon", NULL, 0, 0755, pfm_ctl_table, },
-       {0,},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "perfmon",
+               .mode           = 0755,
+               .child          = pfm_ctl_table,
+       },
+       {}
 };
 static ctl_table pfm_sysctl_root[] = {
-       {1, "kernel", NULL, 0, 0755, pfm_sysctl_dir, },
-       {0,},
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0755,
+               .child          = pfm_sysctl_dir,
+       },
+       {}
 };
 static struct ctl_table_header *pfm_sysctl_header;
 
@@ -6688,7 +6726,7 @@ pfm_init(void)
        /*
         * create /proc/sys/kernel/perfmon (for debugging purposes)
         */
-       pfm_sysctl_header = register_sysctl_table(pfm_sysctl_root, 0);
+       pfm_sysctl_header = register_sysctl_table(pfm_sysctl_root);
 
        /*
         * initialize all our spinlocks
index 7a387d2373637a7ba9801f0691820674680ae24f..68355ef6f84170096b52aee5938a390143841e10 100644 (file)
@@ -101,67 +101,57 @@ static int xpc_disengage_request_max_timelimit = 120;
 
 static ctl_table xpc_sys_xpc_hb_dir[] = {
        {
-               1,
-               "hb_interval",
-               &xpc_hb_interval,
-               sizeof(int),
-               0644,
-               NULL,
-               &proc_dointvec_minmax,
-               &sysctl_intvec,
-               NULL,
-               &xpc_hb_min_interval,
-               &xpc_hb_max_interval
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "hb_interval",
+               .data           = &xpc_hb_interval,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xpc_hb_min_interval,
+               .extra2         = &xpc_hb_max_interval
        },
        {
-               2,
-               "hb_check_interval",
-               &xpc_hb_check_interval,
-               sizeof(int),
-               0644,
-               NULL,
-               &proc_dointvec_minmax,
-               &sysctl_intvec,
-               NULL,
-               &xpc_hb_check_min_interval,
-               &xpc_hb_check_max_interval
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "hb_check_interval",
+               .data           = &xpc_hb_check_interval,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xpc_hb_check_min_interval,
+               .extra2         = &xpc_hb_check_max_interval
        },
-       {0}
+       {}
 };
 static ctl_table xpc_sys_xpc_dir[] = {
        {
-               1,
-               "hb",
-               NULL,
-               0,
-               0555,
-               xpc_sys_xpc_hb_dir
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "hb",
+               .mode           = 0555,
+               .child          = xpc_sys_xpc_hb_dir
        },
        {
-               2,
-               "disengage_request_timelimit",
-               &xpc_disengage_request_timelimit,
-               sizeof(int),
-               0644,
-               NULL,
-               &proc_dointvec_minmax,
-               &sysctl_intvec,
-               NULL,
-               &xpc_disengage_request_min_timelimit,
-               &xpc_disengage_request_max_timelimit
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "disengage_request_timelimit",
+               .data           = &xpc_disengage_request_timelimit,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xpc_disengage_request_min_timelimit,
+               .extra2         = &xpc_disengage_request_max_timelimit
        },
-       {0}
+       {}
 };
 static ctl_table xpc_sys_dir[] = {
        {
-               1,
-               "xpc",
-               NULL,
-               0,
-               0555,
-               xpc_sys_xpc_dir
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "xpc",
+               .mode           = 0555,
+               .child          = xpc_sys_xpc_dir
        },
-       {0}
+       {}
 };
 static struct ctl_table_header *xpc_sysctl;
 
@@ -1251,7 +1241,7 @@ xpc_init(void)
        snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
        snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
 
-       xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);
+       xpc_sysctl = register_sysctl_table(xpc_sys_dir);
 
        /*
         * The first few fields of each entry of xpc_partitions[] need to
index 896cef1aca5f43b8da34b8d9d45b2858f3ce84e5..82abd159dbef495253bb2989093f86809b085ca5 100644 (file)
@@ -293,7 +293,7 @@ long strnlen_user(const char __user *s, long n)
                : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
                : "r0", "r1", "cbit");
 
-       /* NOTE: strnlen_user() algorism:
+       /* NOTE: strnlen_user() algorithm:
         * {
         *   char *p;
         *   for (p = s; n-- && *p != '\0'; ++p)
@@ -369,7 +369,7 @@ long strnlen_user(const char __user *s, long n)
                : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
                : "r0", "r1", "r2", "r3", "cbit");
 
-       /* NOTE: strnlen_user() algorism:
+       /* NOTE: strnlen_user() algorithm:
         * {
         *   char *p;
         *   for (p = s; n-- && *p != '\0'; ++p)
index d01deb46ebbcb60ee092085c0bef142a0c049da6..ab3fd5202b2477c5624e4a23fbac11f78e7063bb 100644 (file)
@@ -174,7 +174,7 @@ int stdma_islocked(void)
 void __init stdma_init(void)
 {
        stdma_isr = NULL;
-       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | SA_SHIRQ,
+       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
                    "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
 }
 
index 87b112b363a618fda2c8c76cb784269e11c5c224..92e58070b01664f31d10625b02822ddc2ede3bff 100644 (file)
@@ -104,7 +104,7 @@ unsigned long coldfire_timer_offset(void)
 
 /*
  *     Choose a reasonably fast profile timer. Make it an odd value to
- *     try and get good coverage of kernal operations.
+ *     try and get good coverage of kernel operations.
  */
 #define        PROFILEHZ       1013
 
index 7504a63646161f81ec3d9176be903d8955c5da57..3901e8e04755502a1af4e5cf55caa8e79beec1a9 100644 (file)
@@ -62,12 +62,6 @@ extern unsigned long save_local_and_disable(int controller);
 extern void restore_local_and_enable(int controller, unsigned long mask);
 extern void local_enable_irq(unsigned int irq_nr);
 
-/* Quick acpi hack. This will have to change! */
-#define        CTL_ACPI 9999
-#define        ACPI_S1_SLP_TYP 19
-#define        ACPI_SLEEP 21
-
-
 static DEFINE_SPINLOCK(pm_lock);
 
 /* We need to save/restore a bunch of core registers that are
@@ -425,15 +419,41 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
 
 
 static struct ctl_table pm_table[] = {
-       {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
-       {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
-       {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "suspend",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0600,
+               .proc_handler   = &pm_do_suspend
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "sleep",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0600,
+               .proc_handler   = &pm_do_sleep
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "freq",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0600,
+               .proc_handler   = &pm_do_freq
+       },
+       {}
 };
 
 static struct ctl_table pm_dir_table[] = {
-       {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "pm",
+               .mode           = 0555,
+               .child          = pm_table
+       },
+       {}
 };
 
 /*
@@ -441,7 +461,7 @@ static struct ctl_table pm_dir_table[] = {
  */
 static int __init pm_init(void)
 {
-       register_sysctl_table(pm_dir_table, 1);
+       register_sysctl_table(pm_dir_table);
        return 0;
 }
 
index e0ad754c7edd2eeb3b2cd37f8eafda4c24c3caca..8f42fa85ac9e4e274ae46aaf9b22b14f8303fe3c 100644 (file)
@@ -13,8 +13,8 @@
 #include <asm/cacheflush.h>
 #include <asm/page.h>
 
-const extern unsigned char relocate_new_kernel[];
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned char relocate_new_kernel[];
+extern const unsigned int relocate_new_kernel_size;
 
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
index 545fcbc8cea2283525f3b7fd6b214c9646c9545e..e5e56bd498dbcf0d650fe22152ad98e6c5d62a8e 100644 (file)
@@ -307,7 +307,7 @@ static unsigned int __init calibrate_hpt(void)
 struct clocksource clocksource_mips = {
        .name           = "MIPS",
        .mask           = 0xffffffff,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init init_mips_clocksource(void)
index 12878359f2c883673950f0e90ec2da01732c543d..699ab1886ceba8deeff05f626e23597a8b560ee8 100644 (file)
@@ -302,42 +302,129 @@ extern int lasat_boot_to_service;
 #ifdef CONFIG_SYSCTL
 
 static ctl_table lasat_table[] = {
-       {LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int),
-        0444, NULL, &proc_dointvec, &sysctl_intvec},
-       {LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int),
-        0444, NULL, &proc_dointvec, &sysctl_intvec},
-       {LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int),
-        0444, NULL, &proc_dointvec, &sysctl_intvec},
-       {LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int),
-        0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "cpu-hz",
+               .data           = &lasat_board_info.li_cpu_hz,
+               .maxlen         = sizeof(int),
+               .mode           = 0444,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "bus-hz",
+               .data           = &lasat_board_info.li_bus_hz,
+               .maxlen         = sizeof(int),
+               .mode           = 0444,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "bmid",
+               .data           = &lasat_board_info.li_bmid,
+               .maxlen         = sizeof(int),
+               .mode           = 0444,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "prid",
+               .data           = &lasat_board_info.li_prid,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_lasat_eeprom_value,
+               .strategy       = &sysctl_lasat_eeprom_value
+       },
 #ifdef CONFIG_INET
-       {LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int),
-        0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
-       {LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int),
-        0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
-       {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
-               sizeof(lasat_bcastaddr), 0600, NULL,
-               &proc_dostring, &sysctl_string},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "ipaddr",
+               .data           = &lasat_board_info.li_eeprom_info.ipaddr,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_lasat_ip,
+               .strategy       = &sysctl_lasat_intvec
+       },
+       {
+               .ctl_name       = LASAT_NETMASK,
+               .procname       = "netmask",
+               .data           = &lasat_board_info.li_eeprom_info.netmask,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_lasat_ip,
+               .strategy       = &sysctl_lasat_intvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "bcastaddr",
+               .data           = &lasat_bcastaddr,
+               .maxlen         = sizeof(lasat_bcastaddr),
+               .mode           = 0600,
+               .proc_handler   = &proc_dostring,
+               .strategy       = &sysctl_string
+       },
 #endif
-       {LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
-        0600, NULL, &proc_dolasatstring, &sysctl_lasatstring},
-       {LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int),
-        0644, NULL, &proc_dointvec, &sysctl_intvec},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "passwd_hash",
+               .data           = &lasat_board_info.li_eeprom_info.passwd_hash,
+               .maxlen         = sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
+               .mode           = 0600,
+               .proc_handler   = &proc_dolasatstring,
+               .strategy       = &sysctl_lasatstring
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "boot-service",
+               .data           = &lasat_boot_to_service,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec
+       },
 #ifdef CONFIG_DS1603
-       {LASAT_RTC, "rtc", &rtctmp, sizeof(int),
-        0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "rtc",
+               .data           = &rtctmp,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dolasatrtc,
+               .strategy       = &sysctl_lasat_rtc
+       },
 #endif
-       {LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr),
-        0444, NULL, &proc_dostring, &sysctl_string},
-       {LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr),
-        0444, NULL, &proc_dostring, &sysctl_string},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "namestr",
+               .data           = &lasat_board_info.li_namestr,
+               .maxlen         = sizeof(lasat_board_info.li_namestr),
+               .mode           = 0444,
+               .proc_handler   =  &proc_dostring,
+               .strategy       = &sysctl_string
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "typestr",
+               .data           = &lasat_board_info.li_typestr,
+               .maxlen         = sizeof(lasat_board_info.li_typestr),
+               .mode           = 0444,
+               .proc_handler   = &proc_dostring,
+               .strategy       = &sysctl_string
+       },
+       {}
 };
 
-#define CTL_LASAT 1    // CTL_ANY ???
 static ctl_table lasat_root_table[] = {
-       { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table },
-       { 0 }
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "lasat",
+               .mode           =  0555,
+               .child          = lasat_table
+       },
+       {}
 };
 
 static int __init lasat_register_sysctl(void)
@@ -345,7 +432,7 @@ static int __init lasat_register_sysctl(void)
        struct ctl_table_header *lasat_table_header;
 
        lasat_table_header =
-               register_sysctl_table(lasat_root_table, 0);
+               register_sysctl_table(lasat_root_table);
 
        return 0;
 }
index 068b20d822e7b9c672983135a0c038e11e491839..d71cb018a21e0466a22f30fe25bc7e0cf49850c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/parisc/kernel/topology.c - Populate driverfs with topology information
+ * arch/parisc/kernel/topology.c - Populate sysfs with topology information
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 340d9beab6d1368978907f387fa1ff9943a71123..6dfbd52694ab855600205680beea9b3b49c89ed4 100644 (file)
@@ -620,6 +620,15 @@ config RTAS_FLASH
        tristate "Firmware flash interface"
        depends on PPC64 && RTAS_PROC
 
+config PPC_PMI
+       tristate "Support for PMI"
+       depends PPC_IBM_CELL_BLADE
+       help
+         PMI (Platform Management Interrupt) is a way to
+         communicate with the BMC (Baseboard Mangement Controller).
+         It is used in some IBM Cell blades.
+       default m
+
 config MMIO_NVRAM
        bool
        default n
index 096e94ac415f6611081f92fef64d387231490660..b89791802e86efcc422c97ba9c71954d022312b0 100644 (file)
@@ -35,7 +35,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
 
                PowerPC,603e { /* Really 8241 */
                        linux,phandle = <2100>;
-                       linux,boot-cpu;
                        device_type = "cpu";
                        reg = <0>;
                        clock-frequency = <bebc200>;    /* Fixed by bootwrapper */
index d06b0b0188996a6673a1d92d6fea54da7c9bbfa7..753102752d8babb0d83142b93681b1053b26f047 100644 (file)
@@ -35,7 +35,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
 
                PowerPC,603e { /* Really 8241 */
                        linux,phandle = <2100>;
-                       linux,boot-cpu;
                        device_type = "cpu";
                        reg = <0>;
                        clock-frequency = <fdad680>;    /* Fixed by bootwrapper */
index c4d9562cbaadd40320f20d45db802ffbe85c77ad..41d0720c5900a2d27eba79f37650ab0b863fba2a 100644 (file)
@@ -36,7 +36,6 @@
                        bus-frequency = <0>;            // From U-Boot
                        32-bit;
                        linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
index 26b44f7513dcfe12cfc46f8f5574921f58a08d83..260b2e447779f5c672ed686dac183416b8864529 100644 (file)
@@ -34,7 +34,6 @@
                        clock-frequency = <0>;
                        32-bit;
                        linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
index 3d2f5a06df3f1216d0861a07a8f5672760668c76..6d721900d00e702d3d4b4b1e5f7709f74227fd51 100644 (file)
@@ -11,7 +11,7 @@
 
 / {
        model = "MPC8313ERDB";
-       compatible = "MPC83xx";
+       compatible = "MPC8313ERDB", "MPC831xRDB", "MPC83xxRDB";
        #address-cells = <1>;
        #size-cells = <1>;
 
@@ -59,7 +59,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -68,7 +68,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -77,7 +77,7 @@
                        compatible = "mpc83xx_spi";
                        reg = <7000 1000>;
                        interrupts = <10 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        mode = <0>;
                };
 
@@ -88,8 +88,8 @@
                        reg = <23000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <26 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <26 8>;
                        phy_type = "utmi_wide";
                };
 
                        reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <700>;
-                               interrupts = <13 2>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <13 8>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@4 {
-                               linux,phandle = <2452004>;
-                               interrupt-parent = <700>;
-                               interrupts = <14 2>;
+                       phy4: ethernet-phy@4 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <14 8>;
                                reg = <4>;
                                device_type = "ethernet-phy";
                        };
                        reg = <24000 1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <25 8 24 8 23 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy1 >;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <22 8 21 8 20 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <2452004>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy4 >;
                };
 
                serial@4500 {
                        reg = <4500 100>;
                        clock-frequency = <0>;
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                pci@8500 {
                        interrupt-map = <
 
                                        /* IDSEL 0x0E -mini PCI */
-                                        7000 0 0 1 700 12 8
-                                        7000 0 0 2 700 12 8
-                                        7000 0 0 3 700 12 8
-                                        7000 0 0 4 700 12 8
+                                        7000 0 0 1 &ipic 12 8
+                                        7000 0 0 2 &ipic 12 8
+                                        7000 0 0 3 &ipic 12 8
+                                        7000 0 0 4 &ipic 12 8
 
                                        /* IDSEL 0x0F - PCI slot */
-                                        7800 0 0 1 700 11 8
-                                        7800 0 0 2 700 12 8
-                                        7800 0 0 3 700 11 8
-                                        7800 0 0 4 700 12 8>;
-                       interrupt-parent = <700>;
+                                        7800 0 0 1 &ipic 11 8
+                                        7800 0 0 2 &ipic 12 8
+                                        7800 0 0 3 &ipic 11 8
+                                        7800 0 0 4 &ipic 12 8>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 90000000 90000000 0 10000000
                        compatible = "talitos";
                        reg = <30000 7000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        /* Rev. 2.2 */
                        num-channels = <1>;
                        channel-fifo-len = <18>;
                 * sense == 8: Level, low assertion
                 * sense == 2: Edge, high-to-low change
                 */
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
similarity index 77%
rename from arch/powerpc/boot/dts/mpc8323emds.dts
rename to arch/powerpc/boot/dts/mpc832x_mds.dts
index fa7ef24d205b7f8c7b1ed7652130a2c94a2f78d3..06b310698a024e95e759302c9f9a79be24ef1add 100644 (file)
 
 / {
        model = "MPC8323EMDS";
-       compatible = "MPC83xx";
+       compatible = "MPC8323EMDS", "MPC832xMDS", "MPC83xxMDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8323@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        32-bit;
-                       linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 08000000>;
        };
 
@@ -69,7 +64,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -79,7 +74,7 @@
                        reg = <4500 100>;
                        clock-frequency = <0>;
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
@@ -88,7 +83,7 @@
                        reg = <4600 100>;
                        clock-frequency = <0>;
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                crypto@30000 {
@@ -97,7 +92,7 @@
                        compatible = "talitos";
                        reg = <30000 7000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        /* Rev. 2.2 */
                        num-channels = <1>;
                        channel-fifo-len = <18>;
                };
 
                pci@8500 {
-                       linux,phandle = <8500>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                        /* IDSEL 0x11 AD17 */
-                                        8800 0 0 1 700 14 8
-                                        8800 0 0 2 700 15 8
-                                        8800 0 0 3 700 16 8
-                                        8800 0 0 4 700 17 8
+                                        8800 0 0 1 &ipic 14 8
+                                        8800 0 0 2 &ipic 15 8
+                                        8800 0 0 3 &ipic 16 8
+                                        8800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x12 AD18 */
-                                        9000 0 0 1 700 16 8
-                                        9000 0 0 2 700 17 8
-                                        9000 0 0 3 700 14 8
-                                        9000 0 0 4 700 15 8
+                                        9000 0 0 1 &ipic 16 8
+                                        9000 0 0 2 &ipic 17 8
+                                        9000 0 0 3 &ipic 14 8
+                                        9000 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x13 AD19 */
-                                        9800 0 0 1 700 17 8
-                                        9800 0 0 2 700 14 8
-                                        9800 0 0 3 700 15 8
-                                        9800 0 0 4 700 16 8
+                                        9800 0 0 1 &ipic 17 8
+                                        9800 0 0 2 &ipic 14 8
+                                        9800 0 0 3 &ipic 15 8
+                                        9800 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x15 AD21*/
-                                        a800 0 0 1 700 14 8
-                                        a800 0 0 2 700 15 8
-                                        a800 0 0 3 700 16 8
-                                        a800 0 0 4 700 17 8
+                                        a800 0 0 1 &ipic 14 8
+                                        a800 0 0 2 &ipic 15 8
+                                        a800 0 0 3 &ipic 16 8
+                                        a800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x16 AD22*/
-                                        b000 0 0 1 700 17 8
-                                        b000 0 0 2 700 14 8
-                                        b000 0 0 3 700 15 8
-                                        b000 0 0 4 700 16 8
+                                        b000 0 0 1 &ipic 17 8
+                                        b000 0 0 2 &ipic 14 8
+                                        b000 0 0 3 &ipic 15 8
+                                        b000 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x17 AD23*/
-                                        b800 0 0 1 700 16 8
-                                        b800 0 0 2 700 17 8
-                                        b800 0 0 3 700 14 8
-                                        b800 0 0 4 700 15 8
+                                        b800 0 0 1 &ipic 16 8
+                                        b800 0 0 2 &ipic 17 8
+                                        b800 0 0 3 &ipic 14 8
+                                        b800 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x18 AD24*/
-                                        c000 0 0 1 700 15 8
-                                        c000 0 0 2 700 16 8
-                                        c000 0 0 3 700 17 8
-                                        c000 0 0 4 700 14 8>;
-                       interrupt-parent = <700>;
+                                        c000 0 0 1 &ipic 15 8
+                                        c000 0 0 2 &ipic 16 8
+                                        c000 0 0 3 &ipic 17 8
+                                        c000 0 0 4 &ipic 14 8>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 90000000 0 10000000
                        device_type = "pci";
                };
 
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        device_type = "par_io";
                        num-ports = <7>;
 
-                       ucc_pin@03 {
-                               linux,phandle = <140003>;
+                       pio3: ucc_pin@03 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        3  4  3  0  2  0  /* MDIO */
                                        1  c  1  0  1  0        /* TX_EN */
                                        1  d  2  0  1  0>;/* CRS */
                        };
-                       ucc_pin@04 {
-                               linux,phandle = <140004>;
+                       pio4: ucc_pin@04 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        3 1f  2  0  1  0        /* RX_CLK (CLK7) */
                        compatible = "fsl_spi";
                        reg = <4c0 40>;
                        interrupts = <2>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "cpu";
                };
 
                        compatible = "fsl_spi";
                        reg = <500 40>;
                        interrupts = <1>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "cpu";
                };
 
                        compatible = "qe_udc";
                        reg = <6c0 40 8B00 100>;
                        interrupts = <b>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "slave";
                };
 
                        device-id = <3>;
                        reg = <2200 200>;
                        interrupts = <22>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mac-address = [ 00 04 9f 00 23 23 ];
                        rx-clock = <19>;
                        tx-clock = <1a>;
-                       phy-handle = <212003>;
-                       pio-handle = <140003>;
+                       phy-handle = < &phy3 >;
+                       pio-handle = < &pio3 >;
                };
 
                ucc@3200 {
                        device-id = <4>;
                        reg = <3000 200>;
                        interrupts = <23>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mac-address = [ 00 11 22 33 44 55 ];
                        rx-clock = <17>;
                        tx-clock = <18>;
-                       phy-handle = <212004>;
-                       pio-handle = <140004>;
+                       phy-handle = < &phy4 >;
+                       pio-handle = < &pio4 >;
                };
 
                mdio@2320 {
                        device_type = "mdio";
                        compatible = "ucc_geth_phy";
 
-                       ethernet-phy@03 {
-                               linux,phandle = <212003>;
-                               interrupt-parent = <700>;
-                               interrupts = <11 2>;
+                       phy3: ethernet-phy@03 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <11 8>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                                interface = <3>; //ENET_100_MII
                        };
-                       ethernet-phy@04 {
-                               linux,phandle = <212004>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy4: ethernet-phy@04 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <4>;
                                device_type = "ethernet-phy";
                                interface = <3>;
                        };
                };
 
-               qeic@80 {
-                       linux,phandle = <80>;
+               qeic: qeic@80 {
                        interrupt-controller;
                        device_type = "qeic";
                        #address-cells = <0>;
                        built-in;
                        big-endian;
                        interrupts = <20 8 21 8>; //high:32 low:33
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
        };
 };
index 27807fc45888d1dee01028e3e7c00000cd4dd017..61b550bf1645df06b9425167b3132d6571db2d7a 100644 (file)
@@ -10,7 +10,7 @@
  */
 / {
        model = "MPC8349EMITX";
-       compatible = "MPC834xMITX";
+       compatible = "MPC8349EMITX", "MPC834xMITX", "MPC83xxMITX";
        #address-cells = <1>;
        #size-cells = <1>;
 
@@ -58,7 +58,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -67,7 +67,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -76,7 +76,7 @@
                        compatible = "mpc83xx_spi";
                        reg = <7000 1000>;
                        interrupts = <10 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        mode = <0>;
                };
 
@@ -86,8 +86,8 @@
                        reg = <22000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <27 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <27 8>;
                        phy_type = "ulpi";
                        port1;
                };
@@ -98,8 +98,8 @@
                        reg = <23000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <26 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <26 8>;
                        phy_type = "ulpi";
                };
 
                        reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       linux,phandle = <24520>;
 
                        /* Vitesse 8201 */
-                       ethernet-phy@1c {
-                               linux,phandle = <245201c>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy1c: ethernet-phy@1c {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <1c>;
                                device_type = "ethernet-phy";
                        };
 
                        /* Vitesse 7385 */
-                       ethernet-phy@1f {
-                               linux,phandle = <245201f>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy1f: ethernet-phy@1f {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <1f>;
                                device_type = "ethernet-phy";
                        };
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <245201c>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy1c >;
                };
 
                ethernet@25000 {
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <245201f>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy1f >;
                };
 
                serial@4500 {
                        reg = <4500 100>;
                        clock-frequency = <0>;          // from bootloader
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;          // from bootloader
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                pci@8500 {
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                        /* IDSEL 0x10 - SATA */
-                                       8000 0 0 1 700 16 8 /* SATA_INTA */
+                                       8000 0 0 1 &ipic 16 8 /* SATA_INTA */
                                        >;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <42000000 0 80000000 80000000 0 10000000
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                        /* IDSEL 0x0E - MiniPCI Slot */
-                                       7000 0 0 1 700 15 8 /* PCI_INTA */
+                                       7000 0 0 1 &ipic 15 8 /* PCI_INTA */
 
                                        /* IDSEL 0x0F - PCI Slot */
-                                       7800 0 0 1 700 14 8 /* PCI_INTA */
-                                       7800 0 0 2 700 15 8 /* PCI_INTB */
+                                       7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+                                       7800 0 0 2 &ipic 15 8 /* PCI_INTB */
                                         >;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <43 8>;
                        bus-range = <1 1>;
                        ranges = <42000000 0 a0000000 a0000000 0 10000000
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
                        descriptor-types-mask = <01010ebf>;
                };
 
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
index 3190774de1d8896ebd07626023579bf0a8530e19..b2e1a5ec3779b60959b5cf6ef2961400f3173a1e 100644 (file)
@@ -10,7 +10,7 @@
  */
 / {
        model = "MPC8349EMITXGP";
-       compatible = "MPC834xMITXGP";
+       compatible = "MPC8349EMITXGP", "MPC834xMITX", "MPC83xxMITX";
        #address-cells = <1>;
        #size-cells = <1>;
 
@@ -58,7 +58,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -67,7 +67,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -76,7 +76,7 @@
                        compatible = "mpc83xx_spi";
                        reg = <7000 1000>;
                        interrupts = <10 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        mode = <0>;
                };
 
@@ -86,8 +86,8 @@
                        reg = <23000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <26 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <26 8>;
                        dr_mode = "otg";
                        phy_type = "ulpi";
                };
                        reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       linux,phandle = <24520>;
 
                        /* Vitesse 8201 */
-                       ethernet-phy@1c {
-                               linux,phandle = <245201c>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy1c: ethernet-phy@1c {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <1c>;
                                device_type = "ethernet-phy";
                        };
                        reg = <24000 1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <245201c>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy1c >;
                };
 
                serial@4500 {
                        reg = <4500 100>;
                        clock-frequency = <0>;          // from bootloader
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;          // from bootloader
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                pci@8600 {
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                        /* IDSEL 0x0F - PCI Slot */
-                                       7800 0 0 1 700 14 8 /* PCI_INTA */
-                                       7800 0 0 2 700 15 8 /* PCI_INTB */
+                                       7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+                                       7800 0 0 2 &ipic 15 8 /* PCI_INTB */
                                         >;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <43 8>;
                        bus-range = <1 1>;
                        ranges = <42000000 0 a0000000 a0000000 0 10000000
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
                        descriptor-types-mask = <01010ebf>;
                };
 
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
index dc121b3cb4a9654a9b6bf48355989651f34b3767..e4b43c24bc0bb54750c6ec9bd2fa864702e000e5 100644 (file)
@@ -11,7 +11,7 @@
 
 / {
        model = "MPC8349EMDS";
-       compatible = "MPC834xMDS";
+       compatible = "MPC8349EMDS", "MPC834xMDS", "MPC83xxMDS";
        #address-cells = <1>;
        #size-cells = <1>;
 
@@ -64,7 +64,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -73,7 +73,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -82,7 +82,7 @@
                        compatible = "mpc83xx_spi";
                        reg = <7000 1000>;
                        interrupts = <10 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        mode = <0>;
                };
 
@@ -94,8 +94,8 @@
                        reg = <22000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <27 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <27 8>;
                        phy_type = "ulpi";
                        port1;
                };
                        reg = <23000 1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       interrupt-parent = <700>;
-                       interrupts = <26 2>;
+                       interrupt-parent = < &ipic >;
+                       interrupts = <26 8>;
                        dr_mode = "otg";
                        phy_type = "ulpi";
                };
                        reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <700>;
-                               interrupts = <11 2>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <11 8>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy0 >;
                };
 
                ethernet@25000 {
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
-                       interrupt-parent = <700>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = < &ipic >;
+                       phy-handle = < &phy1 >;
                };
 
                serial@4500 {
                        reg = <4500 100>;
                        clock-frequency = <0>;
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                pci@8500 {
                        interrupt-map = <
 
                                        /* IDSEL 0x11 */
-                                        8800 0 0 1 700 14 8
-                                        8800 0 0 2 700 15 8
-                                        8800 0 0 3 700 16 8
-                                        8800 0 0 4 700 17 8
+                                        8800 0 0 1 &ipic 14 8
+                                        8800 0 0 2 &ipic 15 8
+                                        8800 0 0 3 &ipic 16 8
+                                        8800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x12 */
-                                        9000 0 0 1 700 16 8
-                                        9000 0 0 2 700 17 8
-                                        9000 0 0 3 700 14 8
-                                        9000 0 0 4 700 15 8
+                                        9000 0 0 1 &ipic 16 8
+                                        9000 0 0 2 &ipic 17 8
+                                        9000 0 0 3 &ipic 14 8
+                                        9000 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x13 */
-                                        9800 0 0 1 700 17 8
-                                        9800 0 0 2 700 14 8
-                                        9800 0 0 3 700 15 8
-                                        9800 0 0 4 700 16 8
+                                        9800 0 0 1 &ipic 17 8
+                                        9800 0 0 2 &ipic 14 8
+                                        9800 0 0 3 &ipic 15 8
+                                        9800 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x15 */
-                                        a800 0 0 1 700 14 8
-                                        a800 0 0 2 700 15 8
-                                        a800 0 0 3 700 16 8
-                                        a800 0 0 4 700 17 8
+                                        a800 0 0 1 &ipic 14 8
+                                        a800 0 0 2 &ipic 15 8
+                                        a800 0 0 3 &ipic 16 8
+                                        a800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x16 */
-                                        b000 0 0 1 700 17 8
-                                        b000 0 0 2 700 14 8
-                                        b000 0 0 3 700 15 8
-                                        b000 0 0 4 700 16 8
+                                        b000 0 0 1 &ipic 17 8
+                                        b000 0 0 2 &ipic 14 8
+                                        b000 0 0 3 &ipic 15 8
+                                        b000 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x17 */
-                                        b800 0 0 1 700 16 8
-                                        b800 0 0 2 700 17 8
-                                        b800 0 0 3 700 14 8
-                                        b800 0 0 4 700 15 8
+                                        b800 0 0 1 &ipic 16 8
+                                        b800 0 0 2 &ipic 17 8
+                                        b800 0 0 3 &ipic 14 8
+                                        b800 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x18 */
-                                        c000 0 0 1 700 15 8
-                                        c000 0 0 2 700 16 8
-                                        c000 0 0 3 700 17 8
-                                        c000 0 0 4 700 14 8>;
-                       interrupt-parent = <700>;
+                                        c000 0 0 1 &ipic 15 8
+                                        c000 0 0 2 &ipic 16 8
+                                        c000 0 0 3 &ipic 17 8
+                                        c000 0 0 4 &ipic 14 8>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 10000000
                        interrupt-map = <
 
                                        /* IDSEL 0x11 */
-                                        8800 0 0 1 700 14 8
-                                        8800 0 0 2 700 15 8
-                                        8800 0 0 3 700 16 8
-                                        8800 0 0 4 700 17 8
+                                        8800 0 0 1 &ipic 14 8
+                                        8800 0 0 2 &ipic 15 8
+                                        8800 0 0 3 &ipic 16 8
+                                        8800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x12 */
-                                        9000 0 0 1 700 16 8
-                                        9000 0 0 2 700 17 8
-                                        9000 0 0 3 700 14 8
-                                        9000 0 0 4 700 15 8
+                                        9000 0 0 1 &ipic 16 8
+                                        9000 0 0 2 &ipic 17 8
+                                        9000 0 0 3 &ipic 14 8
+                                        9000 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x13 */
-                                        9800 0 0 1 700 17 8
-                                        9800 0 0 2 700 14 8
-                                        9800 0 0 3 700 15 8
-                                        9800 0 0 4 700 16 8
+                                        9800 0 0 1 &ipic 17 8
+                                        9800 0 0 2 &ipic 14 8
+                                        9800 0 0 3 &ipic 15 8
+                                        9800 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x15 */
-                                        a800 0 0 1 700 14 8
-                                        a800 0 0 2 700 15 8
-                                        a800 0 0 3 700 16 8
-                                        a800 0 0 4 700 17 8
+                                        a800 0 0 1 &ipic 14 8
+                                        a800 0 0 2 &ipic 15 8
+                                        a800 0 0 3 &ipic 16 8
+                                        a800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x16 */
-                                        b000 0 0 1 700 17 8
-                                        b000 0 0 2 700 14 8
-                                        b000 0 0 3 700 15 8
-                                        b000 0 0 4 700 16 8
+                                        b000 0 0 1 &ipic 17 8
+                                        b000 0 0 2 &ipic 14 8
+                                        b000 0 0 3 &ipic 15 8
+                                        b000 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x17 */
-                                        b800 0 0 1 700 16 8
-                                        b800 0 0 2 700 17 8
-                                        b800 0 0 3 700 14 8
-                                        b800 0 0 4 700 15 8
+                                        b800 0 0 1 &ipic 16 8
+                                        b800 0 0 2 &ipic 17 8
+                                        b800 0 0 3 &ipic 14 8
+                                        b800 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x18 */
-                                        c000 0 0 1 700 15 8
-                                        c000 0 0 2 700 16 8
-                                        c000 0 0 3 700 17 8
-                                        c000 0 0 4 700 14 8>;
-                       interrupt-parent = <700>;
+                                        c000 0 0 1 &ipic 15 8
+                                        c000 0 0 2 &ipic 16 8
+                                        c000 0 0 3 &ipic 17 8
+                                        c000 0 0 4 &ipic 14 8>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 b0000000 b0000000 0 10000000
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
                 * sense == 8: Level, low assertion
                 * sense == 2: Edge, high-to-low change
                 */
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
similarity index 79%
rename from arch/powerpc/boot/dts/mpc8360emds.dts
rename to arch/powerpc/boot/dts/mpc836x_mds.dts
index 9022192155b95a55385ecdf53a6711ab59d6cc49..4fe45c02184898f9dde59a8f94e5077cab5e8974 100644 (file)
 */
 
 / {
-       model = "MPC8360EPB";
-       compatible = "MPC83xx";
+       model = "MPC8360MDS";
+       compatible = "MPC8360EMDS", "MPC836xMDS", "MPC83xxMDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8360@0 {
                        device_type = "cpu";
                        bus-frequency = <FBC5200>;
                        clock-frequency = <1F78A400>;
                        32-bit;
-                       linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 10000000>;
        };
 
@@ -74,7 +69,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -83,7 +78,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        dfsrr;
                };
 
@@ -93,7 +88,7 @@
                        reg = <4500 100>;
                        clock-frequency = <FBC5200>;
                        interrupts = <9 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <FBC5200>;
                        interrupts = <a 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
                crypto@30000 {
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 8>;
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
                };
 
                pci@8500 {
-                       linux,phandle = <8500>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
 
                                        /* IDSEL 0x11 AD17 */
-                                        8800 0 0 1 700 14 8
-                                        8800 0 0 2 700 15 8
-                                        8800 0 0 3 700 16 8
-                                        8800 0 0 4 700 17 8
+                                        8800 0 0 1 &ipic 14 8
+                                        8800 0 0 2 &ipic 15 8
+                                        8800 0 0 3 &ipic 16 8
+                                        8800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x12 AD18 */
-                                        9000 0 0 1 700 16 8
-                                        9000 0 0 2 700 17 8
-                                        9000 0 0 3 700 14 8
-                                        9000 0 0 4 700 15 8
+                                        9000 0 0 1 &ipic 16 8
+                                        9000 0 0 2 &ipic 17 8
+                                        9000 0 0 3 &ipic 14 8
+                                        9000 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x13 AD19 */
-                                        9800 0 0 1 700 17 8
-                                        9800 0 0 2 700 14 8
-                                        9800 0 0 3 700 15 8
-                                        9800 0 0 4 700 16 8
+                                        9800 0 0 1 &ipic 17 8
+                                        9800 0 0 2 &ipic 14 8
+                                        9800 0 0 3 &ipic 15 8
+                                        9800 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x15 AD21*/
-                                        a800 0 0 1 700 14 8
-                                        a800 0 0 2 700 15 8
-                                        a800 0 0 3 700 16 8
-                                        a800 0 0 4 700 17 8
+                                        a800 0 0 1 &ipic 14 8
+                                        a800 0 0 2 &ipic 15 8
+                                        a800 0 0 3 &ipic 16 8
+                                        a800 0 0 4 &ipic 17 8
 
                                        /* IDSEL 0x16 AD22*/
-                                        b000 0 0 1 700 17 8
-                                        b000 0 0 2 700 14 8
-                                        b000 0 0 3 700 15 8
-                                        b000 0 0 4 700 16 8
+                                        b000 0 0 1 &ipic 17 8
+                                        b000 0 0 2 &ipic 14 8
+                                        b000 0 0 3 &ipic 15 8
+                                        b000 0 0 4 &ipic 16 8
 
                                        /* IDSEL 0x17 AD23*/
-                                        b800 0 0 1 700 16 8
-                                        b800 0 0 2 700 17 8
-                                        b800 0 0 3 700 14 8
-                                        b800 0 0 4 700 15 8
+                                        b800 0 0 1 &ipic 16 8
+                                        b800 0 0 2 &ipic 17 8
+                                        b800 0 0 3 &ipic 14 8
+                                        b800 0 0 4 &ipic 15 8
 
                                        /* IDSEL 0x18 AD24*/
-                                        c000 0 0 1 700 15 8
-                                        c000 0 0 2 700 16 8
-                                        c000 0 0 3 700 17 8
-                                        c000 0 0 4 700 14 8>;
-                       interrupt-parent = <700>;
+                                        c000 0 0 1 &ipic 15 8
+                                        c000 0 0 2 &ipic 16 8
+                                        c000 0 0 3 &ipic 17 8
+                                        c000 0 0 4 &ipic 14 8>;
+                       interrupt-parent = < &ipic >;
                        interrupts = <42 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 10000000
                        device_type = "pci";
                };
 
-               pic@700 {
-                       linux,phandle = <700>;
+               ipic: pic@700 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        device_type = "par_io";
                        num-ports = <7>;
 
-                       ucc_pin@01 {
-                               linux,phandle = <140001>;
+                       pio1: ucc_pin@01 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        0  3  1  0  1  0        /* TxD0 */
                                        2  9  1  0  3  0        /* GTX_CLK - CLK10 */
                                        2  8  2  0  1  0>;      /* GTX125 - CLK9 */
                        };
-                       ucc_pin@02 {
-                               linux,phandle = <140002>;
+                       pio2: ucc_pin@02 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        0  11 1  0  1  0   /* TxD0 */
                        compatible = "fsl_spi";
                        reg = <4c0 40>;
                        interrupts = <2>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "cpu";
                };
 
                        compatible = "fsl_spi";
                        reg = <500 40>;
                        interrupts = <1>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "cpu";
                };
 
                        compatible = "qe_udc";
                        reg = <6c0 40 8B00 100>;
                        interrupts = <b>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mode = "slave";
                };
 
                        device-id = <1>;
                        reg = <2000 200>;
                        interrupts = <20>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mac-address = [ 00 04 9f 00 23 23 ];
                        rx-clock = <0>;
                        tx-clock = <19>;
-                       phy-handle = <212000>;
-                       pio-handle = <140001>;
+                       phy-handle = < &phy0 >;
+                       pio-handle = < &pio1 >;
                };
 
                ucc@3000 {
                        device-id = <2>;
                        reg = <3000 200>;
                        interrupts = <21>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = < &qeic >;
                        mac-address = [ 00 11 22 33 44 55 ];
                        rx-clock = <0>;
                        tx-clock = <14>;
-                       phy-handle = <212001>;
-                       pio-handle = <140002>;
+                       phy-handle = < &phy1 >;
+                       pio-handle = < &pio2 >;
                };
 
                mdio@2120 {
                        device_type = "mdio";
                        compatible = "ucc_geth_phy";
 
-                       ethernet-phy@00 {
-                               linux,phandle = <212000>;
-                               interrupt-parent = <700>;
-                               interrupts = <11 2>;
+                       phy0: ethernet-phy@00 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <11 8>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                                interface = <6>; //ENET_1000_GMII
                        };
-                       ethernet-phy@01 {
-                               linux,phandle = <212001>;
-                               interrupt-parent = <700>;
-                               interrupts = <12 2>;
+                       phy1: ethernet-phy@01 {
+                               interrupt-parent = < &ipic >;
+                               interrupts = <12 8>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                                interface = <6>;
                        };
                };
 
-               qeic@80 {
-                       linux,phandle = <80>;
+               qeic: qeic@80 {
                        interrupt-controller;
                        device_type = "qeic";
                        #address-cells = <0>;
                        built-in;
                        big-endian;
                        interrupts = <20 8 21 8>; //high:32 low:33
-                       interrupt-parent = <700>;
+                       interrupt-parent = < &ipic >;
                };
 
        };
index 5f41c1f7a5f311cb83b9d94c55592a681ea091fe..3c0917fa791cff3f512350db29ccf06dac022309 100644 (file)
 
 / {
        model = "MPC8540ADS";
-       compatible = "MPC85xxADS";
+       compatible = "MPC8540ADS", "MPC85xxADS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8540@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;    // 166 MHz
                        clock-frequency = <0>;  // 825 MHz, from uboot
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 08000000>;      // 128M at 0x0
        };
 
@@ -58,7 +54,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@3 {
-                               linux,phandle = <2452003>;
-                               interrupt-parent = <40000>;
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <37 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        address = [ 00 E0 0C 00 73 00 ];
                        local-mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <d 2 e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        address = [ 00 E0 0C 00 73 01 ];
                        local-mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
 
                ethernet@26000 {
                        address = [ 00 E0 0C 00 73 02 ];
                        local-mac-address = [ 00 E0 0C 00 73 02 ];
                        interrupts = <19 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452003>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy3>;
                };
 
                serial@4500 {
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
                pci@8000 {
-                       linux,phandle = <8000>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x02 */
-                               1000 0 0 1 40000 31 1
-                               1000 0 0 2 40000 32 1
-                               1000 0 0 3 40000 33 1
-                               1000 0 0 4 40000 34 1
+                               1000 0 0 1 &mpic 31 1
+                               1000 0 0 2 &mpic 32 1
+                               1000 0 0 3 &mpic 33 1
+                               1000 0 0 4 &mpic 34 1
 
                                /* IDSEL 0x03 */
-                               1800 0 0 1 40000 34 1
-                               1800 0 0 2 40000 31 1
-                               1800 0 0 3 40000 32 1
-                               1800 0 0 4 40000 33 1
+                               1800 0 0 1 &mpic 34 1
+                               1800 0 0 2 &mpic 31 1
+                               1800 0 0 3 &mpic 32 1
+                               1800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x04 */
-                               2000 0 0 1 40000 33 1
-                               2000 0 0 2 40000 34 1
-                               2000 0 0 3 40000 31 1
-                               2000 0 0 4 40000 32 1
+                               2000 0 0 1 &mpic 33 1
+                               2000 0 0 2 &mpic 34 1
+                               2000 0 0 3 &mpic 31 1
+                               2000 0 0 4 &mpic 32 1
 
                                /* IDSEL 0x05 */
-                               2800 0 0 1 40000 32 1
-                               2800 0 0 2 40000 33 1
-                               2800 0 0 3 40000 34 1
-                               2800 0 0 4 40000 31 1
+                               2800 0 0 1 &mpic 32 1
+                               2800 0 0 2 &mpic 33 1
+                               2800 0 0 3 &mpic 34 1
+                               2800 0 0 4 &mpic 31 1
 
                                /* IDSEL 0x0c */
-                               6000 0 0 1 40000 31 1
-                               6000 0 0 2 40000 32 1
-                               6000 0 0 3 40000 33 1
-                               6000 0 0 4 40000 34 1
+                               6000 0 0 1 &mpic 31 1
+                               6000 0 0 2 &mpic 32 1
+                               6000 0 0 3 &mpic 33 1
+                               6000 0 0 4 &mpic 34 1
 
                                /* IDSEL 0x0d */
-                               6800 0 0 1 40000 34 1
-                               6800 0 0 2 40000 31 1
-                               6800 0 0 3 40000 32 1
-                               6800 0 0 4 40000 33 1
+                               6800 0 0 1 &mpic 34 1
+                               6800 0 0 2 &mpic 31 1
+                               6800 0 0 3 &mpic 32 1
+                               6800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x0e */
-                               7000 0 0 1 40000 33 1
-                               7000 0 0 2 40000 34 1
-                               7000 0 0 3 40000 31 1
-                               7000 0 0 4 40000 32 1
+                               7000 0 0 1 &mpic 33 1
+                               7000 0 0 2 &mpic 34 1
+                               7000 0 0 3 &mpic 31 1
+                               7000 0 0 4 &mpic 32 1
 
                                /* IDSEL 0x0f */
-                               7800 0 0 1 40000 32 1
-                               7800 0 0 2 40000 33 1
-                               7800 0 0 3 40000 34 1
-                               7800 0 0 4 40000 31 1
+                               7800 0 0 1 &mpic 32 1
+                               7800 0 0 2 &mpic 33 1
+                               7800 0 0 3 &mpic 34 1
+                               7800 0 0 4 &mpic 31 1
 
                                /* IDSEL 0x12 */
-                               9000 0 0 1 40000 31 1
-                               9000 0 0 2 40000 32 1
-                               9000 0 0 3 40000 33 1
-                               9000 0 0 4 40000 34 1
+                               9000 0 0 1 &mpic 31 1
+                               9000 0 0 2 &mpic 32 1
+                               9000 0 0 3 &mpic 33 1
+                               9000 0 0 4 &mpic 34 1
 
                                /* IDSEL 0x13 */
-                               9800 0 0 1 40000 34 1
-                               9800 0 0 2 40000 31 1
-                               9800 0 0 3 40000 32 1
-                               9800 0 0 4 40000 33 1
+                               9800 0 0 1 &mpic 34 1
+                               9800 0 0 2 &mpic 31 1
+                               9800 0 0 3 &mpic 32 1
+                               9800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x14 */
-                               a000 0 0 1 40000 33 1
-                               a000 0 0 2 40000 34 1
-                               a000 0 0 3 40000 31 1
-                               a000 0 0 4 40000 32 1
+                               a000 0 0 1 &mpic 33 1
+                               a000 0 0 2 &mpic 34 1
+                               a000 0 0 3 &mpic 31 1
+                               a000 0 0 4 &mpic 32 1
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 40000 32 1
-                               a800 0 0 2 40000 33 1
-                               a800 0 0 3 40000 34 1
-                               a800 0 0 4 40000 31 1>;
-                       interrupt-parent = <40000>;
+                               a800 0 0 1 &mpic 32 1
+                               a800 0 0 2 &mpic 33 1
+                               a800 0 0 3 &mpic 34 1
+                               a800 0 0 4 &mpic 31 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <08 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                        device_type = "pci";
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
index 7be0bc659e1c3f42cc4b98c72ee234226e902f21..2a1ae760ab3a9fa349015deb31f2a06cb45b8b2c 100644 (file)
 
 / {
        model = "MPC8541CDS";
-       compatible = "MPC85xxCDS";
+       compatible = "MPC8541CDS", "MPC85xxCDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8541@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;    // 166 MHz
                        clock-frequency = <0>;  // 825 MHz, from uboot
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 08000000>;      // 128M at 0x0
        };
 
@@ -58,7 +54,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <1>;
                                device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
                        reg = <24000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <d 2 e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
 
                serial@4500 {
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
-               pci@8000 {
-                       linux,phandle = <8000>;
+               pci1: pci@8000 {
                        interrupt-map-mask = <1f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 40000 30 1
-                               08000 0 0 2 40000 31 1
-                               08000 0 0 3 40000 32 1
-                               08000 0 0 4 40000 33 1
+                               08000 0 0 1 &mpic 30 1
+                               08000 0 0 2 &mpic 31 1
+                               08000 0 0 3 &mpic 32 1
+                               08000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 40000 30 1
-                               08800 0 0 2 40000 31 1
-                               08800 0 0 3 40000 32 1
-                               08800 0 0 4 40000 33 1
+                               08800 0 0 1 &mpic 30 1
+                               08800 0 0 2 &mpic 31 1
+                               08800 0 0 3 &mpic 32 1
+                               08800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 40000 30 1
-                               09000 0 0 2 40000 31 1
-                               09000 0 0 3 40000 32 1
-                               09000 0 0 4 40000 33 1
+                               09000 0 0 1 &mpic 30 1
+                               09000 0 0 2 &mpic 31 1
+                               09000 0 0 3 &mpic 32 1
+                               09000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 40000 31 1
-                               09800 0 0 2 40000 32 1
-                               09800 0 0 3 40000 33 1
-                               09800 0 0 4 40000 30 1
+                               09800 0 0 1 &mpic 31 1
+                               09800 0 0 2 &mpic 32 1
+                               09800 0 0 3 &mpic 33 1
+                               09800 0 0 4 &mpic 30 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 40000 32 1
-                               0a000 0 0 2 40000 33 1
-                               0a000 0 0 3 40000 30 1
-                               0a000 0 0 4 40000 31 1
+                               0a000 0 0 1 &mpic 32 1
+                               0a000 0 0 2 &mpic 33 1
+                               0a000 0 0 3 &mpic 30 1
+                               0a000 0 0 4 &mpic 31 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 40000 33 1
-                               0a800 0 0 2 40000 30 1
-                               0a800 0 0 3 40000 31 1
-                               0a800 0 0 4 40000 32 1
+                               0a800 0 0 1 &mpic 33 1
+                               0a800 0 0 2 &mpic 30 1
+                               0a800 0 0 3 &mpic 31 1
+                               0a800 0 0 4 &mpic 32 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 40000 30 1
-                               19000 0 0 2 40000 31 1
-                               19000 0 0 3 40000 32 1
-                               19000 0 0 4 40000 33 1>;
-                       interrupt-parent = <40000>;
+                               19000 0 0 1 &mpic 30 1
+                               19000 0 0 2 &mpic 31 1
+                               19000 0 0 3 &mpic 32 1
+                               19000 0 0 4 &mpic 33 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <08 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                compatible = "chrp,iic";
                                big-endian;
                                interrupts = <1>;
-                               interrupt-parent = <8000>;
+                               interrupt-parent = <&pci1>;
                        };
                };
 
                pci@9000 {
-                       linux,phandle = <9000>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 40000 3b 1
-                               a800 0 0 2 40000 3b 1
-                               a800 0 0 3 40000 3b 1
-                               a800 0 0 4 40000 3b 1>;
-                       interrupt-parent = <40000>;
+                               a800 0 0 1 &mpic 3b 1
+                               a800 0 0 2 &mpic 3b 1
+                               a800 0 0 3 &mpic 3b 1
+                               a800 0 0 4 &mpic 3b 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <09 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                        device_type = "pci";
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
index 893d7957c174a1432754e937339663ee1445a02d..7eb5d81d5eec60cb80a8b149970ae60e6f38e362 100644 (file)
 
 / {
        model = "MPC8548CDS";
-       compatible = "MPC85xxCDS";
+       compatible = "MPC8548CDS", "MPC85xxCDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8548@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;    // 166 MHz
                        clock-frequency = <0>;  // 825 MHz, from uboot
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 08000000>;      // 128M at 0x0
        };
 
@@ -58,7 +54,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-
-                       ethernet-phy@2 {
-                               linux,phandle = <2452002>;
-                               interrupt-parent = <40000>;
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@3 {
-                               linux,phandle = <2452003>;
-                               interrupt-parent = <40000>;
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        reg = <24000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <d 2 e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
 
+/* eTSEC 3/4 are currently broken
                ethernet@26000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <26000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 02 ];
                        interrupts = <f 2 10 2 11 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy2>;
                };
 
-/* eTSEC 4 is currently broken
                ethernet@27000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <27000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 03 ];
                        interrupts = <15 2 16 2 17 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy3>;
                };
  */
 
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
-               pci@8000 {
-                       linux,phandle = <8000>;
+               pci1: pci@8000 {
                        interrupt-map-mask = <1f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 40000 30 1
-                               08000 0 0 2 40000 31 1
-                               08000 0 0 3 40000 32 1
-                               08000 0 0 4 40000 33 1
+                               08000 0 0 1 &mpic 30 1
+                               08000 0 0 2 &mpic 31 1
+                               08000 0 0 3 &mpic 32 1
+                               08000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 40000 30 1
-                               08800 0 0 2 40000 31 1
-                               08800 0 0 3 40000 32 1
-                               08800 0 0 4 40000 33 1
+                               08800 0 0 1 &mpic 30 1
+                               08800 0 0 2 &mpic 31 1
+                               08800 0 0 3 &mpic 32 1
+                               08800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 40000 30 1
-                               09000 0 0 2 40000 31 1
-                               09000 0 0 3 40000 32 1
-                               09000 0 0 4 40000 33 1
+                               09000 0 0 1 &mpic 30 1
+                               09000 0 0 2 &mpic 31 1
+                               09000 0 0 3 &mpic 32 1
+                               09000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 40000 31 1
-                               09800 0 0 2 40000 32 1
-                               09800 0 0 3 40000 33 1
-                               09800 0 0 4 40000 30 1
+                               09800 0 0 1 &mpic 31 1
+                               09800 0 0 2 &mpic 32 1
+                               09800 0 0 3 &mpic 33 1
+                               09800 0 0 4 &mpic 30 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 40000 32 1
-                               0a000 0 0 2 40000 33 1
-                               0a000 0 0 3 40000 30 1
-                               0a000 0 0 4 40000 31 1
+                               0a000 0 0 1 &mpic 32 1
+                               0a000 0 0 2 &mpic 33 1
+                               0a000 0 0 3 &mpic 30 1
+                               0a000 0 0 4 &mpic 31 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 40000 33 1
-                               0a800 0 0 2 40000 30 1
-                               0a800 0 0 3 40000 31 1
-                               0a800 0 0 4 40000 32 1
+                               0a800 0 0 1 &mpic 33 1
+                               0a800 0 0 2 &mpic 30 1
+                               0a800 0 0 3 &mpic 31 1
+                               0a800 0 0 4 &mpic 32 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 40000 30 1
-                               19000 0 0 2 40000 31 1
-                               19000 0 0 3 40000 32 1
-                               19000 0 0 4 40000 33 1>;
-                       interrupt-parent = <40000>;
+                               19000 0 0 1 &mpic 30 1
+                               19000 0 0 2 &mpic 31 1
+                               19000 0 0 3 &mpic 32 1
+                               19000 0 0 4 &mpic 33 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <08 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                compatible = "chrp,iic";
                                big-endian;
                                interrupts = <1>;
-                               interrupt-parent = <8000>;
+                               interrupt-parent = <&pci1>;
                        };
                };
 
                pci@9000 {
-                       linux,phandle = <9000>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 40000 3b 1
-                               a800 0 0 2 40000 3b 1
-                               a800 0 0 3 40000 3b 1
-                               a800 0 0 4 40000 3b 1>;
-                       interrupt-parent = <40000>;
+                               a800 0 0 1 &mpic 3b 1
+                               a800 0 0 2 &mpic 3b 1
+                               a800 0 0 3 &mpic 3b 1
+                               a800 0 0 4 &mpic 3b 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <09 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                        device_type = "pci";
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
index 118f5a887651a460ebc4fd51e080cd7095e42959..5f9c102a0ab422ada16bd03bafc1944082a6d22d 100644 (file)
 
 / {
        model = "MPC8555CDS";
-       compatible = "MPC85xxCDS";
+       compatible = "MPC8555CDS", "MPC85xxCDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8555@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;    // 166 MHz
                        clock-frequency = <0>;  // 825 MHz, from uboot
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 08000000>;      // 128M at 0x0
        };
 
@@ -58,7 +54,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 0>;
                                reg = <1>;
                                device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
                        reg = <24000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <0d 2 0e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        local-mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
 
                serial@4500 {
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
-               pci@8000 {
-                       linux,phandle = <8000>;
+               pci1: pci@8000 {
                        interrupt-map-mask = <1f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 40000 30 1
-                               08000 0 0 2 40000 31 1
-                               08000 0 0 3 40000 32 1
-                               08000 0 0 4 40000 33 1
+                               08000 0 0 1 &mpic 30 1
+                               08000 0 0 2 &mpic 31 1
+                               08000 0 0 3 &mpic 32 1
+                               08000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 40000 30 1
-                               08800 0 0 2 40000 31 1
-                               08800 0 0 3 40000 32 1
-                               08800 0 0 4 40000 33 1
+                               08800 0 0 1 &mpic 30 1
+                               08800 0 0 2 &mpic 31 1
+                               08800 0 0 3 &mpic 32 1
+                               08800 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 40000 30 1
-                               09000 0 0 2 40000 31 1
-                               09000 0 0 3 40000 32 1
-                               09000 0 0 4 40000 33 1
+                               09000 0 0 1 &mpic 30 1
+                               09000 0 0 2 &mpic 31 1
+                               09000 0 0 3 &mpic 32 1
+                               09000 0 0 4 &mpic 33 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 40000 31 1
-                               09800 0 0 2 40000 32 1
-                               09800 0 0 3 40000 33 1
-                               09800 0 0 4 40000 30 1
+                               09800 0 0 1 &mpic 31 1
+                               09800 0 0 2 &mpic 32 1
+                               09800 0 0 3 &mpic 33 1
+                               09800 0 0 4 &mpic 30 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 40000 32 1
-                               0a000 0 0 2 40000 33 1
-                               0a000 0 0 3 40000 30 1
-                               0a000 0 0 4 40000 31 1
+                               0a000 0 0 1 &mpic 32 1
+                               0a000 0 0 2 &mpic 33 1
+                               0a000 0 0 3 &mpic 30 1
+                               0a000 0 0 4 &mpic 31 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 40000 33 1
-                               0a800 0 0 2 40000 30 1
-                               0a800 0 0 3 40000 31 1
-                               0a800 0 0 4 40000 32 1
+                               0a800 0 0 1 &mpic 33 1
+                               0a800 0 0 2 &mpic 30 1
+                               0a800 0 0 3 &mpic 31 1
+                               0a800 0 0 4 &mpic 32 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 40000 30 1
-                               19000 0 0 2 40000 31 1
-                               19000 0 0 3 40000 32 1
-                               19000 0 0 4 40000 33 1>;
-                       interrupt-parent = <40000>;
+                               19000 0 0 1 &mpic 30 1
+                               19000 0 0 2 &mpic 31 1
+                               19000 0 0 3 &mpic 32 1
+                               19000 0 0 4 &mpic 33 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <08 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                compatible = "chrp,iic";
                                big-endian;
                                interrupts = <1>;
-                               interrupt-parent = <8000>;
+                               interrupt-parent = <&pci1>;
                        };
                };
 
                pci@9000 {
-                       linux,phandle = <9000>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 40000 3b 1
-                               a800 0 0 2 40000 3b 1
-                               a800 0 0 3 40000 3b 1
-                               a800 0 0 4 40000 3b 1>;
-                       interrupt-parent = <40000>;
+                               a800 0 0 1 &mpic 3b 1
+                               a800 0 0 2 &mpic 3b 1
+                               a800 0 0 3 &mpic 3b 1
+                               a800 0 0 4 &mpic 3b 1>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <09 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                        device_type = "pci";
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
index 119bd5d3a834476d91be6f2e90d3fa8f2e7b68fb..10502638b0e977f06f472c6c76d3fe1524ad6dd9 100644 (file)
 
 / {
        model = "MPC8560ADS";
-       compatible = "MPC85xxADS";
+       compatible = "MPC8560ADS", "MPC85xxADS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8560@0 {
                        device_type = "cpu";
                        bus-frequency = <13ab6680>;
                        clock-frequency = <312c8040>;
                        32-bit;
-                       linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 10000000>;
        };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <35 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@2 {
-                               linux,phandle = <2452002>;
-                               interrupt-parent = <40000>;
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <37 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@3 {
-                               linux,phandle = <2452003>;
-                               interrupt-parent = <40000>;
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <37 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
@@ -98,8 +88,8 @@
                        reg = <24000 1000>;
                        address = [ 00 00 0C 00 00 FD ];
                        interrupts = <d 2 e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        address = [ 00 00 0C 00 01 FD ];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
 
                pci@8000 {
-                       linux,phandle = <8000>;
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
                        interrupt-map = <
 
                                        /* IDSEL 0x2 */
-                                        1000 0 0 1 40000 31 1
-                                        1000 0 0 2 40000 32 1
-                                        1000 0 0 3 40000 33 1
-                                        1000 0 0 4 40000 34 1
+                                        1000 0 0 1 &mpic 31 1
+                                        1000 0 0 2 &mpic 32 1
+                                        1000 0 0 3 &mpic 33 1
+                                        1000 0 0 4 &mpic 34 1
 
                                        /* IDSEL 0x3 */
-                                        1800 0 0 1 40000 34 1
-                                        1800 0 0 2 40000 31 1
-                                        1800 0 0 3 40000 32 1
-                                        1800 0 0 4 40000 33 1
+                                        1800 0 0 1 &mpic 34 1
+                                        1800 0 0 2 &mpic 31 1
+                                        1800 0 0 3 &mpic 32 1
+                                        1800 0 0 4 &mpic 33 1
 
                                        /* IDSEL 0x4 */
-                                        2000 0 0 1 40000 33 1
-                                        2000 0 0 2 40000 34 1
-                                        2000 0 0 3 40000 31 1
-                                        2000 0 0 4 40000 32 1
+                                        2000 0 0 1 &mpic 33 1
+                                        2000 0 0 2 &mpic 34 1
+                                        2000 0 0 3 &mpic 31 1
+                                        2000 0 0 4 &mpic 32 1
 
                                        /* IDSEL 0x5  */
-                                        2800 0 0 1 40000 32 1
-                                        2800 0 0 2 40000 33 1
-                                        2800 0 0 3 40000 34 1
-                                        2800 0 0 4 40000 31 1
+                                        2800 0 0 1 &mpic 32 1
+                                        2800 0 0 2 &mpic 33 1
+                                        2800 0 0 3 &mpic 34 1
+                                        2800 0 0 4 &mpic 31 1
 
                                        /* IDSEL 12 */
-                                        6000 0 0 1 40000 31 1
-                                        6000 0 0 2 40000 32 1
-                                        6000 0 0 3 40000 33 1
-                                        6000 0 0 4 40000 34 1
+                                        6000 0 0 1 &mpic 31 1
+                                        6000 0 0 2 &mpic 32 1
+                                        6000 0 0 3 &mpic 33 1
+                                        6000 0 0 4 &mpic 34 1
 
                                        /* IDSEL 13 */
-                                        6800 0 0 1 40000 34 1
-                                        6800 0 0 2 40000 31 1
-                                        6800 0 0 3 40000 32 1
-                                        6800 0 0 4 40000 33 1
+                                        6800 0 0 1 &mpic 34 1
+                                        6800 0 0 2 &mpic 31 1
+                                        6800 0 0 3 &mpic 32 1
+                                        6800 0 0 4 &mpic 33 1
 
                                        /* IDSEL 14*/
-                                        7000 0 0 1 40000 33 1
-                                        7000 0 0 2 40000 34 1
-                                        7000 0 0 3 40000 31 1
-                                        7000 0 0 4 40000 32 1
+                                        7000 0 0 1 &mpic 33 1
+                                        7000 0 0 2 &mpic 34 1
+                                        7000 0 0 3 &mpic 31 1
+                                        7000 0 0 4 &mpic 32 1
 
                                        /* IDSEL 15 */
-                                        7800 0 0 1 40000 32 1
-                                        7800 0 0 2 40000 33 1
-                                        7800 0 0 3 40000 34 1
-                                        7800 0 0 4 40000 31 1
+                                        7800 0 0 1 &mpic 32 1
+                                        7800 0 0 2 &mpic 33 1
+                                        7800 0 0 3 &mpic 34 1
+                                        7800 0 0 4 &mpic 31 1
 
                                        /* IDSEL 18 */
-                                        9000 0 0 1 40000 31 1
-                                        9000 0 0 2 40000 32 1
-                                        9000 0 0 3 40000 33 1
-                                        9000 0 0 4 40000 34 1
+                                        9000 0 0 1 &mpic 31 1
+                                        9000 0 0 2 &mpic 32 1
+                                        9000 0 0 3 &mpic 33 1
+                                        9000 0 0 4 &mpic 34 1
 
                                        /* IDSEL 19 */
-                                        9800 0 0 1 40000 34 1
-                                        9800 0 0 2 40000 31 1
-                                        9800 0 0 3 40000 32 1
-                                        9800 0 0 4 40000 33 1
+                                        9800 0 0 1 &mpic 34 1
+                                        9800 0 0 2 &mpic 31 1
+                                        9800 0 0 3 &mpic 32 1
+                                        9800 0 0 4 &mpic 33 1
 
                                        /* IDSEL 20 */
-                                        a000 0 0 1 40000 33 1
-                                        a000 0 0 2 40000 34 1
-                                        a000 0 0 3 40000 31 1
-                                        a000 0 0 4 40000 32 1
+                                        a000 0 0 1 &mpic 33 1
+                                        a000 0 0 2 &mpic 34 1
+                                        a000 0 0 3 &mpic 31 1
+                                        a000 0 0 4 &mpic 32 1
 
                                        /* IDSEL 21 */
-                                        a800 0 0 1 40000 32 1
-                                        a800 0 0 2 40000 33 1
-                                        a800 0 0 3 40000 34 1
-                                        a800 0 0 4 40000 31 1>;
+                                        a800 0 0 1 &mpic 32 1
+                                        a800 0 0 2 &mpic 33 1
+                                        a800 0 0 3 &mpic 34 1
+                                        a800 0 0 4 &mpic 31 1>;
 
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <8 0>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 01000000>;
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
-                       reg = <40000 20100>;
+                       reg = <40000 40000>;
                        built-in;
                        device_type = "open-pic";
                };
 
                cpm@e0000000 {
-                       linux,phandle = <e0000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
                        command-proc = <919c0>;
                        brg-frequency = <9d5b340>;
 
-                       pic@90c00 {
-                               linux,phandle = <90c00>;
+                       cpmpic: pic@90c00 {
                                interrupt-controller;
                                #address-cells = <0>;
                                #interrupt-cells = <2>;
                                interrupts = <1e 0>;
-                               interrupt-parent = <40000>;
+                               interrupt-parent = <&mpic>;
                                reg = <90c00 80>;
                                built-in;
                                device_type = "cpm-pic";
                                tx-clock = <1>;
                                current-speed = <1c200>;
                                interrupts = <28 8>;
-                               interrupt-parent = <90c00>;
+                               interrupt-parent = <&cpmpic>;
                        };
 
                        scc@91a20 {
                                tx-clock = <2>;
                                current-speed = <1c200>;
                                interrupts = <29 8>;
-                               interrupt-parent = <90c00>;
+                               interrupt-parent = <&cpmpic>;
                        };
 
                        fcc@91320 {
                                rx-clock = <15>;
                                tx-clock = <16>;
                                interrupts = <21 8>;
-                               interrupt-parent = <90c00>;
-                               phy-handle = <2452002>;
+                               interrupt-parent = <&cpmpic>;
+                               phy-handle = <&phy2>;
                        };
 
                        fcc@91340 {
                                rx-clock = <17>;
                                tx-clock = <18>;
                                interrupts = <22 8>;
-                               interrupt-parent = <90c00>;
-                               phy-handle = <2452003>;
+                               interrupt-parent = <&cpmpic>;
+                               phy-handle = <&phy3>;
                        };
                };
        };
index 06d24653e422979cdbb8d871c06ae3444fa02b69..bf49d8c997b9c7be09d382e54508eaabb96cb3c5 100644 (file)
 
 / {
        model = "MPC8568EMDS";
-       compatible = "MPC85xxMDS";
+       compatible = "MPC8568EMDS", "MPC85xxMDS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8568@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 10000000>;
        };
 
@@ -67,7 +63,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
@@ -76,7 +72,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <1b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <31 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-
-                       ethernet-phy@2 {
-                               linux,phandle = <2452002>;
-                               interrupt-parent = <40000>;
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <31 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@3 {
-                               linux,phandle = <2452003>;
-                               interrupt-parent = <40000>;
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        reg = <24000 1000>;
                        mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <d 2 e 2 12 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452002>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy2>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        mac-address = [ 00 00 00 00 00 00];
                        interrupts = <13 2 14 2 18 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452003>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy3>;
                };
 
                serial@4500 {
                        reg = <4500 100>;
                        clock-frequency = <0>;
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;
                        interrupts = <1a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                crypto@30000 {
                        compatible = "talitos";
                        reg = <30000 f000>;
                        interrupts = <1d 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <000000fe>;
                        descriptor-types-mask = <012b0ebf>;
                };
 
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
                        device_type = "par_io";
                        num-ports = <7>;
 
-                       ucc_pin@01 {
-                               linux,phandle = <e010001>;
+                       pio1: ucc_pin@01 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        4  0a  1  0  2  0       /* TxD0 */
                                        4  13  1  0  2  0       /* GTX_CLK */
                                        1  1f  2  0  3  0>;     /* GTX125 */
                        };
-                       ucc_pin@02 {
-                               linux,phandle = <e010002>;
+                       pio2: ucc_pin@02 {
                                pio-map = <
                        /* port  pin  dir  open_drain  assignment  has_irq */
                                        5  0a 1  0  2  0   /* TxD0 */
                        compatible = "fsl_spi";
                        reg = <4c0 40>;
                        interrupts = <2>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = <&qeic>;
                        mode = "cpu";
                };
 
                        compatible = "fsl_spi";
                        reg = <500 40>;
                        interrupts = <1>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = <&qeic>;
                        mode = "cpu";
                };
 
                        device-id = <1>;
                        reg = <2000 200>;
                        interrupts = <20>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = <&qeic>;
                        mac-address = [ 00 04 9f 00 23 23 ];
                        rx-clock = <0>;
                        tx-clock = <19>;
-                       phy-handle = <212000>;
-                       pio-handle = <e010001>;
+                       phy-handle = <&qe_phy0>;
+                       pio-handle = <&pio1>;
                };
 
                ucc@3000 {
                        device-id = <2>;
                        reg = <3000 200>;
                        interrupts = <21>;
-                       interrupt-parent = <80>;
+                       interrupt-parent = <&qeic>;
                        mac-address = [ 00 11 22 33 44 55 ];
                        rx-clock = <0>;
                        tx-clock = <14>;
-                       phy-handle = <212001>;
-                       pio-handle = <e010002>;
+                       phy-handle = <&qe_phy1>;
+                       pio-handle = <&pio2>;
                };
 
                mdio@2120 {
 
                        /* These are the same PHYs as on
                         * gianfar's MDIO bus */
-                       ethernet-phy@00 {
-                               linux,phandle = <212000>;
-                               interrupt-parent = <40000>;
+                       qe_phy0: ethernet-phy@00 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <31 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                                interface = <6>; //ENET_1000_GMII
                        };
-                       ethernet-phy@01 {
-                               linux,phandle = <212001>;
-                               interrupt-parent = <40000>;
+                       qe_phy1: ethernet-phy@01 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                                interface = <6>;
                        };
-                       ethernet-phy@02 {
-                               linux,phandle = <212002>;
-                               interrupt-parent = <40000>;
+                       qe_phy2: ethernet-phy@02 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <31 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                                interface = <6>; //ENET_1000_GMII
                        };
-                       ethernet-phy@03 {
-                               linux,phandle = <212003>;
-                               interrupt-parent = <40000>;
+                       qe_phy3: ethernet-phy@03 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <32 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                };
 
-               qeic@80 {
-                       linux,phandle = <80>;
+               qeic: qeic@80 {
                        interrupt-controller;
                        device_type = "qeic";
                        #address-cells = <0>;
                        built-in;
                        big-endian;
                        interrupts = <1e 2 1e 2>; //high:30 low:30
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
        };
index f0c7731743ea0dd1a827084f32ed36a5ab9b823b..8a4995a85ba035f28865aacf96a4cca758d89259 100644 (file)
@@ -32,7 +32,6 @@
                        bus-frequency = <0>;            // From uboot
                        clock-frequency = <0>;          // From uboot
                        32-bit;
-                       linux,boot-cpu;
                };
                PowerPC,8641@1 {
                        device_type = "cpu";
@@ -67,7 +66,7 @@
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
@@ -76,7 +75,7 @@
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <2b 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
                        device_type = "mdio";
                        compatible = "gianfar";
                        reg = <24520 20>;
-                       linux,phandle = <24520>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <40000>;
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <4a 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <40000>;
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <4a 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@2 {
-                               linux,phandle = <2452002>;
-                               interrupt-parent = <40000>;
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <4a 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@3 {
-                               linux,phandle = <2452003>;
-                               interrupt-parent = <40000>;
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
                                interrupts = <4a 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        reg = <24000 1000>;
                        mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
                };
 
                ethernet@25000 {
                        reg = <25000 1000>;
                        mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <23 2 24 2 28 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
                };
                
                ethernet@26000 {
                        reg = <26000 1000>;
                        mac-address = [ 00 E0 0C 00 02 FD ];
                        interrupts = <1F 2 20 2 21 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452002>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy2>;
                };
 
                ethernet@27000 {
                        reg = <27000 1000>;
                        mac-address = [ 00 E0 0C 00 03 FD ];
                        interrupts = <25 2 26 2 27 2>;
-                       interrupt-parent = <40000>;
-                       phy-handle = <2452003>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy3>;
                };
                serial@4500 {
                        device_type = "serial";
                        reg = <4500 100>;
                        clock-frequency = <0>;
                        interrupts = <2a 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                serial@4600 {
                        reg = <4600 100>;
                        clock-frequency = <0>;
                        interrupts = <1c 2>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                };
 
                pci@8000 {
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
                        clock-frequency = <1fca055>;
-                       interrupt-parent = <40000>;
+                       interrupt-parent = <&mpic>;
                        interrupts = <18 2>;
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                /* IDSEL 0x11 */
-                               8800 0 0 1 4d0 3 2
-                               8800 0 0 2 4d0 4 2
-                               8800 0 0 3 4d0 5 2
-                               8800 0 0 4 4d0 6 2
+                               8800 0 0 1 &i8259 3 2
+                               8800 0 0 2 &i8259 4 2
+                               8800 0 0 3 &i8259 5 2
+                               8800 0 0 4 &i8259 6 2
 
                                /* IDSEL 0x12 */
-                               9000 0 0 1 4d0 4 2
-                               9000 0 0 2 4d0 5 2
-                               9000 0 0 3 4d0 6 2
-                               9000 0 0 4 4d0 3 2
+                               9000 0 0 1 &i8259 4 2
+                               9000 0 0 2 &i8259 5 2
+                               9000 0 0 3 &i8259 6 2
+                               9000 0 0 4 &i8259 3 2
 
                                /* IDSEL 0x13 */
-                               9800 0 0 1 4d0 0 0
-                               9800 0 0 2 4d0 0 0
-                               9800 0 0 3 4d0 0 0
-                               9800 0 0 4 4d0 0 0
+                               9800 0 0 1 &i8259 0 0
+                               9800 0 0 2 &i8259 0 0
+                               9800 0 0 3 &i8259 0 0
+                               9800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x14 */
-                               a000 0 0 1 4d0 0 0
-                               a000 0 0 2 4d0 0 0
-                               a000 0 0 3 4d0 0 0
-                               a000 0 0 4 4d0 0 0
+                               a000 0 0 1 &i8259 0 0
+                               a000 0 0 2 &i8259 0 0
+                               a000 0 0 3 &i8259 0 0
+                               a000 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 4d0 0 0
-                               a800 0 0 2 4d0 0 0
-                               a800 0 0 3 4d0 0 0
-                               a800 0 0 4 4d0 0 0
+                               a800 0 0 1 &i8259 0 0
+                               a800 0 0 2 &i8259 0 0
+                               a800 0 0 3 &i8259 0 0
+                               a800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x16 */
-                               b000 0 0 1 4d0 0 0
-                               b000 0 0 2 4d0 0 0
-                               b000 0 0 3 4d0 0 0
-                               b000 0 0 4 4d0 0 0
+                               b000 0 0 1 &i8259 0 0
+                               b000 0 0 2 &i8259 0 0
+                               b000 0 0 3 &i8259 0 0
+                               b000 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x17 */
-                               b800 0 0 1 4d0 0 0
-                               b800 0 0 2 4d0 0 0
-                               b800 0 0 3 4d0 0 0
-                               b800 0 0 4 4d0 0 0
+                               b800 0 0 1 &i8259 0 0
+                               b800 0 0 2 &i8259 0 0
+                               b800 0 0 3 &i8259 0 0
+                               b800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x18 */
-                               c000 0 0 1 4d0 0 0
-                               c000 0 0 2 4d0 0 0
-                               c000 0 0 3 4d0 0 0
-                               c000 0 0 4 4d0 0 0
+                               c000 0 0 1 &i8259 0 0
+                               c000 0 0 2 &i8259 0 0
+                               c000 0 0 3 &i8259 0 0
+                               c000 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x19 */
-                               c800 0 0 1 4d0 0 0
-                               c800 0 0 2 4d0 0 0
-                               c800 0 0 3 4d0 0 0
-                               c800 0 0 4 4d0 0 0
+                               c800 0 0 1 &i8259 0 0
+                               c800 0 0 2 &i8259 0 0
+                               c800 0 0 3 &i8259 0 0
+                               c800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x1a */
-                               d000 0 0 1 4d0 6 2
-                               d000 0 0 2 4d0 3 2
-                               d000 0 0 3 4d0 4 2
-                               d000 0 0 4 4d0 5 2
+                               d000 0 0 1 &i8259 6 2
+                               d000 0 0 2 &i8259 3 2
+                               d000 0 0 3 &i8259 4 2
+                               d000 0 0 4 &i8259 5 2
 
 
                                /* IDSEL 0x1b */
-                               d800 0 0 1 4d0 5 2
-                               d800 0 0 2 4d0 0 0
-                               d800 0 0 3 4d0 0 0
-                               d800 0 0 4 4d0 0 0
+                               d800 0 0 1 &i8259 5 2
+                               d800 0 0 2 &i8259 0 0
+                               d800 0 0 3 &i8259 0 0
+                               d800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x1c */
-                               e000 0 0 1 4d0 9 2
-                               e000 0 0 2 4d0 a 2
-                               e000 0 0 3 4d0 c 2
-                               e000 0 0 4 4d0 7 2
+                               e000 0 0 1 &i8259 9 2
+                               e000 0 0 2 &i8259 a 2
+                               e000 0 0 3 &i8259 c 2
+                               e000 0 0 4 &i8259 7 2
 
                                /* IDSEL 0x1d */
-                               e800 0 0 1 4d0 9 2
-                               e800 0 0 2 4d0 a 2
-                               e800 0 0 3 4d0 b 2
-                               e800 0 0 4 4d0 0 0
+                               e800 0 0 1 &i8259 9 2
+                               e800 0 0 2 &i8259 a 2
+                               e800 0 0 3 &i8259 b 2
+                               e800 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x1e */
-                               f000 0 0 1 4d0 c 2
-                               f000 0 0 2 4d0 0 0
-                               f000 0 0 3 4d0 0 0
-                               f000 0 0 4 4d0 0 0
+                               f000 0 0 1 &i8259 c 2
+                               f000 0 0 2 &i8259 0 0
+                               f000 0 0 3 &i8259 0 0
+                               f000 0 0 4 &i8259 0 0
 
                                /* IDSEL 0x1f */
-                               f800 0 0 1 4d0 6 2
-                               f800 0 0 2 4d0 0 0
-                               f800 0 0 3 4d0 0 0
-                               f800 0 0 4 4d0 0 0
+                               f800 0 0 1 &i8259 6 2
+                               f800 0 0 2 &i8259 0 0
+                               f800 0 0 3 &i8259 0 0
+                               f800 0 0 4 &i8259 0 0
                                >;
-                       i8259@4d0 {
-                               linux,phandle = <4d0>;
+                       i8259: i8259@4d0 {
                                clock-frequency = <0>;
                                interrupt-controller;
                                device_type = "interrupt-controller";
                                compatible = "chrp,iic";
                                big-endian;
                                interrupts = <49 2>;
-                               interrupt-parent = <40000>;
+                               interrupt-parent = <&mpic>;
                        };
 
                };
-               pic@40000 {
-                       linux,phandle = <40000>;
+               mpic: pic@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
                        built-in;
                        compatible = "chrp,open-pic";
                        device_type = "open-pic";
-                        big-endian;
-                       interrupts = <
-                               10 2 11 2 12 2 13 2
-                               14 2 15 2 16 2 17 2
-                               18 2 19 2 1a 2 1b 2
-                               1c 2 1d 2 1e 2 1f 2
-                               20 2 21 2 22 2 23 2
-                               24 2 25 2 26 2 27 2
-                               28 2 29 2 2a 2 2b 2
-                               2c 2 2d 2 2e 2 2f 2
-                               30 2 31 2 32 2 33 2
-                               34 2 35 2 36 2 37 2
-                               38 2 39 2 2a 2 3b 2
-                               3c 2 3d 2 3e 2 3f 2
-                               48 1 49 2 4a 1
-                               >;
-                       interrupt-parent = <40000>;
+                       big-endian;
                };
        };
 };
index 5d4005239b83e1f1c8e5bf0d05ad8b804a35a5b4..2b56b5df451a31ab9b2c7e6d5d6124b916e3c569 100644 (file)
@@ -37,7 +37,6 @@
                        interrupts = <f 2>;     // decrementer interrupt
                        interrupt-parent = <ff000000>;
                        linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
index cf1a19f962c5e416d0e08c3f82f098eeeecff996..faecd08c54dae3afddb6bf2aea8dfc5a24f5000a 100644 (file)
@@ -37,7 +37,6 @@
                        interrupts = <f 2>;     // decrementer interrupt
                        interrupt-parent = <ff000000>;
                        linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
index e956548da00ce6276c5343d7200e1fae39676bd4..24367319ce24ac873bb279fb83d00e614f37fbb7 100644 (file)
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=y
+CONFIG_PPC_PMI=m
 CONFIG_MMIO_NVRAM=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
similarity index 97%
rename from arch/powerpc/configs/mpc8360emds_defconfig
rename to arch/powerpc/configs/mpc836x_mds_defconfig
index bbe38ccc3d86c90de70366846eaef08b7dda478b..8eb475cd0df0caf483bfad44d0f0f71c74550f29 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Fri Jan 26 00:19:45 2007
+# Linux kernel version: 2.6.20
+# Sat Feb 17 10:09:26 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_83xx=y
@@ -63,6 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -129,10 +130,11 @@ CONFIG_PPC_GEN550=y
 #
 # Platform support
 #
+# CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC834x_MDS is not set
 # CONFIG_MPC834x_ITX is not set
-CONFIG_MPC8360E_PB=y
+CONFIG_MPC836x_MDS=y
 CONFIG_PPC_MPC836x=y
 # CONFIG_MPIC is not set
 
@@ -162,6 +164,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
@@ -171,6 +174,7 @@ CONFIG_ISA_DMA_API=y
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
 # CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
@@ -219,6 +223,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -528,6 +533,7 @@ CONFIG_UCC_GETH=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -620,6 +626,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -690,6 +697,7 @@ CONFIG_I2C_MPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_I2C_SIS5595 is not set
@@ -804,6 +812,7 @@ CONFIG_FIRMWARE_EDID=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -867,6 +876,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -1011,7 +1024,8 @@ CONFIG_BITREVERSE=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 
 #
 # Instrumentation Support
@@ -1060,8 +1074,10 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1075,6 +1091,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index 058e06d88bc126da16918bd2d9a6ed40d374c018..7b3800674cbf2c7d35eaa403c6561ab60a56aa5d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Wed Feb  7 23:54:25 2007
+# Linux kernel version: 2.6.20
+# Sat Feb 17 16:26:53 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
@@ -63,6 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -130,7 +131,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_MPC8540_ADS is not set
 # CONFIG_MPC8560_ADS is not set
 # CONFIG_MPC85xx_CDS is not set
-CONFIG_MPC8568_MDS=y
+CONFIG_MPC85xx_MDS=y
 CONFIG_MPC85xx=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_MPIC=y
@@ -162,6 +163,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
@@ -171,6 +173,7 @@ CONFIG_ISA_DMA_API=y
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
@@ -216,6 +219,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -301,6 +305,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -341,7 +346,6 @@ CONFIG_BLK_DEV_INITRD=y
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -543,6 +547,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -698,6 +703,7 @@ CONFIG_FIRMWARE_EDID=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -759,6 +765,10 @@ CONFIG_HID=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -896,7 +906,8 @@ CONFIG_BITREVERSE=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 
 #
 # Instrumentation Support
@@ -914,6 +925,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
@@ -922,7 +934,6 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -932,6 +943,8 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUGGER=y
 # CONFIG_XMON is not set
 # CONFIG_BDI_SWITCH is not set
@@ -943,6 +956,8 @@ CONFIG_PPC_EARLY_DEBUG=y
 # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
 # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
 # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
 
 #
 # Security options
@@ -970,8 +985,10 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -985,6 +1002,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index debac66e82589bee8e3518db45e305a06c3c503f..a8da0aea3b8751951d4c47f66d0f68d7e557b88e 100644 (file)
@@ -500,7 +500,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
-CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -646,7 +646,7 @@ CONFIG_SATA_SVW=y
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
 
 #
 # Multi-device support (RAID and LVM)
index 1c794fe718fd52dfe520d19db5f464f514b86d50..6e96e50c362d08c0ebd0443cc894a90bad090b39 100644 (file)
@@ -483,7 +483,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
-CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -628,7 +628,7 @@ CONFIG_ATA=y
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
 
 #
 # Multi-device support (RAID and LVM)
index 8994af327b47a2586aa1719f442d10a052fd14eb..6e7f50967bab10af659e61c227c7974117bbd945 100644 (file)
@@ -110,17 +110,22 @@ static ctl_table powersave_nap_ctl_table[]={
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
-       { 0, },
+       {}
 };
 static ctl_table powersave_nap_sysctl_root[] = {
-       { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
-       { 0,},
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0755,
+               .child          = powersave_nap_ctl_table,
+       },
+       {}
 };
 
 static int __init
 register_powersave_nap_sysctl(void)
 {
-       register_sysctl_table(powersave_nap_sysctl_root, 0);
+       register_sysctl_table(powersave_nap_sysctl_root);
 
        return 0;
 }
index 3e86e6e0f7782d436f8c9e57d9b59f461270633f..8d52b23348bd0b6cb2322fc9f87d626914268a51 100644 (file)
@@ -1599,6 +1599,7 @@ struct property *of_find_property(const struct device_node *np,
 
        return pp;
 }
+EXPORT_SYMBOL(of_find_property);
 
 /*
  * Find a property with a given name for a given node
index 12c51e4ad2b4b97b4468e8fca178fa435d86a025..ea6fd552c7eaf8023114958e093a172e2c2b3015 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/etherdevice.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
@@ -1003,3 +1004,42 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
        return res;
 }
 EXPORT_SYMBOL_GPL(of_irq_map_one);
+
+/**
+ * Search the device tree for the best MAC address to use.  'mac-address' is
+ * checked first, because that is supposed to contain to "most recent" MAC
+ * address. If that isn't set, then 'local-mac-address' is checked next,
+ * because that is the default address.  If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree.
+ *
+ * Note that the 'address' property is supposed to contain a virtual address of
+ * the register set, but some DTS files have redefined that property to be the
+ * MAC address.
+ *
+ * All-zero MAC addresses are rejected, because those could be properties that
+ * exist in the device tree, but were not set by U-Boot.  For example, the
+ * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
+ * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
+ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
+ * but is all zeros.
+*/
+const void *of_get_mac_address(struct device_node *np)
+{
+       struct property *pp;
+
+       pp = of_find_property(np, "mac-address", NULL);
+       if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+               return pp->value;
+
+       pp = of_find_property(np, "local-mac-address", NULL);
+       if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+               return pp->value;
+
+       pp = of_find_property(np, "address", NULL);
+       if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+               return pp->value;
+
+       return NULL;
+}
+EXPORT_SYMBOL(of_get_mac_address);
+
index 76b5d7ebdcc681fe0b8f4730300b90bc55827fce..9d0735a54564cc62e3df51253727028e48eeaa5e 100644 (file)
@@ -182,7 +182,7 @@ void rtas_progress(char *s, unsigned short hex)
        char *os;
        static int display_character, set_indicator;
        static int display_width, display_lines, form_feed;
-       const static int *row_width;
+       static const int *row_width;
        static DEFINE_SPINLOCK(progress_lock);
        static int current_line;
        static int pending_newline = 0;  /* did last write end with unprinted newline? */
index 262790910ff23900f5bef2ab057feb4ff5a4e636..e86c37c82cfda2f3a8d88e1c68ead668c4fc9907 100644 (file)
@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(of_node_to_nid);
  * characteristics relative to its multiple connections.  We ignore
  * this for now.  We also assume that all cpu and memory sets have
  * their distances represented at a common level.  This won't be
- * true for heirarchical NUMA.
+ * true for hierarchical NUMA.
  *
  * In any case the ibm,associativity-reference-points should give
  * the correct depth for a normal NUMA system.
index 16e4ee1c2318e726c8e2bf9df3b6a9b1ec867197..1d443407423ca0b676b9bfc3bd546d3b85a2ed2e 100644 (file)
@@ -103,7 +103,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
                 *
                 */
                if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-                                     mmu_virtual_psize)) {
+                                     mmu_io_psize)) {
                        printk(KERN_ERR "Failed to do bolted mapping IO "
                               "memory at %016lx !\n", pa);
                        return -ENOMEM;
index 1aea1e69ff31c3ac562326d4a4e4900afa1d1a8c..713b31a16ce9e252e47ad25b35d8b5aa677d0d9b 100644 (file)
@@ -38,12 +38,12 @@ config MPC834x_ITX
          Be aware that PCI initialization is the bootloader's
          responsibility.
 
-config MPC8360E_PB
-       bool "Freescale MPC8360E PB"
+config MPC836x_MDS
+       bool "Freescale MPC836x MDS"
        select DEFAULT_UIMAGE
        select QUICC_ENGINE
        help
-         This option enables support for the MPC836x EMDS Processor Board.
+         This option enables support for the MPC836x MDS Processor Board.
 
 endchoice
 
@@ -69,6 +69,6 @@ config PPC_MPC836x
        bool
        select PPC_UDBG_16550
        select PPC_INDIRECT_PCI
-       default y if MPC8360E_PB
+       default y if MPC836x_MDS
 
 endmenu
index 6c8199c4c38214c1da86b58f77137b39486a1b99..dfc970d0df108250ea4c9624da495862945ce67d 100644 (file)
@@ -6,5 +6,5 @@ obj-$(CONFIG_PCI)               += pci.o
 obj-$(CONFIG_MPC8313_RDB)      += mpc8313_rdb.o
 obj-$(CONFIG_MPC834x_MDS)      += mpc834x_mds.o
 obj-$(CONFIG_MPC834x_ITX)      += mpc834x_itx.o
-obj-$(CONFIG_MPC8360E_PB)      += mpc8360e_pb.o
+obj-$(CONFIG_MPC836x_MDS)      += mpc836x_mds.o
 obj-$(CONFIG_MPC832x_MDS)      += mpc832x_mds.o
index c3b98c34eb6ba7b66434f5a4f1bbe3b0d8cec2d2..32e9e9492841ac600f68fb4bf07dfb35218837e3 100644 (file)
@@ -74,16 +74,9 @@ void __init mpc8313_rdb_init_IRQ(void)
  */
 static int __init mpc8313_rdb_probe(void)
 {
-       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "model", NULL);
-       if (model == NULL)
-               return 0;
-       if (strcmp(model, "MPC8313ERDB"))
-               return 0;
+        unsigned long root = of_get_flat_dt_root();
 
-       DBG("MPC8313 RDB found\n");
-
-       return 1;
+        return of_flat_dt_is_compatible(root, "MPC8313ERDB");
 }
 
 define_machine(mpc8313_rdb) {
index 3ecb55f8a6e265c8c16607e3ba9221089d42b10b..17e3a3c6d8b4e45a198c87008d757e69af51da7d 100644 (file)
@@ -57,11 +57,6 @@ unsigned long isa_mem_base = 0;
 
 static u8 *bcsr_regs = NULL;
 
-u8 *get_bcsr(void)
-{
-       return bcsr_regs;
-}
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -74,17 +69,6 @@ static void __init mpc832x_sys_setup_arch(void)
        if (ppc_md.progress)
                ppc_md.progress("mpc832x_sys_setup_arch()", 0);
 
-       np = of_find_node_by_type(NULL, "cpu");
-       if (np != 0) {
-               unsigned int *fp =
-                   (int *)get_property(np, "clock-frequency", NULL);
-               if (fp != 0)
-                       loops_per_jiffy = *fp / HZ;
-               else
-                       loops_per_jiffy = 50000000 / HZ;
-               of_node_put(np);
-       }
-
        /* Map BCSR area */
        np = of_find_node_by_name(NULL, "bcsr");
        if (np != 0) {
@@ -121,34 +105,23 @@ static void __init mpc832x_sys_setup_arch(void)
                iounmap(bcsr_regs);
                of_node_put(np);
        }
-
 #endif                         /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start)
-               ROOT_DEV = Root_RAM0;
-       else
-#endif
-#ifdef  CONFIG_ROOT_NFS
-               ROOT_DEV = Root_NFS;
-#else
-               ROOT_DEV = Root_HDA1;
-#endif
 }
 
+static struct of_device_id mpc832x_ids[] = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       { .type = "qe", },
+       {},
+};
+
 static int __init mpc832x_declare_of_platform_devices(void)
 {
-       struct device_node *np;
-
-       for (np = NULL; (np = of_find_compatible_node(np, "network",
-                                       "ucc_geth")) != NULL;) {
-               int ucc_num;
-               char bus_id[BUS_ID_SIZE];
+       if (!machine_is(mpc832x_mds))
+               return 0;
 
-               ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
-               snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
-               of_platform_device_create(np, bus_id, NULL);
-       }
+       /* Publish the QE devices */
+       of_platform_bus_probe(NULL, mpc832x_ids, NULL);
 
        return 0;
 }
@@ -156,7 +129,6 @@ device_initcall(mpc832x_declare_of_platform_devices);
 
 static void __init mpc832x_sys_init_IRQ(void)
 {
-
        struct device_node *np;
 
        np = of_find_node_by_type(NULL, "ipic");
@@ -189,6 +161,9 @@ static int __init mpc832x_rtc_hookup(void)
 {
        struct timespec tv;
 
+       if (!machine_is(mpc832x_mds))
+               return 0;
+
        ppc_md.get_rtc_time = ds1374_get_rtc_time;
        ppc_md.set_rtc_time = ds1374_set_rtc_time;
 
@@ -207,17 +182,9 @@ late_initcall(mpc832x_rtc_hookup);
  */
 static int __init mpc832x_sys_probe(void)
 {
-       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "model", NULL);
-
-       if (model == NULL)
-               return 0;
-       if (strcmp(model, "MPC8323EMDS"))
-               return 0;
-
-       DBG("%s found\n", model);
+        unsigned long root = of_get_flat_dt_root();
 
-       return 1;
+        return of_flat_dt_is_compatible(root, "MPC832xMDS");
 }
 
 define_machine(mpc832x_mds) {
index 443a3172f370f96295f751e8baafbaddeb9a6acc..3c009f6d4a4f12baec689d577cba7070cb76f097 100644 (file)
@@ -55,28 +55,12 @@ static void __init mpc834x_itx_setup_arch(void)
        if (ppc_md.progress)
                ppc_md.progress("mpc834x_itx_setup_arch()", 0);
 
-       np = of_find_node_by_type(NULL, "cpu");
-       if (np != 0) {
-               const unsigned int *fp =
-                       get_property(np, "clock-frequency", NULL);
-               if (fp != 0)
-                       loops_per_jiffy = *fp / HZ;
-               else
-                       loops_per_jiffy = 50000000 / HZ;
-               of_node_put(np);
-       }
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
                add_bridge(np);
 
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-       ROOT_DEV = Root_NFS;
-#else
-       ROOT_DEV = Root_HDA1;
-#endif
 }
 
 static void __init mpc834x_itx_init_IRQ(void)
@@ -100,10 +84,9 @@ static void __init mpc834x_itx_init_IRQ(void)
  */
 static int __init mpc834x_itx_probe(void)
 {
-       /* We always match for now, eventually we should look at the flat
-          dev tree to ensure this is the board we are suppose to run on
-       */
-       return 1;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC834xMITX");
 }
 
 define_machine(mpc834x_itx) {
index d2736da76c46bb63ca3a1ef6e394b0bf1157a53d..e5d819166874641f39d44e64d8c95dc56d2e8121 100644 (file)
@@ -125,17 +125,6 @@ static void __init mpc834x_mds_setup_arch(void)
        if (ppc_md.progress)
                ppc_md.progress("mpc834x_mds_setup_arch()", 0);
 
-       np = of_find_node_by_type(NULL, "cpu");
-       if (np != 0) {
-               const unsigned int *fp =
-                       get_property(np, "clock-frequency", NULL);
-               if (fp != 0)
-                       loops_per_jiffy = *fp / HZ;
-               else
-                       loops_per_jiffy = 50000000 / HZ;
-               of_node_put(np);
-       }
-
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
                add_bridge(np);
@@ -144,12 +133,6 @@ static void __init mpc834x_mds_setup_arch(void)
 #endif
 
        mpc834x_usb_cfg();
-
-#ifdef  CONFIG_ROOT_NFS
-       ROOT_DEV = Root_NFS;
-#else
-       ROOT_DEV = Root_HDA1;
-#endif
 }
 
 static void __init mpc834x_mds_init_IRQ(void)
@@ -176,6 +159,9 @@ static int __init mpc834x_rtc_hookup(void)
 {
        struct timespec tv;
 
+       if (!machine_is(mpc834x_mds))
+               return 0;
+
        ppc_md.get_rtc_time = ds1374_get_rtc_time;
        ppc_md.set_rtc_time = ds1374_set_rtc_time;
 
@@ -194,10 +180,9 @@ late_initcall(mpc834x_rtc_hookup);
  */
 static int __init mpc834x_mds_probe(void)
 {
-       /* We always match for now, eventually we should look at the flat
-          dev tree to ensure this is the board we are suppose to run on
-       */
-       return 1;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC834xMDS");
 }
 
 define_machine(mpc834x_mds) {
similarity index 67%
rename from arch/powerpc/platforms/83xx/mpc8360e_pb.c
rename to arch/powerpc/platforms/83xx/mpc836x_mds.c
index ccce2f9f283dad9b4db7542f54d93605774d2523..526ed090a446a36c60b4b19db32e964339dc7087 100644 (file)
@@ -5,12 +5,12 @@
  *        Yin Olivia <Hong-hua.Yin@freescale.com>
  *
  * Description:
- * MPC8360E MDS PB board specific routines.
+ * MPC8360E MDS board specific routines.
  *
  * Changelog:
  * Jun 21, 2006        Initial version
  *
- * This program is free software; you can redistribute  it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
@@ -62,33 +62,17 @@ unsigned long isa_mem_base = 0;
 
 static u8 *bcsr_regs = NULL;
 
-u8 *get_bcsr(void)
-{
-       return bcsr_regs;
-}
-
 /* ************************************************************************
  *
  * Setup the architecture
  *
  */
-static void __init mpc8360_sys_setup_arch(void)
+static void __init mpc836x_mds_setup_arch(void)
 {
        struct device_node *np;
 
        if (ppc_md.progress)
-               ppc_md.progress("mpc8360_sys_setup_arch()", 0);
-
-       np = of_find_node_by_type(NULL, "cpu");
-       if (np != 0) {
-               const unsigned int *fp =
-                   get_property(np, "clock-frequency", NULL);
-               if (fp != 0)
-                       loops_per_jiffy = *fp / HZ;
-               else
-                       loops_per_jiffy = 50000000 / HZ;
-               of_node_put(np);
-       }
+               ppc_md.progress("mpc836x_mds_setup_arch()", 0);
 
        /* Map BCSR area */
        np = of_find_node_by_name(NULL, "bcsr");
@@ -128,40 +112,29 @@ static void __init mpc8360_sys_setup_arch(void)
        }
 
 #endif                         /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start)
-               ROOT_DEV = Root_RAM0;
-       else
-#endif
-#ifdef  CONFIG_ROOT_NFS
-               ROOT_DEV = Root_NFS;
-#else
-               ROOT_DEV = Root_HDA1;
-#endif
 }
 
-static int __init mpc8360_declare_of_platform_devices(void)
-{
-       struct device_node *np;
+static struct of_device_id mpc836x_ids[] = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       { .type = "qe", },
+       {},
+};
 
-       for (np = NULL; (np = of_find_compatible_node(np, "network",
-                                       "ucc_geth")) != NULL;) {
-               int ucc_num;
-               char bus_id[BUS_ID_SIZE];
+static int __init mpc836x_declare_of_platform_devices(void)
+{
+       if (!machine_is(mpc836x_mds))
+               return 0;
 
-               ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
-               snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
-               of_platform_device_create(np, bus_id, NULL);
-       }
+       /* Publish the QE devices */
+       of_platform_bus_probe(NULL, mpc836x_ids, NULL);
 
        return 0;
 }
-device_initcall(mpc8360_declare_of_platform_devices);
+device_initcall(mpc836x_declare_of_platform_devices);
 
-static void __init mpc8360_sys_init_IRQ(void)
+static void __init mpc836x_mds_init_IRQ(void)
 {
-
        struct device_node *np;
 
        np = of_find_node_by_type(NULL, "ipic");
@@ -194,6 +167,9 @@ static int __init mpc8360_rtc_hookup(void)
 {
        struct timespec tv;
 
+       if (!machine_is(mpc836x_mds))
+               return 0;
+
        ppc_md.get_rtc_time = ds1374_get_rtc_time;
        ppc_md.set_rtc_time = ds1374_set_rtc_time;
 
@@ -210,28 +186,21 @@ late_initcall(mpc8360_rtc_hookup);
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
-static int __init mpc8360_sys_probe(void)
+static int __init mpc836x_mds_probe(void)
 {
-       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "model", NULL);
-       if (model == NULL)
-               return 0;
-       if (strcmp(model, "MPC8360EPB"))
-               return 0;
-
-       DBG("MPC8360EMDS-PB found\n");
+        unsigned long root = of_get_flat_dt_root();
 
-       return 1;
+        return of_flat_dt_is_compatible(root, "MPC836xMDS");
 }
 
-define_machine(mpc8360_sys) {
-       .name           = "MPC8360E PB",
-       .probe          = mpc8360_sys_probe,
-       .setup_arch     = mpc8360_sys_setup_arch,
-       .init_IRQ       = mpc8360_sys_init_IRQ,
-       .get_irq        = ipic_get_irq,
-       .restart        = mpc83xx_restart,
-       .time_init      = mpc83xx_time_init,
+define_machine(mpc836x_mds) {
+       .name           = "MPC836x MDS",
+       .probe          = mpc836x_mds_probe,
+       .setup_arch     = mpc836x_mds_setup_arch,
+       .init_IRQ       = mpc836x_mds_init_IRQ,
+       .get_irq        = ipic_get_irq,
+       .restart        = mpc83xx_restart,
+       .time_init      = mpc83xx_time_init,
        .calibrate_decr = generic_calibrate_decr,
-       .progress       = udbg_progress,
+       .progress       = udbg_progress,
 };
index 0efdd2f1babe382bfdae1cd4d6f240c7895215fe..eb661ccf2dab6f80098ed485671863c5d2c66090 100644 (file)
@@ -23,12 +23,12 @@ config MPC85xx_CDS
        help
          This option enables support for the MPC85xx CDS board
 
-config MPC8568_MDS
-       bool "Freescale MPC8568 MDS"
+config MPC85xx_MDS
+       bool "Freescale MPC85xx MDS"
        select DEFAULT_UIMAGE
 #      select QUICC_ENGINE
        help
-         This option enables support for the MPC8568 MDS board
+         This option enables support for the MPC85xx MDS board
 
 endchoice
 
@@ -47,7 +47,7 @@ config MPC85xx
        bool
        select PPC_UDBG_16550
        select PPC_INDIRECT_PCI
-       default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC8568_MDS
+       default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS
 
 config PPC_INDIRECT_PCI_BE
        bool
index e40e521816b8147a1d4e508ee137d69360e94f7e..4e63917ada9d4651744f0c08dfd4eeec892b8828 100644 (file)
@@ -5,4 +5,4 @@ obj-$(CONFIG_PPC_85xx)  += misc.o pci.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
-obj-$(CONFIG_MPC8568_MDS) += mpc8568_mds.o
+obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
index c56fce57621c1cb5c943fbfeb94de26c8c3e1cd8..8ed034aeca5f139acfac1875e6a3a19058b4c8e6 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -245,12 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void)
                add_bridge(np);
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-       ROOT_DEV = Root_NFS;
-#else
-       ROOT_DEV = Root_HDA1;
-#endif
 }
 
 static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -279,10 +272,9 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
  */
 static int __init mpc85xx_ads_probe(void)
 {
-       /* We always match for now, eventually we should look at the flat
-          dev tree to ensure this is the board we are suppose to run on
-       */
-       return 1;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC85xxADS");
 }
 
 define_machine(mpc85xx_ads) {
index abc0aca6de4052760ce9b6204eec9604c0a3cef1..4232686be441b4e534777c658e2f352223546114 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
@@ -263,12 +262,6 @@ static void __init mpc85xx_cds_setup_arch(void)
        ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-       ROOT_DEV = Root_NFS;
-#else
-       ROOT_DEV = Root_HDA1;
-#endif
 }
 
 static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -298,11 +291,9 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
  */
 static int __init mpc85xx_cds_probe(void)
 {
-       /* We always match for now, eventually we should look at
-        * the flat dev tree to ensure this is the board we are
-        * supposed to run on
-        */
-       return 1;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC85xxCDS");
 }
 
 define_machine(mpc85xx_cds) {
similarity index 84%
rename from arch/powerpc/platforms/85xx/mpc8568_mds.c
rename to arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 0861d1107bc82f348bfb603e4ce725659359bda2..81144d2ae455a0f75e31535301467176a094d775 100644 (file)
@@ -8,7 +8,7 @@
  *        Yin Olivia <Hong-hua.Yin@freescale.com>
  *
  * Description:
- * MPC8568E MDS PB board specific routines.
+ * MPC85xx MDS board specific routines.
  *
  * 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
@@ -27,7 +27,6 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
@@ -70,14 +69,13 @@ unsigned long isa_mem_base = 0;
  * Setup the architecture
  *
  */
-static void __init mpc8568_mds_setup_arch(void)
+static void __init mpc85xx_mds_setup_arch(void)
 {
        struct device_node *np;
        static u8 *bcsr_regs = NULL;
 
-
        if (ppc_md.progress)
-               ppc_md.progress("mpc8568_mds_setup_arch()", 0);
+               ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
 
        np = of_find_node_by_type(NULL, "cpu");
        if (np != NULL) {
@@ -145,26 +143,26 @@ static void __init mpc8568_mds_setup_arch(void)
 #endif /* CONFIG_QUICC_ENGINE */
 }
 
-static struct of_device_id mpc8568_ids[] = {
+static struct of_device_id mpc85xx_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "qe", },
        {},
 };
 
-static int __init mpc8568_publish_devices(void)
+static int __init mpc85xx_publish_devices(void)
 {
-       if (!machine_is(mpc8568_mds))
+       if (!machine_is(mpc85xx_mds))
                return 0;
 
        /* Publish the QE devices */
-       of_platform_bus_probe(NULL,mpc8568_ids,NULL);
+       of_platform_bus_probe(NULL,mpc85xx_ids,NULL);
 
        return 0;
 }
-device_initcall(mpc8568_publish_devices);
+device_initcall(mpc85xx_publish_devices);
 
-static void __init mpc8568_mds_pic_init(void)
+static void __init mpc85xx_mds_pic_init(void)
 {
        struct mpic *mpic;
        struct resource r;
@@ -207,7 +205,6 @@ static void __init mpc8568_mds_pic_init(void)
 
        mpic_init(mpic);
 
-
 #ifdef CONFIG_QUICC_ENGINE
        np = of_find_node_by_type(NULL, "qeic");
        if (!np)
@@ -218,27 +215,18 @@ static void __init mpc8568_mds_pic_init(void)
 #endif                         /* CONFIG_QUICC_ENGINE */
 }
 
-
-static int __init mpc8568_mds_probe(void)
+static int __init mpc85xx_mds_probe(void)
 {
-       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "model", NULL);
-       if (model == NULL)
-               return 0;
-       if (strcmp(model, "MPC8568EMDS"))
-               return 0;
-
-       DBG("MPC8568EMDS found\n");
+        unsigned long root = of_get_flat_dt_root();
 
-       return 1;
+        return of_flat_dt_is_compatible(root, "MPC85xxMDS");
 }
 
-
-define_machine(mpc8568_mds) {
-       .name           = "MPC8568E MDS",
-       .probe          = mpc8568_mds_probe,
-       .setup_arch     = mpc8568_mds_setup_arch,
-       .init_IRQ       = mpc8568_mds_pic_init,
+define_machine(mpc85xx_mds) {
+       .name           = "MPC85xx MDS",
+       .probe          = mpc85xx_mds_probe,
+       .setup_arch     = mpc85xx_mds_setup_arch,
+       .init_IRQ       = mpc85xx_mds_pic_init,
        .get_irq        = mpic_get_irq,
        .restart        = mpc85xx_restart,
        .calibrate_decr = generic_calibrate_decr,
index f4dd5f2f8a28f262911afba39eb20016784432ab..f42f801cf84ed6af33e7ed21b3110a8a93d0629f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -120,6 +119,8 @@ mpc86xx_hpcn_init_irq(void)
        DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
 
        i8259_init(cascade_node, 0);
+       of_node_put(cascade_node);
+
        set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
 #endif
 }
@@ -365,12 +366,6 @@ mpc86xx_hpcn_setup_arch(void)
 
        printk("MPC86xx HPCN board from Freescale Semiconductor\n");
 
-#ifdef  CONFIG_ROOT_NFS
-       ROOT_DEV = Root_NFS;
-#else
-       ROOT_DEV = Root_HDA1;
-#endif
-
 #ifdef CONFIG_SMP
        mpc86xx_smp_init();
 #endif
index 3baf658ac543dfa78c16f861c0baa74413505619..f4f82520dc4f59aa1d0f35d387f43637185251d8 100644 (file)
@@ -1,9 +1,8 @@
 obj-y                          += interrupt.o iommu.o setup.o \
                                   htab.o beat.o pci.o \
-                                  scc_epci.o hvCall.o
+                                  scc_epci.o scc_uhc.o hvCall.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PPC_UDBG_BEAT)    += udbg_beat.o
-obj-$(CONFIG_USB)              += scc_uhc.o
 obj-$(CONFIG_HAS_TXX9_SERIAL)  += scc_sio.o
 obj-$(CONFIG_SPU_BASE)         += spu_priv1.o
index 1de63acfda873ab8b893f88421eed7c4fa8135db..5f4d0d9332388e1e9455f5a0a7a6c1c49294a7d4 100644 (file)
@@ -137,10 +137,12 @@ static int celleb_check_legacy_ioport(unsigned int baseport)
        return -ENODEV;
 }
 
+#ifdef CONFIG_KEXEC
 static void celleb_kexec_cpu_down(int crash, int secondary)
 {
        beatic_deinit_IRQ();
 }
+#endif
 
 static struct of_device_id celleb_bus_ids[] = {
        { .type = "scc", },
index 39db12890214e5e905cb69b01bc0c9a6c4bf1ad0..5e5c0e4add91dc09cf465d0e3bd9eb0f4dfdabb8 100644 (file)
@@ -305,8 +305,6 @@ static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
        level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
        if (level)
                desc->status |= IRQ_LEVEL;
-       else
-               desc->status |= IRQ_DELAYED_DISABLE;
        set_irq_chip_and_handler(virq, &pmac_pic, level ?
                                 handle_level_irq : handle_edge_irq);
        return 0;
index 4be3943d1c0dca360c13cc144969f3c459b8fdeb..d270a1e374d5981662e788f10dfd9b7f07cd2aac 100644 (file)
@@ -62,4 +62,14 @@ config PS3_PS3AV
          This support is required for graphics and sound. In
          general, all users will say Y or M.
 
+config PS3_SYS_MANAGER
+       bool "PS3 System Manager driver"
+       select PS3_VUART
+       default y
+       help
+         Include support for the PS3 System Manager.
+
+         This support is required for system control.  In
+         general, all users will say Y.
+
 endmenu
index 13d669a8ecae6d00e25fc816d163e711db8cb7f7..ac5df9688dcb9685e06434e901b0b200498dba84 100644 (file)
 #define DBG(fmt...) do{if(0)printk(fmt);}while(0)
 #endif
 
+#if !defined(CONFIG_SMP)
+static void smp_send_stop(void) {}
+#endif
+
 int ps3_get_firmware_version(union ps3_firmware_version *v)
 {
        int result = lv1_get_version_info(&v->raw);
@@ -66,22 +70,35 @@ static void ps3_power_save(void)
        lv1_pause(0);
 }
 
+static void ps3_restart(char *cmd)
+{
+       DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd);
+
+       smp_send_stop();
+       ps3_sys_manager_restart(); /* never returns */
+}
+
+static void ps3_power_off(void)
+{
+       DBG("%s:%d\n", __func__, __LINE__);
+
+       smp_send_stop();
+       ps3_sys_manager_power_off(); /* never returns */
+}
+
 static void ps3_panic(char *str)
 {
        DBG("%s:%d %s\n", __func__, __LINE__, str);
 
-#ifdef CONFIG_SMP
        smp_send_stop();
-#endif
        printk("\n");
        printk("   System does not reboot automatically.\n");
        printk("   Please press POWER button.\n");
        printk("\n");
 
-       for (;;) ;
+       while(1);
 }
 
-
 static void prealloc(struct ps3_prealloc *p)
 {
        if (!p->size)
@@ -219,6 +236,8 @@ define_machine(ps3) {
        .get_rtc_time                   = ps3_get_rtc_time,
        .calibrate_decr                 = ps3_calibrate_decr,
        .progress                       = ps3_progress,
+       .restart                        = ps3_restart,
+       .power_off                      = ps3_power_off,
 #if defined(CONFIG_KEXEC)
        .kexec_cpu_down                 = ps3_kexec_cpu_down,
        .machine_kexec                  = ps3_machine_kexec,
index dc0583bdbc637ec769e817cab5ad68f8216f37ca..2dfd05095a25fac98734f871a9188bba1fbaa1bc 100644 (file)
@@ -4,7 +4,7 @@ endif
 
 obj-y                  := pci.o lpar.o hvCall.o nvram.o reconfig.o \
                           setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
-                          firmware.o
+                          firmware.o power.o
 obj-$(CONFIG_SMP)      += smp.o
 obj-$(CONFIG_XICS)     += xics.o
 obj-$(CONFIG_SCANLOG)  += scanlog.o
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
new file mode 100644 (file)
index 0000000..2624b71
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  Interface for power-management for ppc64 compliant platform
+ *
+ *  Manish Ahuja <mahuja@us.ibm.com>
+ *
+ *  Feb 2007
+ *
+ *  Copyright (C) 2007 IBM Corporation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+unsigned long rtas_poweron_auto; /* default and normal state is 0 */
+
+static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+{
+        return sprintf(buf, "%lu\n", rtas_poweron_auto);
+}
+
+static ssize_t
+auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+{
+       int ret;
+       unsigned long ups_restart;
+       ret = sscanf(buf, "%lu", &ups_restart);
+
+       if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){
+               rtas_poweron_auto = ups_restart;
+               return n;
+       }
+       return -EINVAL;
+}
+
+static struct subsys_attribute auto_poweron_attr = {
+        .attr   = {
+                .name = __stringify(auto_poweron),
+                .mode = 0644,
+        },
+        .show   = auto_poweron_show,
+        .store  = auto_poweron_store,
+};
+
+#ifndef CONFIG_PM
+decl_subsys(power,NULL,NULL);
+
+static struct attribute *g[] = {
+        &auto_poweron_attr.attr,
+        NULL,
+};
+
+static struct attribute_group attr_group = {
+        .attrs = g,
+};
+
+static int __init pm_init(void)
+{
+        int error = subsystem_register(&power_subsys);
+        if (!error)
+                error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+        return error;
+}
+core_initcall(pm_init);
+#else
+extern struct subsystem power_subsys;
+
+static int __init apo_pm_init(void)
+{
+       return (subsys_create_file(&power_subsys, &auto_poweron_attr));
+}
+__initcall(apo_pm_init);
+#endif
index b43f1397a5b63eaa49dc9f3b90c8ce3579cf823f..22bc019897495b3a733b162ef8e8f7195473ee10 100644 (file)
@@ -29,8 +29,11 @@ static inline smp_init_pseries_xics(void) { };
 extern void setup_kexec_cpu_down_xics(void);
 extern void setup_kexec_cpu_down_mpic(void);
 #else
-static inline setup_kexec_cpu_down_xics(void) { };
-static inline setup_kexec_cpu_down_mpic(void) { };
+static inline void setup_kexec_cpu_down_xics(void) { }
+static inline void setup_kexec_cpu_down_mpic(void) { }
 #endif
 
+/* Poweron flag used for enabling auto ups restart */
+extern unsigned long rtas_poweron_auto;
+
 #endif /* _PSERIES_PSERIES_H */
index 435a045965261fec6bff86d23bdfe8c5212f6440..34aff47b1f551c670eca377eeb148a8f618dc946 100644 (file)
@@ -486,6 +486,34 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
        return PCI_PROBE_NORMAL;
 }
 
+/**
+ * pSeries_power_off - tell firmware about how to power off the system.
+ *
+ * This function calls either the power-off rtas token in normal cases
+ * or the ibm,power-off-ups token (if present & requested) in case of
+ * a power failure. If power-off token is used, power on will only be
+ * possible with power button press. If ibm,power-off-ups token is used
+ * it will allow auto poweron after power is restored.
+ */
+void pSeries_power_off(void)
+{
+       int rc;
+       int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
+
+       if (rtas_flash_term_hook)
+               rtas_flash_term_hook(SYS_POWER_OFF);
+
+       if (rtas_poweron_auto == 0 ||
+               rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
+               rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
+               printk(KERN_INFO "RTAS power-off returned %d\n", rc);
+       } else {
+               rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
+               printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
+       }
+       for (;;);
+}
+
 define_machine(pseries) {
        .name                   = "pSeries",
        .probe                  = pSeries_probe,
@@ -496,7 +524,7 @@ define_machine(pseries) {
        .pcibios_fixup          = pSeries_final_fixup,
        .pci_probe_mode         = pSeries_pci_probe_mode,
        .restart                = rtas_restart,
-       .power_off              = rtas_power_off,
+       .power_off              = pSeries_power_off,
        .halt                   = rtas_halt,
        .panic                  = rtas_os_term,
        .get_boot_time          = rtas_get_boot_time,
index 85dcdf178415fe19ae150e1a2498c4965a183019..26ca3ffbc1dee7c12df2cf31bd002d1c937bbc45 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI)  += indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
 obj-$(CONFIG_PPC_DCR)          += dcr.o
 obj-$(CONFIG_PPC_DCR_NATIVE)   += dcr-low.o
+obj-$(CONFIG_PPC_PMI)          += pmi.o
 obj-$(CONFIG_U3_DART)          += dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)       += mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
index 34161bc5a02f6384e7baf33e24de303325025872..d20f02927f7200a83812ad929c9317241718f7b3 100644 (file)
@@ -233,14 +233,7 @@ static int __init gfar_of_init(void)
                        goto err;
                }
 
-               mac_addr = get_property(np, "local-mac-address", NULL);
-               if (mac_addr == NULL)
-                       mac_addr = get_property(np, "mac-address", NULL);
-               if (mac_addr == NULL) {
-                       /* Obsolete */
-                       mac_addr = get_property(np, "address", NULL);
-               }
-
+               mac_addr = of_get_mac_address(np);
                if (mac_addr)
                        memcpy(gfar_data.mac_addr, mac_addr, 6);
 
@@ -646,8 +639,9 @@ static int __init fs_enet_of_init(void)
                        goto unreg;
                }
 
-               mac_addr = get_property(np, "mac-address", NULL);
-               memcpy(fs_enet_data.macaddr, mac_addr, 6);
+               mac_addr = of_get_mac_address(np);
+               if (mac_addr)
+                       memcpy(fs_enet_data.macaddr, mac_addr, 6);
 
                ph = get_property(np, "phy-handle", NULL);
                phy = of_find_node_by_phandle(*ph);
@@ -931,8 +925,9 @@ static int __init fs_enet_of_init(void)
                        goto err;
                r[0].name = enet_regs;
 
-               mac_addr = (void *)get_property(np, "mac-address", NULL);
-               memcpy(fs_enet_data.macaddr, mac_addr, 6);
+               mac_addr = of_get_mac_address(np);
+               if (mac_addr)
+                       memcpy(fs_enet_data.macaddr, mac_addr, 6);
 
                ph = (phandle *) get_property(np, "phy-handle", NULL);
                if (ph != NULL)
index 4e54a09dd33b1fc0c197ad77fa4c47123ba6b0a5..bcfb900481f8fdb6180dc474ed991d1dc7dd164d 100644 (file)
@@ -1370,7 +1370,7 @@ void mpic_request_ipis(void)
                        printk(KERN_ERR "Failed to map IPI %d\n", i);
                        break;
                }
-               request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
+               request_irq(vipi, mpic_ipi_action, IRQF_DISABLED|IRQF_PERCPU,
                            ipi_names[i], mpic);
        }
 }
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
new file mode 100644 (file)
index 0000000..a528201
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * pmi driver
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/io.h>
+#include <asm/pmi.h>
+
+
+struct pmi_data {
+       struct list_head        handler;
+       spinlock_t              handler_spinlock;
+       spinlock_t              pmi_spinlock;
+       struct mutex            msg_mutex;
+       pmi_message_t           msg;
+       struct completion       *completion;
+       struct of_device        *dev;
+       int                     irq;
+       u8 __iomem              *pmi_reg;
+       struct work_struct      work;
+};
+
+
+
+static void __iomem *of_iomap(struct device_node *np)
+{
+       struct resource res;
+
+       if (of_address_to_resource(np, 0, &res))
+               return NULL;
+
+       pr_debug("Resource start: 0x%lx\n", res.start);
+       pr_debug("Resource end: 0x%lx\n", res.end);
+
+       return ioremap(res.start, 1 + res.end - res.start);
+}
+
+
+static int pmi_irq_handler(int irq, void *dev_id)
+{
+       struct pmi_data *data;
+       u8 type;
+       int rc;
+
+       data = dev_id;
+
+       spin_lock(&data->pmi_spinlock);
+
+       type = ioread8(data->pmi_reg + PMI_READ_TYPE);
+       pr_debug("pmi: got message of type %d\n", type);
+
+       if (type & PMI_ACK && !data->completion) {
+               printk(KERN_WARNING "pmi: got unexpected ACK message.\n");
+               rc = -EIO;
+               goto unlock;
+       }
+
+       if (data->completion && !(type & PMI_ACK)) {
+               printk(KERN_WARNING "pmi: expected ACK, but got %d\n", type);
+               rc = -EIO;
+               goto unlock;
+       }
+
+       data->msg.type = type;
+       data->msg.data0 = ioread8(data->pmi_reg + PMI_READ_DATA0);
+       data->msg.data1 = ioread8(data->pmi_reg + PMI_READ_DATA1);
+       data->msg.data2 = ioread8(data->pmi_reg + PMI_READ_DATA2);
+       rc = 0;
+unlock:
+       spin_unlock(&data->pmi_spinlock);
+
+       if (rc == -EIO) {
+               rc = IRQ_HANDLED;
+               goto out;
+       }
+
+       if (data->msg.type & PMI_ACK) {
+               complete(data->completion);
+               rc = IRQ_HANDLED;
+               goto out;
+       }
+
+       schedule_work(&data->work);
+
+       rc = IRQ_HANDLED;
+out:
+       return rc;
+}
+
+
+static struct of_device_id pmi_match[] = {
+       { .type = "ibm,pmi", .name = "ibm,pmi" },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, pmi_match);
+
+static void pmi_notify_handlers(struct work_struct *work)
+{
+       struct pmi_data *data;
+       struct pmi_handler *handler;
+
+       data = container_of(work, struct pmi_data, work);
+
+       spin_lock(&data->handler_spinlock);
+       list_for_each_entry(handler, &data->handler, node) {
+               pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+               if (handler->type == data->msg.type)
+                       handler->handle_pmi_message(data->dev, data->msg);
+       }
+       spin_unlock(&data->handler_spinlock);
+}
+
+static int pmi_of_probe(struct of_device *dev,
+                       const struct of_device_id *match)
+{
+       struct device_node *np = dev->node;
+       struct pmi_data *data;
+       int rc;
+
+       data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL);
+       if (!data) {
+               printk(KERN_ERR "pmi: could not allocate memory.\n");
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       data->pmi_reg = of_iomap(np);
+       if (!data->pmi_reg) {
+               printk(KERN_ERR "pmi: invalid register address.\n");
+               rc = -EFAULT;
+               goto error_cleanup_data;
+       }
+
+       INIT_LIST_HEAD(&data->handler);
+
+       mutex_init(&data->msg_mutex);
+       spin_lock_init(&data->pmi_spinlock);
+       spin_lock_init(&data->handler_spinlock);
+
+       INIT_WORK(&data->work, pmi_notify_handlers);
+
+       dev->dev.driver_data = data;
+       data->dev = dev;
+
+       data->irq = irq_of_parse_and_map(np, 0);
+       if (data->irq == NO_IRQ) {
+               printk(KERN_ERR "pmi: invalid interrupt.\n");
+               rc = -EFAULT;
+               goto error_cleanup_iomap;
+       }
+
+       rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data);
+       if (rc) {
+               printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n",
+                               data->irq, rc);
+               goto error_cleanup_iomap;
+       }
+
+       printk(KERN_INFO "pmi: found pmi device at addr %p.\n", data->pmi_reg);
+
+       goto out;
+
+error_cleanup_iomap:
+       iounmap(data->pmi_reg);
+
+error_cleanup_data:
+       kfree(data);
+
+out:
+       return rc;
+}
+
+static int pmi_of_remove(struct of_device *dev)
+{
+       struct pmi_data *data;
+       struct pmi_handler *handler, *tmp;
+
+       data = dev->dev.driver_data;
+
+       free_irq(data->irq, data);
+       iounmap(data->pmi_reg);
+
+       spin_lock(&data->handler_spinlock);
+
+       list_for_each_entry_safe(handler, tmp, &data->handler, node)
+               list_del(&handler->node);
+
+       spin_unlock(&data->handler_spinlock);
+
+       kfree(dev->dev.driver_data);
+
+       return 0;
+}
+
+static struct of_platform_driver pmi_of_platform_driver = {
+       .name           = "pmi",
+       .match_table    = pmi_match,
+       .probe          = pmi_of_probe,
+       .remove         = pmi_of_remove
+};
+
+static int __init pmi_module_init(void)
+{
+       return of_register_platform_driver(&pmi_of_platform_driver);
+}
+module_init(pmi_module_init);
+
+static void __exit pmi_module_exit(void)
+{
+       of_unregister_platform_driver(&pmi_of_platform_driver);
+}
+module_exit(pmi_module_exit);
+
+void pmi_send_message(struct of_device *device, pmi_message_t msg)
+{
+       struct pmi_data *data;
+       unsigned long flags;
+       DECLARE_COMPLETION_ONSTACK(completion);
+
+       data = device->dev.driver_data;
+
+       mutex_lock(&data->msg_mutex);
+
+       data->msg = msg;
+       pr_debug("pmi_send_message: msg is %08x\n", *(u32*)&msg);
+
+       data->completion = &completion;
+
+       spin_lock_irqsave(&data->pmi_spinlock, flags);
+       iowrite8(msg.data0, data->pmi_reg + PMI_WRITE_DATA0);
+       iowrite8(msg.data1, data->pmi_reg + PMI_WRITE_DATA1);
+       iowrite8(msg.data2, data->pmi_reg + PMI_WRITE_DATA2);
+       iowrite8(msg.type, data->pmi_reg + PMI_WRITE_TYPE);
+       spin_unlock_irqrestore(&data->pmi_spinlock, flags);
+
+       pr_debug("pmi_send_message: wait for completion\n");
+
+       wait_for_completion_interruptible_timeout(data->completion,
+                                                 PMI_TIMEOUT);
+
+       data->completion = NULL;
+
+       mutex_unlock(&data->msg_mutex);
+}
+EXPORT_SYMBOL_GPL(pmi_send_message);
+
+void pmi_register_handler(struct of_device *device,
+                         struct pmi_handler *handler)
+{
+       struct pmi_data *data;
+       data = device->dev.driver_data;
+
+       spin_lock(&data->handler_spinlock);
+       list_add_tail(&handler->node, &data->handler);
+       spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_register_handler);
+
+void pmi_unregister_handler(struct of_device *device,
+                           struct pmi_handler *handler)
+{
+       struct pmi_data *data;
+
+       pr_debug("pmi: unregistering handler %p\n", handler);
+
+       data = device->dev.driver_data;
+
+       spin_lock(&data->handler_spinlock);
+       list_del(&handler->node);
+       spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_unregister_handler);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+MODULE_DESCRIPTION("IBM Platform Management Interrupt driver");
index e657559bea93fdec3f80fad8e6dbdefec4ce1c5a..a457ac1c663924b030c931cfd7a28c84801b2757 100644 (file)
@@ -1,13 +1,12 @@
 /*
- * arch/powerpc/sysdev/qe_lib/ucc_fast.c
- *
- * QE UCC Fast API Set - UCC Fast specific routines implementations.
- *
  * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
  *
  * Authors:    Shlomi Gridish <gridish@freescale.com>
  *             Li Yang <leoli@freescale.com>
  *
+ * Description:
+ * QE UCC Fast API Set - UCC Fast specific routines implementations.
+ *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
 #include <asm/ucc.h>
 #include <asm/ucc_fast.h>
 
-#define uccf_printk(level, format, arg...) \
-       printk(level format "\n", ## arg)
-
-#define uccf_dbg(format, arg...) \
-       uccf_printk(KERN_DEBUG , format , ## arg)
-#define uccf_err(format, arg...) \
-       uccf_printk(KERN_ERR , format , ## arg)
-#define uccf_info(format, arg...) \
-       uccf_printk(KERN_INFO , format , ## arg)
-#define uccf_warn(format, arg...) \
-       uccf_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCF_VERBOSE_DEBUG
-#define uccf_vdbg uccf_dbg
-#else
-#define uccf_vdbg(fmt, args...) do { } while (0)
-#endif                         /* UCCF_VERBOSE_DEBUG */
-
 void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
 {
-       uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
-       uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
+       printk(KERN_INFO "UCC%d Fast registers:", uccf->uf_info->ucc_num);
+       printk(KERN_INFO "Base address: 0x%08x", (u32) uccf->uf_regs);
 
-       uccf_info("gumr  : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "gumr  : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
-       uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "upsmr : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
-       uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "utodr : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
-       uccf_info("udsr  : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "udsr  : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
-       uccf_info("ucce  : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "ucce  : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
-       uccf_info("uccm  : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "uccm  : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
-       uccf_info("uccs  : addr - 0x%08x, val - 0x%02x",
+       printk(KERN_INFO "uccs  : addr - 0x%08x, val - 0x%02x",
                  (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
-       uccf_info("urfb  : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "urfb  : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
-       uccf_info("urfs  : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "urfs  : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
-       uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "urfet : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
-       uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "urfset: addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->urfset,
                  in_be16(&uccf->uf_regs->urfset));
-       uccf_info("utfb  : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "utfb  : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
-       uccf_info("utfs  : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "utfs  : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
-       uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "utfet : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
-       uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "utftt : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
-       uccf_info("utpt  : addr - 0x%08x, val - 0x%04x",
+       printk(KERN_INFO "utpt  : addr - 0x%08x, val - 0x%04x",
                  (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
-       uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
+       printk(KERN_INFO "urtry : addr - 0x%08x, val - 0x%08x",
                  (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
-       uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
+       printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
                  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
 
 u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
 {
        switch (uccf_num) {
-       case 0: return QE_CR_SUBBLOCK_UCCFAST1;
+       case 0: return QE_CR_SUBBLOCK_UCCFAST1;
        case 1: return QE_CR_SUBBLOCK_UCCFAST2;
        case 2: return QE_CR_SUBBLOCK_UCCFAST3;
        case 3: return QE_CR_SUBBLOCK_UCCFAST4;
        case 4: return QE_CR_SUBBLOCK_UCCFAST5;
        case 5: return QE_CR_SUBBLOCK_UCCFAST6;
        case 6: return QE_CR_SUBBLOCK_UCCFAST7;
-       case 7: return QE_CR_SUBBLOCK_UCCFAST8;
+       case 7: return QE_CR_SUBBLOCK_UCCFAST8;
        default: return QE_CR_SUBBLOCK_INVALID;
        }
 }
@@ -153,84 +134,72 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 {
        struct ucc_fast_private *uccf;
        struct ucc_fast *uf_regs;
-       u32 gumr = 0;
+       u32 gumr;
        int ret;
 
-       uccf_vdbg("%s: IN", __FUNCTION__);
-
        if (!uf_info)
                return -EINVAL;
 
        /* check if the UCC port number is in range. */
        if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
-               uccf_err("ucc_fast_init: Illegal UCC number!");
+               printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
                return -EINVAL;
        }
 
        /* Check that 'max_rx_buf_length' is properly aligned (4). */
        if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
-               uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
+               printk(KERN_ERR "%s: max_rx_buf_length not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        /* Validate Virtual Fifo register values */
        if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register urfs too small.");
+               printk(KERN_ERR "%s: urfs is too small", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register urfs not aligned.");
+               printk(KERN_ERR "%s: urfs is not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register urfet not aligned.");
+               printk(KERN_ERR "%s: urfet is not aligned.", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                  ("ucc_fast_init: Virtual Fifo register urfset not aligned.");
+               printk(KERN_ERR "%s: urfset is not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register utfs not aligned.");
+               printk(KERN_ERR "%s: utfs is not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register utfet not aligned.");
+               printk(KERN_ERR "%s: utfet is not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-               uccf_err
-                   ("ucc_fast_init: Virtual Fifo register utftt not aligned.");
+               printk(KERN_ERR "%s: utftt is not aligned", __FUNCTION__);
                return -EINVAL;
        }
 
        uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
        if (!uccf) {
-               uccf_err
-                   ("ucc_fast_init: No memory for UCC slow data structure!");
+               printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
                return -ENOMEM;
        }
 
        /* Fill fast UCC structure */
        uccf->uf_info = uf_info;
        /* Set the PHY base address */
-       uccf->uf_regs =
-           (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
+       uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
        if (uccf->uf_regs == NULL) {
-               uccf_err
-                   ("ucc_fast_init: No memory map for UCC slow controller!");
+               printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
                return -ENOMEM;
        }
 
@@ -249,7 +218,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
        /* Init Guemr register */
        if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
-               uccf_err("ucc_fast_init: Could not init the guemr register.");
+               printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
                ucc_fast_free(uccf);
                return ret;
        }
@@ -258,7 +227,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
        if ((ret = ucc_set_type(uf_info->ucc_num,
                                (struct ucc_common *) (uf_regs),
                                UCC_SPEED_TYPE_FAST))) {
-               uccf_err("ucc_fast_init: Could not set type to fast.");
+               printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
                ucc_fast_free(uccf);
                return ret;
        }
@@ -267,10 +236,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
        /* Set GUMR */
        /* For more details see the hardware spec. */
-       /* gumr starts as zero. */
+       gumr = uf_info->ttx_trx;
        if (uf_info->tci)
                gumr |= UCC_FAST_GUMR_TCI;
-       gumr |= uf_info->ttx_trx;
        if (uf_info->cdp)
                gumr |= UCC_FAST_GUMR_CDP;
        if (uf_info->ctsp)
@@ -298,9 +266,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
        uccf->ucc_fast_tx_virtual_fifo_base_offset =
            qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
        if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
-               uccf_err
-                   ("ucc_fast_init: Can not allocate MURAM memory for "
-                       "struct ucc_fastx_virtual_fifo_base_offset.");
+               printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
                uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
                ucc_fast_free(uccf);
                return -ENOMEM;
@@ -308,14 +274,11 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
        /* Allocate memory for Rx Virtual Fifo */
        uccf->ucc_fast_rx_virtual_fifo_base_offset =
-           qe_muram_alloc(uf_info->urfs +
-                          (u32)
+               qe_muram_alloc(uf_info->urfs +
                           UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
                           UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
        if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
-               uccf_err
-                   ("ucc_fast_init: Can not allocate MURAM memory for "
-                       "ucc_fast_rx_virtual_fifo_base_offset.");
+               printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
                uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
                ucc_fast_free(uccf);
                return -ENOMEM;
@@ -342,26 +305,22 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
        /* If NMSI (not Tsa), set Tx and Rx clock. */
        if (!uf_info->tsa) {
                /* Rx clock routing */
-               if (uf_info->rx_clock != QE_CLK_NONE) {
-                       if (ucc_set_qe_mux_rxtx
-                           (uf_info->ucc_num, uf_info->rx_clock,
-                            COMM_DIR_RX)) {
-                               uccf_err
-               ("ucc_fast_init: Illegal value for parameter 'RxClock'.");
-                               ucc_fast_free(uccf);
-                               return -EINVAL;
-                       }
+               if ((uf_info->rx_clock != QE_CLK_NONE) &&
+                   ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+                                       COMM_DIR_RX)) {
+                       printk(KERN_ERR "%s: illegal value for RX clock",
+                              __FUNCTION__);
+                       ucc_fast_free(uccf);
+                       return -EINVAL;
                }
                /* Tx clock routing */
-               if (uf_info->tx_clock != QE_CLK_NONE) {
-                       if (ucc_set_qe_mux_rxtx
-                           (uf_info->ucc_num, uf_info->tx_clock,
-                            COMM_DIR_TX)) {
-                               uccf_err
-               ("ucc_fast_init: Illegal value for parameter 'TxClock'.");
-                               ucc_fast_free(uccf);
-                               return -EINVAL;
-                       }
+               if ((uf_info->tx_clock != QE_CLK_NONE) &&
+                   ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+                                       COMM_DIR_TX)) {
+                       printk(KERN_ERR "%s: illegal value for TX clock",
+                              __FUNCTION__);
+                       ucc_fast_free(uccf);
+                       return -EINVAL;
                }
        }
 
@@ -370,9 +329,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
        /* First, clear anything pending at UCC level,
         * otherwise, old garbage may come through
-        * as soon as the dam is opened
-        * Writing '1' clears
-        */
+        * as soon as the dam is opened. */
+
+       /* Writing '1' clears */
        out_be32(&uf_regs->ucce, 0xffffffff);
 
        *uccf_ret = uccf;
index 0e97e5c94f8ac98e318eee16ceade00f23aac308..817df73ecf56a8a9cf2810058e9e5e3a46ff7ce2 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 
-#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/immap_qe.h>
 #include <asm/qe.h>
 #include <asm/ucc.h>
 #include <asm/ucc_slow.h>
 
-#define uccs_printk(level, format, arg...) \
-        printk(level format "\n", ## arg)
-
-#define uccs_dbg(format, arg...) \
-       uccs_printk(KERN_DEBUG , format , ## arg)
-#define uccs_err(format, arg...) \
-       uccs_printk(KERN_ERR , format , ## arg)
-#define uccs_info(format, arg...) \
-       uccs_printk(KERN_INFO , format , ## arg)
-#define uccs_warn(format, arg...) \
-       uccs_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCS_VERBOSE_DEBUG
-#define uccs_vdbg uccs_dbg
-#else
-#define uccs_vdbg(fmt, args...) do { } while (0)
-#endif                         /* UCCS_VERBOSE_DEBUG */
-
 u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
 {
        switch (uccs_num) {
@@ -135,51 +116,53 @@ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
 
 int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
 {
+       struct ucc_slow_private *uccs;
        u32 i;
        struct ucc_slow *us_regs;
        u32 gumr;
-       u8 function_code = 0;
-       u8 *bd;
-       struct ucc_slow_private *uccs;
+       struct qe_bd *bd;
        u32 id;
        u32 command;
-       int ret;
-
-       uccs_vdbg("%s: IN", __FUNCTION__);
+       int ret = 0;
 
        if (!us_info)
                return -EINVAL;
 
        /* check if the UCC port number is in range. */
        if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
-               uccs_err("ucc_slow_init: Illegal UCC number!");
+               printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
                return -EINVAL;
        }
 
        /*
         * Set mrblr
         * Check that 'max_rx_buf_length' is properly aligned (4), unless
-        * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
+        * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
         * case when QE accepts 32 bits at a time.
         */
        if ((!us_info->rfw) &&
                (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
-               uccs_err("max_rx_buf_length not aligned.");
+               printk(KERN_ERR "max_rx_buf_length not aligned.");
                return -EINVAL;
        }
 
        uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
        if (!uccs) {
-               uccs_err
-                   ("ucc_slow_init: No memory for UCC slow data structure!");
+               printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
                return -ENOMEM;
        }
 
        /* Fill slow UCC structure */
        uccs->us_info = us_info;
+       /* Set the PHY base address */
+       uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+       if (uccs->us_regs == NULL) {
+               printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
+               return -ENOMEM;
+       }
+
        uccs->saved_uccm = 0;
        uccs->p_rx_frame = 0;
-       uccs->us_regs = us_info->regs;
        us_regs = uccs->us_regs;
        uccs->p_ucce = (u16 *) & (us_regs->ucce);
        uccs->p_uccm = (u16 *) & (us_regs->uccm);
@@ -190,24 +173,22 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 #endif                         /* STATISTICS */
 
        /* Get PRAM base */
-       uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE,
-                                                ALIGNMENT_OF_UCC_SLOW_PRAM);
+       uccs->us_pram_offset =
+               qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
        if (IS_MURAM_ERR(uccs->us_pram_offset)) {
-               uccs_err
-                   ("ucc_slow_init: Can not allocate MURAM memory "
-                       "for Slow UCC.");
+               printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
                ucc_slow_free(uccs);
                return -ENOMEM;
        }
        id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
        qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
-                       (u32) uccs->us_pram_offset);
+                    uccs->us_pram_offset);
 
        uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
 
        /* Init Guemr register */
        if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) {
-               uccs_err("ucc_slow_init: Could not init the guemr register.");
+               printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
                ucc_slow_free(uccs);
                return ret;
        }
@@ -216,7 +197,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
        if ((ret = ucc_set_type(us_info->ucc_num,
                                (struct ucc_common *) (us_info->regs),
                                UCC_SPEED_TYPE_SLOW))) {
-               uccs_err("ucc_slow_init: Could not init the guemr register.");
+               printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
                ucc_slow_free(uccs);
                return ret;
        }
@@ -230,7 +211,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
                qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
                                QE_ALIGNMENT_OF_BD);
        if (IS_MURAM_ERR(uccs->rx_base_offset)) {
-               uccs_err("ucc_slow_init: No memory for Rx BD's.");
+               printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
                uccs->rx_base_offset = 0;
                ucc_slow_free(uccs);
                return -ENOMEM;
@@ -240,7 +221,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
                qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
                        QE_ALIGNMENT_OF_BD);
        if (IS_MURAM_ERR(uccs->tx_base_offset)) {
-               uccs_err("ucc_slow_init: No memory for Tx BD's.");
+               printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
                uccs->tx_base_offset = 0;
                ucc_slow_free(uccs);
                return -ENOMEM;
@@ -248,34 +229,33 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 
        /* Init Tx bds */
        bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
-       for (i = 0; i < us_info->tx_bd_ring_len; i++) {
+       for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
                /* clear bd buffer */
-               out_be32(&(((struct qe_bd *)bd)->buf), 0);
+               out_be32(&bd->buf, 0);
                /* set bd status and length */
-               out_be32((u32*)bd, 0);
-               bd += sizeof(struct qe_bd);
+               out_be32((u32 *) bd, 0);
+               bd++;
        }
-       bd -= sizeof(struct qe_bd);
-       /* set bd status and length */
-       out_be32((u32*)bd, T_W);        /* for last BD set Wrap bit */
+       /* for last BD set Wrap bit */
+       out_be32(&bd->buf, 0);
+       out_be32((u32 *) bd, cpu_to_be32(T_W));
 
        /* Init Rx bds */
        bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
-       for (i = 0; i < us_info->rx_bd_ring_len; i++) {
+       for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
                /* set bd status and length */
                out_be32((u32*)bd, 0);
                /* clear bd buffer */
-               out_be32(&(((struct qe_bd *)bd)->buf), 0);
-               bd += sizeof(struct qe_bd);
+               out_be32(&bd->buf, 0);
+               bd++;
        }
-       bd -= sizeof(struct qe_bd);
-       /* set bd status and length */
-       out_be32((u32*)bd, R_W);        /* for last BD set Wrap bit */
+       /* for last BD set Wrap bit */
+       out_be32((u32*)bd, cpu_to_be32(R_W));
+       out_be32(&bd->buf, 0);
 
        /* Set GUMR (For more details see the hardware spec.). */
        /* gumr_h */
-       gumr = 0;
-       gumr |= us_info->tcrc;
+       gumr = us_info->tcrc;
        if (us_info->cdp)
                gumr |= UCC_SLOW_GUMR_H_CDP;
        if (us_info->ctsp)
@@ -295,7 +275,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
        out_be32(&us_regs->gumr_h, gumr);
 
        /* gumr_l */
-       gumr = 0;
+       gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
+               us_info->diag | us_info->mode;
        if (us_info->tci)
                gumr |= UCC_SLOW_GUMR_L_TCI;
        if (us_info->rinv)
@@ -304,23 +285,14 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
                gumr |= UCC_SLOW_GUMR_L_TINV;
        if (us_info->tend)
                gumr |= UCC_SLOW_GUMR_L_TEND;
-       gumr |= us_info->tdcr;
-       gumr |= us_info->rdcr;
-       gumr |= us_info->tenc;
-       gumr |= us_info->renc;
-       gumr |= us_info->diag;
-       gumr |= us_info->mode;
        out_be32(&us_regs->gumr_l, gumr);
 
        /* Function code registers */
-       /* function_code has initial value 0 */
 
        /* if the data is in cachable memory, the 'global' */
        /* in the function code should be set. */
-       function_code |= us_info->data_mem_part;
-       function_code |= QE_BMR_BYTE_ORDER_BO_MOT;      /* Required for QE */
-       uccs->us_pram->tfcr = function_code;
-       uccs->us_pram->rfcr = function_code;
+       uccs->us_pram->tfcr = uccs->us_pram->rfcr =
+               us_info->data_mem_part | QE_BMR_BYTE_ORDER_BO_MOT;
 
        /* rbase, tbase are offsets from MURAM base */
        out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
@@ -336,34 +308,29 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
        /* If NMSI (not Tsa), set Tx and Rx clock. */
        if (!us_info->tsa) {
                /* Rx clock routing */
-               if (ucc_set_qe_mux_rxtx
-                   (us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) {
-                       uccs_err
-                           ("ucc_slow_init: Illegal value for parameter"
-                               " 'RxClock'.");
+               if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+                                       COMM_DIR_RX)) {
+                       printk(KERN_ERR "%s: illegal value for RX clock",
+                              __FUNCTION__);
                        ucc_slow_free(uccs);
                        return -EINVAL;
                }
                /* Tx clock routing */
-               if (ucc_set_qe_mux_rxtx(us_info->ucc_num,
-                                us_info->tx_clock, COMM_DIR_TX)) {
-                       uccs_err
-                           ("ucc_slow_init: Illegal value for parameter "
-                               "'TxClock'.");
+               if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+                                       COMM_DIR_TX)) {
+                       printk(KERN_ERR "%s: illegal value for TX clock",
+                              __FUNCTION__);
                        ucc_slow_free(uccs);
                        return -EINVAL;
                }
        }
 
-       /*
-        * INTERRUPTS
-        */
        /* Set interrupt mask register at UCC level. */
        out_be16(&us_regs->uccm, us_info->uccm_mask);
 
-       /* First, clear anything pending at UCC level, */
-       /* otherwise, old garbage may come through */
-       /* as soon as the dam is opened. */
+       /* First, clear anything pending at UCC level,
+        * otherwise, old garbage may come through
+        * as soon as the dam is opened. */
 
        /* Writing '1' clears */
        out_be16(&us_regs->ucce, 0xffff);
@@ -400,3 +367,5 @@ void ucc_slow_free(struct ucc_slow_private * uccs)
 
        kfree(uccs);
 }
+
+
index bd129d3c2cc13af95228168f53d6cf76df5d2666..0a7e42d54eaf59dceca3eaa658b7db8986ffbe39 100644 (file)
@@ -442,17 +442,22 @@ static ctl_table htab_ctl_table[]={
                .mode           = 0644,
                .proc_handler   = &proc_dol2crvec,
        },
-       { 0, },
+       {}
 };
 static ctl_table htab_sysctl_root[] = {
-       { 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
-       { 0,},
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0555,
+               .child          = htab_ctl_table,
+       },
+       {}
 };
 
 static int __init
 register_ppc_htab_sysctl(void)
 {
-       register_sysctl_table(htab_sysctl_root, 0);
+       register_sysctl_table(htab_sysctl_root);
 
        return 0;
 }
index a43dda5a83343a7cc39d5ea1ae6794e915ac871c..1e5a00a4b5f55a5280dcc37452ccf847619b7274 100644 (file)
@@ -154,7 +154,7 @@ static struct resource pic_edgectrl_iores = {
 
 static struct irqaction i8259_irqaction = {
        .handler = no_action,
-       .flags = SA_INTERRUPT,
+       .flags = IRQF_DISABLED,
        .mask = CPU_MASK_NONE,
        .name = "82c59 secondary cascade",
 };
index 0429481dea633b9fe2bffb6aff2e50d6f60d6857..4069b81f7f1d159f1fb2b6fc1bc6b9f7d788a8a0 100644 (file)
@@ -21,8 +21,7 @@
 #define APPLDATA_RECORD_NET_SUM_ID     0x03    /* must be < 256 !     */
 #define APPLDATA_RECORD_PROC_ID                0x04
 
-#define CTL_APPLDATA           2120    /* sysctl IDs, must be unique */
-#define CTL_APPLDATA_TIMER     2121
+#define CTL_APPLDATA_TIMER     2121    /* sysctl IDs, must be unique */
 #define CTL_APPLDATA_INTERVAL  2122
 #define CTL_APPLDATA_MEM       2123
 #define CTL_APPLDATA_OS                2124
index c9da7d16145e727f91f77b655016fa29fe5074ac..0c3cf4b16ae488c2949867c93bec362bb5b42b82 100644 (file)
@@ -506,7 +506,7 @@ int appldata_register_ops(struct appldata_ops *ops)
 
        ops->ctl_table[3].ctl_name = 0;
 
-       ops->sysctl_header = register_sysctl_table(ops->ctl_table,1);
+       ops->sysctl_header = register_sysctl_table(ops->ctl_table);
 
        P_INFO("%s-ops registered!\n", ops->name);
        return 0;
@@ -606,7 +606,7 @@ static int __init appldata_init(void)
        /* Register cpu hotplug notifier */
        register_hotcpu_notifier(&appldata_nb);
 
-       appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
+       appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
 #ifdef MODULE
        appldata_dir_table[0].de->owner = THIS_MODULE;
        appldata_table[0].de->owner = THIS_MODULE;
index 51653d82d7df74bcaf8a5607ea1340fdd176dffc..eca3fe595ff4a9b092b6ee8f89f69309731add77 100644 (file)
@@ -852,7 +852,6 @@ debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
 static int debug_stoppable=1;
 static int debug_active=1;
 
-#define CTL_S390DBF 5677
 #define CTL_S390DBF_STOPPABLE 5678
 #define CTL_S390DBF_ACTIVE 5679
 
@@ -1054,7 +1053,7 @@ __init debug_init(void)
 {
        int rc = 0;
 
-       s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
+       s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
        down(&debug_lock);
        debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
        printk(KERN_INFO "debug: Initialization complete\n");
index 3b91f27ab202862e28ae2b10ef5f48e87cadb0c6..ee9fd7b859282941db4ad38ee896ea933cc1809e 100644 (file)
@@ -312,7 +312,7 @@ static struct clocksource clocksource_tod = {
        .mask           = -1ULL,
        .mult           = 1000,
        .shift          = 12,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 
index f93a056869bc5aa7d38f1a88810acf019029eacf..c5b2f4f078bc7fbd3f58ac9c6eb58ad05f3b4e82 100644 (file)
@@ -256,10 +256,6 @@ cmm_skip_blanks(char *cp, char **endp)
 }
 
 #ifdef CONFIG_CMM_PROC
-/* These will someday get removed. */
-#define VM_CMM_PAGES           1111
-#define VM_CMM_TIMED_PAGES     1112
-#define VM_CMM_TIMEOUT         1113
 
 static struct ctl_table cmm_table[];
 
@@ -422,7 +418,7 @@ cmm_init (void)
        int rc = -ENOMEM;
 
 #ifdef CONFIG_CMM_PROC
-       cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
+       cmm_sysctl_header = register_sysctl_table(cmm_dir_table);
        if (!cmm_sysctl_header)
                goto out;
 #endif
index 4f3891215b87c83f3ff03252558e78b74b981bbd..4d16d89170749ccff61b432972cacd6e0e5f36b5 100644 (file)
@@ -135,12 +135,6 @@ config SH_HP6XX
          More information (hardware only) at
          <http://www.hp.com/jornada/>.
 
-config SH_EC3104
-       bool "EC3104"
-       help
-         Select EC3104 if configuring for a system with an Eclipse
-         International EC3104 chip, e.g. the Harris AD2000.
-
 config SH_SATURN
        bool "Saturn"
        select CPU_SUBTYPE_SH7604
@@ -156,9 +150,6 @@ config SH_DREAMCAST
          <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
          Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
-config SH_BIGSUR
-       bool "BigSur"
-
 config SH_MPC1211
        bool "Interface MPC1211"
        help
@@ -481,6 +472,7 @@ config SH_PCLK_FREQ
 
 config SH_CLK_MD
        int "CPU Mode Pin Setting"
+       default 0
        depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
        help
          MD2 - MD0 pin setting.
@@ -510,8 +502,9 @@ source "arch/sh/cchips/Kconfig"
 config HEARTBEAT
        bool "Heartbeat LED"
        depends on SH_MPC1211 || SH_SH03 || \
-                  SH_BIGSUR || SOLUTION_ENGINE || \
-                  SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
+                  SOLUTION_ENGINE || \
+                  SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK || \
+                  SH_R7780RP
        help
          Use the power-on LED on your machine as a load meter.  The exact
          behavior is platform-dependent, but normally the flash frequency is
@@ -596,6 +589,8 @@ menu "Boot options"
 config ZERO_PAGE_OFFSET
        hex "Zero page offset"
        default "0x00004000" if SH_MPC1211 || SH_SH03
+       default "0x00010000" if PAGE_SIZE_64KB
+       default "0x00002000" if PAGE_SIZE_8KB
        default "0x00001000"
        help
          This sets the default offset of zero page.
index c1dbef21263430f68ba594d2b3d893063732cc11..bd9b1729f8b8dab029cd21776908de1e22f84845 100644 (file)
@@ -35,6 +35,7 @@ endif
 endif
 
 cflags-$(CONFIG_CPU_SH2)               := -m2
+cflags-$(CONFIG_CPU_SH2A)              := -m2a $(call cc-option,-m2a-nofpu,)
 cflags-$(CONFIG_CPU_SH3)               := -m3
 cflags-$(CONFIG_CPU_SH4)               := -m4 \
        $(call cc-option,-mno-implicit-fp,-m4-nofpu)
@@ -93,10 +94,8 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)    := se/7300
 machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)      := se/7343
 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)     := se/73180
 machdir-$(CONFIG_SH_HP6XX)                     := hp6xx
-machdir-$(CONFIG_SH_EC3104)                    := ec3104
 machdir-$(CONFIG_SH_SATURN)                    := saturn
 machdir-$(CONFIG_SH_DREAMCAST)                 := dreamcast
-machdir-$(CONFIG_SH_BIGSUR)                    := bigsur
 machdir-$(CONFIG_SH_MPC1211)                   := mpc1211
 machdir-$(CONFIG_SH_SH03)                      := sh03
 machdir-$(CONFIG_SH_SECUREEDGE5410)            := snapgear
diff --git a/arch/sh/boards/bigsur/Makefile b/arch/sh/boards/bigsur/Makefile
deleted file mode 100644 (file)
index 0ff9497..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the BigSur specific parts of the kernel
-#
-
-obj-y   := setup.o io.o irq.o led.o
-
diff --git a/arch/sh/boards/bigsur/io.c b/arch/sh/boards/bigsur/io.c
deleted file mode 100644 (file)
index 23071f9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * arch/sh/boards/bigsur/io.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from io_hd64465.h, which bore the message:
- * By Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc. 
- * and from io_hd64461.h, which bore the message:
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for a Hitachi Big Sur Evaluation Board.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/machvec.h>
-#include <asm/io.h>
-#include <asm/bigsur/bigsur.h>
-
-/* Low iomap maps port 0-1K to addresses in 8byte chunks */
-#define BIGSUR_IOMAP_LO_THRESH 0x400
-#define BIGSUR_IOMAP_LO_SHIFT  3
-#define BIGSUR_IOMAP_LO_MASK   ((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
-#define BIGSUR_IOMAP_LO_NMAP   (BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
-static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
-static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
-
-/* High iomap maps port 1K-64K to addresses in 1K chunks */
-#define BIGSUR_IOMAP_HI_THRESH 0x10000
-#define BIGSUR_IOMAP_HI_SHIFT  10
-#define BIGSUR_IOMAP_HI_MASK   ((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
-#define BIGSUR_IOMAP_HI_NMAP   (BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
-static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
-static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
-
-void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
-{
-       u32 port, endport = baseport + nports;
-
-       pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
-                baseport, nports, addr);
-           
-       for (port = baseport ;
-            port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
-            port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
-               pr_debug("    maplo[0x%x] = 0x%08x\n", port, addr);
-           bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
-           bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
-               addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
-       }
-
-       for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
-            port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
-            port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
-               pr_debug("    maphi[0x%x] = 0x%08x\n", port, addr);
-           bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
-           bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
-               addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
-       }
-}
-EXPORT_SYMBOL(bigsur_port_map);
-
-void bigsur_port_unmap(u32 baseport, u32 nports)
-{
-       u32 port, endport = baseport + nports;
-       
-       pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
-
-       for (port = baseport ;
-            port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
-            port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
-               bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
-       }
-
-       for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
-            port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
-            port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
-               bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
-       }
-}
-EXPORT_SYMBOL(bigsur_port_unmap);
-
-unsigned long bigsur_isa_port2addr(unsigned long port)
-{
-       unsigned long addr = 0;
-       unsigned char shift;
-
-       /* Physical address not in P0, do nothing */
-       if (PXSEG(port)) {
-               addr = port;
-       /* physical address in P0, map to P2 */
-       } else if (port >= 0x30000) {
-               addr = P2SEGADDR(port);
-       /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
-       } else if (port >= BIGSUR_IOMAP_HI_THRESH) {
-               addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
-       /* Handle remapping of high IO/PCI IO ports */
-       } else if (port >= BIGSUR_IOMAP_LO_THRESH) {
-               addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
-               shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
-
-               if (addr != 0)
-                       addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
-       } else {
-               /* Handle remapping of low IO ports */
-               addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
-               shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
-
-               if (addr != 0)
-                       addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
-       }
-
-       pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr);
-
-       return addr;
-}
-
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
deleted file mode 100644 (file)
index 1ab04da..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- *
- * Setup and IRQ handling code for the HD64465 companion chip.
- * by Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc
- *
- * Derived from setup_hd64465.c which bore the message:
- * Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc and
- * Copyright (C) 2000 YAEGASHI Takeshi
- * and setup_cqreek.c which bore message:
- * Copyright (C) 2000  Niibe Yutaka
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IRQ functions for a Hitachi Big Sur Evaluation Board.
- *
- */
-#undef DEBUG
-
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/bigsur/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/bigsur/bigsur.h>
-
-//#define BIGSUR_DEBUG 3
-#undef BIGSUR_DEBUG
-
-#ifdef BIGSUR_DEBUG
-#define DIPRINTK(n, args...)    if (BIGSUR_DEBUG>(n)) printk(args)
-#else
-#define DIPRINTK(n, args...)
-#endif /* BIGSUR_DEBUG */
-
-#ifdef CONFIG_HD64465
-extern int hd64465_irq_demux(int irq);
-#endif /* CONFIG_HD64465 */
-
-
-/*===========================================================*/
-//              Big Sur CPLD IRQ Routines
-/*===========================================================*/
-
-/* Level 1 IRQ routines */
-static void disable_bigsur_l1irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
-        unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                pr_debug("Disable L1 IRQ %d\n", irq);
-                DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Disable IRQ - set mask bit */
-                mask = inb(mask_port) | bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
-}
-
-static void enable_bigsur_l1irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
-        unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                pr_debug("Enable L1 IRQ %d\n", irq);
-                DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-                /* Enable L1 IRQ - clear mask bit */
-                mask = inb(mask_port) & ~bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
-}
-
-
-/* Level 2 irq masks and registers for L2 decoding */
-/* Level2 bitmasks for each level 1 IRQ */
-const u32 bigsur_l2irq_mask[] =
-    {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03};
-/* Level2 to ISR[n] map for each level 1 IRQ */
-const u32 bigsur_l2irq_reg[]  =
-    {   2,   2,   3,   3,   1,   2,   1,   0,   1,   1,   3,   2};
-/* Level2 to Level 1 IRQ map */
-const u32 bigsur_l2_l1_map[]  =
-    {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1};
-/* IRQ inactive level (high or low) */
-const u32 bigsur_l2_inactv_state[]  =   {0x00, 0xBE, 0xFC, 0xF7};
-
-/* CPLD external status and mask registers base and offsets */
-static const u32 isr_base = BIGSUR_IRQ0;
-static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1;
-static const u32 imr_base = BIGSUR_IMR0;
-static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
-
-#define REG_NUM(irq)  ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 )
-
-/* Level 2 IRQ routines */
-static void disable_bigsur_l2irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
-        unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
-
-       if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                pr_debug("Disable L2 IRQ %d\n", irq);
-                DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Disable L2 IRQ - set mask bit */
-                mask = inb(mask_port) | bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
-}
-
-static void enable_bigsur_l2irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
-        unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
-
-       if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                pr_debug("Enable L2 IRQ %d\n", irq);
-                DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Enable L2 IRQ - clear mask bit */
-                mask = inb(mask_port) & ~bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
-}
-
-static void mask_and_ack_bigsur(unsigned int irq)
-{
-        pr_debug("mask_and_ack_bigsur IRQ %d\n", irq);
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                disable_bigsur_l1irq(irq);
-        else
-                disable_bigsur_l2irq(irq);
-}
-
-static void end_bigsur_irq(unsigned int irq)
-{
-        pr_debug("end_bigsur_irq IRQ %d\n", irq);
-        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-                if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                        enable_bigsur_l1irq(irq);
-                else
-                        enable_bigsur_l2irq(irq);
-        }
-}
-
-static unsigned int startup_bigsur_irq(unsigned int irq)
-{
-        u8 mask;
-        u32 reg;
-
-        pr_debug("startup_bigsur_irq IRQ %d\n", irq);
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* Enable the L1 IRQ */
-                enable_bigsur_l1irq(irq);
-                /* Enable all L2 IRQs in this L1 IRQ */
-                mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]);
-                reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset;
-                mask &= inb(reg);
-                outb(mask,reg);
-                DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg));
-        }
-        else {
-                /* Enable the L2 IRQ - clear mask bit */
-                enable_bigsur_l2irq(irq);
-                /* Enable the L1 bit masking this L2 IRQ */
-                enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]);
-                DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n",
-                        bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq);
-        }
-        return 0;
-}
-
-static void shutdown_bigsur_irq(unsigned int irq)
-{
-        pr_debug("shutdown_bigsur_irq IRQ %d\n", irq);
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                disable_bigsur_l1irq(irq);
-        else
-                disable_bigsur_l2irq(irq);
-}
-
-/* Define the IRQ structures for the L1 and L2 IRQ types */
-static struct hw_interrupt_type bigsur_l1irq_type = {
-       .typename  = "BigSur-CPLD-Level1-IRQ",
-       .startup = startup_bigsur_irq,
-       .shutdown = shutdown_bigsur_irq,
-       .enable = enable_bigsur_l1irq,
-       .disable = disable_bigsur_l1irq,
-       .ack = mask_and_ack_bigsur,
-       .end = end_bigsur_irq
-};
-
-static struct hw_interrupt_type bigsur_l2irq_type = {
-       .typename  = "BigSur-CPLD-Level2-IRQ",
-       .startup = startup_bigsur_irq,
-       .shutdown  =shutdown_bigsur_irq,
-       .enable = enable_bigsur_l2irq,
-       .disable = disable_bigsur_l2irq,
-       .ack = mask_and_ack_bigsur,
-       .end = end_bigsur_irq
-};
-
-
-static void make_bigsur_l1isr(unsigned int irq) {
-
-        /* sanity check first */
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* save the handler in the main description table */
-                irq_desc[irq].chip = &bigsur_l1irq_type;
-                irq_desc[irq].status = IRQ_DISABLED;
-                irq_desc[irq].action = 0;
-                irq_desc[irq].depth = 1;
-
-                disable_bigsur_l1irq(irq);
-                return;
-        }
-        pr_debug("make_bigsur_l1isr: bad irq, %d\n", irq);
-        return;
-}
-
-static void make_bigsur_l2isr(unsigned int irq) {
-
-        /* sanity check first */
-        if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                /* save the handler in the main description table */
-                irq_desc[irq].chip = &bigsur_l2irq_type;
-                irq_desc[irq].status = IRQ_DISABLED;
-                irq_desc[irq].action = 0;
-                irq_desc[irq].depth = 1;
-
-                disable_bigsur_l2irq(irq);
-                return;
-        }
-        pr_debug("make_bigsur_l2isr: bad irq, %d\n", irq);
-        return;
-}
-
-/* The IRQ's will be decoded as follows:
- * If a level 2 handler exists and there is an unmasked active
- * IRQ, the 2nd level handler will be called.
- * If a level 2 handler does not exist for the active IRQ
- * the 1st level handler will be called.
- */
-
-int bigsur_irq_demux(int irq)
-{
-        int dmux_irq = irq;
-        u8 mask, actv_irqs;
-        u32 reg_num;
-
-        DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq);
-        /* decode the 1st level IRQ */
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* Get corresponding L2 ISR bitmask and ISR number */
-                mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW];
-                reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW];
-                /* find the active IRQ's (XOR with inactive level)*/
-                actv_irqs = inb(isr_base-reg_num*isr_offset) ^
-                                        bigsur_l2_inactv_state[reg_num];
-                /* decode active IRQ's */
-                actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset));
-                /* if NEZ then we have an active L2 IRQ */
-                if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW;
-                /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */
-                if(!irq_desc[dmux_irq].action && irq_desc[irq].action)
-                        dmux_irq = irq;
-                DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n",
-                        irq, dmux_irq, mask, reg_num);
-        }
-#ifdef CONFIG_HD64465
-        dmux_irq = hd64465_irq_demux(dmux_irq);
-#endif /* CONFIG_HD64465 */
-        DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq);
-
-        return dmux_irq;
-}
-
-/*===========================================================*/
-//              Big Sur Init Routines
-/*===========================================================*/
-void __init init_bigsur_IRQ(void)
-{
-        int i;
-
-        if (!MACH_BIGSUR) return;
-
-        /* Create ISR's for Big Sur CPLD IRQ's */
-        /*==============================================================*/
-        for(i=BIGSUR_IRQ_LOW;i<BIGSUR_IRQ_HIGH;i++)
-                make_bigsur_l1isr(i);
-
-        printk(KERN_INFO "Big Sur CPLD L1 interrupts %d to %d.\n",
-                BIGSUR_IRQ_LOW,BIGSUR_IRQ_HIGH);
-
-        for(i=BIGSUR_2NDLVL_IRQ_LOW;i<BIGSUR_2NDLVL_IRQ_HIGH;i++)
-                make_bigsur_l2isr(i);
-
-        printk(KERN_INFO "Big Sur CPLD L2 interrupts %d to %d.\n",
-                BIGSUR_2NDLVL_IRQ_LOW,BIGSUR_2NDLVL_IRQ_HIGH);
-
-}
diff --git a/arch/sh/boards/bigsur/led.c b/arch/sh/boards/bigsur/led.c
deleted file mode 100644 (file)
index d221439..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/boards/bigsur/led.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from led_se.c and led.c, which bore the message:
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Big Sur specific LED code.
- */
-
-#include <asm/io.h>
-#include <asm/bigsur/bigsur.h>
-
-static void mach_led(int position, int value)
-{
-       int word;
-       
-       word = bigsur_inl(BIGSUR_CSLR);
-       if (value) {
-               bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR);
-       } else {
-               bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED on/off */
-void heartbeat_bigsur(void)
-{
-       static unsigned cnt = 0, period = 0, dist = 0;
-
-       if (cnt == 0 || cnt == dist)
-               mach_led( -1, 1);
-       else if (cnt == 7 || cnt == dist+7)
-               mach_led( -1, 0);
-
-       if (++cnt > period) {
-               cnt = 0;
-               /* The hyperbolic function below modifies the heartbeat period
-                * length in dependency of the current (5min) load. It goes
-                * through the points f(0)=126, f(1)=86, f(5)=51,
-                * f(inf)->30. */
-               period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-               dist = period / 4;
-       }
-}
-#endif /* CONFIG_HEARTBEAT */
-
diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c
deleted file mode 100644 (file)
index 9711c20..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * 
- * Setup and IRQ handling code for the HD64465 companion chip.
- * by Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc
- *
- * Derived from setup_hd64465.c which bore the message:
- * Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc and
- * Copyright (C) 2000 YAEGASHI Takeshi
- * and setup_cqreek.c which bore message:
- * Copyright (C) 2000  Niibe Yutaka
- * 
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Setup functions for a Hitachi Big Sur Evaluation Board.
- * 
- */
-
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/bigsur/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/bigsur/bigsur.h>
-
-/*===========================================================*/
-//             Big Sur Init Routines   
-/*===========================================================*/
-
-static void __init bigsur_setup(char **cmdline_p)
-{
-       /* Mask all 2nd level IRQ's */
-       outb(-1,BIGSUR_IMR0);
-       outb(-1,BIGSUR_IMR1);
-       outb(-1,BIGSUR_IMR2);
-       outb(-1,BIGSUR_IMR3);
-
-       /* Mask 1st level interrupts */
-       outb(-1,BIGSUR_IRLMR0);
-       outb(-1,BIGSUR_IRLMR1);
-
-#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL) 
-       /* remap IO ports for first ISA serial port to HD64465 UART */
-       bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
-#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
-       /* TODO: setup IDE registers */
-       bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8);
-       /* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */
-       bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0);
-       /* set page to 1 */
-       outw(1, BIGSUR_ETHR+0xe);
-       /* set the IO port to BIGSUR_ETHER_IOPORT */
-       outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
-}
-
-/*
- * The Machine Vector
- */
-extern void heartbeat_bigsur(void);
-extern void init_bigsur_IRQ(void);
-
-struct sh_machine_vector mv_bigsur __initmv = {
-       .mv_name                = "Big Sur",
-       .mv_setup               = bigsur_setup,
-
-       .mv_isa_port2addr       = bigsur_isa_port2addr,
-       .mv_irq_demux           = bigsur_irq_demux,
-
-       .mv_init_irq            = init_bigsur_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_bigsur,
-#endif
-};
-ALIAS_MV(bigsur)
diff --git a/arch/sh/boards/ec3104/Makefile b/arch/sh/boards/ec3104/Makefile
deleted file mode 100644 (file)
index 1788915..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the EC3104 specific parts of the kernel
-#
-
-obj-y   := setup.o io.o irq.o
-
diff --git a/arch/sh/boards/ec3104/io.c b/arch/sh/boards/ec3104/io.c
deleted file mode 100644 (file)
index 2f86394..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/io.c
- *  EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-/* EC3104 note:
- * This code was written without any documentation about the EC3104 chip.  While
- * I hope I got most of the basic functionality right, the register names I use
- * are most likely completely different from those in the chip documentation.
- *
- * If you have any further information about the EC3104, please tell me
- * (prumpf@tux.org).
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/ec3104/ec3104.h>
-
-/*
- * EC3104 has a real ISA bus which we redirect low port accesses to (the
- * actual device on mine is a ESS 1868, and I don't want to hack the driver
- * more than strictly necessary).  I am not going to duplicate the
- * hard coding of PC addresses (for the 16550s aso) here though;  it's just
- * too ugly.
- */
-
-#define low_port(port) ((port) < 0x10000)
-
-static inline unsigned long port2addr(unsigned long port)
-{
-       switch(port >> 16) {
-       case 0:
-               return EC3104_ISA_BASE + port * 2;
-
-               /* XXX hack. it's unclear what to do about the serial ports */
-       case 1:
-               return EC3104_BASE + (port&0xffff) * 4;
-
-       default:
-               /* XXX PCMCIA */
-               return 0;
-       }
-}
-
-unsigned char ec3104_inb(unsigned long port)
-{
-       u8 ret;
-
-       ret = *(volatile u8 *)port2addr(port);
-
-       return ret;
-}
-
-unsigned short ec3104_inw(unsigned long port)
-{
-       BUG();
-}
-
-unsigned long ec3104_inl(unsigned long port)
-{
-       BUG();
-}
-
-void ec3104_outb(unsigned char data, unsigned long port)
-{
-       *(volatile u8 *)port2addr(port) = data;
-}
-
-void ec3104_outw(unsigned short data, unsigned long port)
-{
-       BUG();
-}
-
-void ec3104_outl(unsigned long data, unsigned long port)
-{
-       BUG();
-}
diff --git a/arch/sh/boards/ec3104/irq.c b/arch/sh/boards/ec3104/irq.c
deleted file mode 100644 (file)
index ffa4ff1..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/irq.c
- * EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/ec3104/ec3104.h>
-
-/* This is for debugging mostly;  here's the table that I intend to keep
- * in here:
- *
- *   index      function        base addr       power           interrupt bit
- *       0      power           b0ec0000        ---             00000001 (unused)
- *       1      irqs            b0ec1000        ---             00000002 (unused)
- *       2      ??              b0ec2000        b0ec0008        00000004
- *       3      PS2 (1)         b0ec3000        b0ec000c        00000008
- *       4      PS2 (2)         b0ec4000        b0ec0010        00000010
- *       5      ??              b0ec5000        b0ec0014        00000020
- *       6      I2C             b0ec6000        b0ec0018        00000040
- *       7      serial (1)      b0ec7000        b0ec001c        00000080
- *       8      serial (2)      b0ec8000        b0ec0020        00000100
- *       9      serial (3)      b0ec9000        b0ec0024        00000200
- *      10      serial (4)      b0eca000        b0ec0028        00000400
- *      12      GPIO (1)        b0ecc000        b0ec0030
- *      13      GPIO (2)        b0ecc000        b0ec0030
- *      16      pcmcia (1)      b0ed0000        b0ec0040        00010000
- *      17      pcmcia (2)      b0ed1000        b0ec0044        00020000
- */
-
-/* I used the register names from another interrupt controller I worked with,
- * since it seems to be identical to the ec3104 except that all bits are
- * inverted:
- *
- * IRR: Interrupt Request Register (pending and enabled interrupts)
- * IMR: Interrupt Mask Register (which interrupts are enabled)
- * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
- *
- * 0 bits mean pending or enabled, 1 bits mean not pending or disabled.  all
- * IRQs seem to be level-triggered.
- */
-
-#define EC3104_IRR (EC3104_BASE + 0x1000)
-#define EC3104_IMR (EC3104_BASE + 0x1004)
-#define EC3104_IPR (EC3104_BASE + 0x1008)
-
-#define ctrl_readl(addr) (*(volatile u32 *)(addr))
-#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
-#define ctrl_readb(addr) (*(volatile u8 *)(addr))
-
-static char *ec3104_name(unsigned index)
-{
-        switch(index) {
-        case 0:
-                return "power management";
-        case 1:
-                return "interrupts";
-        case 3:
-                return "PS2 (1)";
-        case 4:
-                return "PS2 (2)";
-        case 5:
-                return "I2C (1)";
-        case 6:
-                return "I2C (2)";
-        case 7:
-                return "serial (1)";
-        case 8:
-                return "serial (2)";
-        case 9:
-                return "serial (3)";
-        case 10:
-                return "serial (4)";
-        case 16:
-                return "pcmcia (1)";
-        case 17:
-                return "pcmcia (2)";
-        default: {
-                static char buf[32];
-
-                sprintf(buf, "unknown (%d)", index);
-
-                return buf;
-                }
-        }
-}
-
-int get_pending_interrupts(char *buf)
-{
-        u32 ipr;
-        u32 bit;
-        char *p = buf;
-
-        p += sprintf(p, "pending: (");
-
-        ipr = ctrl_inl(EC3104_IPR);
-
-        for (bit = 1; bit < 32; bit++)
-                if (!(ipr & (1<<bit)))
-                        p += sprintf(p, "%s ", ec3104_name(bit));
-
-        p += sprintf(p, ")\n");
-
-        return p - buf;
-}
-
-static inline u32 ec3104_irq2mask(unsigned int irq)
-{
-        return (1 << (irq - EC3104_IRQBASE));
-}
-
-static inline void mask_ec3104_irq(unsigned int irq)
-{
-        u32 mask;
-
-        mask = ctrl_readl(EC3104_IMR);
-
-        mask |= ec3104_irq2mask(irq);
-
-        ctrl_writel(mask, EC3104_IMR);
-}
-
-static inline void unmask_ec3104_irq(unsigned int irq)
-{
-        u32 mask;
-
-        mask = ctrl_readl(EC3104_IMR);
-
-        mask &= ~ec3104_irq2mask(irq);
-
-        ctrl_writel(mask, EC3104_IMR);
-}
-
-static void disable_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-}
-
-static void enable_ec3104_irq(unsigned int irq)
-{
-        unmask_ec3104_irq(irq);
-}
-
-static void mask_and_ack_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-}
-
-static void end_ec3104_irq(unsigned int irq)
-{
-        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-                unmask_ec3104_irq(irq);
-}
-
-static unsigned int startup_ec3104_irq(unsigned int irq)
-{
-        unmask_ec3104_irq(irq);
-
-        return 0;
-}
-
-static void shutdown_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-
-}
-
-static struct hw_interrupt_type ec3104_int = {
-        .typename       = "EC3104",
-        .enable         = enable_ec3104_irq,
-        .disable        = disable_ec3104_irq,
-        .ack            = mask_and_ack_ec3104_irq,
-        .end            = end_ec3104_irq,
-        .startup        = startup_ec3104_irq,
-        .shutdown       = shutdown_ec3104_irq,
-};
-
-/* Yuck.  the _demux API is ugly */
-int ec3104_irq_demux(int irq)
-{
-        if (irq == EC3104_IRQ) {
-                unsigned int mask;
-
-                mask = ctrl_readl(EC3104_IRR);
-
-                if (mask == 0xffffffff)
-                        return EC3104_IRQ;
-                else
-                        return EC3104_IRQBASE + ffz(mask);
-        }
-
-        return irq;
-}
diff --git a/arch/sh/boards/ec3104/setup.c b/arch/sh/boards/ec3104/setup.c
deleted file mode 100644 (file)
index 902bc97..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/setup.c
- *  EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-/* EC3104 note:
- * This code was written without any documentation about the EC3104 chip.  While
- * I hope I got most of the basic functionality right, the register names I use
- * are most likely completely different from those in the chip documentation.
- *
- * If you have any further information about the EC3104, please tell me
- * (prumpf@tux.org).
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/mach/ec3104.h>
-
-static void __init ec3104_setup(char **cmdline_p)
-{
-       char str[8];
-       int i;
-
-       for (i=0; i<8; i++)
-               str[i] = ctrl_readb(EC3104_BASE + i);
-
-       for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
-               irq_desc[i].handler = &ec3104_int;
-
-       printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
-              str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
-
-       /* mask all interrupts.  this should have been done by the boot
-        * loader for us but we want to be sure ... */
-       ctrl_writel(0xffffffff, EC3104_IMR);
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_ec3104 __initmv = {
-       .mv_name        = "EC3104",
-       .mv_setup       = ec3104_setup,
-       .mv_nr_irqs     = 96,
-
-       .mv_inb         = ec3104_inb,
-       .mv_inw         = ec3104_inw,
-       .mv_inl         = ec3104_inl,
-       .mv_outb        = ec3104_outb,
-       .mv_outw        = ec3104_outw,
-       .mv_outl        = ec3104_outl,
-
-       .mv_irq_demux   = ec3104_irq_demux,
-};
-ALIAS_MV(ec3104)
index 1644ebed78cb68ce732009ad2ef5e7ddd40ec6fa..8cd31b5d200b026372f852a76ffb4d93ac0203c7 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
 #
 
-obj-y   := setup.o rtc.o led.o
+obj-y   := setup.o rtc.o
 
 obj-$(CONFIG_PCI) += pci.o
 
diff --git a/arch/sh/boards/mpc1211/led.c b/arch/sh/boards/mpc1211/led.c
deleted file mode 100644 (file)
index 8df1591..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/arch/sh/boards/mpc1211/led.c
- *
- * Copyright (C) 2001  Saito.K & Jeanne
- *
- * This file contains Interface MPC-1211 specific LED code.
- */
-
-
-static void mach_led(int position, int value)
-{
-       volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
-
-       if (value) {
-               *p |= 1;
-       } else {
-               *p &= ~1;
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_mpc1211(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ( (300<<FSHIFT)/
-                        ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up=0;
-               } else {
-                       bit ++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up=1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1<<bit;
-
-}
-#endif /* CONFIG_HEARTBEAT */
index 7c3d1d304157f48d70555fa4dc71bdc199aeb00d..1a0604b23ce0f4bac86f65fa1e783d8e372cdb04 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mpc1211/mpc1211.h>
@@ -281,6 +282,32 @@ static int put_smb_blk(unsigned char *p, int address, int command, int no)
        return 0;
 }
 
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = 0xa2000000,
+               .end    = 0xa2000000 + 8 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *mpc1211_devices[] __initdata = {
+       &heartbeat_device,
+};
+
+static int __init mpc1211_devices_setup(void)
+{
+       return platform_add_devices(mpc1211_devices,
+                                   ARRAY_SIZE(mpc1211_devices));
+}
+__initcall(mpc1211_devices_setup);
+
 /* arch/sh/boards/mpc1211/rtc.c */
 void mpc1211_time_init(void);
 
@@ -317,9 +344,5 @@ struct sh_machine_vector mv_mpc1211 __initmv = {
        .mv_nr_irqs             = 48,
        .mv_irq_demux           = mpc1211_irq_demux,
        .mv_init_irq            = init_mpc1211_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_mpc1211,
-#endif
 };
 ALIAS_MV(mpc1211)
index 574b0316ed564ace61bd0ca0ce5364f2d38e1741..3c93012e91a33cdd36d2816e849e936bae6b0163 100644 (file)
@@ -4,5 +4,4 @@
 
 obj-y   := setup.o io.o irq.o
 
-obj-$(CONFIG_HEARTBEAT)                += led.o
 obj-$(CONFIG_PUSH_SWITCH)      += psw.o
index 311ccccba718c48e7665403b6b1b722732c9a339..f74d2ffb38517402e48d40346823ddf228ec2a8c 100644 (file)
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/io.h>
 #include <asm/r7780rp.h>
 #include <asm/addrspace.h>
-#include <asm/io.h>
-
-static inline unsigned long port2adr(unsigned int port)
-{
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               if (port == 0x3f6)
-                       return (PA_AREA5_IO + 0x80c);
-               else
-                       return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
-       else
-               maybebadio((unsigned long)port);
-
-       return port;
-}
 
 static inline unsigned long port88796l(unsigned int port, int flag)
 {
@@ -40,18 +27,6 @@ static inline unsigned long port88796l(unsigned int port, int flag)
        return addr;
 }
 
-/* The 7780 R7780RP-1 seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int shifted_port(unsigned long port)
-{
-       /* For IDE registers, value is not shifted */
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               return 0;
-       else
-               return 1;
-}
-
 #if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
 #define CHECK_AX88796L_PORT(port) \
   ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
@@ -70,12 +45,10 @@ u8 r7780rp_inb(unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
                return ctrl_inw(port88796l(port, 0)) & 0xff;
-       else if (PXSEG(port))
-               return ctrl_inb(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                return ctrl_inb(pci_ioaddr(port));
 
-       return ctrl_inw(port2adr(port)) & 0xff;
+       return ctrl_inw(port) & 0xff;
 }
 
 u8 r7780rp_inb_p(unsigned long port)
@@ -84,12 +57,10 @@ u8 r7780rp_inb_p(unsigned long port)
 
        if (CHECK_AX88796L_PORT(port))
                v = ctrl_inw(port88796l(port, 0)) & 0xff;
-       else if (PXSEG(port))
-               v = ctrl_inb(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                v = ctrl_inb(pci_ioaddr(port));
        else
-               v = ctrl_inw(port2adr(port)) & 0xff;
+               v = ctrl_inw(port) & 0xff;
 
        ctrl_delay();
 
@@ -98,80 +69,56 @@ u8 r7780rp_inb_p(unsigned long port)
 
 u16 r7780rp_inw(unsigned long port)
 {
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (PXSEG(port))
-               return ctrl_inw(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       if (is_pci_ioaddr(port))
                return ctrl_inw(pci_ioaddr(port));
-       else
-               maybebadio(port);
 
-       return 0;
+       return ctrl_inw(port);
 }
 
 u32 r7780rp_inl(unsigned long port)
 {
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (PXSEG(port))
-               return ctrl_inl(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       if (is_pci_ioaddr(port))
                return ctrl_inl(pci_ioaddr(port));
-       else
-               maybebadio(port);
 
-       return 0;
+       return ctrl_inl(port);
 }
 
 void r7780rp_outb(u8 value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
                ctrl_outw(value, port88796l(port, 0));
-       else if (PXSEG(port))
-               ctrl_outb(value, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                ctrl_outb(value, pci_ioaddr(port));
        else
-               ctrl_outw(value, port2adr(port));
+               ctrl_outb(value, port);
 }
 
 void r7780rp_outb_p(u8 value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
                ctrl_outw(value, port88796l(port, 0));
-       else if (PXSEG(port))
-               ctrl_outb(value, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                ctrl_outb(value, pci_ioaddr(port));
        else
-               ctrl_outw(value, port2adr(port));
+               ctrl_outb(value, port);
 
        ctrl_delay();
 }
 
 void r7780rp_outw(u16 value, unsigned long port)
 {
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (PXSEG(port))
-               ctrl_outw(value, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       if (is_pci_ioaddr(port))
                ctrl_outw(value, pci_ioaddr(port));
        else
-               maybebadio(port);
+               ctrl_outw(value, port);
 }
 
 void r7780rp_outl(u32 value, unsigned long port)
 {
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (PXSEG(port))
-               ctrl_outl(value, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       if (is_pci_ioaddr(port))
                ctrl_outl(value, pci_ioaddr(port));
        else
-               maybebadio(port);
+               ctrl_outl(value, port);
 }
 
 void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
@@ -183,16 +130,13 @@ void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
                p = (volatile u16 *)port88796l(port, 0);
                while (count--)
                        *buf++ = *p & 0xff;
-       } else if (PXSEG(port)) {
-               while (count--)
-                       *buf++ = *(volatile u8 *)port;
-       } else if (is_pci_ioaddr(port) || shifted_port(port)) {
+       } else if (is_pci_ioaddr(port)) {
                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
                while (count--)
                        *buf++ = *bp;
        } else {
-               p = (volatile u16 *)port2adr(port);
+               p = (volatile u16 *)port;
                while (count--)
                        *buf++ = *p & 0xff;
        }
@@ -205,30 +149,26 @@ void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile u16 *)port88796l(port, 1);
-       else if (PXSEG(port))
-               p = (volatile u16 *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile u16 *)port2adr(port);
+               p = (volatile u16 *)port;
 
        while (count--)
                *buf++ = *p;
+
+       flush_dcache_all();
 }
 
 void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
 {
-       u32 *buf = dst;
-
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+       if (is_pci_ioaddr(port)) {
                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+               u32 *buf = dst;
 
                while (count--)
                        *buf++ = *p;
-       } else
-               maybebadio(port);
+       }
 }
 
 void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
@@ -240,19 +180,14 @@ void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
                p = (volatile u16 *)port88796l(port, 0);
                while (count--)
                        *p = *buf++;
-       } else if (PXSEG(port))
-               while (count--)
-                       ctrl_outb(*buf++, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+       } else if (is_pci_ioaddr(port)) {
                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
                while (count--)
                        *bp = *buf++;
-       } else {
-               p = (volatile u16 *)port2adr(port);
+       } else
                while (count--)
-                       *p = *buf++;
-       }
+                       ctrl_outb(*buf++, port);
 }
 
 void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
@@ -262,40 +197,37 @@ void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile u16 *)port88796l(port, 1);
-       else if (PXSEG(port))
-               p = (volatile u16 *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile u16 *)port2adr(port);
+               p = (volatile u16 *)port;
 
        while (count--)
                *p = *buf++;
+
+       flush_dcache_all();
 }
 
 void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
 {
        const u32 *buf = src;
+       u32 *p;
 
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
-               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+       if (is_pci_ioaddr(port))
+               p = (u32 *)pci_ioaddr(port);
+       else
+               p = (u32 *)port;
 
-               while (count--)
-                       *p = *buf++;
-       } else
-               maybebadio(port);
+       while (count--)
+               ctrl_outl(*buf++, (unsigned long)p);
 }
 
 void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
 {
        if (CHECK_AX88796L_PORT(port))
                return (void __iomem *)port88796l(port, size > 1);
-       else if (PXSEG(port))
-               return (void __iomem *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
+       else if (is_pci_ioaddr(port))
                return (void __iomem *)pci_ioaddr(port);
 
-       return (void __iomem *)port2adr(port);
+       return (void __iomem *)port;
 }
diff --git a/arch/sh/boards/renesas/r7780rp/led.c b/arch/sh/boards/renesas/r7780rp/led.c
deleted file mode 100644 (file)
index 6a00a25..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) Atom Create Engineering Co., Ltd.
- *
- * May be copied or modified under the terms of GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Renesas Solutions HIGHLANDER R7780RP-1 specific LED code.
- */
-#include <linux/sched.h>
-#include <asm/io.h>
-#include <asm/r7780rp/r7780rp.h>
-
-/* Cycle the LED's in the clasic Knightriger/Sun pattern */
-void heartbeat_r7780rp(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short *p = (volatile unsigned short *)PA_OBLED;
-       static unsigned bit = 0, up = 1;
-       unsigned bit_pos[] = {2, 1, 0, 3, 6, 5, 4, 7};
-
-       cnt += 1;
-       if (cnt < period)
-               return;
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
-        */
-       period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
-
-       *p = 1 << bit_pos[bit];
-       if (up)
-               if (bit == 7) {
-                       bit--;
-                       up = 0;
-               } else
-                       bit++;
-       else if (bit == 0)
-               up = 1;
-       else
-               bit--;
-}
index 9f89c8de9db98ba9f5a4e0ad3f6478520af515a0..0d74db9f179298fcd4c86e5333d39dcf76131082 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/boards/renesas/r7780rp/setup.c
  *
  * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
- * Copyright (C) 2005, 2006 Paul Mundt
+ * Copyright (C) 2005 - 2007 Paul Mundt
  *
  * Renesas Solutions Highlander R7780RP-1 Support.
  *
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/pata_platform.h>
 #include <asm/machvec.h>
 #include <asm/r7780rp.h>
 #include <asm/clock.h>
 #include <asm/io.h>
 
-extern void heartbeat_r7780rp(void);
 extern void init_r7780rp_IRQ(void);
 
 static struct resource m66596_usb_host_resources[] = {
@@ -46,14 +46,14 @@ static struct platform_device m66596_usb_host_device = {
 
 static struct resource cf_ide_resources[] = {
        [0] = {
-               .start  = 0x1f0,
-               .end    = 0x1f0 + 8,
-               .flags  = IORESOURCE_IO,
+               .start  = PA_AREA5_IO + 0x1000,
+               .end    = PA_AREA5_IO + 0x1000 + 0x08 - 1,
+               .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = 0x1f0 + 0x206,
-               .end    = 0x1f0 + 8 + 0x206 + 8,
-               .flags  = IORESOURCE_IO,
+               .start  = PA_AREA5_IO + 0x80c,
+               .end    = PA_AREA5_IO + 0x80c + 0x16 - 1,
+               .flags  = IORESOURCE_MEM,
        },
        [2] = {
 #ifdef CONFIG_SH_R7780MP
@@ -65,16 +65,44 @@ static struct resource cf_ide_resources[] = {
        },
 };
 
+static struct pata_platform_info pata_info = {
+       .ioport_shift   = 1,
+};
+
 static struct platform_device cf_ide_device  = {
        .name           = "pata_platform",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(cf_ide_resources),
        .resource       = cf_ide_resources,
+       .dev    = {
+               .platform_data  = &pata_info,
+       },
+};
+
+static unsigned char heartbeat_bit_pos[] = { 2, 1, 0, 3, 6, 5, 4, 7 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_OBLED,
+               .end    = PA_OBLED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
 };
 
 static struct platform_device *r7780rp_devices[] __initdata = {
        &m66596_usb_host_device,
        &cf_ide_device,
+       &heartbeat_device,
 };
 
 static int __init r7780rp_devices_setup(void)
@@ -148,7 +176,7 @@ static void __init r7780rp_setup(char **cmdline_p)
 #ifndef CONFIG_SH_R7780MP
        ctrl_outw(0x0001, PA_SDPOW);    /* SD Power ON */
 #endif
-       ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x0100, PA_IVDRCTL);   /* Si13112 */
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);     /* Si13112 */
 
        pm_power_off = r7780rp_power_off;
 }
@@ -185,8 +213,5 @@ struct sh_machine_vector mv_r7780rp __initmv = {
 
        .mv_ioport_map          = r7780rp_ioport_map,
        .mv_init_irq            = init_r7780rp_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_r7780rp,
-#endif
 };
 ALIAS_MV(r7780rp)
index 686fc9ea5989c01e1968c739eb8d1bd091c5bb5f..0d4c75a72be0950bd2ac9daef868609a17b7e43f 100644 (file)
@@ -2,5 +2,4 @@
 # Makefile for the RTS7751R2D specific parts of the kernel
 #
 
-obj-y   := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
+obj-y   := setup.o irq.o
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
deleted file mode 100644 (file)
index f2507a8..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
- * Based largely on io_se.c.
- *
- * I/O routine for Renesas Technology sales RTS7751R2D.
- *
- * Initial version only to support LAN access; some
- * placeholder code from io_rts7751r2d.c left in with the
- * expectation of later SuperIO and PCMCIA access.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <asm/rts7751r2d.h>
-#include <asm/addrspace.h>
-
-/*
- * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
- * of the 7751R processor, and has a SuperIO accessible via the PCI.
- * The board also includes a PCMCIA controller on its memory bus,
- * like the other Solution Engine boards.
- */
-
-static inline unsigned long port2adr(unsigned int port)
-{
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               if (port == 0x3f6)
-                       return (PA_AREA5_IO + 0x80c);
-               else
-                       return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
-       else
-               maybebadio((unsigned long)port);
-
-       return port;
-}
-
-static inline unsigned long port88796l(unsigned int port, int flag)
-{
-       unsigned long addr;
-
-       if (flag)
-               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
-       else
-               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
-
-       return addr;
-}
-
-/* The 7751R RTS7751R2D seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int shifted_port(unsigned long port)
-{
-       /* For IDE registers, value is not shifted */
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               return 0;
-       else
-               return 1;
-}
-
-#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
-#define CHECK_AX88796L_PORT(port) \
-  ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
-#else
-#define CHECK_AX88796L_PORT(port) (0)
-#endif
-
-/*
- * General outline: remap really low stuff [eventually] to SuperIO,
- * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
- * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
- * should be way beyond the window, and is used  w/o translation for
- * compatibility.
- */
-unsigned char rts7751r2d_inb(unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
-       else if (PXSEG(port))
-               return *(volatile unsigned char *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               return *(volatile unsigned char *)pci_ioaddr(port);
-       else
-               return (*(volatile unsigned short *)port2adr(port) & 0xff);
-}
-
-unsigned char rts7751r2d_inb_p(unsigned long port)
-{
-       unsigned char v;
-
-       if (CHECK_AX88796L_PORT(port))
-               v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
-        else if (PXSEG(port))
-               v = *(volatile unsigned char *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               v = *(volatile unsigned char *)pci_ioaddr(port);
-       else
-               v = (*(volatile unsigned short *)port2adr(port) & 0xff);
-
-       ctrl_delay();
-
-       return v;
-}
-
-unsigned short rts7751r2d_inw(unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-        else if (PXSEG(port))
-               return *(volatile unsigned short *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               return *(volatile unsigned short *)pci_ioaddr(port);
-       else
-               maybebadio(port);
-
-       return 0;
-}
-
-unsigned int rts7751r2d_inl(unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-        else if (PXSEG(port))
-               return *(volatile unsigned long *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               return *(volatile unsigned long *)pci_ioaddr(port);
-       else
-               maybebadio(port);
-
-       return 0;
-}
-
-void rts7751r2d_outb(unsigned char value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               *((volatile unsigned short *)port88796l(port, 0)) = value;
-        else if (PXSEG(port))
-               *(volatile unsigned char *)port = value;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               *(volatile unsigned char *)pci_ioaddr(port) = value;
-       else
-               *(volatile unsigned short *)port2adr(port) = value;
-}
-
-void rts7751r2d_outb_p(unsigned char value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               *((volatile unsigned short *)port88796l(port, 0)) = value;
-        else if (PXSEG(port))
-               *(volatile unsigned char *)port = value;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               *(volatile unsigned char *)pci_ioaddr(port) = value;
-       else
-               *(volatile unsigned short *)port2adr(port) = value;
-
-       ctrl_delay();
-}
-
-void rts7751r2d_outw(unsigned short value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-        else if (PXSEG(port))
-               *(volatile unsigned short *)port = value;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               *(volatile unsigned short *)pci_ioaddr(port) = value;
-       else
-               maybebadio(port);
-}
-
-void rts7751r2d_outl(unsigned int value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-        else if (PXSEG(port))
-               *(volatile unsigned long *)port = value;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               *(volatile unsigned long *)pci_ioaddr(port) = value;
-       else
-               maybebadio(port);
-}
-
-void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
-{
-       unsigned long a = (unsigned long)addr;
-       volatile __u8 *bp;
-       volatile __u16 *p;
-
-       if (CHECK_AX88796L_PORT(port)) {
-               p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--)
-                       ctrl_outb(*p & 0xff, a++);
-       } else if (PXSEG(port))
-               while (count--)
-                       ctrl_outb(ctrl_inb(port), a++);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
-               bp = (__u8 *)pci_ioaddr(port);
-               while (count--)
-                       ctrl_outb(*bp, a++);
-       } else {
-               p = (volatile unsigned short *)port2adr(port);
-               while (count--)
-                       ctrl_outb(*p & 0xff, a++);
-       }
-}
-
-void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
-{
-       unsigned long a = (unsigned long)addr;
-       volatile __u16 *p;
-
-       if (CHECK_AX88796L_PORT(port))
-               p = (volatile unsigned short *)port88796l(port, 1);
-       else if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               p = (volatile unsigned short *)pci_ioaddr(port);
-       else
-               p = (volatile unsigned short *)port2adr(port);
-       while (count--)
-               ctrl_outw(*p, a++);
-}
-
-void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
-               unsigned long a = (unsigned long)addr;
-
-               while (count--) {
-                       ctrl_outl(ctrl_inl(pci_ioaddr(port)), a);
-                       a += 4;
-               }
-       } else
-               maybebadio(port);
-}
-
-void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
-{
-       unsigned long a = (unsigned long)addr;
-       volatile __u8 *bp;
-       volatile __u16 *p;
-
-       if (CHECK_AX88796L_PORT(port)) {
-               p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--)
-                       *p = ctrl_inb(a++);
-       } else if (PXSEG(port))
-               while (count--)
-                       ctrl_outb(a++, port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
-               bp = (__u8 *)pci_ioaddr(port);
-               while (count--)
-                       *bp = ctrl_inb(a++);
-       } else {
-               p = (volatile unsigned short *)port2adr(port);
-               while (count--)
-                       *p = ctrl_inb(a++);
-       }
-}
-
-void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
-{
-       unsigned long a = (unsigned long)addr;
-       volatile __u16 *p;
-
-       if (CHECK_AX88796L_PORT(port))
-               p = (volatile unsigned short *)port88796l(port, 1);
-       else if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (is_pci_ioaddr(port) || shifted_port(port))
-               p = (volatile unsigned short *)pci_ioaddr(port);
-       else
-               p = (volatile unsigned short *)port2adr(port);
-
-       while (count--) {
-               ctrl_outw(*p, a);
-               a += 2;
-       }
-}
-
-void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
-{
-       if (CHECK_AX88796L_PORT(port))
-               maybebadio(port);
-       else if (is_pci_ioaddr(port) || shifted_port(port)) {
-               unsigned long a = (unsigned long)addr;
-
-               while (count--) {
-                       ctrl_outl(ctrl_inl(a), pci_ioaddr(port));
-                       a += 4;
-               }
-       } else
-               maybebadio(port);
-}
-
-unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
-{
-       return port2adr(offset);
-}
index cb0eb20d1b4348fbd58a81c54a88bf7be7973399..0bae9041acebaa04e9a9dede1593096267bb2750 100644 (file)
@@ -9,7 +9,9 @@
  * Atom Create Engineering Co., Ltd. 2002.
  */
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/rts7751r2d.h>
 
@@ -22,79 +24,31 @@ static int mask_pos[] = {6, 11, 9, 8, 12, 10, 5, 4, 7, 14, 13, 0, 0, 0, 0};
 extern int voyagergx_irq_demux(int irq);
 extern void setup_voyagergx_irq(void);
 
-static void enable_rts7751r2d_irq(unsigned int irq);
-static void disable_rts7751r2d_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_rts7751r2d_irq disable_rts7751r2d_irq
-
-static void ack_rts7751r2d_irq(unsigned int irq);
-static void end_rts7751r2d_irq(unsigned int irq);
-
-static unsigned int startup_rts7751r2d_irq(unsigned int irq)
+static void enable_rts7751r2d_irq(unsigned int irq)
 {
-       enable_rts7751r2d_irq(irq);
-       return 0; /* never anything pending */
+       /* Set priority in IPR back to original value */
+       ctrl_outw(ctrl_inw(IRLCNTR1) | (1 << mask_pos[irq]), IRLCNTR1);
 }
 
 static void disable_rts7751r2d_irq(unsigned int irq)
 {
-       unsigned short val;
-       unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
-
        /* Set the priority in IPR to 0 */
-       val = ctrl_inw(IRLCNTR1);
-       val &= mask;
-       ctrl_outw(val, IRLCNTR1);
-}
-
-static void enable_rts7751r2d_irq(unsigned int irq)
-{
-       unsigned short val;
-       unsigned short value = (0x0001 << mask_pos[irq]);
-
-       /* Set priority in IPR back to original value */
-       val = ctrl_inw(IRLCNTR1);
-       val |= value;
-       ctrl_outw(val, IRLCNTR1);
+       ctrl_outw(ctrl_inw(IRLCNTR1) & (0xffff ^ (1 << mask_pos[irq])),
+                 IRLCNTR1);
 }
 
 int rts7751r2d_irq_demux(int irq)
 {
-       int demux_irq;
-
-       demux_irq = voyagergx_irq_demux(irq);
-       return demux_irq;
-}
-
-static void ack_rts7751r2d_irq(unsigned int irq)
-{
-       disable_rts7751r2d_irq(irq);
+       return voyagergx_irq_demux(irq);
 }
 
-static void end_rts7751r2d_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_rts7751r2d_irq(irq);
-}
-
-static struct hw_interrupt_type rts7751r2d_irq_type = {
-       .typename = "RTS7751R2D IRQ",
-       .startup = startup_rts7751r2d_irq,
-       .shutdown = shutdown_rts7751r2d_irq,
-       .enable = enable_rts7751r2d_irq,
-       .disable = disable_rts7751r2d_irq,
-       .ack = ack_rts7751r2d_irq,
-       .end = end_rts7751r2d_irq,
+static struct irq_chip rts7751r2d_irq_chip __read_mostly = {
+       .name           = "rts7751r2d",
+       .mask           = disable_rts7751r2d_irq,
+       .unmask         = enable_rts7751r2d_irq,
+       .mask_ack       = disable_rts7751r2d_irq,
 };
 
-static void make_rts7751r2d_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &rts7751r2d_irq_type;
-       disable_rts7751r2d_irq(irq);
-}
-
 /*
  * Initialize IRQ setting
  */
@@ -119,8 +73,12 @@ void __init init_rts7751r2d_IRQ(void)
         * IRL14=Extention #3
         */
 
-       for (i=0; i<15; i++)
-               make_rts7751r2d_irq(i);
+       for (i=0; i<15; i++) {
+               disable_irq_nosync(i);
+               set_irq_chip_and_handler_name(i, &rts7751r2d_irq_chip,
+                                             handle_level_irq, "level");
+               enable_rts7751r2d_irq(i);
+       }
 
        setup_voyagergx_irq();
 }
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
deleted file mode 100644 (file)
index 509f548..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * linux/arch/sh/boards/renesas/rts7751r2d/led.c
- *
- * Copyright (C) Atom Create Engineering Co., Ltd.
- *
- * May be copied or modified under the terms of GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Renesas Technology Sales RTS7751R2D specific LED code.
- */
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <asm/rts7751r2d.h>
-
-/* Cycle the LED's in the clasic Knightriger/Sun pattern */
-void heartbeat_rts7751r2d(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short *p = (volatile unsigned short *)PA_OUTPORT;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period)
-               return;
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
-        */
-       period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
-
-       *p = 1 << bit;
-       if (up)
-               if (bit == 7) {
-                       bit--;
-                       up = 0;
-               } else
-                       bit++;
-       else if (bit == 0)
-               up = 1;
-       else
-               bit--;
-}
index 5c042d35ec91768d5255d2cba2ddf8c48f59fcb8..44b42082a0afe721a7f9776e80c327652734c15f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Renesas Technology Sales RTS7751R2D Support.
  *
- * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
- * Copyright (C) 2004 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2006 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2004 - 2007 Paul Mundt
  *
  * 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
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/pata_platform.h>
 #include <linux/serial_8250.h>
 #include <linux/pm.h>
 #include <asm/machvec.h>
-#include <asm/mach/rts7751r2d.h>
-#include <asm/io.h>
+#include <asm/rts7751r2d.h>
 #include <asm/voyagergx.h>
-
-extern void heartbeat_rts7751r2d(void);
-extern void init_rts7751r2d_IRQ(void);
-extern int rts7751r2d_irq_demux(int irq);
-
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
-extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
-
-static struct plat_serial8250_port uart_platform_data[] = {
-       {
-               .membase        = (void *)VOYAGER_UART_BASE,
-               .mapbase        = VOYAGER_UART_BASE,
-               .iotype         = UPIO_MEM,
-               .irq            = VOYAGER_UART0_IRQ,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .regshift       = 2,
-               .uartclk        = (9600 * 16),
-       }, {
-               .flags          = 0,
-       },
-};
+#include <asm/io.h>
 
 static void __init voyagergx_serial_init(void)
 {
@@ -45,32 +25,96 @@ static void __init voyagergx_serial_init(void)
        /*
         * GPIO Control
         */
-       val = inl(GPIO_MUX_HIGH);
+       val = readl((void __iomem *)GPIO_MUX_HIGH);
        val |= 0x00001fe0;
-       outl(val, GPIO_MUX_HIGH);
+       writel(val, (void __iomem *)GPIO_MUX_HIGH);
 
        /*
         * Power Mode Gate
         */
-       val = inl(POWER_MODE0_GATE);
+       val = readl((void __iomem *)POWER_MODE0_GATE);
        val |= (POWER_MODE0_GATE_U0 | POWER_MODE0_GATE_U1);
-       outl(val, POWER_MODE0_GATE);
+       writel(val, (void __iomem *)POWER_MODE0_GATE);
 
-       val = inl(POWER_MODE1_GATE);
+       val = readl((void __iomem *)POWER_MODE1_GATE);
        val |= (POWER_MODE1_GATE_U0 | POWER_MODE1_GATE_U1);
-       outl(val, POWER_MODE1_GATE);
+       writel(val, (void __iomem *)POWER_MODE1_GATE);
 }
 
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start  = PA_AREA5_IO + 0x1000,
+               .end    = PA_AREA5_IO + 0x1000 + 0x08 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = PA_AREA5_IO + 0x80c,
+               .end    = PA_AREA5_IO + 0x80c + 0x16 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+#ifdef CONFIG_RTS7751R2D_REV11
+               .start  = 1,
+#else
+               .start  = 2,
+#endif
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct pata_platform_info pata_info = {
+       .ioport_shift   = 1,
+};
+
+static struct platform_device cf_ide_device  = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+       .dev    = {
+               .platform_data  = &pata_info,
+       },
+};
+
+static struct plat_serial8250_port uart_platform_data[] = {
+       {
+               .membase        = (void __iomem *)VOYAGER_UART_BASE,
+               .mapbase        = VOYAGER_UART_BASE,
+               .iotype         = UPIO_MEM,
+               .irq            = VOYAGER_UART0_IRQ,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .regshift       = 2,
+               .uartclk        = (9600 * 16),
+       }
+};
+
 static struct platform_device uart_device = {
        .name           = "serial8250",
-       .id             = -1,
+       .id             = PLAT8250_DEV_PLATFORM,
        .dev            = {
                .platform_data  = uart_platform_data,
        },
 };
 
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_OUTPORT,
+               .end    = PA_OUTPORT + 8 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
 static struct platform_device *rts7751r2d_devices[] __initdata = {
        &uart_device,
+       &heartbeat_device,
+       &cf_ide_device,
 };
 
 static int __init rts7751r2d_devices_setup(void)
@@ -78,6 +122,7 @@ static int __init rts7751r2d_devices_setup(void)
        return platform_add_devices(rts7751r2d_devices,
                                    ARRAY_SIZE(rts7751r2d_devices));
 }
+__initcall(rts7751r2d_devices_setup);
 
 static void rts7751r2d_power_off(void)
 {
@@ -89,14 +134,17 @@ static void rts7751r2d_power_off(void)
  */
 static void __init rts7751r2d_setup(char **cmdline_p)
 {
-       device_initcall(rts7751r2d_devices_setup);
+       u16 ver = ctrl_inw(PA_VERREG);
+
+       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+
+       printk(KERN_INFO "FPGA version:%d (revision:%d)\n",
+                                       (ver >> 4) & 0xf, ver & 0xf);
 
        ctrl_outw(0x0000, PA_OUTPORT);
        pm_power_off = rts7751r2d_power_off;
 
        voyagergx_serial_init();
-
-       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
 }
 
 /*
@@ -107,31 +155,7 @@ struct sh_machine_vector mv_rts7751r2d __initmv = {
        .mv_setup               = rts7751r2d_setup,
        .mv_nr_irqs             = 72,
 
-       .mv_inb                 = rts7751r2d_inb,
-       .mv_inw                 = rts7751r2d_inw,
-       .mv_inl                 = rts7751r2d_inl,
-       .mv_outb                = rts7751r2d_outb,
-       .mv_outw                = rts7751r2d_outw,
-       .mv_outl                = rts7751r2d_outl,
-
-       .mv_inb_p               = rts7751r2d_inb_p,
-       .mv_inw_p               = rts7751r2d_inw,
-       .mv_inl_p               = rts7751r2d_inl,
-       .mv_outb_p              = rts7751r2d_outb_p,
-       .mv_outw_p              = rts7751r2d_outw,
-       .mv_outl_p              = rts7751r2d_outl,
-
-       .mv_insb                = rts7751r2d_insb,
-       .mv_insw                = rts7751r2d_insw,
-       .mv_insl                = rts7751r2d_insl,
-       .mv_outsb               = rts7751r2d_outsb,
-       .mv_outsw               = rts7751r2d_outsw,
-       .mv_outsl               = rts7751r2d_outsl,
-
        .mv_init_irq            = init_rts7751r2d_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_rts7751r2d,
-#endif
        .mv_irq_demux           = rts7751r2d_irq_demux,
 
 #ifdef CONFIG_USB_SM501
index 63950f4f24533e54949b5bb49bec81de58af7175..63e7ed699f39b3c41d8578daa8b57ce31807c689 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y   := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
-
diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c
deleted file mode 100644 (file)
index ef79460..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/arch/sh/kernel/led_se.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/config.h>
-#include <asm/se7206.h>
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ( (300<<FSHIFT)/
-                        ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up=0;
-               } else {
-                       bit ++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up=1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1<<(bit+8);
-
-}
-#endif /* CONFIG_HEARTBEAT */
index 0f42e91a3238b20bdd25026bdc3dff0155b54f6c..ca714879f55972bba43862ba70073702c9612d22 100644 (file)
@@ -3,6 +3,7 @@
  * linux/arch/sh/boards/se/7206/setup.c
  *
  * Copyright (C) 2006  Yoshinori Sato
+ * Copyright (C) 2007  Paul Mundt
  *
  * Hitachi 7206 SolutionEngine Support.
  *
@@ -34,15 +35,37 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *se7206_devices[] __initdata = {
+       &smc91x_device,
+       &heartbeat_device,
+};
+
 static int __init se7206_devices_setup(void)
 {
-       return platform_device_register(&smc91x_device);
+       return platform_add_devices(se7206_devices, ARRAY_SIZE(se7206_devices));
 }
-
 __initcall(se7206_devices_setup);
 
-void heartbeat_se(void);
-
 /*
  * The Machine Vector
  */
@@ -72,8 +95,5 @@ struct sh_machine_vector mv_se __initmv = {
        .mv_outsl               = se7206_outsl,
 
        .mv_init_irq            = init_se7206_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_se,
-#endif
 };
 ALIAS_MV(se)
index 0fbd4f47815cdb1bc8defab1433b204f26912671..46247368f14be7d19c9e2ced2d90e154a134cef6 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y   := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7300/led.c b/arch/sh/boards/se/7300/led.c
deleted file mode 100644 (file)
index 4d03bb7..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7300/led.c
- *
- * Derived from linux/arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/se7300.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7300se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up = 0;
-               } else {
-                       bit++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up = 1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1 << (bit + 8);
-
-}
-
index 6f082a722d42842f5502ff9b0a7497f3f35fd659..f1960956bad051f282ec74638432415eb985781a 100644 (file)
@@ -6,14 +6,43 @@
  * SH-Mobile SolutionEngine 7300 Support.
  *
  */
-
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se7300.h>
 
-void heartbeat_7300se(void);
 void init_7300se_IRQ(void);
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *se7300_devices[] __initdata = {
+       &heartbeat_device,
+};
+
+static int __init se7300_devices_setup(void)
+{
+       return platform_add_devices(se7300_devices, ARRAY_SIZE(se7300_devices));
+}
+__initcall(se7300_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -42,8 +71,5 @@ struct sh_machine_vector mv_7300se __initmv = {
        .mv_outsl = sh7300se_outsl,
 
        .mv_init_irq = init_7300se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat = heartbeat_7300se,
-#endif
 };
 ALIAS_MV(7300se)
index 8f63886a0f3f12f2322fe50106d9af079dbd76b6..e7c09967c529e424cd6b45f8597b097bcb8a2835 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y   := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/73180/led.c b/arch/sh/boards/se/73180/led.c
deleted file mode 100644 (file)
index 4b72e9a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/sh/boards/se/73180/led.c
- *
- * Derived from arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/mach/se73180.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_73180se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up = 0;
-               } else {
-                       bit++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up = 1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1 << (bit + LED_SHIFT);
-
-}
index b38ef50a160a2114b4c7a290d420797de3871e12..911ce1cdbd7f86865bb903ac054b359f0f6be82b 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se73180.h>
 #include <asm/irq.h>
 
-void heartbeat_73180se(void);
 void init_73180se_IRQ(void);
 
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + 8 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *se73180_devices[] __initdata = {
+       &heartbeat_device,
+};
+
+static int __init se73180_devices_setup(void)
+{
+       return platform_add_devices(sh7343se_platform_devices,
+                                   ARRAY_SIZE(sh7343se_platform_devices));
+}
+__initcall(se73180_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -46,8 +72,5 @@ struct sh_machine_vector mv_73180se __initmv = {
 
        .mv_init_irq = init_73180se_IRQ,
        .mv_irq_demux = shmse_irq_demux,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat = heartbeat_73180se,
-#endif
 };
 ALIAS_MV(73180se)
index 4291069c0b4f79e3304cb69cb4212b9c45c51228..3024796c6203b61771592cd6de0c701d4d367c41 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y   := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7343/led.c b/arch/sh/boards/se/7343/led.c
deleted file mode 100644 (file)
index 6b39e19..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/sh/boards/se/7343/led.c
- *
- */
-#include <linux/sched.h>
-#include <asm/mach/se7343.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7343se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up = 0;
-               } else {
-                       bit++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up = 1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1 << (bit + LED_SHIFT);
-
-}
index c7d17fe7764ed2cbabd145726ea31b75912df125..3fdb16f2cef1dfd400677bfd7b9d623706e79ef2 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/mach/se7343.h>
 #include <asm/irq.h>
 
-void heartbeat_7343se(void);
 void init_7343se_IRQ(void);
 
 static struct resource smc91x_resources[] = {
@@ -31,14 +30,30 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
-static struct platform_device *smc91x_platform_devices[] __initdata = {
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + 8 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *sh7343se_platform_devices[] __initdata = {
        &smc91x_device,
+       &heartbeat_device,
 };
 
 static int __init sh7343se_devices_setup(void)
 {
-       return platform_add_devices(smc91x_platform_devices,
-                                   ARRAY_SIZE(smc91x_platform_devices));
+       return platform_add_devices(sh7343se_platform_devices,
+                                   ARRAY_SIZE(sh7343se_platform_devices));
 }
 
 static void __init sh7343se_setup(char **cmdline_p)
@@ -76,8 +91,5 @@ struct sh_machine_vector mv_7343se __initmv = {
 
        .mv_init_irq = init_7343se_IRQ,
        .mv_irq_demux = shmse_irq_demux,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat = heartbeat_7343se,
-#endif
 };
 ALIAS_MV(7343se)
index 9a5035f80ec03987aadf37f3e72623a76c6ed179..8e624b06d5ea67efc746ecab0716485d9a4742bc 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 obj-y   := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
index fcd7cd7fa05f1d8f623f8981a616078edcda8ae9..307ca5da6232c54b53821ff86bdddcc2944aab2a 100644 (file)
@@ -2,56 +2,96 @@
  * linux/arch/sh/boards/se/770x/irq.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
  *
  * Hitachi SolutionEngine Support.
  *
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/se.h>
 
+/* 
+ * If the problem of make_ipr_irq is solved, 
+ * this code will become unnecessary. :-) 
+ */
+static void se770x_disable_ipr_irq(unsigned int irq)
+{
+       struct ipr_data *p = get_irq_chip_data(irq);
+
+       ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
+}
+
+static void se770x_enable_ipr_irq(unsigned int irq)
+{
+       struct ipr_data *p = get_irq_chip_data(irq);
+
+       ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
+}
+
+static struct irq_chip se770x_irq_chip = {
+       .name           = "MS770xSE-FPGA",
+       .mask           = se770x_disable_ipr_irq,
+       .unmask         = se770x_enable_ipr_irq,
+       .mask_ack       = se770x_disable_ipr_irq,
+};
+
+void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
+{
+       int i;
+
+       for (i = 0; i < nr_irqs; i++) {
+               unsigned int irq = table[i].irq;
+               disable_irq_nosync(irq);
+               set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
+                       handle_level_irq, "level");
+               set_irq_chip_data(irq, &table[i]);
+               se770x_enable_ipr_irq(irq);
+       }
+}
+
 static struct ipr_data se770x_ipr_map[] = {
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
        /* This is default value */
-       { 0xf-0x2, BCR_ILCRA, 2, 0x2 },
-       { 0xf-0xa, BCR_ILCRA, 1, 0xa },
-       { 0xf-0x5, BCR_ILCRB, 0, 0x5 },
-       { 0xf-0x8, BCR_ILCRC, 1, 0x8 },
-       { 0xf-0xc, BCR_ILCRC, 0, 0xc },
-       { 0xf-0xe, BCR_ILCRD, 3, 0xe },
-       { 0xf-0x3, BCR_ILCRD, 1, 0x3 }, /* LAN */
-       { 0xf-0xd, BCR_ILCRE, 2, 0xd },
-       { 0xf-0x9, BCR_ILCRE, 1, 0x9 },
-       { 0xf-0x1, BCR_ILCRE, 0, 0x1 },
-       { 0xf-0xf, BCR_ILCRF, 3, 0xf },
-       { 0xf-0xb, BCR_ILCRF, 1, 0xb },
-       { 0xf-0x7, BCR_ILCRG, 3, 0x7 },
-       { 0xf-0x6, BCR_ILCRG, 2, 0x6 },
-       { 0xf-0x4, BCR_ILCRG, 1, 0x4 },
+       { 0xf-0x2, 0, 8,  0x2 , BCR_ILCRA},
+       { 0xf-0xa, 0, 4,  0xa , BCR_ILCRA},
+       { 0xf-0x5, 0, 0,  0x5 , BCR_ILCRB},
+       { 0xf-0x8, 0, 4,  0x8 , BCR_ILCRC},
+       { 0xf-0xc, 0, 0,  0xc , BCR_ILCRC},
+       { 0xf-0xe, 0, 12, 0xe , BCR_ILCRD},
+       { 0xf-0x3, 0, 4,  0x3 , BCR_ILCRD}, /* LAN */
+       { 0xf-0xd, 0, 8,  0xd , BCR_ILCRE},
+       { 0xf-0x9, 0, 4,  0x9 , BCR_ILCRE},
+       { 0xf-0x1, 0, 0,  0x1 , BCR_ILCRE},
+       { 0xf-0xf, 0, 12, 0xf , BCR_ILCRF},
+       { 0xf-0xb, 0, 4,  0xb , BCR_ILCRF},
+       { 0xf-0x7, 0, 12, 0x7 , BCR_ILCRG},
+       { 0xf-0x6, 0, 8,  0x6 , BCR_ILCRG},
+       { 0xf-0x4, 0, 4,  0x4 , BCR_ILCRG},
 #else
-       { 14, BCR_ILCRA, 2, 0x0f-14 },
-       { 12, BCR_ILCRA, 1, 0x0f-12 },
-       {  8, BCR_ILCRB, 1, 0x0f- 8 },
-       {  6, BCR_ILCRC, 3, 0x0f- 6 },
-       {  5, BCR_ILCRC, 2, 0x0f- 5 },
-       {  4, BCR_ILCRC, 1, 0x0f- 4 },
-       {  3, BCR_ILCRC, 0, 0x0f- 3 },
-       {  1, BCR_ILCRD, 3, 0x0f- 1 },
-
-       { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
-
-       {  0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
-       { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
-       {  9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
-       {  7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
-
+       { 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
+       { 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
+       {  8, 0,  4, 0x0f- 8 ,BCR_ILCRB},
+       {  6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
+       {  5, 0,  8, 0x0f- 5 ,BCR_ILCRC},
+       {  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
+       {  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
+       {  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+       /* ST NIC */
+       { 10, 0,  4, 0x0f-10 ,BCR_ILCRD},       /* LAN */
+       /* MRSHPC IRQs setting */
+       {  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},       /* PCIRQ3 */
+       { 11, 0,  8, 0x0f-11 ,BCR_ILCRE},       /* PCIRQ2 */
+       {  9, 0,  4, 0x0f- 9 ,BCR_ILCRE},       /* PCIRQ1 */
+       {  7, 0,  0, 0x0f- 7 ,BCR_ILCRE},       /* PCIRQ0 */
        /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
        /* NOTE: #2 and #13 are not used on PC */
-       { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
-       {  2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
+       { 13, 0,  4, 0x0f-13 ,BCR_ILCRG},       /* SLOTIRQ2 */
+       {  2, 0,  0, 0x0f- 2 ,BCR_ILCRG},       /* SLOTIRQ1 */
 #endif
 };
 
@@ -81,5 +121,5 @@ void __init init_se_IRQ(void)
        ctrl_outw(0, BCR_ILCRF);
        ctrl_outw(0, BCR_ILCRG);
 #endif
-       make_ipr_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
+       make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
 }
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
deleted file mode 100644 (file)
index d93dd83..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/se.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ( (300<<FSHIFT)/
-                        ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up=0;
-               } else {
-                       bit ++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up=1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1<<(bit+8);
-
-}
index a1d51d5fa925cbb56512a98cf913c2d40d27312b..45cbc36b9fb70780e820cba14f05e6ec1b5164f8 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $
- *
+/*
  * linux/arch/sh/boards/se/770x/setup.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
@@ -8,12 +7,12 @@
  *
  */
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se.h>
 #include <asm/io.h>
 #include <asm/smc37c93x.h>
 
-void heartbeat_se(void);
 void init_se_IRQ(void);
 
 /*
@@ -36,11 +35,6 @@ static void __init smsc_setup(char **cmdline_p)
        smsc_config(ACTIVATE_INDEX, 0x01);
        smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
 
-       /* IDE1 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
-
        /* AUXIO (GPIO): to use IDE1 */
        smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
        smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
@@ -69,6 +63,36 @@ static void __init smsc_setup(char **cmdline_p)
        outb_p(CONFIG_EXIT, CONFIG_PORT);
 }
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *se_devices[] __initdata = {
+       &heartbeat_device,
+};
+
+static int __init se_devices_setup(void)
+{
+       return platform_add_devices(se_devices, ARRAY_SIZE(se_devices));
+}
+__initcall(se_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -107,8 +131,5 @@ struct sh_machine_vector mv_se __initmv = {
        .mv_outsl               = se_outsl,
 
        .mv_init_irq            = init_se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_se,
-#endif
 };
 ALIAS_MV(se)
index 188900c48321335bca050c9d1b8b161d9fec7c3a..dbc29f3a9de50be179088eb1f1e69f5fb9fc2cfe 100644 (file)
@@ -5,4 +5,3 @@
 obj-y   := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
deleted file mode 100644 (file)
index de4194d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7751/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-#include <linux/sched.h>
-#include <asm/se7751.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7751se(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ( (300<<FSHIFT)/
-                        ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up=0;
-               } else {
-                       bit ++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up=1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1<<(bit+8);
-
-}
index f7e1dd39c8364c30db40874a04e391144f249b17..e3feae6ec0bfe503f7ec66340f6cffe731adc89e 100644 (file)
@@ -9,11 +9,11 @@
  * Ian da Silva and Jeremy Siegel, 2001.
  */
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se7751.h>
 #include <asm/io.h>
 
-void heartbeat_7751se(void);
 void init_7751se_IRQ(void);
 
 #ifdef CONFIG_SH_KGDB
@@ -161,11 +161,40 @@ static int kgdb_uart_setup(void)
 }
 #endif /* CONFIG_SH_KGDB */
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *se7751_devices[] __initdata = {
+       &smc91x_device,
+       &heartbeat_device,
+};
+
+static int __init se7751_devices_setup(void)
+{
+       return platform_add_devices(se7751_devices, ARRAY_SIZE(se7751_devices));
+}
+__initcall(se7751_devices_setup);
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_7751se __initmv = {
        .mv_name                = "7751 SolutionEngine",
        .mv_setup               = sh7751se_setup,
@@ -189,8 +218,5 @@ struct sh_machine_vector mv_7751se __initmv = {
        .mv_outsl               = sh7751se_outsl,
 
        .mv_init_irq            = init_7751se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_7751se,
-#endif
 };
 ALIAS_MV(7751se)
index 321be50e36a5aeaa23db1e44130941dbca66ea72..400306a796ec5427f9554b5a78074d1f10302495 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 obj-y   := setup.o rtc.o
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/sh03/led.c b/arch/sh/boards/sh03/led.c
deleted file mode 100644 (file)
index d38562a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/sh/boards/sh03/led.c
- *
- * Copyright (C) 2004  Saito.K Interface Corporation.
- *
- * This file contains Interface CTP/PCI-SH03 specific LED code.
- */
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_sh03(void)
-{
-       static unsigned int cnt = 0, period = 0;
-       volatile unsigned char* p = (volatile unsigned char*)0xa0800000;
-       static unsigned bit = 0, up = 1;
-
-       cnt += 1;
-       if (cnt < period) {
-               return;
-       }
-
-       cnt = 0;
-
-       /* Go through the points (roughly!):
-        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-        */
-       period = 110 - ( (300<<FSHIFT)/
-                        ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if (up) {
-               if (bit == 7) {
-                       bit--;
-                       up=0;
-               } else {
-                       bit ++;
-               }
-       } else {
-               if (bit == 0) {
-                       bit++;
-                       up=1;
-               } else {
-                       bit--;
-               }
-       }
-       *p = 1<<bit;
-
-}
index 5ad1e19771be79cdcd924d0dda701a54253a8f65..c069c444b4eca13663f4f645a592e555720ac7f2 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
 #include <asm/sh03/io.h>
@@ -48,15 +49,36 @@ static void __init sh03_setup(char **cmdline_p)
        board_time_init = sh03_time_init;
 }
 
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = 0xa0800000,
+               .end    = 0xa0800000 + 8 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct platform_device *sh03_devices[] __initdata = {
+       &heartbeat_device,
+};
+
+static int __init sh03_devices_setup(void)
+{
+       return platform_add_devices(sh03_devices, ARRAY_SIZE(sh03_devices));
+}
+__initcall(sh03_devices_setup);
+
 struct sh_machine_vector mv_sh03 __initmv = {
        .mv_name                = "Interface (CTP/PCI-SH03)",
        .mv_setup               = sh03_setup,
        .mv_nr_irqs             = 48,
        .mv_ioport_map          = sh03_ioport_map,
        .mv_init_irq            = init_sh03_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_sh03,
-#endif
 };
 ALIAS_MV(sh03)
index a31a1d1e2681f06e16dff61cf2eef069977949ab..4a9df4a6b034d2f3cfe4013d3c2e4fea4e8dc711 100644 (file)
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#define PFC_PHCR       0xa400010e
+#define PFC_PHCR       0xa400010eUL
+#define INTC_ICR1      0xa4000010UL
+#define INTC_IPRC      0xa4000016UL
+
+static struct ipr_data shmin_ipr_map[] = {
+       { .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
+       { .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
+       { .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
+       { .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
+};
 
 static void __init init_shmin_irq(void)
 {
        ctrl_outw(0x2a00, PFC_PHCR);    // IRQ0-3=IRQ
        ctrl_outw(0x0aaa, INTC_ICR1);   // IRQ0-3=IRQ-mode,Low-active.
+       make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
 }
 
 static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
index f7ea700d05ae53c022493c791f601aa25266f7e5..70f12907647f13a32e73b3476c967dcb3cd0d237 100644 (file)
@@ -28,21 +28,21 @@ static void disable_voyagergx_irq(unsigned int irq)
        unsigned long val;
        unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-       pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-        val = inl(VOYAGER_INT_MASK);
-        val &= ~mask;
-        outl(val, VOYAGER_INT_MASK);
+       pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+       val = readl((void __iomem *)VOYAGER_INT_MASK);
+       val &= ~mask;
+       writel(val, (void __iomem *)VOYAGER_INT_MASK);
 }
 
 static void enable_voyagergx_irq(unsigned int irq)
 {
-        unsigned long val;
-        unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+       unsigned long val;
+       unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-        pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-        val = inl(VOYAGER_INT_MASK);
-        val |= mask;
-        outl(val, VOYAGER_INT_MASK);
+       pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+       val = readl((void __iomem *)VOYAGER_INT_MASK);
+       val |= mask;
+       writel(val, (void __iomem *)VOYAGER_INT_MASK);
 }
 
 static void mask_and_ack_voyagergx(unsigned int irq)
@@ -68,20 +68,20 @@ static void shutdown_voyagergx_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type voyagergx_irq_type = {
-       .typename = "VOYAGERGX-IRQ",
-       .startup = startup_voyagergx_irq,
-       .shutdown = shutdown_voyagergx_irq,
-       .enable = enable_voyagergx_irq,
-       .disable = disable_voyagergx_irq,
-       .ack = mask_and_ack_voyagergx,
-       .end = end_voyagergx_irq,
+       .typename       = "VOYAGERGX-IRQ",
+       .startup        = startup_voyagergx_irq,
+       .shutdown       = shutdown_voyagergx_irq,
+       .enable         = enable_voyagergx_irq,
+       .disable        = disable_voyagergx_irq,
+       .ack            = mask_and_ack_voyagergx,
+       .end            = end_voyagergx_irq,
 };
 
 static irqreturn_t voyagergx_interrupt(int irq, void *dev_id)
 {
        printk(KERN_INFO
               "VoyagerGX: spurious interrupt, status: 0x%x\n",
-                       inl(INT_STATUS));
+                       (unsigned int)readl((void __iomem *)INT_STATUS));
        return IRQ_HANDLED;
 }
 
@@ -93,13 +93,13 @@ static struct {
 void voyagergx_register_irq_demux(int irq,
                int (*demux)(int irq, void *dev), void *dev)
 {
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
+       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
+       voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
 }
 
 void voyagergx_unregister_irq_demux(int irq)
 {
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
+       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
 }
 
 int voyagergx_irq_demux(int irq)
@@ -107,31 +107,25 @@ int voyagergx_irq_demux(int irq)
 
        if (irq == IRQ_VOYAGER ) {
                unsigned long i = 0, bit __attribute__ ((unused));
-               unsigned long val  = inl(INT_STATUS);
-#if 1
-               if ( val & ( 1 << 1 )){
+               unsigned long val  = readl((void __iomem *)INT_STATUS);
+
+               if (val & (1 << 1))
                        i = 1;
-               } else if ( val & ( 1 << 2 )){
+               else if (val & (1 << 2))
                        i = 2;
-               } else if ( val & ( 1 << 6 )){
+               else if (val & (1 << 6))
                        i = 6;
-               } else if( val & ( 1 << 10 )){
+               else if (val & (1 << 10))
                        i = 10;
-               } else if( val & ( 1 << 11 )){
+               else if (val & (1 << 11))
                        i = 11;
-               } else if( val & ( 1 << 12 )){
+               else if (val & (1 << 12))
                        i = 12;
-               } else if( val & ( 1 << 17 )){
+               else if (val & (1 << 17))
                        i = 17;
-               } else {
+               else
                        printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
-               }
-               pr_debug("voyagergx_irq_demux %ld\n", i);
-#else
-               for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
-                       if (val & bit)
-                               break;
-#endif
+               pr_debug("voyagergx_irq_demux %d \n", i);
                if (i < VOYAGER_IRQ_NUM) {
                        irq = VOYAGER_IRQ_BASE + i;
                        if (voyagergx_demux[i].func != 0)
index 66b2fedd7ad9308c53648116d56c317a15c3b533..33f03027c193840a47c52023a5a30e569230d90a 100644 (file)
@@ -19,7 +19,7 @@ static int __init setup_voyagergx(void)
 {
        unsigned long val;
 
-       val = inl(DRAM_CTRL);
+       val = readl((void __iomem *)DRAM_CTRL);
        val |= (DRAM_CTRL_CPU_COLUMN_SIZE_256   |
                DRAM_CTRL_CPU_ACTIVE_PRECHARGE  |
                DRAM_CTRL_CPU_RESET             |
@@ -29,7 +29,7 @@ static int __init setup_voyagergx(void)
                DRAM_CTRL_ACTIVE_PRECHARGE      |
                DRAM_CTRL_RESET                 |
                DRAM_CTRL_REMAIN_ACTIVE);
-       outl(val, DRAM_CTRL);
+       writel(val, (void __iomem *)DRAM_CTRL);
 
        return 0;
 }
index 099e98f14729429566128e0be141b5f6bcb872f6..db6a02df5af680eef0b5c74dcaa4fee5e0ec1596 100644 (file)
@@ -1,15 +1,21 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:38:36 2006
+# Linux kernel version: 2.6.20
+# Thu Feb 15 17:17:29 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -33,8 +39,8 @@ CONFIG_SYSVIPC=y
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -97,10 +103,8 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
 # CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_MPC1211 is not set
 # CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
@@ -113,6 +117,9 @@ CONFIG_SH_RTS7751R2D=y
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_ASDAP310 is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -124,6 +131,12 @@ CONFIG_CPU_SH4=y
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -159,12 +172,14 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -174,6 +189,9 @@ CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -183,6 +201,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 
 #
 # Cache configuration
@@ -195,11 +214,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
 # Timer support
@@ -210,6 +232,8 @@ CONFIG_SH_TMU=y
 # RTS7751R2D options
 #
 CONFIG_RTS7751R2D_REV11=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=60000000
 
 #
@@ -231,11 +255,17 @@ CONFIG_VOYAGERGX=y
 # CONFIG_HD6446X_SERIES is not set
 CONFIG_HEARTBEAT=y
 
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
@@ -251,7 +281,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
 #
 # Bus options
@@ -260,7 +290,6 @@ CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -302,6 +331,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -319,11 +349,13 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -380,7 +412,7 @@ CONFIG_WIRELESS_EXT=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -422,44 +454,145 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_ATA_OVER_ETH is not set
 
 #
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Misc devices
 #
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
 
 #
-# IDE chipset support/bugfixes
+# ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
-# CONFIG_ATA is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -470,6 +603,9 @@ CONFIG_IDE_GENERIC=y
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -540,6 +676,7 @@ CONFIG_8139TOO=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -559,14 +696,17 @@ CONFIG_8139TOO=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -611,6 +751,7 @@ CONFIG_NET_WIRELESS=y
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -646,14 +787,23 @@ CONFIG_NET_WIRELESS=y
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=1
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 
@@ -671,10 +821,6 @@ CONFIG_HW_RANDOM=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -682,7 +828,6 @@ CONFIG_HW_RANDOM=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -698,6 +843,7 @@ CONFIG_HW_RANDOM=y
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -706,18 +852,14 @@ CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
-#
-# Misc devices
-#
-
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -759,7 +901,6 @@ CONFIG_SND_VERBOSE_PROCFS=y
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_OPL3_LIB=m
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
@@ -782,6 +923,18 @@ CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -801,6 +954,7 @@ CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -812,18 +966,23 @@ CONFIG_SND_AC97_BUS=m
 CONFIG_SND_YMFPCI=m
 # CONFIG_SND_AC97_POWER_SAVE is not set
 
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
 #
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
-# CONFIG_OSS_OBSOLETE_DRIVER is not set
+# CONFIG_OBSOLETE_OSS is not set
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_AC97_BUS=m
 
 #
 # USB support
@@ -872,7 +1031,29 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
 # DMA Engine support
@@ -887,6 +1068,14 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
 #
 # File systems
 #
@@ -894,10 +1083,12 @@ CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=y
 # CONFIG_ROMFS_FS is not set
@@ -932,7 +1123,8 @@ CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -1017,6 +1209,11 @@ CONFIG_NLS_CODEPAGE_932=y
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Profiling support
 #
@@ -1026,16 +1223,20 @@ CONFIG_OPROFILE=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_SH_STANDARD_BIOS is not set
-# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
+CONFIG_EARLY_PRINTK=y
 # CONFIG_KGDB is not set
 
 #
@@ -1052,8 +1253,11 @@ CONFIG_LOG_BUF_SHIFT=14
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index 5d357d68b234e866d26a2efb4e27297e11d4b350..4e6e77fa4ce761b7baafb6335ef9ea4e24d6153c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:49:01 2006
+# Linux kernel version: 2.6.20-rc2
+# Thu Dec 28 23:15:49 2006
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -10,6 +10,11 @@ CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -35,6 +40,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -116,6 +122,8 @@ CONFIG_SH_SOLUTION_ENGINE=y
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -127,6 +135,12 @@ CONFIG_CPU_SH4=y
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -162,12 +176,14 @@ CONFIG_CPU_SUBTYPE_SH7750=y
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -177,6 +193,9 @@ CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -202,17 +221,22 @@ CONFIG_CF_BASE_ADDR=0xb8000000
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
 # Timer support
 #
 CONFIG_SH_TMU=y
-CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=33333333
 
 #
 # CPU Frequency scaling
@@ -230,11 +254,17 @@ CONFIG_SH_PCLK_FREQ=50000000
 # CONFIG_HD6446X_SERIES is not set
 CONFIG_HEARTBEAT=y
 
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
@@ -249,8 +279,7 @@ CONFIG_PREEMPT_NONE=y
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC1,38400 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
@@ -313,11 +342,13 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -479,17 +510,80 @@ CONFIG_MTD_ROM=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
 #
 # ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -633,17 +727,12 @@ CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -659,6 +748,7 @@ CONFIG_HW_RANDOM=y
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -667,18 +757,14 @@ CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
-#
-# Misc devices
-#
-
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -757,15 +843,21 @@ CONFIG_FIRMWARE_EDID=y
 # DMA Devices
 #
 
+#
+# Virtualization
+#
+
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -814,7 +906,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -874,6 +965,11 @@ CONFIG_PARTITION_ADVANCED=y
 #
 # CONFIG_NLS is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Profiling support
 #
@@ -882,14 +978,16 @@ CONFIG_PARTITION_ADVANCED=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
@@ -908,6 +1006,7 @@ CONFIG_LOG_BUF_SHIFT=14
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -915,3 +1014,4 @@ CONFIG_CRC32=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
index bf18dbfb6787db618d339e082b08bd0a8d6e2713..6cb92676c5fc4a51178a72524a61ee6d93ac7f11 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_PCI)               += pci/
 obj-$(CONFIG_SH_DMA)           += dma/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_PUSH_SWITCH)      += push-switch.o
+obj-$(CONFIG_HEARTBEAT)                += heartbeat.o
index f63721ed86c273fc20864fe107e0877e88d3b65c..06ed0609a95d6c58ecf476d483f0ef6ea617e83e 100644 (file)
 #include <asm/io.h>
 #include "dma-sh.h"
 
-
-
-#ifdef CONFIG_CPU_SH4
-static struct ipr_data dmae_ipr_map[] = {
-       { DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-};
+static int dmte_irq_map[] = {
+       DMTE0_IRQ,
+       DMTE1_IRQ,
+       DMTE2_IRQ,
+       DMTE3_IRQ,
+#if defined(CONFIG_CPU_SUBTYPE_SH7751R) ||     \
+    defined(CONFIG_CPU_SUBTYPE_SH7760)  ||     \
+    defined(CONFIG_CPU_SUBTYPE_SH7780)
+       DMTE4_IRQ,
+       DMTE5_IRQ,
+       DMTE6_IRQ,
+       DMTE7_IRQ,    
 #endif
-static struct ipr_data dmte_ipr_map[] = {
-       /*
-        * Normally we could just do DMTE0_IRQ + chan outright, though in the
-        * case of the 7751R, the DMTE IRQs for channels > 4 start right above
-        * the SCIF
-        */
-       { DMTE0_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE0_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE0_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE0_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE4_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE4_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE4_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-       { DMTE4_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
 };
 
 static inline unsigned int get_dmte_irq(unsigned int chan)
 {
        unsigned int irq = 0;
-       if (chan < ARRAY_SIZE(dmte_ipr_map))
-               irq = dmte_ipr_map[chan].irq;
+       if (chan < ARRAY_SIZE(dmte_irq_map))
+               irq = dmte_irq_map[chan];
        return irq;
 }
 
@@ -103,7 +95,7 @@ static void sh_dmac_free_dma(struct dma_channel *chan)
        free_irq(get_dmte_irq(chan->chan), chan);
 }
 
-static void
+static int
 sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
 {
        if (!chcr)
@@ -119,6 +111,7 @@ sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
        ctrl_outl(chcr, CHCR[chan->chan]);
 
        chan->flags |= DMA_CONFIGURED;
+       return 0;
 }
 
 static void sh_dmac_enable_dma(struct dma_channel *chan)
@@ -262,17 +255,11 @@ static int __init sh_dmac_init(void)
        int i;
 
 #ifdef CONFIG_CPU_SH4
-       make_ipr_irq(dmae_ipr_map, ARRAY_SIZE(dmae_ipr_map));
        i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
        if (unlikely(i < 0))
                return i;
 #endif
 
-       i = info->nr_channels;
-       if (i > ARRAY_SIZE(dmte_ipr_map))
-               i = ARRAY_SIZE(dmte_ipr_map);
-       make_ipr_irq(dmte_ipr_map, i);
-
        /*
         * Initialize DMAOR, and clean up any error flags that may have
         * been set.
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
new file mode 100644 (file)
index 0000000..bc59cb6
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Generic heartbeat driver for regular LED banks
+ *
+ * Copyright (C) 2007  Paul Mundt
+ *
+ * Most SH reference boards include a number of individual LEDs that can
+ * be independently controlled (either via a pre-defined hardware
+ * function or via the LED class, if desired -- the hardware tends to
+ * encapsulate some of the same "triggers" that the LED class supports,
+ * so there's not too much value in it).
+ *
+ * Additionally, most of these boards also have a LED bank that we've
+ * traditionally used for strobing the load average. This use case is
+ * handled by this driver, rather than giving each LED bit position its
+ * own struct device.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#define DRV_NAME "heartbeat"
+#define DRV_VERSION "0.1.0"
+
+struct heartbeat_data {
+       void __iomem *base;
+       unsigned char bit_pos[8];
+       struct timer_list timer;
+};
+
+static void heartbeat_timer(unsigned long data)
+{
+       struct heartbeat_data *hd = (struct heartbeat_data *)data;
+       static unsigned bit = 0, up = 1;
+
+       ctrl_outw(1 << hd->bit_pos[bit], (unsigned long)hd->base);
+       if (up)
+               if (bit == (ARRAY_SIZE(hd->bit_pos) - 1)) {
+                       bit--;
+                       up = 0;
+               } else
+                       bit++;
+       else if (bit == 0)
+               up = 1;
+       else
+               bit--;
+
+       mod_timer(&hd->timer, jiffies + (110 - ((300 << FSHIFT) /
+                       ((avenrun[0] / 5) + (3 << FSHIFT)))));
+}
+
+static int heartbeat_drv_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct heartbeat_data *hd;
+
+       if (unlikely(pdev->num_resources != 1)) {
+               dev_err(&pdev->dev, "invalid number of resources\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(res == NULL)) {
+               dev_err(&pdev->dev, "invalid resource\n");
+               return -EINVAL;
+       }
+
+       hd = kmalloc(sizeof(struct heartbeat_data), GFP_KERNEL);
+       if (unlikely(!hd))
+               return -ENOMEM;
+
+       if (pdev->dev.platform_data) {
+               memcpy(hd->bit_pos, pdev->dev.platform_data,
+                      ARRAY_SIZE(hd->bit_pos));
+       } else {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(hd->bit_pos); i++)
+                       hd->bit_pos[i] = i;
+       }
+
+       hd->base = (void __iomem *)res->start;
+
+       setup_timer(&hd->timer, heartbeat_timer, (unsigned long)hd);
+       platform_set_drvdata(pdev, hd);
+
+       return mod_timer(&hd->timer, jiffies + 1);
+}
+
+static int heartbeat_drv_remove(struct platform_device *pdev)
+{
+       struct heartbeat_data *hd = platform_get_drvdata(pdev);
+
+       del_timer_sync(&hd->timer);
+
+       platform_set_drvdata(pdev, NULL);
+
+       kfree(hd);
+
+       return 0;
+}
+
+static struct platform_driver heartbeat_driver = {
+       .probe          = heartbeat_drv_probe,
+       .remove         = heartbeat_drv_remove,
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init heartbeat_init(void)
+{
+       printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
+       return platform_driver_register(&heartbeat_driver);
+}
+
+static void __exit heartbeat_exit(void)
+{
+       platform_driver_unregister(&heartbeat_driver);
+}
+module_init(heartbeat_init);
+module_exit(heartbeat_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt");
+MODULE_LICENSE("GPLv2");
index 9e00cb8a39e90365f8745d42f76cae5e2b24d411..cc8d0d0b142749cbd325bc2621c815c073d86e26 100644 (file)
@@ -12,7 +12,6 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780)      += pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_SH_DREAMCAST)             += ops-dreamcast.o fixups-dreamcast.o \
                                           dma-dreamcast.o
 obj-$(CONFIG_SH_SECUREEDGE5410)                += ops-snapgear.o
-obj-$(CONFIG_SH_BIGSUR)                        += ops-bigsur.o
 obj-$(CONFIG_SH_RTS7751R2D)            += ops-rts7751r2d.o fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)                  += ops-sh03.o fixups-sh03.o
 obj-$(CONFIG_SH_R7780RP)               += ops-r7780rp.o fixups-r7780rp.o
diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c
deleted file mode 100644 (file)
index eb31be7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-bigsur.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- *
- * Ported to new API by Paul Mundt <lethal@linux-sh.org>.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Hitachi Big Sur Evaluation Board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-#include <asm/bigsur/bigsur.h>
-
-#define BIGSUR_PCI_IO  0x4000
-#define BIGSUR_PCI_MEM 0xfd000000
-
-static struct resource sh7751_io_resource = {
-       .name           = "SH7751 IO",
-       .start          = BIGSUR_PCI_IO,
-       .end            = BIGSUR_PCI_IO + (64*1024) - 1,
-       .flags          = IORESOURCE_IO,
-};
-
-static struct resource sh7751_mem_resource = {
-       .name           = "SH7751 mem",
-       .start          = BIGSUR_PCI_MEM,
-       .end            = BIGSUR_PCI_MEM + (64*1024*1024) - 1,
-       .flags          = IORESOURCE_MEM,
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-       { 0, }
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-       .window0        = {
-               .base   = SH7751_CS3_BASE_ADDR,
-               .size   = BIGSUR_LSR0_SIZE,
-       },
-
-       .window1        = {
-               .base   = SH7751_CS3_BASE_ADDR,
-               .size   = BIGSUR_LSR1_SIZE,
-       },
-};
-
-/*
- * Initialize the Big Sur PCI interface
- * Setup hardware to be Central Funtion
- * Copy the BSR regs to the PCI interface
- * Setup PCI windows into local RAM
- */
-int __init pcibios_init_platform(void)
-{
-       return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-       /*
-        * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
-        * interface is on the wrong end of the board so that it can also
-        * support a V320 CPI interface chip...  Therefor the IRQ mapping is
-        * somewhat use dependent... I'l assume a linear map for now, i.e.
-        * INTA=slot0,pin0... INTD=slot3,pin0...
-        */
-       int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
-
-       PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
-              slot, pin-1+'A', irq);
-
-       return irq;
-}
index 85e1ee2e2e7b47d6997304768bfbc25c5998d92b..9ddff760d3c6fdbf856e92b79fae6c6c2c36bc68 100644 (file)
@@ -157,15 +157,6 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
                 PCIBIOS_MIN_IO, (64 << 10),
                 SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
 
-       /*
-        * XXX: For now, leave this board-specific. In the event we have other
-        * boards that need to do similar work, this can be wrapped.
-        */
-#ifdef CONFIG_SH_BIGSUR
-       bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
-                       SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
-#endif
-
        /* Make sure the MSB's of IO window are set to access PCI space
         * correctly */
        word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
index 2f6d2bcb1c93f8fbc26b7daee131b894e02dd9ad..ff30d7f58043662b8ec85f79118412ca8107e526 100644 (file)
@@ -6,7 +6,8 @@ extra-y := head.o init_task.o vmlinux.lds
 
 obj-y  := process.o signal.o traps.o irq.o \
        ptrace.o setup.o time.o sys_sh.o semaphore.o \
-       io.o io_generic.o sh_ksyms.o syscalls.o
+       io.o io_generic.o sh_ksyms.o syscalls.o \
+       debugtraps.o
 
 obj-y                          += cpu/ timers/
 obj-$(CONFIG_VSYSCALL)         += vsyscall/
index 48121766e8d243e07065e3f3797da7376092cc9b..4b339a640b13c86dc02d9a6de09eab4f8c8ab9f0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU init code
  *
- * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2002 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -12,6 +12,8 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -46,7 +48,7 @@ static void __init cache_init(void)
 {
        unsigned long ccr, flags;
 
-       if (cpu_data->type == CPU_SH_NONE)
+       if (current_cpu_data.type == CPU_SH_NONE)
                panic("Unknown CPU");
 
        jump_to_P2();
@@ -66,7 +68,7 @@ static void __init cache_init(void)
        if (ccr & CCR_CACHE_ENABLE) {
                unsigned long ways, waysize, addrstart;
 
-               waysize = cpu_data->dcache.sets;
+               waysize = current_cpu_data.dcache.sets;
 
 #ifdef CCR_CACHE_ORA
                /*
@@ -77,7 +79,7 @@ static void __init cache_init(void)
                        waysize >>= 1;
 #endif
 
-               waysize <<= cpu_data->dcache.entry_shift;
+               waysize <<= current_cpu_data.dcache.entry_shift;
 
 #ifdef CCR_CACHE_EMODE
                /* If EMODE is not set, we only have 1 way to flush. */
@@ -85,7 +87,7 @@ static void __init cache_init(void)
                        ways = 1;
                else
 #endif
-                       ways = cpu_data->dcache.ways;
+                       ways = current_cpu_data.dcache.ways;
 
                addrstart = CACHE_OC_ADDRESS_ARRAY;
                do {
@@ -93,10 +95,10 @@ static void __init cache_init(void)
 
                        for (addr = addrstart;
                             addr < addrstart + waysize;
-                            addr += cpu_data->dcache.linesz)
+                            addr += current_cpu_data.dcache.linesz)
                                ctrl_outl(0, addr);
 
-                       addrstart += cpu_data->dcache.way_incr;
+                       addrstart += current_cpu_data.dcache.way_incr;
                } while (--ways);
        }
 
@@ -108,7 +110,7 @@ static void __init cache_init(void)
 
 #ifdef CCR_CACHE_EMODE
        /* Force EMODE if possible */
-       if (cpu_data->dcache.ways > 1)
+       if (current_cpu_data.dcache.ways > 1)
                flags |= CCR_CACHE_EMODE;
        else
                flags &= ~CCR_CACHE_EMODE;
@@ -125,10 +127,10 @@ static void __init cache_init(void)
 #ifdef CONFIG_SH_OCRAM
        /* Turn on OCRAM -- halve the OC */
        flags |= CCR_CACHE_ORA;
-       cpu_data->dcache.sets >>= 1;
+       current_cpu_data.dcache.sets >>= 1;
 
-       cpu_data->dcache.way_size = cpu_data->dcache.sets *
-                                   cpu_data->dcache.linesz;
+       current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
+                                   current_cpu_data.dcache.linesz;
 #endif
 
        ctrl_outl(flags, CCR);
@@ -170,7 +172,7 @@ static void __init dsp_init(void)
 
        /* If the DSP bit is still set, this CPU has a DSP */
        if (sr & SR_DSP)
-               cpu_data->flags |= CPU_HAS_DSP;
+               current_cpu_data.flags |= CPU_HAS_DSP;
 
        /* Now that we've determined the DSP status, clear the DSP bit. */
        release_dsp();
@@ -202,22 +204,28 @@ asmlinkage void __init sh_cpu_init(void)
        cache_init();
 
        shm_align_mask = max_t(unsigned long,
-                              cpu_data->dcache.way_size - 1,
+                              current_cpu_data.dcache.way_size - 1,
                               PAGE_SIZE - 1);
 
        /* Disable the FPU */
        if (fpu_disabled) {
                printk("FPU Disabled\n");
-               cpu_data->flags &= ~CPU_HAS_FPU;
+               current_cpu_data.flags &= ~CPU_HAS_FPU;
                disable_fpu();
        }
 
        /* FPU initialization */
-       if ((cpu_data->flags & CPU_HAS_FPU)) {
+       if ((current_cpu_data.flags & CPU_HAS_FPU)) {
                clear_thread_flag(TIF_USEDFPU);
                clear_used_math();
        }
 
+       /*
+        * Initialize the per-CPU ASID cache very early, since the
+        * TLB flushing routines depend on this being setup.
+        */
+       current_cpu_data.asid_cache = NO_CONTEXT;
+
 #ifdef CONFIG_SH_DSP
        /* Probe for DSP */
        dsp_init();
@@ -225,7 +233,7 @@ asmlinkage void __init sh_cpu_init(void)
        /* Disable the DSP */
        if (dsp_disabled) {
                printk("DSP Disabled\n");
-               cpu_data->flags &= ~CPU_HAS_DSP;
+               current_cpu_data.flags &= ~CPU_HAS_DSP;
                release_dsp();
        }
 #endif
@@ -240,4 +248,3 @@ asmlinkage void __init sh_cpu_init(void)
        ubc_wakeup();
 #endif
 }
-
index 35eb5751a3aaf842ecaecdb59e66f2dc70bc6d01..210280b6fddfdb5484ef472a2307cf54d7363a23 100644 (file)
@@ -43,16 +43,29 @@ static struct irq_chip ipr_irq_chip = {
        .mask_ack       = disable_ipr_irq,
 };
 
+unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
+unsigned int map_ipridx_to_addr(int idx)
+{
+       return 0;
+}
+
 void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
 {
        int i;
 
        for (i = 0; i < nr_irqs; i++) {
                unsigned int irq = table[i].irq;
-               table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+
+               if (!irq)
+                       irq = table[i].irq = i;
+
                /* could the IPR index be mapped, if not we ignore this */
-               if (table[i].addr == 0)
-                       continue;
+               if (!table[i].addr) {
+                       table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+                       if (!table[i].addr)
+                               continue;
+               }
+
                disable_irq_nosync(irq);
                set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
                                      handle_level_irq, "level");
index d0440b26970217411df06d17ab7fdf9057a3d973..d2c157917999870078cc79c6b2bdaf431cac76d6 100644 (file)
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2};
-const static int pfc_divisors[]={1,2,0,4};
+static const int pll1rate[] = {1,2};
+static const int pfc_divisors[] = {1,2,0,4};
 
 #if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
 #define PLL2 (4)
index d51fa5e9904a8b92d3b5254720de5288fd0e77d5..7f7d292f36ec12d49aebaf956cbeafe4db2369bb 100644 (file)
@@ -178,12 +178,10 @@ interrupt_entry:
 8:     .long   do_exception_error
        
 trap_entry:
-       /* verbose BUG trapa entry check */
-       mov     #0x3e,r8
-       cmp/ge  r8,r9
-       bf/s    1f
-        add    #-0x10,r9
-       add     #0x10,r9
+       mov     #0x30,r8
+       cmp/ge  r8,r9           ! vector 0x20-0x2f is systemcall
+       bt      1f
+       add     #-0x10,r9       ! convert SH2 to SH3/4 ABI
 1:     
        shll2   r9                      ! TRA
        mov     #OFF_TRA,r8
@@ -206,7 +204,7 @@ trap_entry:
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
        /* Unwind the stack and jmp to the debug entry */
-debug_kernel_fw:
+ENTRY(sh_bios_handler)
        mov     r15,r0
        add     #(22-4)*4-4,r0
        ldc.l   @r0+,gbr
index ba527d9b502411a56db05cb9b840688f8e4ba4fb..108e81b682ed0cb18cfb72f72892f1d08316002c 100644 (file)
 int __init detect_cpu_and_cache_system(void)
 {
 #if defined(CONFIG_CPU_SUBTYPE_SH7604)
-       cpu_data->type                  = CPU_SH7604;
-       cpu_data->dcache.ways           = 4;
-       cpu_data->dcache.way_incr       = (1<<10);
-       cpu_data->dcache.sets           = 64;
-       cpu_data->dcache.entry_shift    = 4;
-       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
-       cpu_data->dcache.flags          = 0;
+       current_cpu_data.type                   = CPU_SH7604;
+       current_cpu_data.dcache.ways            = 4;
+       current_cpu_data.dcache.way_incr        = (1<<10);
+       current_cpu_data.dcache.sets            = 64;
+       current_cpu_data.dcache.entry_shift     = 4;
+       current_cpu_data.dcache.linesz          = L1_CACHE_BYTES;
+       current_cpu_data.dcache.flags           = 0;
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-       cpu_data->type                  = CPU_SH7619;
-       cpu_data->dcache.ways           = 4;
-       cpu_data->dcache.way_incr       = (1<<12);
-       cpu_data->dcache.sets           = 256;
-       cpu_data->dcache.entry_shift    = 4;
-       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
-       cpu_data->dcache.flags          = 0;
+       current_cpu_data.type                   = CPU_SH7619;
+       current_cpu_data.dcache.ways            = 4;
+       current_cpu_data.dcache.way_incr        = (1<<12);
+       current_cpu_data.dcache.sets            = 256;
+       current_cpu_data.dcache.entry_shift     = 4;
+       current_cpu_data.dcache.linesz          = L1_CACHE_BYTES;
+       current_cpu_data.dcache.flags           = 0;
 #endif
        /*
         * SH-2 doesn't have separate caches
         */
-       cpu_data->dcache.flags |= SH_CACHE_COMBINED;
-       cpu_data->icache = cpu_data->dcache;
+       current_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
+       current_cpu_data.icache = current_cpu_data.dcache;
 
        return 0;
 }
index 79283e6c1d8f069a87efb9241e6dee36ca23c94c..f83ff8a68f3567a5b70cc435ba0195feece808a9 100644 (file)
@@ -52,42 +52,38 @@ static int __init sh7619_devices_setup(void)
 }
 __initcall(sh7619_devices_setup);
 
-#define INTC_IPRC      0xf8080000UL
-#define INTC_IPRD      0xf8080002UL
-
-#define CMI0_IRQ       86
-
-#define SCIF0_ERI_IRQ  88
-#define SCIF0_RXI_IRQ  89
-#define SCIF0_BRI_IRQ  90
-#define SCIF0_TXI_IRQ  91
-
-#define SCIF1_ERI_IRQ  92
-#define SCIF1_RXI_IRQ  93
-#define SCIF1_BRI_IRQ  94
-#define SCIF1_TXI_IRQ  95
-
-#define SCIF2_BRI_IRQ  96
-#define SCIF2_ERI_IRQ  97
-#define SCIF2_RXI_IRQ  98
-#define SCIF2_TXI_IRQ  99
-
 static struct ipr_data sh7619_ipr_map[] = {
-       { CMI0_IRQ,      INTC_IPRC, 1, 2 },
-       { SCIF0_ERI_IRQ, INTC_IPRD, 3, 3 },
-       { SCIF0_RXI_IRQ, INTC_IPRD, 3, 3 },
-       { SCIF0_BRI_IRQ, INTC_IPRD, 3, 3 },
-       { SCIF0_TXI_IRQ, INTC_IPRD, 3, 3 },
-       { SCIF1_ERI_IRQ, INTC_IPRD, 2, 3 },
-       { SCIF1_RXI_IRQ, INTC_IPRD, 2, 3 },
-       { SCIF1_BRI_IRQ, INTC_IPRD, 2, 3 },
-       { SCIF1_TXI_IRQ, INTC_IPRD, 2, 3 },
-       { SCIF2_ERI_IRQ, INTC_IPRD, 1, 3 },
-       { SCIF2_RXI_IRQ, INTC_IPRD, 1, 3 },
-       { SCIF2_BRI_IRQ, INTC_IPRD, 1, 3 },
-       { SCIF2_TXI_IRQ, INTC_IPRD, 1, 3 },
+       { 86, 0,  4, 2 },       /* CMI0 */
+       { 88, 1, 12, 3 },       /* SCIF0_ERI */
+       { 89, 1, 12, 3 },       /* SCIF0_RXI */
+       { 90, 1, 12, 3 },       /* SCIF0_BRI */
+       { 91, 1, 12, 3 },       /* SCIF0_TXI */
+       { 92, 1,  8, 3 },       /* SCIF1_ERI */
+       { 93, 1,  8, 3 },       /* SCIF1_RXI */
+       { 94, 1,  8, 3 },       /* SCIF1_BRI */
+       { 95, 1,  8, 3 },       /* SCIF1_TXI */
+       { 96, 1,  4, 3 },       /* SCIF2_ERI */
+       { 97, 1,  4, 3 },       /* SCIF2_RXI */
+       { 98, 1,  4, 3 },       /* SCIF2_BRI */
+       { 99, 1,  4, 3 },       /* SCIF2_TXI */
 };
 
+static unsigned int ipr_offsets[] = {
+       0xf8080000,     /* IPRC */
+       0xf8080002,     /* IPRD */
+       0xf8080004,     /* IPRE */
+       0xf8080006,     /* IPRF */
+       0xf8080008,     /* IPRG */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+               return 0;
+       return ipr_offsets[idx];
+}
+
 void __init init_IRQ_ipr(void)
 {
        make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
index a9ad309c6a338aacbe12e393c9e4fbb3097734dc..82d7f991ef6bd8acb3da60c2238b18c69ebc616a 100644 (file)
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2,3,4,6,8};
-const static int pfc_divisors[]={1,2,3,4,6,8,12};
+static const int pll1rate[]={1,2,3,4,6,8};
+static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
 #if (CONFIG_SH_CLK_MD == 2)
index 87c6c05420898f0128d27a4677e52f7caa307e87..426f6db01fc69d117621398e5be60f29a09f261a 100644 (file)
 int __init detect_cpu_and_cache_system(void)
 {
        /* Just SH7206 for now .. */
-       cpu_data->type                  = CPU_SH7206;
+       current_cpu_data.type                   = CPU_SH7206;
 
-       cpu_data->dcache.ways           = 4;
-       cpu_data->dcache.way_incr       = (1 << 11);
-       cpu_data->dcache.sets           = 128;
-       cpu_data->dcache.entry_shift    = 4;
-       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
-       cpu_data->dcache.flags          = 0;
+       current_cpu_data.dcache.ways            = 4;
+       current_cpu_data.dcache.way_incr        = (1 << 11);
+       current_cpu_data.dcache.sets            = 128;
+       current_cpu_data.dcache.entry_shift     = 4;
+       current_cpu_data.dcache.linesz          = L1_CACHE_BYTES;
+       current_cpu_data.dcache.flags           = 0;
 
        /*
         * The icache is the same as the dcache as far as this setup is
@@ -32,7 +32,7 @@ int __init detect_cpu_and_cache_system(void)
         * lacks the U bit that the dcache has, none of this has any bearing
         * on the cache info.
         */
-       cpu_data->icache                = cpu_data->dcache;
+       current_cpu_data.icache         = current_cpu_data.dcache;
 
        return 0;
 }
index 4b60fcc7d66755e9d7c9614adeaac9251df8a1f5..4ed9110632bc5d0d368c0437a0d372dbf4bc651f 100644 (file)
@@ -57,55 +57,52 @@ static int __init sh7206_devices_setup(void)
 }
 __initcall(sh7206_devices_setup);
 
-#define INTC_IPR08     0xfffe0c04UL
-#define INTC_IPR09     0xfffe0c06UL
-#define INTC_IPR14     0xfffe0c10UL
-
-#define CMI0_IRQ       140
-
-#define MTU1_TGI1A     164
-
-#define SCIF0_BRI_IRQ  240
-#define SCIF0_ERI_IRQ  241
-#define SCIF0_RXI_IRQ  242
-#define SCIF0_TXI_IRQ  243
-
-#define SCIF1_BRI_IRQ  244
-#define SCIF1_ERI_IRQ  245
-#define SCIF1_RXI_IRQ  246
-#define SCIF1_TXI_IRQ  247
-
-#define SCIF2_BRI_IRQ  248
-#define SCIF2_ERI_IRQ  249
-#define SCIF2_RXI_IRQ  250
-#define SCIF2_TXI_IRQ  251
-
-#define SCIF3_BRI_IRQ  252
-#define SCIF3_ERI_IRQ  253
-#define SCIF3_RXI_IRQ  254
-#define SCIF3_TXI_IRQ  255
-
 static struct ipr_data sh7206_ipr_map[] = {
-       { CMI0_IRQ,      INTC_IPR08, 3, 2 },
-       { MTU2_TGI1A,    INTC_IPR09, 1, 2 },
-       { SCIF0_ERI_IRQ, INTC_IPR14, 3, 3 },
-       { SCIF0_RXI_IRQ, INTC_IPR14, 3, 3 },
-       { SCIF0_BRI_IRQ, INTC_IPR14, 3, 3 },
-       { SCIF0_TXI_IRQ, INTC_IPR14, 3, 3 },
-       { SCIF1_ERI_IRQ, INTC_IPR14, 2, 3 },
-       { SCIF1_RXI_IRQ, INTC_IPR14, 2, 3 },
-       { SCIF1_BRI_IRQ, INTC_IPR14, 2, 3 },
-       { SCIF1_TXI_IRQ, INTC_IPR14, 2, 3 },
-       { SCIF2_ERI_IRQ, INTC_IPR14, 1, 3 },
-       { SCIF2_RXI_IRQ, INTC_IPR14, 1, 3 },
-       { SCIF2_BRI_IRQ, INTC_IPR14, 1, 3 },
-       { SCIF2_TXI_IRQ, INTC_IPR14, 1, 3 },
-       { SCIF3_ERI_IRQ, INTC_IPR14, 0, 3 },
-       { SCIF3_RXI_IRQ, INTC_IPR14, 0, 3 },
-       { SCIF3_BRI_IRQ, INTC_IPR14, 0, 3 },
-       { SCIF3_TXI_IRQ, INTC_IPR14, 0, 3 },
+       { 140,  7, 12, 2 },     /* CMI0 */
+       { 164,  8,  4, 2 },     /* MTU2_TGI1A */
+       { 240, 13, 12, 3 },     /* SCIF0_BRI */
+       { 241, 13, 12, 3 },     /* SCIF0_ERI */
+       { 242, 13, 12, 3 },     /* SCIF0_RXI */
+       { 243, 13, 12, 3 },     /* SCIF0_TXI */
+       { 244, 13,  8, 3 },     /* SCIF1_BRI */
+       { 245, 13,  8, 3 },     /* SCIF1_ERI */
+       { 246, 13,  8, 3 },     /* SCIF1_RXI */
+       { 247, 13,  8, 3 },     /* SCIF1_TXI */
+       { 248, 13,  4, 3 },     /* SCIF2_BRI */
+       { 249, 13,  4, 3 },     /* SCIF2_ERI */
+       { 250, 13,  4, 3 },     /* SCIF2_RXI */
+       { 251, 13,  4, 3 },     /* SCIF2_TXI */
+       { 252, 13,  0, 3 },     /* SCIF3_BRI */
+       { 253, 13,  0, 3 },     /* SCIF3_ERI */
+       { 254, 13,  0, 3 },     /* SCIF3_RXI */
+       { 255, 13,  0, 3 },     /* SCIF3_TXI */
+};
+
+static unsigned int ipr_offsets[] = {
+       0xfffe0818,     /* IPR01 */
+       0xfffe081a,     /* IPR02 */
+       0,              /* unused */
+       0,              /* unused */
+       0xfffe0820,     /* IPR05 */
+       0xfffe0c00,     /* IPR06 */
+       0xfffe0c02,     /* IPR07 */
+       0xfffe0c04,     /* IPR08 */
+       0xfffe0c06,     /* IPR09 */
+       0xfffe0c08,     /* IPR10 */
+       0xfffe0c0a,     /* IPR11 */
+       0xfffe0c0c,     /* IPR12 */
+       0xfffe0c0e,     /* IPR13 */
+       0xfffe0c10,     /* IPR14 */
 };
 
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+               return 0;
+       return ipr_offsets[idx];
+}
+
 void __init init_IRQ_ipr(void)
 {
        make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
index 8c0dc2700c69ebc79df3085e0c2e93ce2099a6bb..c19205b0f2c001d2ce1cd73c7dba7674890d102f 100644 (file)
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
-#include <asm/unistd.h>
 #include <asm/cpu/mmu_context.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <asm/unistd.h>
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -138,14 +136,29 @@ ENTRY(tlb_protection_violation_store)
 
 call_dpf:
        mov.l   1f, r0
-       mov.l   @r0, r6         ! address
+       mov     r5, r8
+       mov.l   @r0, r6
+       mov     r6, r9
+       mov.l   2f, r0
+       sts     pr, r10
+       jsr     @r0
+        mov    r15, r4
+       !
+       tst     r0, r0
+       bf/s    0f
+        lds    r10, pr
+       rts
+        nop
+0:     sti
        mov.l   3f, r0
-
+       mov     r9, r6
+       mov     r8, r5
        jmp     @r0
-        mov    r15, r4         ! regs
+        mov    r15, r4
 
        .align 2
 1:     .long   MMU_TEA
+2:     .long   __do_page_fault
 3:     .long   do_page_fault
 
        .align  2
@@ -173,7 +186,7 @@ call_dae:
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
        /* Unwind the stack and jmp to the debug entry */
-debug_kernel_fw:
+ENTRY(sh_bios_handler)
        mov.l   @r15+, r0
        mov.l   @r15+, r1
        mov.l   @r15+, r2
@@ -332,175 +345,9 @@ general_exception:
 !
 !
 
-/* This code makes some assumptions to improve performance.
- * Make sure they are stil true. */
-#if PTRS_PER_PGD != PTRS_PER_PTE
-#error PGD and PTE sizes don't match
-#endif
-
-/* gas doesn't flag impossible values for mov #immediate as an error */
-#if (_PAGE_PRESENT >> 2) > 0x7f
-#error cannot load PAGE_PRESENT as an immediate
-#endif
-#if _PAGE_DIRTY > 0x7f
-#error cannot load PAGE_DIRTY as an immediate
-#endif
-#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
-#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
-#endif
-
-#if defined(CONFIG_CPU_SH4)
-#define ldmmupteh(r)   mov.l   8f, r
-#else
-#define ldmmupteh(r)   mov     #MMU_PTEH, r
-#endif
-
        .balign         1024,0,1024
 tlb_miss:
-#ifdef COUNT_EXCEPTIONS
-       ! Increment the counts
-       mov.l   9f, k1
-       mov.l   @k1, k2
-       add     #1, k2
-       mov.l   k2, @k1
-#endif
-
-       ! k0 scratch
-       ! k1 pgd and pte pointers
-       ! k2 faulting address
-       ! k3 pgd and pte index masks
-       ! k4 shift
-
-       ! Load up the pgd entry (k1)
-
-       ldmmupteh(k0)                   !  9 LS (latency=2)     MMU_PTEH
-
-       mov.w   4f, k3                  !  8 LS (latency=2)     (PTRS_PER_PGD-1) << 2
-       mov     #-(PGDIR_SHIFT-2), k4   !  6 EX
-
-       mov.l   @(MMU_TEA-MMU_PTEH,k0), k2      ! 18 LS (latency=2)
-
-       mov.l   @(MMU_TTB-MMU_PTEH,k0), k1      ! 18 LS (latency=2)
-
-       mov     k2, k0                  !   5 MT (latency=0)
-       shld    k4, k0                  !  99 EX
-
-       and     k3, k0                  !  78 EX
-
-       mov.l   @(k0, k1), k1           !  21 LS (latency=2)
-       mov     #-(PAGE_SHIFT-2), k4    !   6 EX
-
-       ! Load up the pte entry (k2)
-
-       mov     k2, k0                  !   5 MT (latency=0)
-       shld    k4, k0                  !  99 EX
-
-       tst     k1, k1                  !  86 MT
-
-       bt      20f                     ! 110 BR
-
-       and     k3, k0                  !  78 EX
-       mov.w   5f, k4                  !   8 LS (latency=2)    _PAGE_PRESENT
-
-       mov.l   @(k0, k1), k2           !  21 LS (latency=2)
-       add     k0, k1                  !  49 EX
-
-#ifdef CONFIG_CPU_HAS_PTEA
-       ! Test the entry for present and _PAGE_ACCESSED
-
-       mov     #-28, k3                !   6 EX
-       mov     k2, k0                  !   5 MT (latency=0)
-
-       tst     k4, k2                  !  68 MT
-       shld    k3, k0                  !  99 EX
-
-       bt      20f                     ! 110 BR
-
-       ! Set PTEA register
-       ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
-       !
-       ! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
-
-       and     #0xe, k0                !  79 EX
-
-       mov     k0, k3                  !   5 MT (latency=0)
-       mov     k2, k0                  !   5 MT (latency=0)
-
-       and     #1, k0                  !  79 EX
-
-       or      k0, k3                  !  82 EX
-
-       ldmmupteh(k0)                   !   9 LS (latency=2)
-       shll2   k4                      ! 101 EX                _PAGE_ACCESSED
-
-       tst     k4, k2                  !  68 MT
-
-       mov.l   k3, @(MMU_PTEA-MMU_PTEH,k0)     ! 27 LS
-
-       mov.l   7f, k3                  !   9 LS (latency=2)    _PAGE_FLAGS_HARDWARE_MASK
-
-       ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
-#else
-
-       ! Test the entry for present and _PAGE_ACCESSED
-
-       mov.l   7f, k3                  !   9 LS (latency=2)    _PAGE_FLAGS_HARDWARE_MASK
-       tst     k4, k2                  !  68 MT
-
-       shll2   k4                      ! 101 EX                _PAGE_ACCESSED
-       ldmmupteh(k0)                   !   9 LS (latency=2)
-
-       bt      20f                     ! 110 BR
-       tst     k4, k2                  !  68 MT
-
-       ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
-
-#endif
-
-       ! Set up the entry
-
-       and     k2, k3                  !  78 EX
-       bt/s    10f                     ! 108 BR
-
-        mov.l  k3, @(MMU_PTEL-MMU_PTEH,k0)     ! 27 LS
-
-       ldtlb                           ! 128 CO
-
-       ! At least one instruction between ldtlb and rte
-       nop                             ! 119 NOP
-
-       rte                             ! 126 CO
-
-        nop                            ! 119 NOP
-
-
-10:    or      k4, k2                  !  82 EX
-
-       ldtlb                           ! 128 CO
-
-       ! At least one instruction between ldtlb and rte
-       mov.l   k2, @k1                 !  27 LS
-
-       rte                             ! 126 CO
-
-       ! Note we cannot execute mov here, because it is executed after
-       ! restoring SSR, so would be executed in user space.
-        nop                            ! 119 NOP
-
-
-       .align 5
-       ! Once cache line if possible...
-1:     .long   swapper_pg_dir
-4:     .short  (PTRS_PER_PGD-1) << 2
-5:     .short  _PAGE_PRESENT
-7:     .long   _PAGE_FLAGS_HARDWARE_MASK
-8:     .long   MMU_PTEH
-#ifdef COUNT_EXCEPTIONS
-9:     .long   exception_count_miss
-#endif
-
-       ! Either pgd or pte not present
-20:    mov.l   1f, k2
+       mov.l   1f, k2
        mov.l   4f, k3
        bra     handle_exception
         mov.l  @k2, k2
@@ -651,15 +498,6 @@ skip_save:
        bf      interrupt_exception
        shlr2   r8
        shlr    r8
-
-#ifdef COUNT_EXCEPTIONS
-       mov.l   5f, r9
-       add     r8, r9
-       mov.l   @r9, r10
-       add     #1, r10
-       mov.l   r10, @r9
-#endif
-
        mov.l   4f, r9
        add     r8, r9
        mov.l   @r9, r9
@@ -673,9 +511,6 @@ skip_save:
 2:     .long   0x000080f0      ! FD=1, IMASK=15
 3:     .long   0xcfffffff      ! RB=0, BL=0
 4:     .long   exception_handling_table
-#ifdef COUNT_EXCEPTIONS
-5:     .long   exception_count_table
-#endif
 
 interrupt_exception:
        mov.l   1f, r9
index e67098836290ea9ff583991fe0a6e05c27876175..821b0ab7b528226f6d3244a914b8164d1ead4532 100644 (file)
@@ -50,41 +50,41 @@ int __init detect_cpu_and_cache_system(void)
 
        back_to_P1();
 
-       cpu_data->dcache.ways           = 4;
-       cpu_data->dcache.entry_shift    = 4;
-       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
-       cpu_data->dcache.flags          = 0;
+       current_cpu_data.dcache.ways            = 4;
+       current_cpu_data.dcache.entry_shift     = 4;
+       current_cpu_data.dcache.linesz          = L1_CACHE_BYTES;
+       current_cpu_data.dcache.flags           = 0;
 
        /*
         * 7709A/7729 has 16K cache (256-entry), while 7702 has only
         * 2K(direct) 7702 is not supported (yet)
         */
        if (data0 == data1 && data2 == data3) { /* Shadow */
-               cpu_data->dcache.way_incr       = (1 << 11);
-               cpu_data->dcache.entry_mask     = 0x7f0;
-               cpu_data->dcache.sets           = 128;
-               cpu_data->type = CPU_SH7708;
+               current_cpu_data.dcache.way_incr        = (1 << 11);
+               current_cpu_data.dcache.entry_mask      = 0x7f0;
+               current_cpu_data.dcache.sets            = 128;
+               current_cpu_data.type = CPU_SH7708;
 
-               cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC;
+               current_cpu_data.flags |= CPU_HAS_MMU_PAGE_ASSOC;
        } else {                                /* 7709A or 7729  */
-               cpu_data->dcache.way_incr       = (1 << 12);
-               cpu_data->dcache.entry_mask     = 0xff0;
-               cpu_data->dcache.sets           = 256;
-               cpu_data->type = CPU_SH7729;
+               current_cpu_data.dcache.way_incr        = (1 << 12);
+               current_cpu_data.dcache.entry_mask      = 0xff0;
+               current_cpu_data.dcache.sets            = 256;
+               current_cpu_data.type = CPU_SH7729;
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7706)
-               cpu_data->type = CPU_SH7706;
+               current_cpu_data.type = CPU_SH7706;
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7710)
-               cpu_data->type = CPU_SH7710;
+               current_cpu_data.type = CPU_SH7710;
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
-               cpu_data->type = CPU_SH7705;
+               current_cpu_data.type = CPU_SH7705;
 
 #if defined(CONFIG_SH7705_CACHE_32KB)
-               cpu_data->dcache.way_incr       = (1 << 13);
-               cpu_data->dcache.entry_mask     = 0x1ff0;
-               cpu_data->dcache.sets           = 512;
+               current_cpu_data.dcache.way_incr        = (1 << 13);
+               current_cpu_data.dcache.entry_mask      = 0x1ff0;
+               current_cpu_data.dcache.sets            = 512;
                ctrl_outl(CCR_CACHE_32KB, CCR3);
 #else
                ctrl_outl(CCR_CACHE_16KB, CCR3);
@@ -95,8 +95,8 @@ int __init detect_cpu_and_cache_system(void)
        /*
         * SH-3 doesn't have separate caches
         */
-       cpu_data->dcache.flags |= SH_CACHE_COMBINED;
-       cpu_data->icache = cpu_data->dcache;
+       current_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
+       current_cpu_data.icache = current_cpu_data.dcache;
 
        return 0;
 }
index ff43ef2a1f0c20cd644a88430835d8ff312a989b..dc9b211cf87f75dc00de23f3f99b3b30c23daae7 100644 (file)
@@ -51,3 +51,24 @@ static int __init sh7709_devices_setup(void)
                                    ARRAY_SIZE(sh7709_devices));
 }
 __initcall(sh7709_devices_setup);
+
+#define IPRx(A,N) .addr=A, .shift=0*N*-1
+#define IPRA(N)        IPRx(0xfffffee2UL,N)
+#define IPRB(N)        IPRx(0xfffffee4UL,N)
+#define IPRE(N)        IPRx(0xa400001aUL,N)
+
+static struct ipr_data sh7709_ipr_map[] = {
+       [16]            = { IPRA(15-12), 2 }, /* TMU TUNI0 */
+       [17]            = { IPRA(11-8),  4 }, /* TMU TUNI1 */
+       [22]            = { IPRA(3-0),   2 }, /* RTC CUI */
+       [23 ... 26]     = { IPRB(7-4),   3 }, /* SCI */
+       [27]            = { IPRB(15-12), 2 }, /* WDT ITI */
+       [48 ... 51]     = { IPRE(15-12), 7 }, /* DMA */
+       [52 ... 55]     = { IPRE(11-8),  3 }, /* IRDA */
+       [56 ... 59]     = { IPRE(7-4),   3 }, /* SCIF */
+};
+
+void __init init_IRQ_ipr()
+{
+       make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
+}
index 9031a22a2ce7878b03378c48c353b39866fbce5b..9d28c88d2f9de65f829c8cf96208c5ac0705067d 100644 (file)
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #include <linux/init.h>
+#include <linux/io.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include <asm/io.h>
 
 int __init detect_cpu_and_cache_system(void)
 {
@@ -36,20 +35,20 @@ int __init detect_cpu_and_cache_system(void)
        /*
         * Setup some sane SH-4 defaults for the icache
         */
-       cpu_data->icache.way_incr       = (1 << 13);
-       cpu_data->icache.entry_shift    = 5;
-       cpu_data->icache.sets           = 256;
-       cpu_data->icache.ways           = 1;
-       cpu_data->icache.linesz         = L1_CACHE_BYTES;
+       current_cpu_data.icache.way_incr        = (1 << 13);
+       current_cpu_data.icache.entry_shift     = 5;
+       current_cpu_data.icache.sets            = 256;
+       current_cpu_data.icache.ways            = 1;
+       current_cpu_data.icache.linesz          = L1_CACHE_BYTES;
 
        /*
         * And again for the dcache ..
         */
-       cpu_data->dcache.way_incr       = (1 << 14);
-       cpu_data->dcache.entry_shift    = 5;
-       cpu_data->dcache.sets           = 512;
-       cpu_data->dcache.ways           = 1;
-       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
+       current_cpu_data.dcache.way_incr        = (1 << 14);
+       current_cpu_data.dcache.entry_shift     = 5;
+       current_cpu_data.dcache.sets            = 512;
+       current_cpu_data.dcache.ways            = 1;
+       current_cpu_data.dcache.linesz          = L1_CACHE_BYTES;
 
        /*
         * Setup some generic flags we can probe
@@ -57,16 +56,16 @@ int __init detect_cpu_and_cache_system(void)
         */
        if (((pvr >> 16) & 0xff) == 0x10) {
                if ((cvr & 0x02000000) == 0)
-                       cpu_data->flags |= CPU_HAS_L2_CACHE;
+                       current_cpu_data.flags |= CPU_HAS_L2_CACHE;
                if ((cvr & 0x10000000) == 0)
-                       cpu_data->flags |= CPU_HAS_DSP;
+                       current_cpu_data.flags |= CPU_HAS_DSP;
 
-               cpu_data->flags |= CPU_HAS_LLSC;
+               current_cpu_data.flags |= CPU_HAS_LLSC;
        }
 
        /* FPU detection works for everyone */
        if ((cvr & 0x20000000) == 1)
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.flags |= CPU_HAS_FPU;
 
        /* Mask off the upper chip ID */
        pvr &= 0xffff;
@@ -77,151 +76,151 @@ int __init detect_cpu_and_cache_system(void)
         */
        switch (pvr) {
        case 0x205:
-               cpu_data->type = CPU_SH7750;
-               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+               current_cpu_data.type = CPU_SH7750;
+               current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
                                   CPU_HAS_PERF_COUNTER;
                break;
        case 0x206:
-               cpu_data->type = CPU_SH7750S;
-               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+               current_cpu_data.type = CPU_SH7750S;
+               current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
                                   CPU_HAS_PERF_COUNTER;
                break;
        case 0x1100:
-               cpu_data->type = CPU_SH7751;
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.type = CPU_SH7751;
+               current_cpu_data.flags |= CPU_HAS_FPU;
                break;
        case 0x2000:
-               cpu_data->type = CPU_SH73180;
-               cpu_data->icache.ways = 4;
-               cpu_data->dcache.ways = 4;
-               cpu_data->flags |= CPU_HAS_LLSC;
+               current_cpu_data.type = CPU_SH73180;
+               current_cpu_data.icache.ways = 4;
+               current_cpu_data.dcache.ways = 4;
+               current_cpu_data.flags |= CPU_HAS_LLSC;
                break;
        case 0x2001:
        case 0x2004:
-               cpu_data->type = CPU_SH7770;
-               cpu_data->icache.ways = 4;
-               cpu_data->dcache.ways = 4;
+               current_cpu_data.type = CPU_SH7770;
+               current_cpu_data.icache.ways = 4;
+               current_cpu_data.dcache.ways = 4;
 
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
+               current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
                break;
        case 0x2006:
        case 0x200A:
                if (prr == 0x61)
-                       cpu_data->type = CPU_SH7781;
+                       current_cpu_data.type = CPU_SH7781;
                else
-                       cpu_data->type = CPU_SH7780;
+                       current_cpu_data.type = CPU_SH7780;
 
-               cpu_data->icache.ways = 4;
-               cpu_data->dcache.ways = 4;
+               current_cpu_data.icache.ways = 4;
+               current_cpu_data.dcache.ways = 4;
 
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+               current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
                                   CPU_HAS_LLSC;
                break;
        case 0x3000:
        case 0x3003:
        case 0x3009:
-               cpu_data->type = CPU_SH7343;
-               cpu_data->icache.ways = 4;
-               cpu_data->dcache.ways = 4;
-               cpu_data->flags |= CPU_HAS_LLSC;
+               current_cpu_data.type = CPU_SH7343;
+               current_cpu_data.icache.ways = 4;
+               current_cpu_data.dcache.ways = 4;
+               current_cpu_data.flags |= CPU_HAS_LLSC;
                break;
        case 0x3008:
                if (prr == 0xa0) {
-                       cpu_data->type = CPU_SH7722;
-                       cpu_data->icache.ways = 4;
-                       cpu_data->dcache.ways = 4;
-                       cpu_data->flags |= CPU_HAS_LLSC;
+                       current_cpu_data.type = CPU_SH7722;
+                       current_cpu_data.icache.ways = 4;
+                       current_cpu_data.dcache.ways = 4;
+                       current_cpu_data.flags |= CPU_HAS_LLSC;
                }
                break;
        case 0x8000:
-               cpu_data->type = CPU_ST40RA;
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.type = CPU_ST40RA;
+               current_cpu_data.flags |= CPU_HAS_FPU;
                break;
        case 0x8100:
-               cpu_data->type = CPU_ST40GX1;
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.type = CPU_ST40GX1;
+               current_cpu_data.flags |= CPU_HAS_FPU;
                break;
        case 0x700:
-               cpu_data->type = CPU_SH4_501;
-               cpu_data->icache.ways = 2;
-               cpu_data->dcache.ways = 2;
+               current_cpu_data.type = CPU_SH4_501;
+               current_cpu_data.icache.ways = 2;
+               current_cpu_data.dcache.ways = 2;
                break;
        case 0x600:
-               cpu_data->type = CPU_SH4_202;
-               cpu_data->icache.ways = 2;
-               cpu_data->dcache.ways = 2;
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.type = CPU_SH4_202;
+               current_cpu_data.icache.ways = 2;
+               current_cpu_data.dcache.ways = 2;
+               current_cpu_data.flags |= CPU_HAS_FPU;
                break;
        case 0x500 ... 0x501:
                switch (prr) {
                case 0x10:
-                       cpu_data->type = CPU_SH7750R;
+                       current_cpu_data.type = CPU_SH7750R;
                        break;
                case 0x11:
-                       cpu_data->type = CPU_SH7751R;
+                       current_cpu_data.type = CPU_SH7751R;
                        break;
                case 0x50 ... 0x5f:
-                       cpu_data->type = CPU_SH7760;
+                       current_cpu_data.type = CPU_SH7760;
                        break;
                }
 
-               cpu_data->icache.ways = 2;
-               cpu_data->dcache.ways = 2;
+               current_cpu_data.icache.ways = 2;
+               current_cpu_data.dcache.ways = 2;
 
-               cpu_data->flags |= CPU_HAS_FPU;
+               current_cpu_data.flags |= CPU_HAS_FPU;
 
                break;
        default:
-               cpu_data->type = CPU_SH_NONE;
+               current_cpu_data.type = CPU_SH_NONE;
                break;
        }
 
 #ifdef CONFIG_SH_DIRECT_MAPPED
-       cpu_data->icache.ways = 1;
-       cpu_data->dcache.ways = 1;
+       current_cpu_data.icache.ways = 1;
+       current_cpu_data.dcache.ways = 1;
 #endif
 
 #ifdef CONFIG_CPU_HAS_PTEA
-       cpu_data->flags |= CPU_HAS_PTEA;
+       current_cpu_data.flags |= CPU_HAS_PTEA;
 #endif
 
        /*
         * On anything that's not a direct-mapped cache, look to the CVR
         * for I/D-cache specifics.
         */
-       if (cpu_data->icache.ways > 1) {
+       if (current_cpu_data.icache.ways > 1) {
                size = sizes[(cvr >> 20) & 0xf];
-               cpu_data->icache.way_incr       = (size >> 1);
-               cpu_data->icache.sets           = (size >> 6);
+               current_cpu_data.icache.way_incr        = (size >> 1);
+               current_cpu_data.icache.sets            = (size >> 6);
 
        }
 
        /* Setup the rest of the I-cache info */
-       cpu_data->icache.entry_mask = cpu_data->icache.way_incr -
-                                     cpu_data->icache.linesz;
+       current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr -
+                                     current_cpu_data.icache.linesz;
 
-       cpu_data->icache.way_size = cpu_data->icache.sets *
-                                   cpu_data->icache.linesz;
+       current_cpu_data.icache.way_size = current_cpu_data.icache.sets *
+                                   current_cpu_data.icache.linesz;
 
        /* And the rest of the D-cache */
-       if (cpu_data->dcache.ways > 1) {
+       if (current_cpu_data.dcache.ways > 1) {
                size = sizes[(cvr >> 16) & 0xf];
-               cpu_data->dcache.way_incr       = (size >> 1);
-               cpu_data->dcache.sets           = (size >> 6);
+               current_cpu_data.dcache.way_incr        = (size >> 1);
+               current_cpu_data.dcache.sets            = (size >> 6);
        }
 
-       cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr -
-                                     cpu_data->dcache.linesz;
+       current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr -
+                                     current_cpu_data.dcache.linesz;
 
-       cpu_data->dcache.way_size = cpu_data->dcache.sets *
-                                   cpu_data->dcache.linesz;
+       current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
+                                   current_cpu_data.dcache.linesz;
 
        /*
         * Setup the L2 cache desc
         *
         * SH-4A's have an optional PIPT L2.
         */
-       if (cpu_data->flags & CPU_HAS_L2_CACHE) {
+       if (current_cpu_data.flags & CPU_HAS_L2_CACHE) {
                /*
                 * Size calculation is much more sensible
                 * than it is for the L1.
@@ -232,16 +231,22 @@ int __init detect_cpu_and_cache_system(void)
 
                BUG_ON(!size);
 
-               cpu_data->scache.way_incr       = (1 << 16);
-               cpu_data->scache.entry_shift    = 5;
-               cpu_data->scache.ways           = 4;
-               cpu_data->scache.linesz         = L1_CACHE_BYTES;
-               cpu_data->scache.entry_mask     =
-                       (cpu_data->scache.way_incr - cpu_data->scache.linesz);
-               cpu_data->scache.sets           = size /
-                       (cpu_data->scache.linesz * cpu_data->scache.ways);
-               cpu_data->scache.way_size       =
-                       (cpu_data->scache.sets * cpu_data->scache.linesz);
+               current_cpu_data.scache.way_incr        = (1 << 16);
+               current_cpu_data.scache.entry_shift     = 5;
+               current_cpu_data.scache.ways            = 4;
+               current_cpu_data.scache.linesz          = L1_CACHE_BYTES;
+
+               current_cpu_data.scache.entry_mask      =
+                       (current_cpu_data.scache.way_incr -
+                        current_cpu_data.scache.linesz);
+
+               current_cpu_data.scache.sets            = size /
+                       (current_cpu_data.scache.linesz *
+                        current_cpu_data.scache.ways);
+
+               current_cpu_data.scache.way_size        =
+                       (current_cpu_data.scache.sets *
+                        current_cpu_data.scache.linesz);
        }
 
        return 0;
index cbac27634c0b23441409c7835dcb9a914bf2706c..6f8f458912c7c5759844f94023e5c896640303ba 100644 (file)
@@ -46,11 +46,13 @@ static struct platform_device rtc_device = {
 
 static struct plat_sci_port sci_platform_data[] = {
        {
+#ifndef CONFIG_SH_RTS7751R2D
                .mapbase        = 0xffe00000,
                .flags          = UPF_BOOT_AUTOCONF,
                .type           = PORT_SCI,
                .irqs           = { 23, 24, 25, 0 },
        }, {
+#endif
                .mapbase        = 0xffe80000,
                .flags          = UPF_BOOT_AUTOCONF,
                .type           = PORT_SCIF,
@@ -101,7 +103,7 @@ static struct ipr_data sh7750_ipr_map[] = {
        { 35, 2,  8, 7 }, /* DMAC DMTE1 */
        { 36, 2,  8, 7 }, /* DMAC DMTE2 */
        { 37, 2,  8, 7 }, /* DMAC DMTE3 */
-       { 28, 2,  8, 7 }, /* DMAC DMAE */
+       { 38, 2,  8, 7 }, /* DMAC DMAE */
 };
 
 static struct ipr_data sh7751_ipr_map[] = {
index 07e5377bf55016edfb299b52a9a0e2896db386df..b7c702821e6fed19ef060e0e2469ec7619246c71 100644 (file)
@@ -52,17 +52,11 @@ static int __init sh7760_devices_setup(void)
 }
 __initcall(sh7760_devices_setup);
 
-/*
- * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
- */
 static struct intc2_data intc2_irq_table[] = {
-       /* INTPRIO0 | INTMSK0 */
        {48,  0, 28, 0, 31,  3},        /* IRQ 4 */
        {49,  0, 24, 0, 30,  3},        /* IRQ 3 */
        {50,  0, 20, 0, 29,  3},        /* IRQ 2 */
        {51,  0, 16, 0, 28,  3},        /* IRQ 1 */
-       /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
-       /* INTPRIO4 | INTMSK0 */
        {56,  4, 28, 0, 25,  3},        /* HCAN2_CHAN0 */
        {57,  4, 24, 0, 24,  3},        /* HCAN2_CHAN1 */
        {58,  4, 20, 0, 23,  3},        /* I2S_CHAN0   */
@@ -71,18 +65,15 @@ static struct intc2_data intc2_irq_table[] = {
        {61,  4,  8, 0, 20,  3},        /* AC97_CHAN1  */
        {62,  4,  4, 0, 19,  3},        /* I2C_CHAN0   */
        {63,  4,  0, 0, 18,  3},        /* I2C_CHAN1   */
-       /* INTPRIO8 | INTMSK0 */
        {52,  8, 16, 0, 11,  3},        /* SCIF0_ERI_IRQ */
        {53,  8, 16, 0, 10,  3},        /* SCIF0_RXI_IRQ */
        {54,  8, 16, 0,  9,  3},        /* SCIF0_BRI_IRQ */
        {55,  8, 16, 0,  8,  3},        /* SCIF0_TXI_IRQ */
        {64,  8, 28, 0, 17,  3},        /* USBHI_IRQ */
        {65,  8, 24, 0, 16,  3},        /* LCDC      */
-       /* 66, 67 unused */
        {68,  8, 20, 0, 14, 13},        /* DMABRGI0_IRQ */
        {69,  8, 20, 0, 13, 13},        /* DMABRGI1_IRQ */
        {70,  8, 20, 0, 12, 13},        /* DMABRGI2_IRQ */
-       /* 71 unused */
        {72,  8, 12, 0,  7,  3},        /* SCIF1_ERI_IRQ */
        {73,  8, 12, 0,  6,  3},        /* SCIF1_RXI_IRQ */
        {74,  8, 12, 0,  5,  3},        /* SCIF1_BRI_IRQ */
@@ -91,26 +82,71 @@ static struct intc2_data intc2_irq_table[] = {
        {77,  8,  8, 0,  2,  3},        /* SCIF2_RXI_IRQ */
        {78,  8,  8, 0,  1,  3},        /* SCIF2_BRI_IRQ */
        {79,  8,  8, 0,  0,  3},        /* SCIF2_TXI_IRQ */
-       /*          | INTMSK4 */
        {80,  8,  4, 4, 23,  3},        /* SIM_ERI */
        {81,  8,  4, 4, 22,  3},        /* SIM_RXI */
        {82,  8,  4, 4, 21,  3},        /* SIM_TXI */
        {83,  8,  4, 4, 20,  3},        /* SIM_TEI */
        {84,  8,  0, 4, 19,  3},        /* HSPII */
-       /* INTPRIOC | INTMSK4 */
-       /* 85-87 unused/reserved */
        {88, 12, 20, 4, 18,  3},        /* MMCI0 */
        {89, 12, 20, 4, 17,  3},        /* MMCI1 */
        {90, 12, 20, 4, 16,  3},        /* MMCI2 */
        {91, 12, 20, 4, 15,  3},        /* MMCI3 */
-       {92, 12, 12, 4,  6,  3},        /* MFI (unsure, bug? in my 7760 manual*/
-       /* 93-107 reserved/undocumented */
+       {92, 12, 12, 4,  6,  3},        /* MFI */
        {108,12,  4, 4,  1,  3},        /* ADC  */
        {109,12,  0, 4,  0,  3},        /* CMTI */
-       /* 110-111 reserved/unused */
 };
 
+static struct ipr_data sh7760_ipr_map[] = {
+       /* IRQ, IPR-idx, shift, priority */
+       { 16, 0, 12, 2 }, /* TMU0 TUNI*/
+       { 17, 0,  8, 2 }, /* TMU1 TUNI */
+       { 18, 0,  4, 2 }, /* TMU2 TUNI */
+       { 19, 0,  4, 2 }, /* TMU2 TIPCI */
+       { 27, 1, 12, 2 }, /* WDT ITI */
+       { 28, 1,  8, 2 }, /* REF RCMI */
+       { 29, 1,  8, 2 }, /* REF ROVI */
+       { 32, 2,  0, 7 }, /* HUDI */
+       { 33, 2, 12, 7 }, /* GPIOI */
+       { 34, 2,  8, 7 }, /* DMAC DMTE0 */
+       { 35, 2,  8, 7 }, /* DMAC DMTE1 */
+       { 36, 2,  8, 7 }, /* DMAC DMTE2 */
+       { 37, 2,  8, 7 }, /* DMAC DMTE3 */
+       { 38, 2,  8, 7 }, /* DMAC DMAE */
+       { 44, 2,  8, 7 }, /* DMAC DMTE4 */
+       { 45, 2,  8, 7 }, /* DMAC DMTE5 */
+       { 46, 2,  8, 7 }, /* DMAC DMTE6 */
+       { 47, 2,  8, 7 }, /* DMAC DMTE7 */
+/* these here are only valid if INTC_ICR bit 7 is set to 1!
+ * XXX: maybe CONFIG_SH_IRLMODE symbol? SH7751 could use it too */
+#if 0
+       {  2, 3, 12, 3 }, /* IRL0 */
+       {  5, 3,  8, 3 }, /* IRL1 */
+       {  8, 3,  4, 3 }, /* IRL2 */
+       { 11, 3,  0, 3 }, /* IRL3 */
+#endif
+};
+
+static unsigned long ipr_offsets[] = {
+       0xffd00004UL,   /* 0: IPRA */
+       0xffd00008UL,   /* 1: IPRB */
+       0xffd0000cUL,   /* 2: IPRC */
+       0xffd00010UL,   /* 3: IPRD */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (idx >= ARRAY_SIZE(ipr_offsets))
+               return 0;
+       return ipr_offsets[idx];
+}
+
 void __init init_IRQ_intc2(void)
 {
        make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
 }
+
+void __init  init_IRQ_ipr(void)
+{
+       make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
+}
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S
new file mode 100644 (file)
index 0000000..13b6674
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/kernel/debugtraps.S
+ *
+ * Debug trap jump tables for SuperH
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+#if !defined(CONFIG_SH_KGDB)
+#define kgdb_handle_exception  debug_trap_handler
+#endif
+
+#if !defined(CONFIG_SH_STANDARD_BIOS)
+#define sh_bios_handler                debug_trap_handler
+#endif
+
+       .data
+
+ENTRY(debug_trap_table)
+       .long debug_trap_handler        /* 0x30 */
+       .long debug_trap_handler        /* 0x31 */
+       .long debug_trap_handler        /* 0x32 */
+       .long debug_trap_handler        /* 0x33 */
+       .long debug_trap_handler        /* 0x34 */
+       .long debug_trap_handler        /* 0x35 */
+       .long debug_trap_handler        /* 0x36 */
+       .long debug_trap_handler        /* 0x37 */
+       .long debug_trap_handler        /* 0x38 */
+       .long debug_trap_handler        /* 0x39 */
+       .long debug_trap_handler        /* 0x3a */
+       .long debug_trap_handler        /* 0x3b */
+       .long kgdb_handle_exception     /* 0x3c */
+       .long debug_trap_handler        /* 0x3d */
+       .long bug_trap_handler          /* 0x3e */
+       .long sh_bios_handler           /* 0x3f */
index 560b91cdd15ced07aef986db027f9b3ad6daf1fa..9048c0326d879452cee49cfbccec42d4812aae26 100644 (file)
@@ -106,12 +106,32 @@ static struct console scif_console = {
 };
 
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
+#define DEFAULT_BAUD 115200
 /*
  * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
  * devices that aren't using sh-ipl+g.
  */
-static void scif_sercon_init(int baud)
+static void scif_sercon_init(char *s)
 {
+       unsigned baud = DEFAULT_BAUD;
+       char *e;
+
+       if (*s == ',')
+               ++s;
+
+       if (*s) {
+               /* ignore ioport/device name */
+               s += strcspn(s, ",");
+               if (*s == ',')
+                       s++;
+       }
+
+       if (*s) {
+               baud = simple_strtoul(s, &e, 0);
+               if (baud == 0 || s == e)
+                       baud = DEFAULT_BAUD;
+       }
+
        ctrl_outw(0, scif_port.mapbase + 8);
        ctrl_outw(0, scif_port.mapbase);
 
@@ -167,7 +187,7 @@ int __init setup_early_printk(char *buf)
                early_console = &scif_console;
 
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
-               scif_sercon_init(115200);
+               scif_sercon_init(buf + 6);
 #endif
        }
 #endif
index fc279aeb73ab946c83106be747659f1d2fb04e48..ab4ebb856c2a3cc7ca9f2e75ceb94c32ebdc1c22 100644 (file)
 #  define resume_kernel                __restore_all
 #endif
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
-! If both are configured, handle the debug traps (breakpoints) in SW,
-! but still allow BIOS traps to FW.
-
-       .align  2
-debug_kernel:
-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
-       /* Force BIOS call to FW (debug_trap put TRA in r8) */
-       mov     r8,r0
-       shlr2   r0
-       cmp/eq  #0x3f,r0
-       bt      debug_kernel_fw
-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
-
-debug_enter:           
-#if defined(CONFIG_SH_KGDB)
-       /* Jump to kgdb, pass stacked regs as arg */
-debug_kernel_sw:
-       mov.l   3f, r0
-       jmp     @r0
-        mov    r15, r4
-       .align  2
-3:     .long   kgdb_handle_exception
-#endif /* CONFIG_SH_KGDB */
-#ifdef CONFIG_SH_STANDARD_BIOS
-       bra     debug_kernel_fw
-        nop
-#endif
-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-
-       .align  2
-debug_trap:    
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-       mov     r8, r0
-       shlr2   r0
-       cmp/eq  #0x3f, r0               ! sh_bios() trap
-       bf      1f
-#ifdef CONFIG_SH_KGDB
-       cmp/eq  #0xff, r0               ! XXX: KGDB trap, fix for SH-2.
-       bf      1f
-#endif
-       mov     #OFF_SR, r0
-       mov.l   @(r0,r15), r0           ! get status register
-       shll    r0
-       shll    r0                      ! kernel space?
-       bt/s    debug_kernel
-1:
-#endif
-        mov.l  @r15, r0                ! Restore R0 value
-       mov.l   1f, r8
-       jmp     @r8
-        nop
 
        .align  2
 ENTRY(exception_error)
        !
 #ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   3f, r0
+       mov.l   2f, r0
        jsr     @r0
         nop
 #endif
        sti
-       mov.l   2f, r0
+       mov.l   1f, r0
        jmp     @r0
         nop
 
-!
        .align  2
-1:     .long   break_point_trap_software
-2:     .long   do_exception_error
+1:     .long   do_exception_error
 #ifdef CONFIG_TRACE_IRQFLAGS
-3:     .long   trace_hardirqs_on
+2:     .long   trace_hardirqs_on
 #endif
 
        .align  2
@@ -330,17 +275,32 @@ __restore_all:
        .align  2
 1:     .long   restore_all
 
-       .align  2
-not_syscall_tra:       
-       bra     debug_trap
-        nop
-
        .align  2
 syscall_badsys:                        ! Bad syscall number
        mov     #-ENOSYS, r0
        bra     resume_userspace
         mov.l  r0, @(OFF_R0,r15)       ! Return value
-       
+
+/*
+ * The main debug trap handler.
+ *
+ * r8=TRA (not the trap number!)
+ *
+ * Note: This assumes that the trapa value is left in its original
+ * form (without the shlr2 shift) so the calculation for the jump
+ * call table offset remains a simple in place mask.
+ */
+debug_trap:
+       mov     r8, r0
+       and     #(0xf << 2), r0
+       mov.l   1f, r8
+       add     r0, r8
+       mov.l   @r8, r8
+       jmp     @r8
+        nop
+
+       .align  2
+1:     .long   debug_trap_table
 
 /*
  * Syscall interface:
@@ -348,17 +308,19 @@ syscall_badsys:                   ! Bad syscall number
  *     Syscall #: R3
  *     Arguments #0 to #3: R4--R7
  *     Arguments #4 to #6: R0, R1, R2
- *     TRA: (number of arguments + 0x10) x 4
+ *     TRA: (number of arguments + ABI revision) x 4
  *
  * This code also handles delegating other traps to the BIOS/gdb stub
  * according to:
  *
  * Trap number
- * (TRA>>2)        Purpose
- * --------        -------
- * 0x0-0xf         old syscall ABI
- * 0x10-0x1f       new syscall ABI
- * 0x20-0xff       delegated through debug_trap to BIOS/gdb stub.
+ * (TRA>>2)    Purpose
+ * --------    -------
+ * 0x00-0x0f   original SH-3/4 syscall ABI (not in general use).
+ * 0x10-0x1f   general SH-3/4 syscall ABI.
+ * 0x20-0x2f   syscall ABI for SH-2 parts.
+ * 0x30-0x3f   debug traps used by the kernel.
+ * 0x40-0xff   Not supported by all parts, so left unhandled.
  *
  * Note: When we're first called, the TRA value must be shifted
  * right 2 bits in order to get the value that was used as the "trapa"
@@ -375,17 +337,22 @@ ret_from_fork:
         nop
        .align  2
 1:     .long   schedule_tail
-       !
+
+/*
+ * The poorly named main trapa decode and dispatch routine, for
+ * system calls and debug traps through their respective jump tables.
+ */
 ENTRY(system_call)
 #if !defined(CONFIG_CPU_SH2)
        mov.l   1f, r9
        mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
 #endif
-       !
-       ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-       mov     #0x7f, r9
+       /*
+        * Check the trap type
+        */
+       mov     #((0x20 << 2) - 1), r9
        cmp/hi  r9, r8
-       bt/s    not_syscall_tra
+       bt/s    debug_trap              ! it's a debug trap..
         mov    #OFF_TRA, r9
        add     r15, r9
        mov.l   r8, @r9                 ! set TRA value to tra
index 28ec7487de8ce2461e035964d20805a9f8f9c2ee..66626c03e1eeb4b8e72f09871f6e83f1daa1b1c5 100644 (file)
@@ -1,9 +1,8 @@
-/* $Id: io_generic.c,v 1.2 2003/05/04 19:29:53 lethal Exp $
- *
- * linux/arch/sh/kernel/io_generic.c
+/*
+ * arch/sh/kernel/io_generic.c
  *
  * Copyright (C) 2000  Niibe Yutaka
- * Copyright (C) 2005  Paul Mundt
+ * Copyright (C) 2005 - 2007 Paul Mundt
  *
  * Generic I/O routine. These can be used where a machine specific version
  * is not required.
@@ -13,8 +12,9 @@
  * for more details.
  */
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/machvec.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_CPU_SH3
 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
@@ -96,6 +96,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count)
        while (count--)
                *buf++ = *port_addr;
 
+       flush_dcache_all();
        dummy_read();
 }
 
@@ -170,6 +171,7 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count)
        while (count--)
                *port_addr = *buf++;
 
+       flush_dcache_all();
        dummy_read();
 }
 
index 9c6315f0335dfdc45bac2f8aa47a3fc9fa0adb11..d8927d85492e389d84cb954e6b150714e15d6938 100644 (file)
@@ -1323,8 +1323,11 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
 }
 
 /* There has been an exception, most likely a breakpoint. */
-void kgdb_handle_exception(struct pt_regs *regs)
+asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
+                                     unsigned long r6, unsigned long r7,
+                                     struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int excep_code, vbr_val;
        int count;
        int trapa_value = ctrl_inl(TRA);
@@ -1368,8 +1371,6 @@ void kgdb_handle_exception(struct pt_regs *regs)
 
        vbr_val = trap_registers.vbr;
        asm("ldc %0, vbr": :"r"(vbr_val));
-
-       return;
 }
 
 /* Trigger a breakpoint by function */
index 486c06e180333404baf796be54b796b110d7f448..9d6a438b3eaf7a8e7692e69eab757886c9ee952d 100644 (file)
@@ -1,42 +1,30 @@
-/* $Id: process.c,v 1.28 2004/05/05 16:54:23 lethal Exp $
+/*
+ * arch/sh/kernel/process.c
  *
- *  linux/arch/sh/kernel/process.c
+ * This file handles the architecture-dependent parts of process handling..
  *
  *  Copyright (C) 1995  Linus Torvalds
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *                  Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
+ *                  Copyright (C) 2002 - 2006  Paul Mundt
  */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
 #include <linux/module.h>
-#include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
-#include <linux/a.out.h>
-#include <linux/slab.h>
 #include <linux/pm.h>
-#include <linux/ptrace.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/elf.h>
 #include <asm/ubc.h>
 
-static int hlt_counter=0;
-
+static int hlt_counter;
 int ubc_usercnt = 0;
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
 void (*pm_idle)(void);
-
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
@@ -44,14 +32,12 @@ void disable_hlt(void)
 {
        hlt_counter++;
 }
-
 EXPORT_SYMBOL(disable_hlt);
 
 void enable_hlt(void)
 {
        hlt_counter--;
 }
-
 EXPORT_SYMBOL(enable_hlt);
 
 void default_idle(void)
@@ -152,19 +138,21 @@ __asm__(".align 5\n"
        ".align 2\n\t"
        "1:.long do_exit");
 
+/* Don't use this in BL=1(cli).  Or else, CPU resets! */
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{      /* Don't use this in BL=1(cli).  Or else, CPU resets! */
+{
        struct pt_regs regs;
 
        memset(&regs, 0, sizeof(regs));
-       regs.regs[4] = (unsigned long) arg;
-       regs.regs[5] = (unsigned long) fn;
+       regs.regs[4] = (unsigned long)arg;
+       regs.regs[5] = (unsigned long)fn;
 
-       regs.pc = (unsigned long) kernel_thread_helper;
+       regs.pc = (unsigned long)kernel_thread_helper;
        regs.sr = (1 << 30);
 
        /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+                      &regs, 0, NULL, NULL);
 }
 
 /*
@@ -211,21 +199,20 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
        return fpvalid;
 }
 
-/* 
+/*
  * Capture the user space registers if the task is not running (in user space)
  */
 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 {
        struct pt_regs ptregs;
-       
+
        ptregs = *task_pt_regs(tsk);
        elf_core_copy_regs(regs, &ptregs);
 
        return 1;
 }
 
-int
-dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
+int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu)
 {
        int fpvalid = 0;
 
@@ -263,12 +250,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                childregs->regs[15] = usp;
                ti->addr_limit = USER_DS;
        } else {
-               childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+               childregs->regs[15] = (unsigned long)task_stack_page(p) +
+                                                       THREAD_SIZE;
                ti->addr_limit = KERNEL_DS;
        }
-        if (clone_flags & CLONE_SETTLS) {
+
+        if (clone_flags & CLONE_SETTLS)
                childregs->gbr = childregs->regs[0];
-       }
+
        childregs->regs[0] = 0; /* Set return value for child */
 
        p->thread.sp = (unsigned long) childregs;
@@ -280,8 +269,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 }
 
 /* Tracing by user break controller.  */
-static void
-ubc_set_tracing(int asid, unsigned long pc)
+static void ubc_set_tracing(int asid, unsigned long pc)
 {
 #if defined(CONFIG_CPU_SH4A)
        unsigned long val;
@@ -297,7 +285,7 @@ ubc_set_tracing(int asid, unsigned long pc)
        val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
        ctrl_outl(val, UBC_CRR0);
 
-       /* Read UBC register that we writed last. For chekking UBC Register changed */
+       /* Read UBC register that we wrote last, for checking update */
        val = ctrl_inl(UBC_CRR0);
 
 #else  /* CONFIG_CPU_SH4A */
@@ -305,13 +293,14 @@ ubc_set_tracing(int asid, unsigned long pc)
 
 #ifdef CONFIG_MMU
        /* We don't have any ASID settings for the SH-2! */
-       if (cpu_data->type != CPU_SH7604)
+       if (current_cpu_data.type != CPU_SH7604)
                ctrl_outb(asid, UBC_BASRA);
 #endif
 
        ctrl_outl(0, UBC_BAMRA);
 
-       if (cpu_data->type == CPU_SH7729 || cpu_data->type == CPU_SH7710) {
+       if (current_cpu_data.type == CPU_SH7729 ||
+           current_cpu_data.type == CPU_SH7710) {
                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
        } else {
@@ -325,7 +314,8 @@ ubc_set_tracing(int asid, unsigned long pc)
  *     switch_to(x,y) should switch tasks from x to y.
  *
  */
-struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)
+struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next)
 {
 #if defined(CONFIG_SH_FPU)
        unlazy_fpu(prev, task_pt_regs(prev));
@@ -354,7 +344,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
 #ifdef CONFIG_MMU
        /*
         * Restore the kernel mode register
-        *      k7 (r7_bank1)
+        *      k7 (r7_bank1)
         */
        asm volatile("ldc       %0, r7_bank"
                     : /* no output */
@@ -367,7 +357,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
        else if (next->thread.ubc_pc && next->mm) {
                int asid = 0;
 #ifdef CONFIG_MMU
-               asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;
+               asid |= cpu_asid(smp_processor_id(), next->mm);
 #endif
                ubc_set_tracing(asid, next->thread.ubc_pc);
        } else {
@@ -405,7 +395,8 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
        if (!newsp)
                newsp = regs->regs[15];
        return do_fork(clone_flags, newsp, regs, 0,
-                       (int __user *)parent_tidptr, (int __user *)child_tidptr);
+                       (int __user *)parent_tidptr,
+                       (int __user *)child_tidptr);
 }
 
 /*
@@ -493,9 +484,27 @@ asmlinkage void break_point_trap(void)
        force_sig(SIGTRAP, current);
 }
 
-asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
-                                         unsigned long r6, unsigned long r7,
-                                         struct pt_regs __regs)
+/*
+ * Generic trap handler.
+ */
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+                                  unsigned long r6, unsigned long r7,
+                                  struct pt_regs __regs)
+{
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+
+       /* Rewind */
+       regs->pc -= 2;
+
+       force_sig(SIGTRAP, current);
+}
+
+/*
+ * Special handler for BUG() traps.
+ */
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+                                unsigned long r6, unsigned long r7,
+                                struct pt_regs __regs)
 {
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
index d6b817aa568fae84d1c63c0181c2407d7164ee30..98802ab282114239f0d3d4cc401ace5dcd27cbcf 100644 (file)
@@ -1,14 +1,11 @@
 /*
- *  linux/arch/sh/kernel/setup.c
+ * arch/sh/kernel/setup.c
  *
- *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002, 2003  Paul Mundt
- */
-
-/*
  * This file handles the architecture-dependent parts of initialization
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2002 - 2006 Paul Mundt
  */
-
 #include <linux/screen_info.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
@@ -395,9 +392,9 @@ static const char *cpu_name[] = {
        [CPU_SH_NONE]   = "Unknown"
 };
 
-const char *get_cpu_subtype(void)
+const char *get_cpu_subtype(struct sh_cpuinfo *c)
 {
-       return cpu_name[boot_cpu_data.type];
+       return cpu_name[c->type];
 }
 
 #ifdef CONFIG_PROC_FS
@@ -407,19 +404,19 @@ static const char *cpu_flags[] = {
        "ptea", "llsc", "l2", NULL
 };
 
-static void show_cpuflags(struct seq_file *m)
+static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
 {
        unsigned long i;
 
        seq_printf(m, "cpu flags\t:");
 
-       if (!cpu_data->flags) {
+       if (!c->flags) {
                seq_printf(m, " %s\n", cpu_flags[0]);
                return;
        }
 
        for (i = 0; cpu_flags[i]; i++)
-               if ((cpu_data->flags & (1 << i)))
+               if ((c->flags & (1 << i)))
                        seq_printf(m, " %s", cpu_flags[i+1]);
 
        seq_printf(m, "\n");
@@ -441,16 +438,20 @@ static void show_cacheinfo(struct seq_file *m, const char *type,
  */
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-       unsigned int cpu = smp_processor_id();
+       struct sh_cpuinfo *c = v;
+       unsigned int cpu = c - cpu_data;
+
+       if (!cpu_online(cpu))
+               return 0;
 
-       if (!cpu && cpu_online(cpu))
+       if (cpu == 0)
                seq_printf(m, "machine\t\t: %s\n", get_system_type());
 
        seq_printf(m, "processor\t: %d\n", cpu);
        seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
-       seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype());
+       seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
 
-       show_cpuflags(m);
+       show_cpuflags(m, c);
 
        seq_printf(m, "cache type\t: ");
 
@@ -459,22 +460,22 @@ static int show_cpuinfo(struct seq_file *m, void *v)
         * unified cache on the SH-2 and SH-3, as well as the harvard
         * style cache on the SH-4.
         */
-       if (boot_cpu_data.icache.flags & SH_CACHE_COMBINED) {
+       if (c->icache.flags & SH_CACHE_COMBINED) {
                seq_printf(m, "unified\n");
-               show_cacheinfo(m, "cache", boot_cpu_data.icache);
+               show_cacheinfo(m, "cache", c->icache);
        } else {
                seq_printf(m, "split (harvard)\n");
-               show_cacheinfo(m, "icache", boot_cpu_data.icache);
-               show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
+               show_cacheinfo(m, "icache", c->icache);
+               show_cacheinfo(m, "dcache", c->dcache);
        }
 
        /* Optional secondary cache */
-       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
-               show_cacheinfo(m, "scache", boot_cpu_data.scache);
+       if (c->flags & CPU_HAS_L2_CACHE)
+               show_cacheinfo(m, "scache", c->scache);
 
        seq_printf(m, "bogomips\t: %lu.%02lu\n",
-                    boot_cpu_data.loops_per_jiffy/(500000/HZ),
-                    (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
+                    c->loops_per_jiffy/(500000/HZ),
+                    (c->loops_per_jiffy/(5000/HZ)) % 100);
 
        return show_clocks(m);
 }
index e6106239a0fec627120ee62c116fa830fb82322e..fe1b276c97c6140a1a8f2ae911ff0697af3a2734 100644 (file)
@@ -105,7 +105,6 @@ EXPORT_SYMBOL(__flush_purge_region);
 EXPORT_SYMBOL(clear_user_page);
 #endif
 
-EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(__down_trylock);
 
 #ifdef CONFIG_SMP
index 379c88bf5d9a0a8faeb50bd1ab39c6d524784e54..32f10a03fbb5e9388d27d1d889dffbff3df03b03 100644 (file)
@@ -127,7 +127,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
 {
        struct task_struct *tsk = current;
 
-       if (!(cpu_data->flags & CPU_HAS_FPU))
+       if (!(current_cpu_data.flags & CPU_HAS_FPU))
                return 0;
 
        set_used_math();
@@ -140,7 +140,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
 {
        struct task_struct *tsk = current;
 
-       if (!(cpu_data->flags & CPU_HAS_FPU))
+       if (!(current_cpu_data.flags & CPU_HAS_FPU))
                return 0;
 
        if (!used_math()) {
@@ -181,7 +181,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
 #undef COPY
 
 #ifdef CONFIG_SH_FPU
-       if (cpu_data->flags & CPU_HAS_FPU) {
+       if (current_cpu_data.flags & CPU_HAS_FPU) {
                int owned_fp;
                struct task_struct *tsk = current;
 
index ca81976e9e3485fb01f0a45d811f5e9a0bab702a..38fc8cd3ea3a12fbe35dc6a014d12b651eab6795 100644 (file)
@@ -319,15 +319,15 @@ ENTRY(sys_call_table)
        .long sys_mq_getsetattr
        .long sys_kexec_load
        .long sys_waitid
-       .long sys_ni_syscall            /* 285 */
-       .long sys_add_key
+       .long sys_add_key               /* 285 */
        .long sys_request_key
        .long sys_keyctl
        .long sys_ioprio_set
-       .long sys_ioprio_get            /* 290 */
-       .long sys_inotify_init
+       .long sys_ioprio_get
+       .long sys_inotify_init          /* 290 */
        .long sys_inotify_add_watch
        .long sys_inotify_rm_watch
+       .long sys_ni_syscall
        .long sys_migrate_pages
        .long sys_openat                /* 295 */
        .long sys_mkdirat
index ec110157992df81c91d8b38eddc3e5f4634894b4..e9f168f60f95ef2f99efaf7c06c95250e643d25e 100644 (file)
@@ -156,13 +156,13 @@ static inline void do_bug_verbose(struct pt_regs *regs)
 {
 }
 #endif /* CONFIG_DEBUG_BUGVERBOSE */
-#endif /* CONFIG_BUG */
 
 void handle_BUG(struct pt_regs *regs)
 {
        do_bug_verbose(regs);
        die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
 }
+#endif /* CONFIG_BUG */
 
 /*
  * handle an instruction that does an unaligned memory access by emulating the
@@ -641,7 +641,7 @@ int is_dsp_inst(struct pt_regs *regs)
         * Safe guard if DSP mode is already enabled or we're lacking
         * the DSP altogether.
         */
-       if (!(cpu_data->flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
+       if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
                return 0;
 
        get_user(inst, ((unsigned short *) regs->pc));
index 29f4ee35c6dc44e356aa0cf59891e0253c71d929..6b0d28ac9241cd20e91ac5474af7d221c8161854 100644 (file)
@@ -20,7 +20,7 @@ config CPU_SH4
        bool
        select CPU_HAS_INTEVT
        select CPU_HAS_SR_RB
-       select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
+       select CPU_HAS_PTEA if (!CPU_SUBTYPE_ST40 && !CPU_SH4A) || CPU_SHX2
 
 config CPU_SH4A
        bool
@@ -72,6 +72,7 @@ config CPU_SUBTYPE_SH7705
 config CPU_SUBTYPE_SH7706
        bool "Support SH7706 processor"
        select CPU_SH3
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU.
 
@@ -92,6 +93,7 @@ config CPU_SUBTYPE_SH7708
 config CPU_SUBTYPE_SH7709
        bool "Support SH7709 processor"
        select CPU_SH3
+       select CPU_HAS_IPR_IRQ
        select CPU_HAS_PINT_IRQ
        help
          Select SH7709 if you have a  80 Mhz SH-3 HD6417709 CPU.
@@ -149,6 +151,7 @@ config CPU_SUBTYPE_SH7760
        bool "Support SH7760 processor"
        select CPU_SH4
        select CPU_HAS_INTC2_IRQ
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH4_202
        bool "Support SH4-202 processor"
index 909dcfa8c8c69e1941125c064ce5b6d14b86c4bb..de6d2c9aa4773c1b1b989b66fd2e764524c8c03d 100644 (file)
@@ -46,10 +46,10 @@ static int cache_seq_show(struct seq_file *file, void *iter)
 
        if (cache_type == CACHE_TYPE_DCACHE) {
                base = CACHE_OC_ADDRESS_ARRAY;
-               cache = &cpu_data->dcache;
+               cache = &current_cpu_data.dcache;
        } else {
                base = CACHE_IC_ADDRESS_ARRAY;
-               cache = &cpu_data->icache;
+               cache = &current_cpu_data.icache;
        }
 
        /*
index 838731fc608dd6459178fc5fa5ecd9ef440b2629..6d1dbec08ad4694fd1b8ba57b47cfc1f50c6247a 100644 (file)
@@ -44,11 +44,11 @@ void __flush_wback_region(void *start, int size)
 
        for (v = begin; v < end; v+=L1_CACHE_BYTES) {
                unsigned long addrstart = CACHE_OC_ADDRESS_ARRAY;
-               for (j = 0; j < cpu_data->dcache.ways; j++) {
+               for (j = 0; j < current_cpu_data.dcache.ways; j++) {
                        unsigned long data, addr, p;
 
                        p = __pa(v);
-                       addr = addrstart | (v & cpu_data->dcache.entry_mask);
+                       addr = addrstart | (v & current_cpu_data.dcache.entry_mask);
                        local_irq_save(flags);
                        data = ctrl_inl(addr);
 
@@ -60,7 +60,7 @@ void __flush_wback_region(void *start, int size)
                                break;
                        }
                        local_irq_restore(flags);
-                       addrstart += cpu_data->dcache.way_incr;
+                       addrstart += current_cpu_data.dcache.way_incr;
                }
        }
 }
@@ -85,7 +85,7 @@ void __flush_purge_region(void *start, int size)
 
                data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
                addr = CACHE_OC_ADDRESS_ARRAY |
-                       (v & cpu_data->dcache.entry_mask) | SH_CACHE_ASSOC;
+                       (v & current_cpu_data.dcache.entry_mask) | SH_CACHE_ASSOC;
                ctrl_outl(data, addr);
        }
 }
index c6955157c9897fc20d43567d09622fcfe6ab2d79..e0cd4b7f4aeb4d510ad74680b8c89aa18781f978 100644 (file)
@@ -54,21 +54,21 @@ static void __init emit_cache_params(void)
                ctrl_inl(CCN_CVR),
                ctrl_inl(CCN_PRR));
        printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-               cpu_data->icache.ways,
-               cpu_data->icache.sets,
-               cpu_data->icache.way_incr);
+               current_cpu_data.icache.ways,
+               current_cpu_data.icache.sets,
+               current_cpu_data.icache.way_incr);
        printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-               cpu_data->icache.entry_mask,
-               cpu_data->icache.alias_mask,
-               cpu_data->icache.n_aliases);
+               current_cpu_data.icache.entry_mask,
+               current_cpu_data.icache.alias_mask,
+               current_cpu_data.icache.n_aliases);
        printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-               cpu_data->dcache.ways,
-               cpu_data->dcache.sets,
-               cpu_data->dcache.way_incr);
+               current_cpu_data.dcache.ways,
+               current_cpu_data.dcache.sets,
+               current_cpu_data.dcache.way_incr);
        printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-               cpu_data->dcache.entry_mask,
-               cpu_data->dcache.alias_mask,
-               cpu_data->dcache.n_aliases);
+               current_cpu_data.dcache.entry_mask,
+               current_cpu_data.dcache.alias_mask,
+               current_cpu_data.dcache.n_aliases);
 
        if (!__flush_dcache_segment_fn)
                panic("unknown number of cache ways\n");
@@ -87,10 +87,10 @@ void __init p3_cache_init(void)
 {
        int i;
 
-       compute_alias(&cpu_data->icache);
-       compute_alias(&cpu_data->dcache);
+       compute_alias(&current_cpu_data.icache);
+       compute_alias(&current_cpu_data.dcache);
 
-       switch (cpu_data->dcache.ways) {
+       switch (current_cpu_data.dcache.ways) {
        case 1:
                __flush_dcache_segment_fn = __flush_dcache_segment_1way;
                break;
@@ -110,7 +110,7 @@ void __init p3_cache_init(void)
        if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL))
                panic("%s failed.", __FUNCTION__);
 
-       for (i = 0; i < cpu_data->dcache.n_aliases; i++)
+       for (i = 0; i < current_cpu_data.dcache.n_aliases; i++)
                mutex_init(&p3map_mutex[i]);
 }
 
@@ -200,13 +200,14 @@ void flush_cache_sigtramp(unsigned long addr)
                     : /* no output */
                     : "m" (__m(v)));
 
-       index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask);
+       index = CACHE_IC_ADDRESS_ARRAY |
+                       (v & current_cpu_data.icache.entry_mask);
 
        local_irq_save(flags);
        jump_to_P2();
 
-       for (i = 0; i < cpu_data->icache.ways;
-            i++, index += cpu_data->icache.way_incr)
+       for (i = 0; i < current_cpu_data.icache.ways;
+            i++, index += current_cpu_data.icache.way_incr)
                ctrl_outl(0, index);    /* Clear out Valid-bit */
 
        back_to_P1();
@@ -223,7 +224,7 @@ static inline void flush_cache_4096(unsigned long start,
         * All types of SH-4 require PC to be in P2 to operate on the I-cache.
         * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
         */
-       if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
+       if ((current_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
            (start < CACHE_OC_ADDRESS_ARRAY))
                exec_offset = 0x20000000;
 
@@ -236,16 +237,26 @@ static inline void flush_cache_4096(unsigned long start,
 /*
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
+ *
+ * This uses a lazy write-back on UP, which is explicitly
+ * disabled on SMP.
  */
 void flush_dcache_page(struct page *page)
 {
-       if (test_bit(PG_mapped, &page->flags)) {
+#ifndef CONFIG_SMP
+       struct address_space *mapping = page_mapping(page);
+
+       if (mapping && !mapping_mapped(mapping))
+               set_bit(PG_dcache_dirty, &page->flags);
+       else
+#endif
+       {
                unsigned long phys = PHYSADDR(page_address(page));
                unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
                int i, n;
 
                /* Loop all the D-cache */
-               n = cpu_data->dcache.n_aliases;
+               n = current_cpu_data.dcache.n_aliases;
                for (i = 0; i < n; i++, addr += 4096)
                        flush_cache_4096(addr, phys);
        }
@@ -277,7 +288,7 @@ static inline void flush_icache_all(void)
 
 void flush_dcache_all(void)
 {
-       (*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size);
+       (*__flush_dcache_segment_fn)(0UL, current_cpu_data.dcache.way_size);
        wmb();
 }
 
@@ -291,8 +302,8 @@ static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
                             unsigned long end)
 {
        unsigned long d = 0, p = start & PAGE_MASK;
-       unsigned long alias_mask = cpu_data->dcache.alias_mask;
-       unsigned long n_aliases = cpu_data->dcache.n_aliases;
+       unsigned long alias_mask = current_cpu_data.dcache.alias_mask;
+       unsigned long n_aliases = current_cpu_data.dcache.n_aliases;
        unsigned long select_bit;
        unsigned long all_aliases_mask;
        unsigned long addr_offset;
@@ -379,7 +390,7 @@ void flush_cache_mm(struct mm_struct *mm)
         * If cache is only 4k-per-way, there are never any 'aliases'.  Since
         * the cache is physically tagged, the data can just be left in there.
         */
-       if (cpu_data->dcache.n_aliases == 0)
+       if (current_cpu_data.dcache.n_aliases == 0)
                return;
 
        /*
@@ -416,7 +427,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
        unsigned long phys = pfn << PAGE_SHIFT;
        unsigned int alias_mask;
 
-       alias_mask = cpu_data->dcache.alias_mask;
+       alias_mask = current_cpu_data.dcache.alias_mask;
 
        /* We only need to flush D-cache when we have alias */
        if ((address^phys) & alias_mask) {
@@ -430,7 +441,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
                        phys);
        }
 
-       alias_mask = cpu_data->icache.alias_mask;
+       alias_mask = current_cpu_data.icache.alias_mask;
        if (vma->vm_flags & VM_EXEC) {
                /*
                 * Evict entries from the portion of the cache from which code
@@ -462,7 +473,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
         * If cache is only 4k-per-way, there are never any 'aliases'.  Since
         * the cache is physically tagged, the data can just be left in there.
         */
-       if (cpu_data->dcache.n_aliases == 0)
+       if (current_cpu_data.dcache.n_aliases == 0)
                return;
 
        /*
@@ -523,7 +534,7 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys,
        unsigned long a, ea, p;
        unsigned long temp_pc;
 
-       dcache = &cpu_data->dcache;
+       dcache = &current_cpu_data.dcache;
        /* Write this way for better assembly. */
        way_count = dcache->ways;
        way_incr = dcache->way_incr;
@@ -598,7 +609,7 @@ static void __flush_dcache_segment_1way(unsigned long start,
        base_addr = ((base_addr >> 16) << 16);
        base_addr |= start;
 
-       dcache = &cpu_data->dcache;
+       dcache = &current_cpu_data.dcache;
        linesz = dcache->linesz;
        way_incr = dcache->way_incr;
        way_size = dcache->way_size;
@@ -640,7 +651,7 @@ static void __flush_dcache_segment_2way(unsigned long start,
        base_addr = ((base_addr >> 16) << 16);
        base_addr |= start;
 
-       dcache = &cpu_data->dcache;
+       dcache = &current_cpu_data.dcache;
        linesz = dcache->linesz;
        way_incr = dcache->way_incr;
        way_size = dcache->way_size;
@@ -699,7 +710,7 @@ static void __flush_dcache_segment_4way(unsigned long start,
        base_addr = ((base_addr >> 16) << 16);
        base_addr |= start;
 
-       dcache = &cpu_data->dcache;
+       dcache = &current_cpu_data.dcache;
        linesz = dcache->linesz;
        way_incr = dcache->way_incr;
        way_size = dcache->way_size;
index 045abdf078f5bdc71a99c67f64da9c6cf76e6f4b..31f8deb7a158e410b61069a2a4aa6320cb397b1f 100644 (file)
@@ -3,11 +3,11 @@
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
  * Copyright (C) 2004  Alex Song
+ * Copyright (C) 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
 #include <linux/init.h>
 #include <linux/mman.h>
@@ -32,9 +32,9 @@ static inline void cache_wback_all(void)
 {
        unsigned long ways, waysize, addrstart;
 
-       ways = cpu_data->dcache.ways;
-       waysize = cpu_data->dcache.sets;
-       waysize <<= cpu_data->dcache.entry_shift;
+       ways = current_cpu_data.dcache.ways;
+       waysize = current_cpu_data.dcache.sets;
+       waysize <<= current_cpu_data.dcache.entry_shift;
 
        addrstart = CACHE_OC_ADDRESS_ARRAY;
 
@@ -43,7 +43,7 @@ static inline void cache_wback_all(void)
 
                for (addr = addrstart;
                     addr < addrstart + waysize;
-                    addr += cpu_data->dcache.linesz) {
+                    addr += current_cpu_data.dcache.linesz) {
                        unsigned long data;
                        int v = SH_CACHE_UPDATED | SH_CACHE_VALID;
 
@@ -51,10 +51,9 @@ static inline void cache_wback_all(void)
 
                        if ((data & v) == v)
                                ctrl_outl(data & ~v, addr);
-
                }
 
-               addrstart += cpu_data->dcache.way_incr;
+               addrstart += current_cpu_data.dcache.way_incr;
        } while (--ways);
 }
 
@@ -94,9 +93,9 @@ static void __flush_dcache_page(unsigned long phys)
        local_irq_save(flags);
        jump_to_P2();
 
-       ways = cpu_data->dcache.ways;
-       waysize = cpu_data->dcache.sets;
-       waysize <<= cpu_data->dcache.entry_shift;
+       ways = current_cpu_data.dcache.ways;
+       waysize = current_cpu_data.dcache.sets;
+       waysize <<= current_cpu_data.dcache.entry_shift;
 
        addrstart = CACHE_OC_ADDRESS_ARRAY;
 
@@ -105,7 +104,7 @@ static void __flush_dcache_page(unsigned long phys)
 
                for (addr = addrstart;
                     addr < addrstart + waysize;
-                    addr += cpu_data->dcache.linesz) {
+                    addr += current_cpu_data.dcache.linesz) {
                        unsigned long data;
 
                        data = ctrl_inl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
@@ -115,7 +114,7 @@ static void __flush_dcache_page(unsigned long phys)
                        }
                }
 
-               addrstart += cpu_data->dcache.way_incr;
+               addrstart += current_cpu_data.dcache.way_incr;
        } while (--ways);
 
        back_to_P1();
@@ -128,7 +127,11 @@ static void __flush_dcache_page(unsigned long phys)
  */
 void flush_dcache_page(struct page *page)
 {
-       if (test_bit(PG_mapped, &page->flags))
+       struct address_space *mapping = page_mapping(page);
+
+       if (mapping && !mapping_mapped(mapping))
+               set_bit(PG_dcache_dirty, &page->flags);
+       else
                __flush_dcache_page(PHYSADDR(page_address(page)));
 }
 
index 716ebf568af20d2e2e7e303161d11304886ff794..fa5d7f0b9f1877a5b8bccedc71d97ce84d660a22 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kprobes.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
 #include <asm/kgdb.h>
 
 extern void die(const char *,struct pt_regs *,long);
@@ -224,3 +225,89 @@ do_sigbus:
        if (!user_mode(regs))
                goto no_context;
 }
+
+#ifdef CONFIG_SH_STORE_QUEUES
+/*
+ * This is a special case for the SH-4 store queues, as pages for this
+ * space still need to be faulted in before it's possible to flush the
+ * store queue cache for writeout to the remapped region.
+ */
+#define P3_ADDR_MAX            (P4SEG_STORE_QUE + 0x04000000)
+#else
+#define P3_ADDR_MAX            P4SEG
+#endif
+
+/*
+ * Called with interrupts disabled.
+ */
+asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
+                                        unsigned long writeaccess,
+                                        unsigned long address)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t entry;
+       struct mm_struct *mm = current->mm;
+       spinlock_t *ptl;
+       int ret = 1;
+
+#ifdef CONFIG_SH_KGDB
+       if (kgdb_nofault && kgdb_bus_err_hook)
+               kgdb_bus_err_hook();
+#endif
+
+       /*
+        * We don't take page faults for P1, P2, and parts of P4, these
+        * are always mapped, whether it be due to legacy behaviour in
+        * 29-bit mode, or due to PMB configuration in 32-bit mode.
+        */
+       if (address >= P3SEG && address < P3_ADDR_MAX) {
+               pgd = pgd_offset_k(address);
+               mm = NULL;
+       } else {
+               if (unlikely(address >= TASK_SIZE || !mm))
+                       return 1;
+
+               pgd = pgd_offset(mm, address);
+       }
+
+       pud = pud_offset(pgd, address);
+       if (pud_none_or_clear_bad(pud))
+               return 1;
+       pmd = pmd_offset(pud, address);
+       if (pmd_none_or_clear_bad(pmd))
+               return 1;
+
+       if (mm)
+               pte = pte_offset_map_lock(mm, pmd, address, &ptl);
+       else
+               pte = pte_offset_kernel(pmd, address);
+
+       entry = *pte;
+       if (unlikely(pte_none(entry) || pte_not_present(entry)))
+               goto unlock;
+       if (unlikely(writeaccess && !pte_write(entry)))
+               goto unlock;
+
+       if (writeaccess)
+               entry = pte_mkdirty(entry);
+       entry = pte_mkyoung(entry);
+
+#ifdef CONFIG_CPU_SH4
+       /*
+        * ITLB is not affected by "ldtlb" instruction.
+        * So, we need to flush the entry by ourselves.
+        */
+       local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+#endif
+
+       set_pte(pte, entry);
+       update_mmu_cache(NULL, address, entry);
+       ret = 0;
+unlock:
+       if (mm)
+               pte_unmap_unlock(pte, ptl);
+       return ret;
+}
index bf0c263cb6fd036ec3f3f9e971799dc41f18fa56..ae957a9323754a2eb12c50a62e5c9cb436d304fb 100644 (file)
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-/*
- * Cache of MMU context last used.
- */
-unsigned long mmu_context_cache = NO_CONTEXT;
-
 #ifdef CONFIG_MMU
 /* It'd be good if these lines were in the standard header file. */
 #define START_PFN      (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
@@ -111,7 +106,7 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 
        set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
 
-       __flush_tlb_page(get_asid(), addr);
+       flush_tlb_one(get_asid(), addr);
 }
 
 /*
index 90b494a0cf45b5f78c1c98c5d8b9c7b28c8868ac..be03d74e99cbc4412c713ba96141b66a0443a21d 100644 (file)
@@ -44,12 +44,6 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
        if (!size || last_addr < phys_addr)
                return NULL;
 
-       /*
-        * Don't remap the low PCI/ISA area, it's always mapped..
-        */
-       if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-               return (void __iomem *)phys_to_virt(phys_addr);
-
        /*
         * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
         * mapped at the end of the address space (typically 0xfd000000)
index 3f98d2a4f936355507e4386855e442b7fa6860ac..969efeceb9282ae1b434dfc025a9728923e696c2 100644 (file)
@@ -13,7 +13,7 @@
 
 extern struct mutex p3map_mutex[];
 
-#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
+#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
 
 /*
  * clear_user_page
@@ -23,7 +23,6 @@ extern struct mutex p3map_mutex[];
  */
 void clear_user_page(void *to, unsigned long address, struct page *page)
 {
-       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                clear_page(to);
        else {
@@ -40,7 +39,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
                mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
                set_pte(pte, entry);
                local_irq_save(flags);
-               __flush_tlb_page(get_asid(), p3_addr);
+               flush_tlb_one(get_asid(), p3_addr);
                local_irq_restore(flags);
                update_mmu_cache(NULL, p3_addr, entry);
                __clear_user_page((void *)p3_addr, to);
@@ -59,7 +58,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
 void copy_user_page(void *to, void *from, unsigned long address,
                    struct page *page)
 {
-       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                copy_page(to, from);
        else {
@@ -76,7 +74,7 @@ void copy_user_page(void *to, void *from, unsigned long address,
                mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
                set_pte(pte, entry);
                local_irq_save(flags);
-               __flush_tlb_page(get_asid(), p3_addr);
+               flush_tlb_one(get_asid(), p3_addr);
                local_irq_restore(flags);
                update_mmu_cache(NULL, p3_addr, entry);
                __copy_user_page((void *)p3_addr, from, to);
@@ -84,23 +82,3 @@ void copy_user_page(void *to, void *from, unsigned long address,
                mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
        }
 }
-
-/*
- * For SH-4, we have our own implementation for ptep_get_and_clear
- */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-
-       pte_clear(mm, addr, ptep);
-       if (!pte_not_present(pte)) {
-               unsigned long pfn = pte_pfn(pte);
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-                       struct address_space *mapping = page_mapping(page);
-                       if (!mapping || !mapping_writably_mapped(mapping))
-                               __clear_bit(PG_mapped, &page->flags);
-               }
-       }
-       return pte;
-}
index ff9ece986cbcb822f2e85bf1adb8991330c0f97e..887ab9d18ccd25b16d4e5bc8d6d50db5f6020192 100644 (file)
@@ -7,9 +7,7 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
-
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
@@ -45,13 +43,13 @@ static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
 
                p = __pa(p1_begin);
 
-               ways = cpu_data->dcache.ways;
+               ways = current_cpu_data.dcache.ways;
                addr = CACHE_OC_ADDRESS_ARRAY;
 
                do {
                        unsigned long data;
 
-                       addr |= (v & cpu_data->dcache.entry_mask);
+                       addr |= (v & current_cpu_data.dcache.entry_mask);
 
                        data = ctrl_inl(addr);
                        if ((data & CACHE_PHYSADDR_MASK) ==
@@ -60,7 +58,7 @@ static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
                                ctrl_outl(data, addr);
                        }
 
-                       addr += cpu_data->dcache.way_incr;
+                       addr += current_cpu_data.dcache.way_incr;
                } while (--ways);
 
                p1_begin += L1_CACHE_BYTES;
@@ -76,7 +74,6 @@ void clear_user_page(void *to, unsigned long address, struct page *pg)
 {
        struct page *page = virt_to_page(to);
 
-       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
                clear_page(to);
                __flush_wback_region(to, PAGE_SIZE);
@@ -95,12 +92,11 @@ void clear_user_page(void *to, unsigned long address, struct page *pg)
  * @from: P1 address
  * @address: U0 address to be mapped
  */
-void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
+void copy_user_page(void *to, void *from, unsigned long address,
+                   struct page *pg)
 {
        struct page *page = virt_to_page(to);
 
-
-       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
                copy_page(to, from);
                __flush_wback_region(to, PAGE_SIZE);
@@ -112,26 +108,3 @@ void copy_user_page(void *to, void *from, unsigned long address, struct page *pg
                __flush_wback_region(to, PAGE_SIZE);
        }
 }
-
-/*
- * For SH7705, we have our own implementation for ptep_get_and_clear
- * Copied from pg-sh4.c
- */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-
-       pte_clear(mm, addr, ptep);
-       if (!pte_not_present(pte)) {
-               unsigned long pfn = pte_pfn(pte);
-               if (pfn_valid(pfn)) {
-                       struct page *page = pfn_to_page(pfn);
-                       struct address_space *mapping = page_mapping(page);
-                       if (!mapping || !mapping_writably_mapped(mapping))
-                               __clear_bit(PG_mapped, &page->flags);
-               }
-       }
-
-       return pte;
-}
-
index 73ec7f6084fa404def63f9e86d8e8afda763ac60..d2f7b4a2eb05356339a0599638c935c08fd9d0fd 100644 (file)
@@ -2,24 +2,28 @@
  * TLB flushing operations for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
 #include <linux/mm.h>
+#include <linux/io.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-       if (vma->vm_mm && vma->vm_mm->context.id != NO_CONTEXT) {
+       unsigned int cpu = smp_processor_id();
+
+       if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {
                unsigned long flags;
                unsigned long asid;
                unsigned long saved_asid = MMU_NO_ASID;
 
-               asid = vma->vm_mm->context.id & MMU_CONTEXT_ASID_MASK;
+               asid = cpu_asid(cpu, vma->vm_mm);
                page &= PAGE_MASK;
 
                local_irq_save(flags);
@@ -27,33 +31,34 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
                        saved_asid = get_asid();
                        set_asid(asid);
                }
-               __flush_tlb_page(asid, page);
+               local_flush_tlb_one(asid, page);
                if (saved_asid != MMU_NO_ASID)
                        set_asid(saved_asid);
                local_irq_restore(flags);
        }
 }
 
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-                    unsigned long end)
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                          unsigned long end)
 {
        struct mm_struct *mm = vma->vm_mm;
+       unsigned int cpu = smp_processor_id();
 
-       if (mm->context.id != NO_CONTEXT) {
+       if (cpu_context(cpu, mm) != NO_CONTEXT) {
                unsigned long flags;
                int size;
 
                local_irq_save(flags);
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
                if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-                       mm->context.id = NO_CONTEXT;
+                       cpu_context(cpu, mm) = NO_CONTEXT;
                        if (mm == current->mm)
-                               activate_context(mm);
+                               activate_context(mm, cpu);
                } else {
                        unsigned long asid;
                        unsigned long saved_asid = MMU_NO_ASID;
 
-                       asid = mm->context.id & MMU_CONTEXT_ASID_MASK;
+                       asid = cpu_asid(cpu, mm);
                        start &= PAGE_MASK;
                        end += (PAGE_SIZE - 1);
                        end &= PAGE_MASK;
@@ -62,7 +67,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                                set_asid(asid);
                        }
                        while (start < end) {
-                               __flush_tlb_page(asid, start);
+                               local_flush_tlb_one(asid, start);
                                start += PAGE_SIZE;
                        }
                        if (saved_asid != MMU_NO_ASID)
@@ -72,26 +77,27 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
        }
 }
 
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
+       unsigned int cpu = smp_processor_id();
        unsigned long flags;
        int size;
 
        local_irq_save(flags);
        size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
        if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-               flush_tlb_all();
+               local_flush_tlb_all();
        } else {
                unsigned long asid;
                unsigned long saved_asid = get_asid();
 
-               asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;
+               asid = cpu_asid(cpu, &init_mm);
                start &= PAGE_MASK;
                end += (PAGE_SIZE - 1);
                end &= PAGE_MASK;
                set_asid(asid);
                while (start < end) {
-                       __flush_tlb_page(asid, start);
+                       local_flush_tlb_one(asid, start);
                        start += PAGE_SIZE;
                }
                set_asid(saved_asid);
@@ -99,22 +105,24 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
        local_irq_restore(flags);
 }
 
-void flush_tlb_mm(struct mm_struct *mm)
+void local_flush_tlb_mm(struct mm_struct *mm)
 {
+       unsigned int cpu = smp_processor_id();
+
        /* Invalidate all TLB of this process. */
        /* Instead of invalidating each TLB, we get new MMU context. */
-       if (mm->context.id != NO_CONTEXT) {
+       if (cpu_context(cpu, mm) != NO_CONTEXT) {
                unsigned long flags;
 
                local_irq_save(flags);
-               mm->context.id = NO_CONTEXT;
+               cpu_context(cpu, mm) = NO_CONTEXT;
                if (mm == current->mm)
-                       activate_context(mm);
+                       activate_context(mm, cpu);
                local_irq_restore(flags);
        }
 }
 
-void flush_tlb_all(void)
+void local_flush_tlb_all(void)
 {
        unsigned long flags, status;
 
@@ -132,3 +140,54 @@ void flush_tlb_all(void)
        ctrl_barrier();
        local_irq_restore(flags);
 }
+
+void update_mmu_cache(struct vm_area_struct *vma,
+                     unsigned long address, pte_t pte)
+{
+       unsigned long flags;
+       unsigned long pteval;
+       unsigned long vpn;
+       struct page *page;
+       unsigned long pfn = pte_pfn(pte);
+       struct address_space *mapping;
+
+       if (!pfn_valid(pfn))
+               return;
+
+       page = pfn_to_page(pfn);
+       mapping = page_mapping(page);
+       if (mapping) {
+               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+               int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
+
+               if (dirty)
+                       __flush_wback_region((void *)P1SEGADDR(phys),
+                                            PAGE_SIZE);
+       }
+
+       local_irq_save(flags);
+
+       /* Set PTEH register */
+       vpn = (address & MMU_VPN_MASK) | get_asid();
+       ctrl_outl(vpn, MMU_PTEH);
+
+       pteval = pte_val(pte);
+
+#ifdef CONFIG_CPU_HAS_PTEA
+       /* Set PTEA register */
+       /* TODO: make this look less hacky */
+       ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
+#endif
+
+       /* Set PTEL register */
+       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4)
+       pteval |= _PAGE_WT;
+#endif
+       /* conveniently, we want all the software flags to be 0 anyway */
+       ctrl_outl(pteval, MMU_PTEL);
+
+       /* Load the TLB */
+       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+       local_irq_restore(flags);
+}
index e55cfea01092dc4531c0d8acb07cfa41ef8ef853..1ccca7c0532e54a5da01227a45b4a5234c913f11 100644 (file)
 /*
  * Nothing too terribly exciting here ..
  */
-
-void flush_tlb(void)
-{
-       BUG();
-}
-
-void flush_tlb_all(void)
+void local_flush_tlb_all(void)
 {
        BUG();
 }
 
-void flush_tlb_mm(struct mm_struct *mm)
+void local_flush_tlb_mm(struct mm_struct *mm)
 {
        BUG();
 }
 
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                            unsigned long end)
 {
        BUG();
 }
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
        BUG();
 }
 
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
        BUG();
 }
 
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
        BUG();
 }
@@ -55,4 +49,3 @@ void update_mmu_cache(struct vm_area_struct * vma,
 {
        BUG();
 }
-
index 46b09e26e0825fa411a593fdd4f5755e01d4f77a..e5e76eb7ee09e1b2c6f118201335349847e0c4ec 100644 (file)
@@ -8,71 +8,11 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
-{
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
-
-       /* Ptrace may call this routine. */
-       if (vma && current->active_mm != vma->vm_mm)
-               return;
-
-#if defined(CONFIG_SH7705_CACHE_32KB)
-       {
-               struct page *page = pte_page(pte);
-               unsigned long pfn = pte_pfn(pte);
-
-               if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
-                       unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-
-                       __flush_wback_region((void *)P1SEGADDR(phys),
-                                            PAGE_SIZE);
-                       __set_bit(PG_mapped, &page->flags);
-               }
-       }
-#endif
-
-       local_irq_save(flags);
-
-       /* Set PTEH register */
-       vpn = (address & MMU_VPN_MASK) | get_asid();
-       ctrl_outl(vpn, MMU_PTEH);
-
-       pteval = pte_val(pte);
-
-       /* Set PTEL register */
-       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-       /* conveniently, we want all the software flags to be 0 anyway */
-       ctrl_outl(pteval, MMU_PTEL);
-
-       /* Load the TLB */
-       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-       local_irq_restore(flags);
-}
-
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
        unsigned long addr, data;
        int i, ways = MMU_NTLB_WAYS;
@@ -86,7 +26,7 @@ void __flush_tlb_page(unsigned long asid, unsigned long page)
        addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000);
        data = (page & 0xfffe0000) | asid; /* VALID bit is off */
 
-       if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) {
+       if ((current_cpu_data.flags & CPU_HAS_MMU_PAGE_ASSOC)) {
                addr |= MMU_PAGE_ASSOC_BIT;
                ways = 1;       /* we already know the way .. */
        }
@@ -94,4 +34,3 @@ void __flush_tlb_page(unsigned long asid, unsigned long page)
        for (i = 0; i < ways; i++)
                ctrl_outl(data, addr + (i << 8));
 }
-
index 812b2d567de2f6e57a7519864923a1bbd69bbfb9..221e7095473d383348d57c9389f5f7be146ac34f 100644 (file)
@@ -8,76 +8,11 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-                     unsigned long address, pte_t pte)
-{
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
-       struct page *page;
-       unsigned long pfn;
-
-       /* Ptrace may call this routine. */
-       if (vma && current->active_mm != vma->vm_mm)
-               return;
-
-       pfn = pte_pfn(pte);
-       if (pfn_valid(pfn)) {
-               page = pfn_to_page(pfn);
-               if (!test_bit(PG_mapped, &page->flags)) {
-                       unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-                       __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
-                       __set_bit(PG_mapped, &page->flags);
-               }
-       }
-
-       local_irq_save(flags);
-
-       /* Set PTEH register */
-       vpn = (address & MMU_VPN_MASK) | get_asid();
-       ctrl_outl(vpn, MMU_PTEH);
-
-       pteval = pte_val(pte);
-
-       /* Set PTEA register */
-       if (cpu_data->flags & CPU_HAS_PTEA)
-               /* TODO: make this look less hacky */
-               ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
-
-       /* Set PTEL register */
-       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-#ifdef CONFIG_SH_WRITETHROUGH
-       pteval |= _PAGE_WT;
-#endif
-       /* conveniently, we want all the software flags to be 0 anyway */
-       ctrl_outl(pteval, MMU_PTEL);
-
-       /* Load the TLB */
-       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-       local_irq_restore(flags);
-}
-
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
        unsigned long addr, data;
 
@@ -93,4 +28,3 @@ void __flush_tlb_page(unsigned long asid, unsigned long page)
        ctrl_outl(data, addr);
        back_to_P1();
 }
-
index 0104e44bc76a3be52352d7de5d9e5cabe37e6a6f..ebee7e24ede9e253cf87f7d78ca5fc35114f848b 100644 (file)
@@ -259,7 +259,7 @@ static struct oprofile_operations sh7750_perf_counter_ops = {
 
 int __init oprofile_arch_init(struct oprofile_operations **ops)
 {
-       if (!(cpu_data->flags & CPU_HAS_PERF_COUNTER))
+       if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
                return -ENODEV;
 
        sh7750_perf_counter_ops.cpu_type = (char *)get_cpu_subtype();
index 0571755e9a84e8e6b2ae55e266043923f03423e8..4fe0f94cbf429687b648d37ff29f7429501e4f0a 100644 (file)
@@ -16,7 +16,6 @@ HD64461                       HD64461
 HD64465                        HD64465
 SATURN                 SH_SATURN
 DREAMCAST              SH_DREAMCAST
-BIGSUR                 SH_BIGSUR
 MPC1211                        SH_MPC1211
 SNAPGEAR               SH_SECUREEDGE5410
 HS7751RVOIP            SH_HS7751RVOIP
index 224b7f5b92246efdccfbd00be1575f57d3ebca9d..c346d7ef9280f3452ec54b4edacba5698e58ce96 100644 (file)
@@ -910,30 +910,57 @@ static int misaligned_fixup(struct pt_regs *regs)
 }
 
 static ctl_table unaligned_table[] = {
-       {1, "kernel_reports", &kernel_mode_unaligned_fixup_count,
-               sizeof(int), 0644, NULL, &proc_dointvec},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "kernel_reports",
+               .data           = &kernel_mode_unaligned_fixup_count,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
 #if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
-       {2, "user_reports", &user_mode_unaligned_fixup_count,
-               sizeof(int), 0644, NULL, &proc_dointvec},
-       {3, "user_enable", &user_mode_unaligned_fixup_enable,
-               sizeof(int), 0644, NULL, &proc_dointvec},
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "user_reports",
+               .data           = &user_mode_unaligned_fixup_count,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "user_enable",
+               .data           = &user_mode_unaligned_fixup_enable,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec},
 #endif
-       {0}
+       {}
 };
 
 static ctl_table unaligned_root[] = {
-       {1, "unaligned_fixup", NULL, 0, 0555, unaligned_table},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "unaligned_fixup",
+               .mode           = 0555,
+               unaligned_table
+       },
+       {}
 };
 
 static ctl_table sh64_root[] = {
-       {1, "sh64", NULL, 0, 0555, unaligned_root},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "sh64",
+               .mode           = 0555,
+               .child          = unaligned_root
+       },
+       {}
 };
 static struct ctl_table_header *sysctl_header;
 static int __init init_sysctl(void)
 {
-       sysctl_header = register_sysctl_table(sh64_root, 0);
+       sysctl_header = register_sysctl_table(sh64_root);
        return 0;
 }
 
index 925a65240cfec96c0f6c424e6009bf24a2012f90..b2e1fd8e35712504c1b8190acd2175f923ce7e5e 100644 (file)
@@ -97,20 +97,22 @@ static int write_sigio_thread(void *unused)
 
 static int need_poll(struct pollfds *polls, int n)
 {
-       if(n <= polls->size){
-               polls->used = n;
+       struct pollfd *new;
+
+       if(n <= polls->size)
                return 0;
-       }
-       kfree(polls->poll);
-       polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
-       if(polls->poll == NULL){
+
+       new = um_kmalloc_atomic(n * sizeof(struct pollfd));
+       if(new == NULL){
                printk("need_poll : failed to allocate new pollfds\n");
-               polls->size = 0;
-               polls->used = 0;
                return -ENOMEM;
        }
+
+       memcpy(new, polls->poll, polls->used * sizeof(struct pollfd));
+       kfree(polls->poll);
+
+       polls->poll = new;
        polls->size = n;
-       polls->used = n;
        return 0;
 }
 
@@ -171,15 +173,15 @@ int add_sigio_fd(int fd)
                        goto out;
        }
 
-       n = current_poll.used + 1;
-       err = need_poll(&next_poll, n);
+       n = current_poll.used;
+       err = need_poll(&next_poll, n + 1);
        if(err)
                goto out;
 
-       for(i = 0; i < current_poll.used; i++)
-               next_poll.poll[i] = current_poll.poll[i];
-
-       next_poll.poll[n - 1] = *p;
+       memcpy(next_poll.poll, current_poll.poll,
+              current_poll.used * sizeof(struct pollfd));
+       next_poll.poll[n] = *p;
+       next_poll.used = n + 1;
        update_thread();
  out:
        sigio_unlock();
@@ -214,6 +216,7 @@ int ignore_sigio_fd(int fd)
                if(p->fd != fd)
                        next_poll.poll[n++] = *p;
        }
+       next_poll.used = current_poll.used - 1;
 
        update_thread();
  out:
@@ -331,10 +334,9 @@ void maybe_sigio_broken(int fd, int read)
 
        sigio_lock();
        err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
-       if(err){
-               printk("maybe_sigio_broken - failed to add pollfd\n");
+       if(err)
                goto out;
-       }
+
        all_sigio_fds.poll[all_sigio_fds.used++] =
                ((struct pollfd) { .fd          = fd,
                                   .events      = read ? POLLIN : POLLOUT,
index dbfab8fc9b49c2c4c6e620558401f57af2bedf50..50ccc7f57cd0ffece7f9ccac025f80f31e5d9a9a 100644 (file)
@@ -217,7 +217,7 @@ menu "Processor type and features"
    # Some platforms pre-zero memory, in which case the kernel doesn't need to
    config ZERO_BSS
          bool
-         depends !V850E2_SIM85E2C
+         depends on !V850E2_SIM85E2C
          default y
 
    # The crappy-ass zone allocator requires that the start of allocatable
index 02dd39457bcf20cfb487dc1d34833427d714cce3..56eb14c9847524ef7072da08969b84b086438f2e 100644 (file)
@@ -24,6 +24,14 @@ config X86
        bool
        default y
 
+config GENERIC_TIME
+       bool
+       default y
+
+config GENERIC_TIME_VSYSCALL
+       bool
+       default y
+
 config ZONE_DMA32
        bool
        default y
@@ -152,18 +160,18 @@ config MPSC
          Optimize for Intel Pentium 4 and older Nocona/Dempsey Xeon CPUs
          with Intel Extended Memory 64 Technology(EM64T). For details see
          <http://www.intel.com/technology/64bitextensions/>.
-         Note the the latest Xeons (Xeon 51xx and 53xx) are not based on the
-          Netburst core and shouldn't use this option. You can distingush them
+         Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
+          Netburst core and shouldn't use this option. You can distinguish them
          using the cpu family field
-         in /proc/cpuinfo. Family 15 is a older Xeon, Family 6 a newer one
-         (this rule only applies to system that support EM64T)
+         in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one
+         (this rule only applies to systems that support EM64T)
 
 config MCORE2
        bool "Intel Core2 / newer Xeon"
        help
          Optimize for Intel Core2 and newer Xeons (51xx)
-         You can distingush the newer Xeons from the older ones using
-         the cpu family field in /proc/cpuinfo. 15 is a older Xeon
+         You can distinguish the newer Xeons from the older ones using
+         the cpu family field in /proc/cpuinfo. 15 is an older Xeon
          (use CONFIG_MPSC then), 6 is a newer one. This rule only
          applies to CPUs that support EM64T.
 
@@ -458,8 +466,8 @@ config IOMMU
          on systems with more than 3GB. This is usually needed for USB,
          sound, many IDE/SATA chipsets and some other devices.
          Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
-         based IOMMU and a software bounce buffer based IOMMU used on Intel
-         systems and as fallback.
+         based hardware IOMMU and a software bounce buffer based IOMMU used
+         on Intel systems and as fallback.
          The code is only active when needed (enough memory and limited
          device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
          too.
@@ -496,6 +504,12 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
        bool
+       help
+         Support for software bounce buffers used on x86-64 systems
+         which don't have a hardware IOMMU (e.g. the current generation
+         of Intel's x86-64 CPUs). Using this PCI devices which can only
+         access 32-bits of memory can be used on systems with more than
+         3 GB of memory. If unsure, say Y.
 
 config X86_MCE
        bool "Machine check support" if EMBEDDED
index 69584c2953057fdda7b69b723920ecd8dbb38185..293a4a4c609e2c16649c685e6541d108be7fee31 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc3
-# Fri Jan  5 11:54:41 2007
+# Linux kernel version: 2.6.20-git8
+# Tue Feb 13 11:25:16 2007
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@ CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -153,6 +154,7 @@ CONFIG_NEED_MULTIPLE_NODES=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y
 CONFIG_NR_CPUS=32
@@ -201,13 +203,14 @@ CONFIG_ACPI=y
 CONFIG_ACPI_SLEEP=y
 CONFIG_ACPI_SLEEP_PROC_FS=y
 CONFIG_ACPI_SLEEP_PROC_SLEEP=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_AC=y
 CONFIG_ACPI_BATTERY=y
 CONFIG_ACPI_BUTTON=y
-# CONFIG_ACPI_VIDEO is not set
 # CONFIG_ACPI_HOTKEY is not set
 CONFIG_ACPI_FAN=y
 # CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_BAY is not set
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=y
@@ -263,7 +266,6 @@ CONFIG_PCI_MMCONFIG=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
 CONFIG_PCI_MSI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_HT_IRQ is not set
 
@@ -398,6 +400,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -466,6 +469,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -497,6 +501,7 @@ CONFIG_BLK_DEV_ATIIXP=y
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -507,6 +512,7 @@ CONFIG_BLK_DEV_PDC202XX_NEW=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -599,6 +605,7 @@ CONFIG_MEGARAID_SAS=y
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_SVW=y
 CONFIG_ATA_PIIX=y
@@ -614,6 +621,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_SATA_ULI is not set
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
@@ -630,6 +638,7 @@ CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -682,9 +691,7 @@ CONFIG_IEEE1394=y
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
 # CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
 # Device Drivers
@@ -706,6 +713,11 @@ CONFIG_IEEE1394_RAWIO=y
 #
 # CONFIG_I2O is not set
 
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+
 #
 # Network device support
 #
@@ -774,6 +786,7 @@ CONFIG_8139TOO=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -795,11 +808,13 @@ CONFIG_E1000=y
 CONFIG_TIGON3=y
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
@@ -1115,6 +1130,7 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+CONFIG_OBSOLETE_OSS=y
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
@@ -1128,6 +1144,7 @@ CONFIG_SOUND_ICH=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1142,10 +1159,8 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1155,9 +1170,11 @@ CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1208,6 +1225,7 @@ CONFIG_USB_HID=y
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1312,6 +1330,10 @@ CONFIG_USB_MON=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
 #
 # Virtualization
 #
@@ -1512,6 +1534,7 @@ CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
@@ -1520,7 +1543,6 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1560,4 +1582,5 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index 6efe04f3cbca8601bd39605d8e2085290953b73c..071100ea12512fe409361542ad7a7cf8ae5a62ad 100644 (file)
@@ -344,20 +344,30 @@ EXPORT_SYMBOL(ia32_setup_arg_pages);
 #include <linux/sysctl.h>
 
 static ctl_table abi_table2[] = {
-       { 99, "vsyscall32", &sysctl_vsyscall32, sizeof(int), 0644, NULL,
-         proc_dointvec },
-       { 0, }
-}; 
+       {
+               .ctl_name       = 99,
+               .procname       = "vsyscall32",
+               .data           = &sysctl_vsyscall32,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {}
+};
 
-static ctl_table abi_root_table2[] = { 
-       { .ctl_name = CTL_ABI, .procname = "abi", .mode = 0555, 
-         .child = abi_table2 }, 
-       { 0 }, 
-}; 
+static ctl_table abi_root_table2[] = {
+       {
+               .ctl_name = CTL_ABI,
+               .procname = "abi",
+               .mode = 0555,
+               .child = abi_table2
+       },
+       {}
+};
 
 static __init int ia32_binfmt_init(void)
 { 
-       register_sysctl_table(abi_root_table2, 1);
+       register_sysctl_table(abi_root_table2);
        return 0;
 }
 __initcall(ia32_binfmt_init);
index ff499ef2a1ba10674cba34782c546cbeac43a51a..359eacc385094f76e4cc7d6eff8c288bda6ff4f6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/compat.h>
+#include <linux/binfmts.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
@@ -449,7 +450,11 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 
        /* Return stub is in 32bit vsyscall page */
        { 
-               void __user *restorer = VSYSCALL32_SIGRETURN; 
+               void __user *restorer;
+               if (current->binfmt->hasvdso)
+                       restorer = VSYSCALL32_SIGRETURN;
+               else
+                       restorer = (void *)&frame->retcode;
                if (ka->sa.sa_flags & SA_RESTORER)
                        restorer = ka->sa.sa_restorer;       
                err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
@@ -495,7 +500,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
                ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
@@ -601,7 +606,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
index 5f32cf4de5fb56e54cd0f5210c10cc62e8306866..eda7a0d4dc15c8050c65bcb3b2c1d81369115435 100644 (file)
@@ -718,4 +718,5 @@ ia32_sys_call_table:
        .quad compat_sys_vmsplice
        .quad compat_sys_move_pages
        .quad sys_getcpu
+       .quad sys_epoll_pwait
 ia32_syscall_end:              
index 3c7cbff04d3d78a2d8f5a73ecf8dbc1438475152..bb47e86f3d0228ae59a09834e1815de37ed5a983 100644 (file)
@@ -8,7 +8,7 @@ obj-y   := process.o signal.o entry.o traps.o irq.o \
                ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
                x8664_ksyms.o i387.o syscall.o vsyscall.o \
                setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
-               pci-dma.o pci-nommu.o alternative.o
+               pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_X86_MCE)          += mce.o therm_throt.o
@@ -19,7 +19,7 @@ obj-$(CONFIG_ACPI)            += acpi/
 obj-$(CONFIG_X86_MSR)          += msr.o
 obj-$(CONFIG_MICROCODE)                += microcode.o
 obj-$(CONFIG_X86_CPUID)                += cpuid.o
-obj-$(CONFIG_SMP)              += smp.o smpboot.o trampoline.o
+obj-$(CONFIG_SMP)              += smp.o smpboot.o trampoline.o tsc_sync.o
 obj-y                          += apic.o  nmi.o
 obj-y                          += io_apic.o mpparse.o \
                genapic.o genapic_cluster.o genapic_flat.o
@@ -43,6 +43,7 @@ obj-$(CONFIG_PCI)             += early-quirks.o
 
 obj-y                          += topology.o
 obj-y                          += intel_cacheinfo.o
+obj-y                          += pcspeaker.o
 
 CFLAGS_vsyscall.o              := $(PROFILING) -g0
 
@@ -56,3 +57,4 @@ quirks-y                      += ../../i386/kernel/quirks.o
 i8237-y                                += ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
 alternative-y                  += ../../i386/kernel/alternative.o
+pcspeaker-y                    += ../../i386/kernel/pcspeaker.o
index 5ebf62c7a3d2ba936c2e22dfcd0b0ae02b9bdde5..23178ce6c78380bc29f85e146e375676cd4e5242 100644 (file)
@@ -58,7 +58,7 @@ unsigned long acpi_wakeup_address = 0;
 unsigned long acpi_video_flags;
 extern char wakeup_start, wakeup_end;
 
-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 
 static pgd_t low_ptr;
 
index 124b2d27b4acd2e912d0d7db6f9dbe1a85bb5019..723417d924c09717c9c6659fbf5fe7361b0caafb 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/idle.h>
 #include <asm/proto.h>
 #include <asm/timex.h>
+#include <asm/hpet.h>
 #include <asm/apic.h>
 
 int apic_mapped;
@@ -763,7 +764,7 @@ static void setup_APIC_timer(unsigned int clocks)
        local_irq_save(flags);
 
        /* wait for irq slice */
-       if (vxtime.hpet_address && hpet_use_timer) {
+       if (hpet_address && hpet_use_timer) {
                int trigger = hpet_readl(HPET_T0_CMP);
                while (hpet_readl(HPET_COUNTER) >= trigger)
                        /* do nothing */ ;
@@ -785,7 +786,7 @@ static void setup_APIC_timer(unsigned int clocks)
        /* Turn off PIT interrupt if we use APIC timer as main timer.
           Only works with the PM timer right now
           TBD fix it for HPET too. */
-       if (vxtime.mode == VXTIME_PMTMR &&
+       if ((pmtmr_ioport != 0) &&
                smp_processor_id() == boot_cpu_id &&
                apic_runs_main_timer == 1 &&
                !cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
index 6fe191c5808465ddc7c8673c8996d52a67858d98..4651fd22b213bf047e7e9ffd9bf904ddeb4d1cd4 100644 (file)
@@ -83,6 +83,13 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
                return 1;
        }
 
+#ifdef CONFIG_NUMA
+       /* NUMA memory to node map */
+       if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
+               *addrp = nodemap_addr + nodemap_size;
+               return 1;
+       }
+#endif
        /* XXX ramdisk image here? */ 
        return 0;
 } 
@@ -183,6 +190,37 @@ unsigned long __init e820_end_of_ram(void)
        return end_pfn; 
 }
 
+/*
+ * Find the hole size in the range.
+ */
+unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
+{
+       unsigned long ram = 0;
+       int i;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               unsigned long last, addr;
+
+               if (ei->type != E820_RAM ||
+                   ei->addr+ei->size <= start ||
+                   ei->addr >= end)
+                       continue;
+
+               addr = round_up(ei->addr, PAGE_SIZE);
+               if (addr < start)
+                       addr = start;
+
+               last = round_down(ei->addr + ei->size, PAGE_SIZE);
+               if (last >= end)
+                       last = end;
+
+               if (last > addr)
+                       ram += last - addr;
+       }
+       return ((end - start) - ram);
+}
+
 /*
  * Mark e820 reserved areas as busy for the resource manager.
  */
index bd30d138113fa9e270a8e7974df36f185db11d50..8047ea8c2ab271e9e315547e3a77450d31edcab4 100644 (file)
@@ -53,7 +53,9 @@ static void nvidia_bugs(void)
                return;
 
        nvidia_hpet_detected = 0;
-       acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check);
+       if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check))
+               return;
+
        if (nvidia_hpet_detected == 0) {
                acpi_skip_timer_override = 1;
                printk(KERN_INFO "Nvidia board "
index 1e6f80870679506482ef7d2714621e8ad4df4d08..598a4d0351fc15190274f504995ec738f0b63cec 100644 (file)
@@ -163,6 +163,20 @@ startup_64:
         */
        lgdt    cpu_gdt_descr
 
+       /* set up data segments. actually 0 would do too */
+       movl $__KERNEL_DS,%eax
+       movl %eax,%ds
+       movl %eax,%ss
+       movl %eax,%es
+
+       /*
+        * We don't really need to load %fs or %gs, but load them anyway
+        * to kill any stale realmode selectors.  This allows execution
+        * under VT hardware.
+        */
+       movl %eax,%fs
+       movl %eax,%gs
+
        /* 
         * Setup up a dummy PDA. this is just for some early bootup code
         * that does in_interrupt() 
@@ -173,12 +187,6 @@ startup_64:
        shrq    $32,%rdx
        wrmsr   
 
-       /* set up data segments. actually 0 would do too */
-       movl $__KERNEL_DS,%eax
-       movl %eax,%ds   
-       movl %eax,%ss
-       movl %eax,%es
-                       
        /* esi is pointer to real mode structure with interesting info.
           pass it to C */
        movl    %esi, %edi
similarity index 57%
rename from arch/i386/kernel/time_hpet.c
rename to arch/x86_64/kernel/hpet.c
index 1e4702dfcd017e7649961465eaeb734116d9178b..65a0edd71a17ebd296336ef6162ff8c14590a933 100644 (file)
-/*
- *  linux/arch/i386/kernel/time_hpet.c
- *  This code largely copied from arch/x86_64/kernel/time.c
- *  See that file for credits.
- *
- *  2003-06-30    Venkatesh Pallipadi - Additional changes for HPET support
- */
-
-#include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
+#include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/smp.h>
+#include <linux/mc146818rtc.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
+#include <linux/hpet.h>
+#include <asm/pgtable.h>
+#include <asm/vsyscall.h>
+#include <asm/timex.h>
+#include <asm/hpet.h>
 
-#include <asm/timer.h>
-#include <asm/fixmap.h>
-#include <asm/apic.h>
+int nohpet __initdata;
 
-#include <linux/timex.h>
+unsigned long hpet_address;
+unsigned long hpet_period;     /* fsecs / HPET clock */
+unsigned long hpet_tick;       /* HPET clocks / interrupt */
 
-#include <asm/hpet.h>
-#include <linux/hpet.h>
+int hpet_use_timer;            /* Use counter of hpet for time keeping,
+                                * otherwise PIT
+                                */
 
-static unsigned long hpet_period;      /* fsecs / HPET clock */
-unsigned long hpet_tick;               /* hpet clks count per tick */
-unsigned long hpet_address;            /* hpet memory map physical address */
-int hpet_use_timer;
+#ifdef CONFIG_HPET
+static __init int late_hpet_init(void)
+{
+       struct hpet_data        hd;
+       unsigned int            ntimer;
 
-static int use_hpet;           /* can be used for runtime check of hpet */
-static int boot_hpet_disable;  /* boottime override for HPET timer */
-static void __iomem * hpet_virt_address;       /* hpet kernel virtual address */
+       if (!hpet_address)
+               return 0;
 
-#define FSEC_TO_USEC (1000000000UL)
+       memset(&hd, 0, sizeof(hd));
 
-int hpet_readl(unsigned long a)
-{
-       return readl(hpet_virt_address + a);
-}
+       ntimer = hpet_readl(HPET_ID);
+       ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
+       ntimer++;
 
-static void hpet_writel(unsigned long d, unsigned long a)
-{
-       writel(d, hpet_virt_address + a);
-}
+       /*
+        * Register with driver.
+        * Timer0 and Timer1 is used by platform.
+        */
+       hd.hd_phys_address = hpet_address;
+       hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
+       hd.hd_nirqs = ntimer;
+       hd.hd_flags = HPET_DATA_PLATFORM;
+       hpet_reserve_timer(&hd, 0);
+#ifdef CONFIG_HPET_EMULATE_RTC
+       hpet_reserve_timer(&hd, 1);
+#endif
+       hd.hd_irq[0] = HPET_LEGACY_8254;
+       hd.hd_irq[1] = HPET_LEGACY_RTC;
+       if (ntimer > 2) {
+               struct hpet             *hpet;
+               struct hpet_timer       *timer;
+               int                     i;
+
+               hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
+               timer = &hpet->hpet_timers[2];
+               for (i = 2; i < ntimer; timer++, i++)
+                       hd.hd_irq[i] = (timer->hpet_config &
+                                       Tn_INT_ROUTE_CNF_MASK) >>
+                               Tn_INT_ROUTE_CNF_SHIFT;
 
-#ifdef CONFIG_X86_LOCAL_APIC
-/*
- * HPET counters dont wrap around on every tick. They just change the
- * comparator value and continue. Next tick can be caught by checking
- * for a change in the comparator value. Used in apic.c.
- */
-static void __devinit wait_hpet_tick(void)
-{
-       unsigned int start_cmp_val, end_cmp_val;
+       }
 
-       start_cmp_val = hpet_readl(HPET_T0_CMP);
-       do {
-               end_cmp_val = hpet_readl(HPET_T0_CMP);
-       } while (start_cmp_val == end_cmp_val);
+       hpet_alloc(&hd);
+       return 0;
 }
+fs_initcall(late_hpet_init);
 #endif
 
-static int hpet_timer_stop_set_go(unsigned long tick)
+int hpet_timer_stop_set_go(unsigned long tick)
 {
        unsigned int cfg;
 
-       /*
-        * Stop the timers and reset the main counter.
-        */
+/*
+ * Stop the timers and reset the main counter.
+ */
+
        cfg = hpet_readl(HPET_CFG);
-       cfg &= ~HPET_CFG_ENABLE;
+       cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
        hpet_writel(cfg, HPET_CFG);
        hpet_writel(0, HPET_COUNTER);
        hpet_writel(0, HPET_COUNTER + 4);
 
+/*
+ * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
+ * and period also hpet_tick.
+ */
        if (hpet_use_timer) {
-               /*
-                * Set up timer 0, as periodic with first interrupt to happen at
-                * hpet_tick, and period also hpet_tick.
-                */
-               cfg = hpet_readl(HPET_T0_CFG);
-               cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-                      HPET_TN_SETVAL | HPET_TN_32BIT;
-               hpet_writel(cfg, HPET_T0_CFG);
-
-               /*
-                * The first write after writing TN_SETVAL to the config register sets
-                * the counter value, the second write sets the threshold.
-                */
-               hpet_writel(tick, HPET_T0_CMP);
-               hpet_writel(tick, HPET_T0_CMP);
-       }
-       /*
-        * Go!
-        */
-       cfg = hpet_readl(HPET_CFG);
-       if (hpet_use_timer)
+               hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+                   HPET_TN_32BIT, HPET_T0_CFG);
+               hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
+               hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
                cfg |= HPET_CFG_LEGACY;
+       }
+/*
+ * Go!
+ */
+
        cfg |= HPET_CFG_ENABLE;
        hpet_writel(cfg, HPET_CFG);
 
        return 0;
 }
 
-/*
- * Check whether HPET was found by ACPI boot parse. If yes setup HPET
- * counter 0 for kernel base timer.
- */
-int __init hpet_enable(void)
+int hpet_arch_init(void)
 {
        unsigned int id;
-       unsigned long tick_fsec_low, tick_fsec_high; /* tick in femto sec */
-       unsigned long hpet_tick_rem;
 
-       if (boot_hpet_disable)
+       if (!hpet_address)
                return -1;
+       set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
+       __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+
+/*
+ * Read the period, compute tick and quotient.
+ */
 
-       if (!hpet_address) {
-               return -1;
-       }
-       hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
-       /*
-        * Read the period, compute tick and quotient.
-        */
        id = hpet_readl(HPET_ID);
 
-       /*
-        * We are checking for value '1' or more in number field if
-        * CONFIG_HPET_EMULATE_RTC is set because we will need an
-        * additional timer for RTC emulation.
-        * However, we can do with one timer otherwise using the
-        * the single HPET timer for system time.
-        */
-#ifdef CONFIG_HPET_EMULATE_RTC
-       if (!(id & HPET_ID_NUMBER)) {
-               iounmap(hpet_virt_address);
-               hpet_virt_address = NULL;
+       if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
                return -1;
-       }
-#endif
-
 
        hpet_period = hpet_readl(HPET_PERIOD);
-       if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) {
-               iounmap(hpet_virt_address);
-               hpet_virt_address = NULL;
+       if (hpet_period < 100000 || hpet_period > 100000000)
                return -1;
-       }
 
-       /*
-        * 64 bit math
-        * First changing tick into fsec
-        * Then 64 bit div to find number of hpet clk per tick
-        */
-       ASM_MUL64_REG(tick_fsec_low, tick_fsec_high,
-                       KERNEL_TICK_USEC, FSEC_TO_USEC);
-       ASM_DIV64_REG(hpet_tick, hpet_tick_rem,
-                       hpet_period, tick_fsec_low, tick_fsec_high);
-
-       if (hpet_tick_rem > (hpet_period >> 1))
-               hpet_tick++; /* rounding the result */
-
-       hpet_use_timer = id & HPET_ID_LEGSUP;
-
-       if (hpet_timer_stop_set_go(hpet_tick)) {
-               iounmap(hpet_virt_address);
-               hpet_virt_address = NULL;
-               return -1;
-       }
+       hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
 
-       use_hpet = 1;
+       hpet_use_timer = (id & HPET_ID_LEGSUP);
 
-#ifdef CONFIG_HPET
-       {
-               struct hpet_data        hd;
-               unsigned int            ntimer;
-
-               memset(&hd, 0, sizeof (hd));
-
-               ntimer = hpet_readl(HPET_ID);
-               ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
-               ntimer++;
-
-               /*
-                * Register with driver.
-                * Timer0 and Timer1 is used by platform.
-                */
-               hd.hd_phys_address = hpet_address;
-               hd.hd_address = hpet_virt_address;
-               hd.hd_nirqs = ntimer;
-               hd.hd_flags = HPET_DATA_PLATFORM;
-               hpet_reserve_timer(&hd, 0);
-#ifdef CONFIG_HPET_EMULATE_RTC
-               hpet_reserve_timer(&hd, 1);
-#endif
-               hd.hd_irq[0] = HPET_LEGACY_8254;
-               hd.hd_irq[1] = HPET_LEGACY_RTC;
-               if (ntimer > 2) {
-                       struct hpet __iomem     *hpet;
-                       struct hpet_timer __iomem *timer;
-                       int                     i;
-
-                       hpet = hpet_virt_address;
-
-                       for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
-                               timer++, i++)
-                               hd.hd_irq[i] = (timer->hpet_config &
-                                       Tn_INT_ROUTE_CNF_MASK) >>
-                                       Tn_INT_ROUTE_CNF_SHIFT;
-
-               }
-
-               hpet_alloc(&hd);
-       }
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
-       if (hpet_use_timer)
-               wait_timer_tick = wait_hpet_tick;
-#endif
-       return 0;
+       return hpet_timer_stop_set_go(hpet_tick);
 }
 
 int hpet_reenable(void)
@@ -226,28 +140,51 @@ int hpet_reenable(void)
        return hpet_timer_stop_set_go(hpet_tick);
 }
 
-int is_hpet_enabled(void)
-{
-       return use_hpet;
-}
+/*
+ * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
+ * it to the HPET timer of known frequency.
+ */
 
-int is_hpet_capable(void)
+#define TICK_COUNT 100000000
+#define TICK_MIN   5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
 {
-       if (!boot_hpet_disable && hpet_address)
-               return 1;
-       return 0;
+       int tsc1, tsc2, hpet1;
+
+       do {
+               tsc1 = get_cycles_sync();
+               hpet1 = hpet_readl(HPET_COUNTER);
+               tsc2 = get_cycles_sync();
+       } while (tsc2 - tsc1 > TICK_MIN);
+       *hpet = hpet1;
+       *tsc = tsc2;
 }
 
-static int __init hpet_setup(char* str)
+unsigned int __init hpet_calibrate_tsc(void)
 {
-       if (str) {
-               if (!strncmp("disable", str, 7))
-                       boot_hpet_disable = 1;
-       }
-       return 1;
-}
+       int tsc_start, hpet_start;
+       int tsc_now, hpet_now;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       read_hpet_tsc(&hpet_start, &tsc_start);
 
-__setup("hpet=", hpet_setup);
+       do {
+               local_irq_disable();
+               read_hpet_tsc(&hpet_now, &tsc_now);
+               local_irq_restore(flags);
+       } while ((tsc_now - tsc_start) < TICK_COUNT &&
+               (hpet_now - hpet_start) < TICK_COUNT);
+
+       return (tsc_now - tsc_start) * 1000000000L
+               / ((hpet_now - hpet_start) * hpet_period / 1000);
+}
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
@@ -264,7 +201,6 @@ __setup("hpet=", hpet_setup);
  * For (3), we use interrupts at 64Hz or user specified periodic
  * frequency, whichever is higher.
  */
-#include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
 
 #define DEFAULT_RTC_INT_FREQ   64
@@ -283,6 +219,11 @@ static unsigned long PIE_count;
 static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
 static unsigned int hpet_t1_cmp; /* cached comparator register */
 
+int is_hpet_enabled(void)
+{
+       return hpet_address != 0;
+}
+
 /*
  * Timer 1 for RTC, we do not use periodic interrupt feature,
  * even if HPET supports periodic interrupts on Timer 1.
@@ -367,8 +308,9 @@ static void hpet_rtc_timer_reinit(void)
                if (PIE_on)
                        PIE_count += lost_ints;
 
-               printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-                      hpet_rtc_int_freq);
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+                              hpet_rtc_int_freq);
        }
 }
 
@@ -450,7 +392,7 @@ int hpet_rtc_dropped_irq(void)
        return 1;
 }
 
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct rtc_time curr_time;
        unsigned long rtc_int_flag = 0;
@@ -495,3 +437,75 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
 }
 #endif
 
+static int __init nohpet_setup(char *s)
+{
+       nohpet = 1;
+       return 1;
+}
+
+__setup("nohpet", nohpet_setup);
+
+#define HPET_MASK      0xFFFFFFFF
+#define HPET_SHIFT     22
+
+/* FSEC = 10^-15 NSEC = 10^-9 */
+#define FSEC_PER_NSEC  1000000
+
+static void *hpet_ptr;
+
+static cycle_t read_hpet(void)
+{
+       return (cycle_t)readl(hpet_ptr);
+}
+
+static cycle_t __vsyscall_fn vread_hpet(void)
+{
+       return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+
+struct clocksource clocksource_hpet = {
+       .name           = "hpet",
+       .rating         = 250,
+       .read           = read_hpet,
+       .mask           = (cycle_t)HPET_MASK,
+       .mult           = 0, /* set below */
+       .shift          = HPET_SHIFT,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .vread          = vread_hpet,
+};
+
+static int __init init_hpet_clocksource(void)
+{
+       unsigned long hpet_period;
+       void __iomem *hpet_base;
+       u64 tmp;
+
+       if (!hpet_address)
+               return -ENODEV;
+
+       /* calculate the hpet address: */
+       hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+       hpet_ptr = hpet_base + HPET_COUNTER;
+
+       /* calculate the frequency: */
+       hpet_period = readl(hpet_base + HPET_PERIOD);
+
+       /*
+        * hpet period is in femto seconds per cycle
+        * so we need to convert this to ns/cyc units
+        * aproximated by mult/2^shift
+        *
+        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+        *  (fsec/cyc << shift)/1000000 = mult
+        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+        */
+       tmp = (u64)hpet_period << HPET_SHIFT;
+       do_div(tmp, FSEC_PER_NSEC);
+       clocksource_hpet.mult = (u32)tmp;
+
+       return clocksource_register(&clocksource_hpet);
+}
+
+module_init(init_hpet_clocksource);
index d73c79e821f172ee3efe48f490e97b947bb8c153..01e2cf0bdeb10a60bbfb967d9dae2880b2f9827f 100644 (file)
@@ -103,6 +103,7 @@ static void mask_and_ack_8259A(unsigned int);
 static struct irq_chip i8259A_chip = {
        .name           = "XT-PIC",
        .mask           = disable_8259A_irq,
+       .disable        = disable_8259A_irq,
        .unmask         = enable_8259A_irq,
        .mask_ack       = mask_and_ack_8259A,
 };
index 6be6730acb5c9039ead2720c1a8219b011f3cde5..950682f3576697b3fa7bcc8b916be3b8a3547c8d 100644 (file)
@@ -810,11 +810,9 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
                        trigger == IOAPIC_LEVEL)
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_fasteoi_irq, "fasteoi");
-       else {
-               irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
+       else
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_edge_irq, "edge");
-       }
 }
 static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
 {
@@ -831,7 +829,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
        entry.delivery_mode = INT_DELIVERY_MODE;
        entry.dest_mode = INT_DEST_MODE;
        entry.mask = 0;                         /* enable IRQ */
-       entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+       entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
 
        entry.trigger = irq_trigger(idx);
        entry.polarity = irq_polarity(idx);
@@ -839,7 +837,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
        if (irq_trigger(idx)) {
                entry.trigger = 1;
                entry.mask = 1;
-               entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+               entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
        }
 
        if (!apic && !IO_APIC_IRQ(irq))
@@ -851,7 +849,7 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
                if (vector < 0)
                        return;
 
-               entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+               entry.dest = cpu_mask_to_apicid(mask);
                entry.vector = vector;
 
                ioapic_register_intr(irq, vector, IOAPIC_AUTO);
@@ -920,7 +918,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
         */
        entry.dest_mode = INT_DEST_MODE;
        entry.mask = 0;                                 /* unmask IRQ now */
-       entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+       entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
        entry.delivery_mode = INT_DELIVERY_MODE;
        entry.polarity = 0;
        entry.trigger = 0;
@@ -1020,18 +1018,17 @@ void __apicdebuginit print_IO_APIC(void)
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-       printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
-                         " Stat Dest Deli Vect:   \n");
+       printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+                         " Stat Dmod Deli Vect:   \n");
 
        for (i = 0; i <= reg_01.bits.entries; i++) {
                struct IO_APIC_route_entry entry;
 
                entry = ioapic_read_entry(apic, i);
 
-               printk(KERN_DEBUG " %02x %03X %02X  ",
+               printk(KERN_DEBUG " %02x %03X ",
                        i,
-                       entry.dest.logical.logical_dest,
-                       entry.dest.physical.physical_dest
+                       entry.dest
                );
 
                printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
@@ -1293,8 +1290,7 @@ void disable_IO_APIC(void)
                entry.dest_mode       = 0; /* Physical */
                entry.delivery_mode   = dest_ExtINT; /* ExtInt */
                entry.vector          = 0;
-               entry.dest.physical.physical_dest =
-                                       GET_APIC_ID(apic_read(APIC_ID));
+               entry.dest          = GET_APIC_ID(apic_read(APIC_ID));
 
                /*
                 * Add it to the IO-APIC irq-routing table:
@@ -1556,7 +1552,7 @@ static inline void unlock_ExtINT_logic(void)
 
        entry1.dest_mode = 0;                   /* physical delivery */
        entry1.mask = 0;                        /* unmask IRQ now */
-       entry1.dest.physical.physical_dest = hard_smp_processor_id();
+       entry1.dest = hard_smp_processor_id();
        entry1.delivery_mode = dest_ExtINT;
        entry1.polarity = entry0.polarity;
        entry1.trigger = 0;
@@ -2131,7 +2127,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
 
        entry.delivery_mode = INT_DELIVERY_MODE;
        entry.dest_mode = INT_DEST_MODE;
-       entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+       entry.dest = cpu_mask_to_apicid(mask);
        entry.trigger = triggering;
        entry.polarity = polarity;
        entry.mask = 1;                                  /* Disabled (masked) */
index fe063d3cfe42b7ff8c09184cd6986492cce01eeb..745b1f0f494ecdaa2dffce605549c127a52df567 100644 (file)
@@ -114,6 +114,6 @@ asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
                if (!capable(CAP_SYS_RAWIO))
                        return -EPERM;
        }
-       regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
+       regs->eflags = (regs->eflags &~ X86_EFLAGS_IOPL) | (level << 12);
        return 0;
 }
index 0c06af6c13bcb6c4d4e8331da76279442ce378a3..3bc30d2c13d3289809cd538f07cef4fc8033c0dc 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/uaccess.h>
 #include <asm/io_apic.h>
 #include <asm/idle.h>
+#include <asm/smp.h>
 
 atomic_t irq_err_count;
 
@@ -120,9 +121,14 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
 
        if (likely(irq < NR_IRQS))
                generic_handle_irq(irq);
-       else if (printk_ratelimit())
-               printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
-                       __func__, smp_processor_id(), vector);
+       else {
+               if (!disable_apic)
+                       ack_APIC_irq();
+
+               if (printk_ratelimit())
+                       printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
+                               __func__, smp_processor_id(), vector);
+       }
 
        irq_exit();
 
index bdb54a2c9f186be6acbb4eed72edcf943de9e8f7..8011a8e1c7d41d8a5baf2876c87697b37eec39ca 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/percpu.h>
 #include <linux/ctype.h>
+#include <linux/kmod.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -42,6 +43,10 @@ static unsigned long console_logged;
 static int notify_user;
 static int rip_msr;
 static int mce_bootlog = 1;
+static atomic_t mce_events;
+
+static char trigger[128];
+static char *trigger_argv[2] = { trigger, NULL };
 
 /*
  * Lockless MCE logging infrastructure.
@@ -57,6 +62,7 @@ struct mce_log mcelog = {
 void mce_log(struct mce *mce)
 {
        unsigned next, entry;
+       atomic_inc(&mce_events);
        mce->finished = 0;
        wmb();
        for (;;) {
@@ -161,6 +167,17 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
        }
 }
 
+static void do_mce_trigger(void)
+{
+       static atomic_t mce_logged;
+       int events = atomic_read(&mce_events);
+       if (events != atomic_read(&mce_logged) && trigger[0]) {
+               /* Small race window, but should be harmless.  */
+               atomic_set(&mce_logged, events);
+               call_usermodehelper(trigger, trigger_argv, NULL, -1);
+       }
+}
+
 /* 
  * The actual machine check handler
  */
@@ -234,8 +251,12 @@ void do_machine_check(struct pt_regs * regs, long error_code)
        }
 
        /* Never do anything final in the polling timer */
-       if (!regs)
+       if (!regs) {
+               /* Normal interrupt context here. Call trigger for any new
+                  events. */
+               do_mce_trigger();
                goto out;
+       }
 
        /* If we didn't find an uncorrectable error, pick
           the last one (shouldn't happen, just being safe). */
@@ -606,17 +627,42 @@ DEFINE_PER_CPU(struct sys_device, device_mce);
        }                                                                          \
        static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name);
 
+/* TBD should generate these dynamically based on number of available banks */
 ACCESSOR(bank0ctl,bank[0],mce_restart())
 ACCESSOR(bank1ctl,bank[1],mce_restart())
 ACCESSOR(bank2ctl,bank[2],mce_restart())
 ACCESSOR(bank3ctl,bank[3],mce_restart())
 ACCESSOR(bank4ctl,bank[4],mce_restart())
 ACCESSOR(bank5ctl,bank[5],mce_restart())
-static struct sysdev_attribute * bank_attributes[NR_BANKS] = {
-       &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
-       &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl};
+
+static ssize_t show_trigger(struct sys_device *s, char *buf)
+{
+       strcpy(buf, trigger);
+       strcat(buf, "\n");
+       return strlen(trigger) + 1;
+}
+
+static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz)
+{
+       char *p;
+       int len;
+       strncpy(trigger, buf, sizeof(trigger));
+       trigger[sizeof(trigger)-1] = 0;
+       len = strlen(trigger);
+       p = strchr(trigger, '\n');
+       if (*p) *p = 0;
+       return len;
+}
+
+static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
 ACCESSOR(tolerant,tolerant,)
 ACCESSOR(check_interval,check_interval,mce_restart())
+static struct sysdev_attribute *mce_attributes[] = {
+       &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
+       &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl,
+       &attr_tolerant, &attr_check_interval, &attr_trigger,
+       NULL
+};
 
 /* Per cpu sysdev init.  All of the cpus still share the same ctl bank */
 static __cpuinit int mce_create_device(unsigned int cpu)
@@ -632,11 +678,9 @@ static __cpuinit int mce_create_device(unsigned int cpu)
        err = sysdev_register(&per_cpu(device_mce,cpu));
 
        if (!err) {
-               for (i = 0; i < banks; i++)
+               for (i = 0; mce_attributes[i]; i++)
                        sysdev_create_file(&per_cpu(device_mce,cpu),
-                               bank_attributes[i]);
-               sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant);
-               sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval);
+                               mce_attributes[i]);
        }
        return err;
 }
@@ -645,11 +689,9 @@ static void mce_remove_device(unsigned int cpu)
 {
        int i;
 
-       for (i = 0; i < banks; i++)
+       for (i = 0; mce_attributes[i]; i++)
                sysdev_remove_file(&per_cpu(device_mce,cpu),
-                       bank_attributes[i]);
-       sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant);
-       sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
+                       mce_attributes[i]);
        sysdev_unregister(&per_cpu(device_mce,cpu));
        memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
 }
index 93c707257637cdea3b40eb472e7ab7baa442245f..d0bd5d66e103d8d491dc728cb06a82dec86425ba 100644 (file)
@@ -37,6 +37,8 @@
 #define THRESHOLD_MAX     0xFFF
 #define INT_TYPE_APIC     0x00020000
 #define MASK_VALID_HI     0x80000000
+#define MASK_CNTP_HI      0x40000000
+#define MASK_LOCKED_HI    0x20000000
 #define MASK_LVTOFF_HI    0x00F00000
 #define MASK_COUNT_EN_HI  0x00080000
 #define MASK_INT_TYPE_HI  0x00060000
@@ -122,14 +124,17 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
                for (block = 0; block < NR_BLOCKS; ++block) {
                        if (block == 0)
                                address = MSR_IA32_MC0_MISC + bank * 4;
-                       else if (block == 1)
-                               address = MCG_XBLK_ADDR
-                                       + ((low & MASK_BLKPTR_LO) >> 21);
+                       else if (block == 1) {
+                               address = (low & MASK_BLKPTR_LO) >> 21;
+                               if (!address)
+                                       break;
+                               address += MCG_XBLK_ADDR;
+                       }
                        else
                                ++address;
 
                        if (rdmsr_safe(address, &low, &high))
-                               continue;
+                               break;
 
                        if (!(high & MASK_VALID_HI)) {
                                if (block)
@@ -138,8 +143,8 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
                                        break;
                        }
 
-                       if (!(high & MASK_VALID_HI >> 1)  ||
-                            (high & MASK_VALID_HI >> 2))
+                       if (!(high & MASK_CNTP_HI)  ||
+                            (high & MASK_LOCKED_HI))
                                continue;
 
                        if (!block)
@@ -187,17 +192,22 @@ asmlinkage void mce_threshold_interrupt(void)
 
        /* assume first bank caused it */
        for (bank = 0; bank < NR_BANKS; ++bank) {
+               if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
+                       continue;
                for (block = 0; block < NR_BLOCKS; ++block) {
                        if (block == 0)
                                address = MSR_IA32_MC0_MISC + bank * 4;
-                       else if (block == 1)
-                               address = MCG_XBLK_ADDR
-                                       + ((low & MASK_BLKPTR_LO) >> 21);
+                       else if (block == 1) {
+                               address = (low & MASK_BLKPTR_LO) >> 21;
+                               if (!address)
+                                       break;
+                               address += MCG_XBLK_ADDR;
+                       }
                        else
                                ++address;
 
                        if (rdmsr_safe(address, &low, &high))
-                               continue;
+                               break;
 
                        if (!(high & MASK_VALID_HI)) {
                                if (block)
@@ -206,10 +216,14 @@ asmlinkage void mce_threshold_interrupt(void)
                                        break;
                        }
 
-                       if (!(high & MASK_VALID_HI >> 1)  ||
-                            (high & MASK_VALID_HI >> 2))
+                       if (!(high & MASK_CNTP_HI)  ||
+                            (high & MASK_LOCKED_HI))
                                continue;
 
+                       /* Log the machine check that caused the threshold
+                          event. */
+                       do_machine_check(NULL, 0);
+
                        if (high & MASK_OVERFLOW_HI) {
                                rdmsrl(address, m.misc);
                                rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
@@ -385,7 +399,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
                return 0;
 
        if (rdmsr_safe(address, &low, &high))
-               goto recurse;
+               return 0;
 
        if (!(high & MASK_VALID_HI)) {
                if (block)
@@ -394,8 +408,8 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
                        return 0;
        }
 
-       if (!(high & MASK_VALID_HI >> 1)  ||
-            (high & MASK_VALID_HI >> 2))
+       if (!(high & MASK_CNTP_HI)  ||
+            (high & MASK_LOCKED_HI))
                goto recurse;
 
        b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
index 9cb42ecb7f8966bb90bf3426f8b82e0cad9b55cf..486f4c61a948851f3b729a646da78e679e689341 100644 (file)
@@ -172,7 +172,7 @@ static __cpuinit inline int nmi_known_cpu(void)
 {
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
-               return boot_cpu_data.x86 == 15;
+               return boot_cpu_data.x86 == 15 || boot_cpu_data.x86 == 16;
        case X86_VENDOR_INTEL:
                if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
                        return 1;
@@ -214,6 +214,23 @@ static __init void nmi_cpu_busy(void *data)
 }
 #endif
 
+static unsigned int adjust_for_32bit_ctr(unsigned int hz)
+{
+       unsigned int retval = hz;
+
+       /*
+        * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
+        * are writable, with higher bits sign extending from bit 31.
+        * So, we can only program the counter with 31 bit values and
+        * 32nd bit should be 1, for 33.. to be 1.
+        * Find the appropriate nmi_hz
+        */
+       if ((((u64)cpu_khz * 1000) / retval) > 0x7fffffffULL) {
+               retval = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
+       }
+       return retval;
+}
+
 int __init check_nmi_watchdog (void)
 {
        int *counts;
@@ -268,17 +285,8 @@ int __init check_nmi_watchdog (void)
                struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
                nmi_hz = 1;
-               /*
-                * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
-                * are writable, with higher bits sign extending from bit 31.
-                * So, we can only program the counter with 31 bit values and
-                * 32nd bit should be 1, for 33.. to be 1.
-                * Find the appropriate nmi_hz
-                */
-               if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
-                       ((u64)cpu_khz * 1000) > 0x7fffffffULL) {
-                       nmi_hz = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
-               }
+               if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0)
+                       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
        }
 
        kfree(counts);
@@ -360,6 +368,33 @@ void enable_timer_nmi_watchdog(void)
        }
 }
 
+static void __acpi_nmi_disable(void *__unused)
+{
+       apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
+}
+
+/*
+ * Disable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_disable(void)
+{
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
+}
+
+static void __acpi_nmi_enable(void *__unused)
+{
+       apic_write(APIC_LVT0, APIC_DM_NMI);
+}
+
+/*
+ * Enable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_enable(void)
+{
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
+}
 #ifdef CONFIG_PM
 
 static int nmi_pm_active; /* nmi_active before suspend */
@@ -634,7 +669,9 @@ static int setup_intel_arch_watchdog(void)
 
        /* setup the timer */
        wrmsr(evntsel_msr, evntsel, 0);
-       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+
+       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+       wrmsr(perfctr_msr, (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
 
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
@@ -855,15 +892,23 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                                dummy &= ~P4_CCCR_OVF;
                                wrmsrl(wd->cccr_msr, dummy);
                                apic_write(APIC_LVTPC, APIC_DM_NMI);
+                               /* start the cycle over again */
+                               wrmsrl(wd->perfctr_msr,
+                                      -((u64)cpu_khz * 1000 / nmi_hz));
                        } else if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
                                /*
                                 * ArchPerfom/Core Duo needs to re-unmask
                                 * the apic vector
                                 */
                                apic_write(APIC_LVTPC, APIC_DM_NMI);
+                               /* ARCH_PERFMON has 32 bit counter writes */
+                               wrmsr(wd->perfctr_msr,
+                                    (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
+                       } else {
+                               /* start the cycle over again */
+                               wrmsrl(wd->perfctr_msr,
+                                      -((u64)cpu_khz * 1000 / nmi_hz));
                        }
-                       /* start the cycle over again */
-                       wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
                        rc = 1;
                } else  if (nmi_watchdog == NMI_IO_APIC) {
                        /* don't know how to accurately check for this.
index 3d65b1d4c2b39e4110dc913159615089e4a5ab02..04480c3b68f5d15177192e8336fcdecda4f52b68 100644 (file)
@@ -138,6 +138,8 @@ static const unsigned long phb_debug_offsets[] = {
 
 #define PHB_DEBUG_STUFF_OFFSET 0x0020
 
+#define EMERGENCY_PAGES 32 /* = 128KB */
+
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
@@ -296,6 +298,16 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
 {
        unsigned long entry;
        unsigned long badbit;
+       unsigned long badend;
+
+       /* were we called with bad_dma_address? */
+       badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE);
+       if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) {
+               printk(KERN_ERR "Calgary: driver tried unmapping bad DMA "
+                      "address 0x%Lx\n", dma_addr);
+               WARN_ON(1);
+               return;
+       }
 
        entry = dma_addr >> PAGE_SHIFT;
 
@@ -656,8 +668,8 @@ static void __init calgary_reserve_regions(struct pci_dev *dev)
        u64 start;
        struct iommu_table *tbl = dev->sysdata;
 
-       /* reserve bad_dma_address in case it's a legal address */
-       iommu_range_reserve(tbl, bad_dma_address, 1);
+       /* reserve EMERGENCY_PAGES from bad_dma_address and up */
+       iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES);
 
        /* avoid the BIOS/VGA first 640KB-1MB region */
        start = (640 * 1024);
@@ -1176,6 +1188,7 @@ int __init calgary_iommu_init(void)
        }
 
        force_iommu = 1;
+       bad_dma_address = 0x0;
        dma_ops = &calgary_dma_ops;
 
        return 0;
index 683b7a5c1ab30170d716a99fe90c633187f4a827..651ccfb06697dae54fbd96ffde647f12e98e691d 100644 (file)
@@ -223,30 +223,10 @@ int dma_set_mask(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL(dma_set_mask);
 
-/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge][,biomerge]
-   size  set size of iommu (in bytes)
-   noagp don't initialize the AGP driver and use full aperture.
-   off   don't use the IOMMU
-   leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
-   memaper[=order] allocate an own aperture over RAM with size 32MB^order.
-   noforce don't force IOMMU usage. Default.
-   force  Force IOMMU.
-   merge  Do lazy merging. This may improve performance on some block devices.
-          Implies force (experimental)
-   biomerge Do merging at the BIO layer. This is more efficient than merge,
-            but should be only done with very big IOMMUs. Implies merge,force.
-   nomerge Don't do SG merging.
-   forcesac For SAC mode for masks <40bits  (experimental)
-   fullflush Flush IOMMU on each allocation (default)
-   nofullflush Don't use IOMMU fullflush
-   allowed  overwrite iommu off workarounds for specific chipsets.
-   soft         Use software bounce buffering (default for Intel machines)
-   noaperture Don't touch the aperture for AGP.
-   allowdac Allow DMA >4GB
-   nodac    Forbid DMA >4GB
-   panic    Force panic when IOMMU overflows
-*/
+/*
+ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+ * documentation.
+ */
 __init int iommu_setup(char *p)
 {
        iommu_merge = 1;
index fc1960f1f243982f8ecd6746ce0bddb8828ab633..030eb3753358146c207f99864225cd88020137ba 100644 (file)
@@ -185,7 +185,7 @@ static void iommu_full(struct device *dev, size_t size, int dir)
 static inline int need_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
        u64 mask = *dev->dma_mask;
-       int high = addr + size >= mask;
+       int high = addr + size > mask;
        int mmu = high;
        if (force_iommu) 
                mmu = 1; 
@@ -195,7 +195,7 @@ static inline int need_iommu(struct device *dev, unsigned long addr, size_t size
 static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
        u64 mask = *dev->dma_mask;
-       int high = addr + size >= mask;
+       int high = addr + size > mask;
        int mmu = high;
        return mmu; 
 }
index 7554458dc9cbb6f35c2d8caf9f0333f5c7e41410..ae8f91214f1564e510cf63c49efe079eb504853a 100644 (file)
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
 
-/* The I/O port the PMTMR resides at.
- * The location is detected during setup_arch(),
- * in arch/i386/kernel/acpi/boot.c */
-u32 pmtmr_ioport __read_mostly;
-
-/* value of the Power timer at last timer interrupt */
-static u32 offset_delay;
-static u32 last_pmtmr_tick;
-
 #define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
 
 static inline u32 cyc2us(u32 cycles)
@@ -48,38 +39,6 @@ static inline u32 cyc2us(u32 cycles)
        return (cycles >> 10);
 }
 
-int pmtimer_mark_offset(void)
-{
-       static int first_run = 1;
-       unsigned long tsc;
-       u32 lost;
-
-       u32 tick = inl(pmtmr_ioport);
-       u32 delta;
-
-       delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
-
-       last_pmtmr_tick = tick;
-       monotonic_base += delta * NSEC_PER_USEC;
-
-       delta += offset_delay;
-
-       lost = delta / (USEC_PER_SEC / HZ);
-       offset_delay = delta % (USEC_PER_SEC / HZ);
-
-       rdtscll(tsc);
-       vxtime.last_tsc = tsc - offset_delay * (u64)cpu_khz / 1000;
-
-       /* don't calculate delay for first run,
-          or if we've got less then a tick */
-       if (first_run || (lost < 1)) {
-               first_run = 0;
-               offset_delay = 0;
-       }
-
-       return lost - 1;
-}
-
 static unsigned pmtimer_wait_tick(void)
 {
        u32 a, b;
@@ -101,23 +60,6 @@ void pmtimer_wait(unsigned us)
        } while (cyc2us(b - a) < us);
 }
 
-void pmtimer_resume(void)
-{
-       last_pmtmr_tick = inl(pmtmr_ioport);
-}
-
-unsigned int do_gettimeoffset_pm(void)
-{
-       u32 now, offset, delta = 0;
-
-       offset = last_pmtmr_tick;
-       now = inl(pmtmr_ioport);
-       delta = (now - offset) & ACPI_PM_MASK;
-
-       return offset_delay + cyc2us(delta);
-}
-
-
 static int __init nopmtimer_setup(char *s)
 {
        pmtmr_ioport = 0;
index addc14af0c562a7ec485c89fc6c69d71bb3ed1ca..4326a690a509a14ae2c5c4d2980233a82864eebc 100644 (file)
@@ -536,8 +536,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                }
                ret = 0;
                for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-                       ret |= __get_user(tmp, (unsigned long __user *) data);
-                       putreg(child, ui, tmp);
+                       ret = __get_user(tmp, (unsigned long __user *) data);
+                       if (ret)
+                               break;
+                       ret = putreg(child, ui, tmp);
+                       if (ret)
+                               break;
                        data += sizeof(long);
                }
                break;
index 60477244d1a371847ad69ac1c05237f0d0d06722..3d98b696881d7b012b9a176fadb5b482e810786c 100644 (file)
@@ -138,128 +138,6 @@ struct resource code_resource = {
        .flags = IORESOURCE_RAM,
 };
 
-#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
-
-static struct resource system_rom_resource = {
-       .name = "System ROM",
-       .start = 0xf0000,
-       .end = 0xfffff,
-       .flags = IORESOURCE_ROM,
-};
-
-static struct resource extension_rom_resource = {
-       .name = "Extension ROM",
-       .start = 0xe0000,
-       .end = 0xeffff,
-       .flags = IORESOURCE_ROM,
-};
-
-static struct resource adapter_rom_resources[] = {
-       { .name = "Adapter ROM", .start = 0xc8000, .end = 0,
-               .flags = IORESOURCE_ROM },
-       { .name = "Adapter ROM", .start = 0, .end = 0,
-               .flags = IORESOURCE_ROM },
-       { .name = "Adapter ROM", .start = 0, .end = 0,
-               .flags = IORESOURCE_ROM },
-       { .name = "Adapter ROM", .start = 0, .end = 0,
-               .flags = IORESOURCE_ROM },
-       { .name = "Adapter ROM", .start = 0, .end = 0,
-               .flags = IORESOURCE_ROM },
-       { .name = "Adapter ROM", .start = 0, .end = 0,
-               .flags = IORESOURCE_ROM }
-};
-
-static struct resource video_rom_resource = {
-       .name = "Video ROM",
-       .start = 0xc0000,
-       .end = 0xc7fff,
-       .flags = IORESOURCE_ROM,
-};
-
-static struct resource video_ram_resource = {
-       .name = "Video RAM area",
-       .start = 0xa0000,
-       .end = 0xbffff,
-       .flags = IORESOURCE_RAM,
-};
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static int __init romchecksum(unsigned char *rom, unsigned long length)
-{
-       unsigned char *p, sum = 0;
-
-       for (p = rom; p < rom + length; p++)
-               sum += *p;
-       return sum == 0;
-}
-
-static void __init probe_roms(void)
-{
-       unsigned long start, length, upper;
-       unsigned char *rom;
-       int           i;
-
-       /* video rom */
-       upper = adapter_rom_resources[0].start;
-       for (start = video_rom_resource.start; start < upper; start += 2048) {
-               rom = isa_bus_to_virt(start);
-               if (!romsignature(rom))
-                       continue;
-
-               video_rom_resource.start = start;
-
-               /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
-
-               /* if checksum okay, trust length byte */
-               if (length && romchecksum(rom, length))
-                       video_rom_resource.end = start + length - 1;
-
-               request_resource(&iomem_resource, &video_rom_resource);
-               break;
-                       }
-
-       start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
-       if (start < upper)
-               start = upper;
-
-       /* system rom */
-       request_resource(&iomem_resource, &system_rom_resource);
-       upper = system_rom_resource.start;
-
-       /* check for extension rom (ignore length byte!) */
-       rom = isa_bus_to_virt(extension_rom_resource.start);
-       if (romsignature(rom)) {
-               length = extension_rom_resource.end - extension_rom_resource.start + 1;
-               if (romchecksum(rom, length)) {
-                       request_resource(&iomem_resource, &extension_rom_resource);
-                       upper = extension_rom_resource.start;
-               }
-       }
-
-       /* check for adapter roms on 2k boundaries */
-       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper;
-            start += 2048) {
-               rom = isa_bus_to_virt(start);
-               if (!romsignature(rom))
-                       continue;
-
-               /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
-
-               /* but accept any length that fits if checksum okay */
-               if (!length || start + length > upper || !romchecksum(rom, length))
-                       continue;
-
-               adapter_rom_resources[i].start = start;
-               adapter_rom_resources[i].end = start + length - 1;
-               request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
-               start = adapter_rom_resources[i++].end & ~2047UL;
-       }
-}
-
 #ifdef CONFIG_PROC_VMCORE
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel. This option will be passed
@@ -444,6 +322,11 @@ void __init setup_arch(char **cmdline_p)
        /* reserve ebda region */
        if (ebda_addr)
                reserve_bootmem_generic(ebda_addr, ebda_size);
+#ifdef CONFIG_NUMA
+       /* reserve nodemap region */
+       if (nodemap_addr)
+               reserve_bootmem_generic(nodemap_addr, nodemap_size);
+#endif
 
 #ifdef CONFIG_SMP
        /*
@@ -519,15 +402,11 @@ void __init setup_arch(char **cmdline_p)
        init_apic_mappings();
 
        /*
-        * Request address space for all standard RAM and ROM resources
-        * and also for regions reported as reserved by the e820.
-        */
-       probe_roms();
+        * We trust e820 completely. No explicit ROM probing in memory.
+        */
        e820_reserve_resources(); 
        e820_mark_nosave_regions();
 
-       request_resource(&iomem_resource, &video_ram_resource);
-
        {
        unsigned i;
        /* request I/O space for devices used on all i[345]86 PCs */
@@ -1063,7 +942,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
-               NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+               NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+               "3dnowext", "3dnow",
 
                /* Transmeta-defined */
                "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1081,7 +961,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                /* Intel-defined (#2) */
                "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
                "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
-               NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* VIA/Cyrix/Centaur-defined */
@@ -1091,8 +971,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* AMD-defined (#2) */
-               "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+               "altmovcr8", "abm", "sse4a",
+               "misalignsse", "3dnowprefetch",
+               "osvw", "ibs", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        };
@@ -1103,6 +985,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "ttp",  /* thermal trip */
                "tm",
                "stc",
+               "100mhzsteps",
+               "hwpstate",
+               NULL,   /* tsc invariant mapped to constant_tsc */
                NULL,
                /* nothing */   /* constant_tsc - moved to flags */
        };
@@ -1219,23 +1104,3 @@ struct seq_operations cpuinfo_op = {
        .stop = c_stop,
        .show = show_cpuinfo,
 };
-
-#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
-#include <linux/platform_device.h>
-static __init int add_pcspkr(void)
-{
-       struct platform_device *pd;
-       int ret;
-
-       pd = platform_device_alloc("pcspkr", -1);
-       if (!pd)
-               return -ENOMEM;
-
-       ret = platform_device_add(pd);
-       if (ret)
-               platform_device_put(pd);
-
-       return ret;
-}
-device_initcall(add_pcspkr);
-#endif
index 8c4b80fe71a146c73447d4af46ced0e60d80c5b9..6a70b55f719d7cb47a463b3d8c638f7aae378c25 100644 (file)
@@ -37,7 +37,6 @@ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
 
 unsigned long __supported_pte_mask __read_mostly = ~0UL;
-EXPORT_SYMBOL(__supported_pte_mask);
 static int do_not_nx __cpuinitdata = 0;
 
 /* noexec=on|off
index daf19332f0dd02ed7ab4257e5c887989dfeb0ef8..35443729aad8b5fef81caba0483d5e6ab66d5856 100644 (file)
@@ -148,217 +148,6 @@ static void __cpuinit smp_store_cpu_info(int id)
        print_cpu_info(c);
 }
 
-/*
- * New Funky TSC sync algorithm borrowed from IA64.
- * Main advantage is that it doesn't reset the TSCs fully and
- * in general looks more robust and it works better than my earlier
- * attempts. I believe it was written by David Mosberger. Some minor
- * adjustments for x86-64 by me -AK
- *
- * Original comment reproduced below.
- *
- * Synchronize TSC of the current (slave) CPU with the TSC of the
- * MASTER CPU (normally the time-keeper CPU).  We use a closed loop to
- * eliminate the possibility of unaccounted-for errors (such as
- * getting a machine check in the middle of a calibration step).  The
- * basic idea is for the slave to ask the master what itc value it has
- * and to read its own itc before and after the master responds.  Each
- * iteration gives us three timestamps:
- *
- *     slave           master
- *
- *     t0 ---\
- *             ---\
- *                --->
- *                     tm
- *                /---
- *            /---
- *     t1 <---
- *
- *
- * The goal is to adjust the slave's TSC such that tm falls exactly
- * half-way between t0 and t1.  If we achieve this, the clocks are
- * synchronized provided the interconnect between the slave and the
- * master is symmetric.  Even if the interconnect were asymmetric, we
- * would still know that the synchronization error is smaller than the
- * roundtrip latency (t0 - t1).
- *
- * When the interconnect is quiet and symmetric, this lets us
- * synchronize the TSC to within one or two cycles.  However, we can
- * only *guarantee* that the synchronization is accurate to within a
- * round-trip time, which is typically in the range of several hundred
- * cycles (e.g., ~500 cycles).  In practice, this means that the TSCs
- * are usually almost perfectly synchronized, but we shouldn't assume
- * that the accuracy is much better than half a micro second or so.
- *
- * [there are other errors like the latency of RDTSC and of the
- * WRMSR. These can also account to hundreds of cycles. So it's
- * probably worse. It claims 153 cycles error on a dual Opteron,
- * but I suspect the numbers are actually somewhat worse -AK]
- */
-
-#define MASTER 0
-#define SLAVE  (SMP_CACHE_BYTES/8)
-
-/* Intentionally don't use cpu_relax() while TSC synchronization
-   because we don't want to go into funky power save modi or cause
-   hypervisors to schedule us away.  Going to sleep would likely affect
-   latency and low latency is the primary objective here. -AK */
-#define no_cpu_relax() barrier()
-
-static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static volatile __cpuinitdata unsigned long go[SLAVE + 1];
-static int notscsync __cpuinitdata;
-
-#undef DEBUG_TSC_SYNC
-
-#define NUM_ROUNDS     64      /* magic value */
-#define NUM_ITERS      5       /* likewise */
-
-/* Callback on boot CPU */
-static __cpuinit void sync_master(void *arg)
-{
-       unsigned long flags, i;
-
-       go[MASTER] = 0;
-
-       local_irq_save(flags);
-       {
-               for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
-                       while (!go[MASTER])
-                               no_cpu_relax();
-                       go[MASTER] = 0;
-                       rdtscll(go[SLAVE]);
-               }
-       }
-       local_irq_restore(flags);
-}
-
-/*
- * Return the number of cycles by which our tsc differs from the tsc
- * on the master (time-keeper) CPU.  A positive number indicates our
- * tsc is ahead of the master, negative that it is behind.
- */
-static inline long
-get_delta(long *rt, long *master)
-{
-       unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
-       unsigned long tcenter, t0, t1, tm;
-       int i;
-
-       for (i = 0; i < NUM_ITERS; ++i) {
-               rdtscll(t0);
-               go[MASTER] = 1;
-               while (!(tm = go[SLAVE]))
-                       no_cpu_relax();
-               go[SLAVE] = 0;
-               rdtscll(t1);
-
-               if (t1 - t0 < best_t1 - best_t0)
-                       best_t0 = t0, best_t1 = t1, best_tm = tm;
-       }
-
-       *rt = best_t1 - best_t0;
-       *master = best_tm - best_t0;
-
-       /* average best_t0 and best_t1 without overflow: */
-       tcenter = (best_t0/2 + best_t1/2);
-       if (best_t0 % 2 + best_t1 % 2 == 2)
-               ++tcenter;
-       return tcenter - best_tm;
-}
-
-static __cpuinit void sync_tsc(unsigned int master)
-{
-       int i, done = 0;
-       long delta, adj, adjust_latency = 0;
-       unsigned long flags, rt, master_time_stamp, bound;
-#ifdef DEBUG_TSC_SYNC
-       static struct syncdebug {
-               long rt;        /* roundtrip time */
-               long master;    /* master's timestamp */
-               long diff;      /* difference between midpoint and master's timestamp */
-               long lat;       /* estimate of tsc adjustment latency */
-       } t[NUM_ROUNDS] __cpuinitdata;
-#endif
-
-       printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n",
-               smp_processor_id(), master);
-
-       go[MASTER] = 1;
-
-       /* It is dangerous to broadcast IPI as cpus are coming up,
-        * as they may not be ready to accept them.  So since
-        * we only need to send the ipi to the boot cpu direct
-        * the message, and avoid the race.
-        */
-       smp_call_function_single(master, sync_master, NULL, 1, 0);
-
-       while (go[MASTER])      /* wait for master to be ready */
-               no_cpu_relax();
-
-       spin_lock_irqsave(&tsc_sync_lock, flags);
-       {
-               for (i = 0; i < NUM_ROUNDS; ++i) {
-                       delta = get_delta(&rt, &master_time_stamp);
-                       if (delta == 0) {
-                               done = 1;       /* let's lock on to this... */
-                               bound = rt;
-                       }
-
-                       if (!done) {
-                               unsigned long t;
-                               if (i > 0) {
-                                       adjust_latency += -delta;
-                                       adj = -delta + adjust_latency/4;
-                               } else
-                                       adj = -delta;
-
-                               rdtscll(t);
-                               wrmsrl(MSR_IA32_TSC, t + adj);
-                       }
-#ifdef DEBUG_TSC_SYNC
-                       t[i].rt = rt;
-                       t[i].master = master_time_stamp;
-                       t[i].diff = delta;
-                       t[i].lat = adjust_latency/4;
-#endif
-               }
-       }
-       spin_unlock_irqrestore(&tsc_sync_lock, flags);
-
-#ifdef DEBUG_TSC_SYNC
-       for (i = 0; i < NUM_ROUNDS; ++i)
-               printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
-                      t[i].rt, t[i].master, t[i].diff, t[i].lat);
-#endif
-
-       printk(KERN_INFO
-              "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
-              "maxerr %lu cycles)\n",
-              smp_processor_id(), master, delta, rt);
-}
-
-static void __cpuinit tsc_sync_wait(void)
-{
-       /*
-        * When the CPU has synchronized TSCs assume the BIOS
-        * or the hardware already synced.  Otherwise we could
-        * mess up a possible perfect synchronization with a
-        * not-quite-perfect algorithm.
-        */
-       if (notscsync || !cpu_has_tsc || !unsynchronized_tsc())
-               return;
-       sync_tsc(0);
-}
-
-static __init int notscsync_setup(char *s)
-{
-       notscsync = 1;
-       return 1;
-}
-__setup("notscsync", notscsync_setup);
-
 static atomic_t init_deasserted __cpuinitdata;
 
 /*
@@ -546,6 +335,11 @@ void __cpuinit start_secondary(void)
        /* otherwise gcc will move up the smp_processor_id before the cpu_init */
        barrier();
 
+       /*
+        * Check TSC sync first:
+        */
+       check_tsc_sync_target();
+
        Dprintk("cpu %d: setting up apic clock\n", smp_processor_id());         
        setup_secondary_APIC_clock();
 
@@ -565,14 +359,6 @@ void __cpuinit start_secondary(void)
         */
        set_cpu_sibling_map(smp_processor_id());
 
-       /* 
-        * Wait for TSC sync to not schedule things before.
-        * We still process interrupts, which could see an inconsistent
-        * time in that window unfortunately. 
-        * Do this here because TSC sync has global unprotected state.
-        */
-       tsc_sync_wait();
-
        /*
         * We need to hold call_lock, so there is no inconsistency
         * between the time smp_call_function() determines number of
@@ -592,6 +378,7 @@ void __cpuinit start_secondary(void)
        cpu_set(smp_processor_id(), cpu_online_map);
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
        spin_unlock(&vector_lock);
+
        unlock_ipi_call_lock();
 
        cpu_idle();
@@ -1168,6 +955,11 @@ int __cpuinit __cpu_up(unsigned int cpu)
        /* Unleash the CPU! */
        Dprintk("waiting for cpu %d\n", cpu);
 
+       /*
+        * Make sure and check TSC sync:
+        */
+       check_tsc_sync_source(cpu);
+
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
 
@@ -1190,7 +982,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
        smp_cleanup_boot();
        setup_ioapic_dest();
        check_nmi_watchdog();
-       time_init_gtod();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index 6026b31d037ef72a9b92213f1b522b8ba8e8f0b0..65ac2c6b34a6a1f80c9be549572e1d2f2e1d102e 100644 (file)
@@ -32,7 +32,7 @@ static void save_stack_address(void *data, unsigned long addr)
                trace->skip--;
                return;
        }
-       if (trace->nr_entries < trace->max_entries - 1)
+       if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = addr;
 }
 
@@ -49,7 +49,8 @@ static struct stacktrace_ops save_stack_ops = {
 void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
        dump_trace(task, NULL, NULL, &save_stack_ops, trace);
-       trace->entries[trace->nr_entries++] = ULONG_MAX;
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL(save_stack_trace);
 
index 335cc91c49b722c87ba12e8b4040c1f0ee38869b..c9addcfb96dc32793fc266178acc257eb4407f15 100644 (file)
 #include <linux/cpufreq.h>
 #include <linux/hpet.h>
 #include <asm/apic.h>
+#include <asm/hpet.h>
 
-#ifdef CONFIG_CPU_FREQ
-static void cpufreq_delayed_get(void);
-#endif
 extern void i8254_timer_resume(void);
 extern int using_apic_timer;
 
@@ -55,128 +53,7 @@ DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
 
-int nohpet __initdata = 0;
-static int notsc __initdata = 0;
-
-#define USEC_PER_TICK (USEC_PER_SEC / HZ)
-#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
-#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
-
-#define NS_SCALE       10 /* 2^10, carefully chosen */
-#define US_SCALE       32 /* 2^32, arbitralrily chosen */
-
-unsigned int cpu_khz;                                  /* TSC clocks / usec, not used here */
-EXPORT_SYMBOL(cpu_khz);
-static unsigned long hpet_period;                      /* fsecs / HPET clock */
-unsigned long hpet_tick;                               /* HPET clocks / interrupt */
-int hpet_use_timer;                            /* Use counter of hpet for time keeping, otherwise PIT */
-unsigned long vxtime_hz = PIT_TICK_RATE;
-int report_lost_ticks;                         /* command line option */
-unsigned long long monotonic_base;
-
-struct vxtime_data __vxtime __section_vxtime;  /* for vsyscalls */
-
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
-struct timespec __xtime __section_xtime;
-struct timezone __sys_tz __section_sys_tz;
-
-/*
- * do_gettimeoffset() returns microseconds since last timer interrupt was
- * triggered by hardware. A memory read of HPET is slower than a register read
- * of TSC, but much more reliable. It's also synchronized to the timer
- * interrupt. Note that do_gettimeoffset() may return more than hpet_tick, if a
- * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
- * This is not a problem, because jiffies hasn't updated either. They are bound
- * together by xtime_lock.
- */
-
-static inline unsigned int do_gettimeoffset_tsc(void)
-{
-       unsigned long t;
-       unsigned long x;
-       t = get_cycles_sync();
-       if (t < vxtime.last_tsc) 
-               t = vxtime.last_tsc; /* hack */
-       x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;
-       return x;
-}
-
-static inline unsigned int do_gettimeoffset_hpet(void)
-{
-       /* cap counter read to one tick to avoid inconsistencies */
-       unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
-       return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
-}
-
-unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
-
-/*
- * This version of gettimeofday() has microsecond resolution and better than
- * microsecond precision, as we're using at least a 10 MHz (usually 14.31818
- * MHz) HPET timer.
- */
-
-void do_gettimeofday(struct timeval *tv)
-{
-       unsigned long seq;
-       unsigned int sec, usec;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-
-               sec = xtime.tv_sec;
-               usec = xtime.tv_nsec / NSEC_PER_USEC;
-
-               /* i386 does some correction here to keep the clock 
-                  monotonous even when ntpd is fixing drift.
-                  But they didn't work for me, there is a non monotonic
-                  clock anyways with ntp.
-                  I dropped all corrections now until a real solution can
-                  be found. Note when you fix it here you need to do the same
-                  in arch/x86_64/kernel/vsyscall.c and export all needed
-                  variables in vmlinux.lds. -AK */ 
-               usec += do_gettimeoffset();
-
-       } while (read_seqretry(&xtime_lock, seq));
-
-       tv->tv_sec = sec + usec / USEC_PER_SEC;
-       tv->tv_usec = usec % USEC_PER_SEC;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-/*
- * settimeofday() first undoes the correction that gettimeofday would do
- * on the time, and then saves it. This is ugly, but has been like this for
- * ages already.
- */
-
-int do_settimeofday(struct timespec *tv)
-{
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
-
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irq(&xtime_lock);
-
-       nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-       ntp_clear();
-
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-       return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
 
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -267,84 +144,9 @@ static void set_rtc_mmss(unsigned long nowtime)
 }
 
 
-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
- *             Note: This function is required to return accurate
- *             time even in the absence of multiple timer ticks.
- */
-static inline unsigned long long cycles_2_ns(unsigned long long cyc);
-unsigned long long monotonic_clock(void)
-{
-       unsigned long seq;
-       u32 last_offset, this_offset, offset;
-       unsigned long long base;
-
-       if (vxtime.mode == VXTIME_HPET) {
-               do {
-                       seq = read_seqbegin(&xtime_lock);
-
-                       last_offset = vxtime.last;
-                       base = monotonic_base;
-                       this_offset = hpet_readl(HPET_COUNTER);
-               } while (read_seqretry(&xtime_lock, seq));
-               offset = (this_offset - last_offset);
-               offset *= NSEC_PER_TICK / hpet_tick;
-       } else {
-               do {
-                       seq = read_seqbegin(&xtime_lock);
-
-                       last_offset = vxtime.last_tsc;
-                       base = monotonic_base;
-               } while (read_seqretry(&xtime_lock, seq));
-               this_offset = get_cycles_sync();
-               offset = cycles_2_ns(this_offset - last_offset);
-       }
-       return base + offset;
-}
-EXPORT_SYMBOL(monotonic_clock);
-
-static noinline void handle_lost_ticks(int lost)
-{
-       static long lost_count;
-       static int warned;
-       if (report_lost_ticks) {
-               printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
-               print_symbol("rip %s)\n", get_irq_regs()->rip);
-       }
-
-       if (lost_count == 1000 && !warned) {
-               printk(KERN_WARNING "warning: many lost ticks.\n"
-                      KERN_WARNING "Your time source seems to be instable or "
-                               "some driver is hogging interupts\n");
-               print_symbol("rip %s\n", get_irq_regs()->rip);
-               if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
-                       printk(KERN_WARNING "Falling back to HPET\n");
-                       if (hpet_use_timer)
-                               vxtime.last = hpet_readl(HPET_T0_CMP) - 
-                                                       hpet_tick;
-                       else
-                               vxtime.last = hpet_readl(HPET_COUNTER);
-                       vxtime.mode = VXTIME_HPET;
-                       do_gettimeoffset = do_gettimeoffset_hpet;
-               }
-               /* else should fall back to PIT, but code missing. */
-               warned = 1;
-       } else
-               lost_count++;
-
-#ifdef CONFIG_CPU_FREQ
-       /* In some cases the CPU can change frequency without us noticing
-          Give cpufreq a change to catch up. */
-       if ((lost_count+1) % 25 == 0)
-               cpufreq_delayed_get();
-#endif
-}
-
 void main_timer_handler(void)
 {
        static unsigned long rtc_update = 0;
-       unsigned long tsc;
-       int delay = 0, offset = 0, lost = 0;
-
 /*
  * Here we are in the timer irq handler. We have irqs locally disabled (so we
  * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
@@ -354,72 +156,11 @@ void main_timer_handler(void)
 
        write_seqlock(&xtime_lock);
 
-       if (vxtime.hpet_address)
-               offset = hpet_readl(HPET_COUNTER);
-
-       if (hpet_use_timer) {
-               /* if we're using the hpet timer functionality,
-                * we can more accurately know the counter value
-                * when the timer interrupt occured.
-                */
-               offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-               delay = hpet_readl(HPET_COUNTER) - offset;
-       } else if (!pmtmr_ioport) {
-               spin_lock(&i8253_lock);
-               outb_p(0x00, 0x43);
-               delay = inb_p(0x40);
-               delay |= inb(0x40) << 8;
-               spin_unlock(&i8253_lock);
-               delay = LATCH - 1 - delay;
-       }
-
-       tsc = get_cycles_sync();
-
-       if (vxtime.mode == VXTIME_HPET) {
-               if (offset - vxtime.last > hpet_tick) {
-                       lost = (offset - vxtime.last) / hpet_tick - 1;
-               }
-
-               monotonic_base += 
-                       (offset - vxtime.last) * NSEC_PER_TICK / hpet_tick;
-
-               vxtime.last = offset;
-#ifdef CONFIG_X86_PM_TIMER
-       } else if (vxtime.mode == VXTIME_PMTMR) {
-               lost = pmtimer_mark_offset();
-#endif
-       } else {
-               offset = (((tsc - vxtime.last_tsc) *
-                          vxtime.tsc_quot) >> US_SCALE) - USEC_PER_TICK;
-
-               if (offset < 0)
-                       offset = 0;
-
-               if (offset > USEC_PER_TICK) {
-                       lost = offset / USEC_PER_TICK;
-                       offset %= USEC_PER_TICK;
-               }
-
-               monotonic_base += cycles_2_ns(tsc - vxtime.last_tsc);
-
-               vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
-
-               if ((((tsc - vxtime.last_tsc) *
-                     vxtime.tsc_quot) >> US_SCALE) < offset)
-                       vxtime.last_tsc = tsc -
-                               (((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
-       }
-
-       if (lost > 0)
-               handle_lost_ticks(lost);
-       else
-               lost = 0;
-
 /*
  * Do the timer stuff.
  */
 
-       do_timer(lost + 1);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(get_irq_regs()));
 #endif
@@ -460,40 +201,6 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static unsigned int cyc2ns_scale __read_mostly;
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
-       cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
-       return (cyc * cyc2ns_scale) >> NS_SCALE;
-}
-
-unsigned long long sched_clock(void)
-{
-       unsigned long a = 0;
-
-#if 0
-       /* Don't do a HPET read here. Using TSC always is much faster
-          and HPET may not be mapped yet when the scheduler first runs.
-           Disadvantage is a small drift between CPUs in some configurations,
-          but that should be tolerable. */
-       if (__vxtime.mode == VXTIME_HPET)
-               return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> US_SCALE;
-#endif
-
-       /* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
-          which means it is not completely exact and may not be monotonous between
-          CPUs. But the errors should be too small to matter for scheduling
-          purposes. */
-
-       rdtscll(a);
-       return cycles_2_ns(a);
-}
-
 static unsigned long get_cmos_time(void)
 {
        unsigned int year, mon, day, hour, min, sec;
@@ -545,159 +252,6 @@ static unsigned long get_cmos_time(void)
        return mktime(year, mon, day, hour, min, sec);
 }
 
-#ifdef CONFIG_CPU_FREQ
-
-/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
-   changes.
-   
-   RED-PEN: On SMP we assume all CPUs run with the same frequency.  It's
-   not that important because current Opteron setups do not support
-   scaling on SMP anyroads.
-
-   Should fix up last_tsc too. Currently gettimeofday in the
-   first tick after the change will be slightly wrong. */
-
-#include <linux/workqueue.h>
-
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(struct work_struct *v)
-{
-       unsigned int cpu;
-       for_each_online_cpu(cpu) {
-               cpufreq_get(cpu);
-       }
-       cpufreq_delayed_issched = 0;
-}
-
-/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
- * to verify the CPU frequency the timing core thinks the CPU is running
- * at is still correct.
- */
-static void cpufreq_delayed_get(void)
-{
-       static int warned;
-       if (cpufreq_init && !cpufreq_delayed_issched) {
-               cpufreq_delayed_issched = 1;
-               if (!warned) {
-                       warned = 1;
-                       printk(KERN_DEBUG 
-       "Losing some ticks... checking if CPU frequency changed.\n");
-               }
-               schedule_work(&cpufreq_delayed_get_work);
-       }
-}
-
-static unsigned int  ref_freq = 0;
-static unsigned long loops_per_jiffy_ref = 0;
-
-static unsigned long cpu_khz_ref = 0;
-
-static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-                                void *data)
-{
-        struct cpufreq_freqs *freq = data;
-       unsigned long *lpj, dummy;
-
-       if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
-               return 0;
-
-       lpj = &dummy;
-       if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-#ifdef CONFIG_SMP
-               lpj = &cpu_data[freq->cpu].loops_per_jiffy;
-#else
-               lpj = &boot_cpu_data.loops_per_jiffy;
-#endif
-
-       if (!ref_freq) {
-               ref_freq = freq->old;
-               loops_per_jiffy_ref = *lpj;
-               cpu_khz_ref = cpu_khz;
-       }
-        if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
-            (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
-           (val == CPUFREQ_RESUMECHANGE)) {
-                *lpj =
-               cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
-
-               cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-               if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-                       vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-       }
-       
-       set_cyc2ns_scale(cpu_khz_ref);
-
-       return 0;
-}
-static struct notifier_block time_cpufreq_notifier_block = {
-         .notifier_call  = time_cpufreq_notifier
-};
-
-static int __init cpufreq_tsc(void)
-{
-       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
-       if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
-                                      CPUFREQ_TRANSITION_NOTIFIER))
-               cpufreq_init = 1;
-       return 0;
-}
-
-core_initcall(cpufreq_tsc);
-
-#endif
-
-/*
- * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
- * it to the HPET timer of known frequency.
- */
-
-#define TICK_COUNT 100000000
-#define TICK_MIN   5000
-
-/*
- * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
- * occurs between the reads of the hpet & TSC.
- */
-static void __init read_hpet_tsc(int *hpet, int *tsc)
-{
-       int tsc1, tsc2, hpet1;
-
-       do {
-               tsc1 = get_cycles_sync();
-               hpet1 = hpet_readl(HPET_COUNTER);
-               tsc2 = get_cycles_sync();
-       } while (tsc2 - tsc1 > TICK_MIN);
-       *hpet = hpet1;
-       *tsc = tsc2;
-}
-
-
-static unsigned int __init hpet_calibrate_tsc(void)
-{
-       int tsc_start, hpet_start;
-       int tsc_now, hpet_now;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       local_irq_disable();
-
-       read_hpet_tsc(&hpet_start, &tsc_start);
-
-       do {
-               local_irq_disable();
-               read_hpet_tsc(&hpet_now, &tsc_now);
-               local_irq_restore(flags);
-       } while ((tsc_now - tsc_start) < TICK_COUNT &&
-                (hpet_now - hpet_start) < TICK_COUNT);
-
-       return (tsc_now - tsc_start) * 1000000000L
-               / ((hpet_now - hpet_start) * hpet_period / 1000);
-}
-
 
 /*
  * pit_calibrate_tsc() uses the speaker output (channel 2) of
@@ -728,124 +282,6 @@ static unsigned int __init pit_calibrate_tsc(void)
        return (end - start) / 50;
 }
 
-#ifdef CONFIG_HPET
-static __init int late_hpet_init(void)
-{
-       struct hpet_data        hd;
-       unsigned int            ntimer;
-
-       if (!vxtime.hpet_address)
-               return 0;
-
-       memset(&hd, 0, sizeof (hd));
-
-       ntimer = hpet_readl(HPET_ID);
-       ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
-       ntimer++;
-
-       /*
-        * Register with driver.
-        * Timer0 and Timer1 is used by platform.
-        */
-       hd.hd_phys_address = vxtime.hpet_address;
-       hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
-       hd.hd_nirqs = ntimer;
-       hd.hd_flags = HPET_DATA_PLATFORM;
-       hpet_reserve_timer(&hd, 0);
-#ifdef CONFIG_HPET_EMULATE_RTC
-       hpet_reserve_timer(&hd, 1);
-#endif
-       hd.hd_irq[0] = HPET_LEGACY_8254;
-       hd.hd_irq[1] = HPET_LEGACY_RTC;
-       if (ntimer > 2) {
-               struct hpet             *hpet;
-               struct hpet_timer       *timer;
-               int                     i;
-
-               hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
-               timer = &hpet->hpet_timers[2];
-               for (i = 2; i < ntimer; timer++, i++)
-                       hd.hd_irq[i] = (timer->hpet_config &
-                                       Tn_INT_ROUTE_CNF_MASK) >>
-                               Tn_INT_ROUTE_CNF_SHIFT;
-
-       }
-
-       hpet_alloc(&hd);
-       return 0;
-}
-fs_initcall(late_hpet_init);
-#endif
-
-static int hpet_timer_stop_set_go(unsigned long tick)
-{
-       unsigned int cfg;
-
-/*
- * Stop the timers and reset the main counter.
- */
-
-       cfg = hpet_readl(HPET_CFG);
-       cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
-       hpet_writel(cfg, HPET_CFG);
-       hpet_writel(0, HPET_COUNTER);
-       hpet_writel(0, HPET_COUNTER + 4);
-
-/*
- * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
- * and period also hpet_tick.
- */
-       if (hpet_use_timer) {
-               hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
-                   HPET_TN_32BIT, HPET_T0_CFG);
-               hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
-               hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
-               cfg |= HPET_CFG_LEGACY;
-       }
-/*
- * Go!
- */
-
-       cfg |= HPET_CFG_ENABLE;
-       hpet_writel(cfg, HPET_CFG);
-
-       return 0;
-}
-
-static int hpet_init(void)
-{
-       unsigned int id;
-
-       if (!vxtime.hpet_address)
-               return -1;
-       set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
-       __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
-
-/*
- * Read the period, compute tick and quotient.
- */
-
-       id = hpet_readl(HPET_ID);
-
-       if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
-               return -1;
-
-       hpet_period = hpet_readl(HPET_PERIOD);
-       if (hpet_period < 100000 || hpet_period > 100000000)
-               return -1;
-
-       hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
-
-       hpet_use_timer = (id & HPET_ID_LEGSUP);
-
-       return hpet_timer_stop_set_go(hpet_tick);
-}
-
-static int hpet_reenable(void)
-{
-       return hpet_timer_stop_set_go(hpet_tick);
-}
-
 #define PIT_MODE 0x43
 #define PIT_CH0  0x40
 
@@ -873,7 +309,7 @@ void __init pit_stop_interrupt(void)
 void __init stop_timer_interrupt(void)
 {
        char *name;
-       if (vxtime.hpet_address) {
+       if (hpet_address) {
                name = "HPET";
                hpet_timer_stop_set_go(0);
        } else {
@@ -883,12 +319,6 @@ void __init stop_timer_interrupt(void)
        printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
 }
 
-int __init time_setup(char *str)
-{
-       report_lost_ticks = 1;
-       return 1;
-}
-
 static struct irqaction irq0 = {
        timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
 };
@@ -896,124 +326,41 @@ static struct irqaction irq0 = {
 void __init time_init(void)
 {
        if (nohpet)
-               vxtime.hpet_address = 0;
-
+               hpet_address = 0;
        xtime.tv_sec = get_cmos_time();
        xtime.tv_nsec = 0;
 
        set_normalized_timespec(&wall_to_monotonic,
                                -xtime.tv_sec, -xtime.tv_nsec);
 
-       if (!hpet_init())
-                vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period;
-       else
-               vxtime.hpet_address = 0;
+       if (hpet_arch_init())
+               hpet_address = 0;
 
        if (hpet_use_timer) {
                /* set tick_nsec to use the proper rate for HPET */
                tick_nsec = TICK_NSEC_HPET;
                cpu_khz = hpet_calibrate_tsc();
                timename = "HPET";
-#ifdef CONFIG_X86_PM_TIMER
-       } else if (pmtmr_ioport && !vxtime.hpet_address) {
-               vxtime_hz = PM_TIMER_FREQUENCY;
-               timename = "PM";
-               pit_init();
-               cpu_khz = pit_calibrate_tsc();
-#endif
        } else {
                pit_init();
                cpu_khz = pit_calibrate_tsc();
                timename = "PIT";
        }
 
-       vxtime.mode = VXTIME_TSC;
-       vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
-       vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-       vxtime.last_tsc = get_cycles_sync();
-       set_cyc2ns_scale(cpu_khz);
-       setup_irq(0, &irq0);
-
-#ifndef CONFIG_SMP
-       time_init_gtod();
-#endif
-}
-
-/*
- * Make an educated guess if the TSC is trustworthy and synchronized
- * over all CPUs.
- */
-__cpuinit int unsynchronized_tsc(void)
-{
-#ifdef CONFIG_SMP
-       if (apic_is_clustered_box())
-               return 1;
-#endif
-       /* Most intel systems have synchronized TSCs except for
-          multi node systems */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
-#ifdef CONFIG_ACPI
-               /* But TSC doesn't tick in C3 so don't use it there */
-               if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000)
-                       return 1;
-#endif
-               return 0;
-       }
-
-       /* Assume multi socket systems are not synchronized */
-       return num_present_cpus() > 1;
-}
-
-/*
- * Decide what mode gettimeofday should use.
- */
-void time_init_gtod(void)
-{
-       char *timetype;
-
        if (unsynchronized_tsc())
-               notsc = 1;
+               mark_tsc_unstable();
 
-       if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
+       if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
                vgetcpu_mode = VGETCPU_RDTSCP;
        else
                vgetcpu_mode = VGETCPU_LSL;
 
-       if (vxtime.hpet_address && notsc) {
-               timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
-               if (hpet_use_timer)
-                       vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
-               else
-                       vxtime.last = hpet_readl(HPET_COUNTER);
-               vxtime.mode = VXTIME_HPET;
-               do_gettimeoffset = do_gettimeoffset_hpet;
-#ifdef CONFIG_X86_PM_TIMER
-       /* Using PM for gettimeofday is quite slow, but we have no other
-          choice because the TSC is too unreliable on some systems. */
-       } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
-               timetype = "PM";
-               do_gettimeoffset = do_gettimeoffset_pm;
-               vxtime.mode = VXTIME_PMTMR;
-               sysctl_vsyscall = 0;
-               printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
-#endif
-       } else {
-               timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
-               vxtime.mode = VXTIME_TSC;
-       }
-
-       printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
-              vxtime_hz / 1000000, vxtime_hz % 1000000, timename, timetype);
+       set_cyc2ns_scale(cpu_khz);
        printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
                cpu_khz / 1000, cpu_khz % 1000);
-       vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
-       vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-       vxtime.last_tsc = get_cycles_sync();
-
-       set_cyc2ns_scale(cpu_khz);
+       setup_irq(0, &irq0);
 }
 
-__setup("report_lost_ticks", time_setup);
 
 static long clock_cmos_diff;
 static unsigned long sleep_start;
@@ -1050,7 +397,7 @@ static int timer_resume(struct sys_device *dev)
                sleep_length = 0;
                ctime = sleep_start;
        }
-       if (vxtime.hpet_address)
+       if (hpet_address)
                hpet_reenable();
        else
                i8254_timer_resume();
@@ -1059,20 +406,8 @@ static int timer_resume(struct sys_device *dev)
        write_seqlock_irqsave(&xtime_lock,flags);
        xtime.tv_sec = sec;
        xtime.tv_nsec = 0;
-       if (vxtime.mode == VXTIME_HPET) {
-               if (hpet_use_timer)
-                       vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
-               else
-                       vxtime.last = hpet_readl(HPET_COUNTER);
-#ifdef CONFIG_X86_PM_TIMER
-       } else if (vxtime.mode == VXTIME_PMTMR) {
-               pmtimer_resume();
-#endif
-       } else
-               vxtime.last_tsc = get_cycles_sync();
-       write_sequnlock_irqrestore(&xtime_lock,flags);
        jiffies += sleep_length;
-       monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
+       write_sequnlock_irqrestore(&xtime_lock,flags);
        touch_softlockup_watchdog();
        return 0;
 }
@@ -1083,7 +418,7 @@ static struct sysdev_class timer_sysclass = {
        set_kset_name("timer"),
 };
 
-/* XXX this driverfs stuff should probably go elsewhere later -john */
+/* XXX this sysfs stuff should probably go elsewhere later -john */
 static struct sys_device device_timer = {
        .id     = 0,
        .cls    = &timer_sysclass,
@@ -1098,269 +433,3 @@ static int time_init_device(void)
 }
 
 device_initcall(time_init_device);
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
- * is enabled, we support RTC interrupt functionality in software.
- * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
- */
-#include <linux/rtc.h>
-
-#define DEFAULT_RTC_INT_FREQ   64
-#define RTC_NUM_INTS           1
-
-static unsigned long UIE_on;
-static unsigned long prev_update_sec;
-
-static unsigned long AIE_on;
-static struct rtc_time alarm_time;
-
-static unsigned long PIE_on;
-static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
-static unsigned long PIE_count;
-
-static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
-static unsigned int hpet_t1_cmp; /* cached comparator register */
-
-int is_hpet_enabled(void)
-{
-       return vxtime.hpet_address != 0;
-}
-
-/*
- * Timer 1 for RTC, we do not use periodic interrupt feature,
- * even if HPET supports periodic interrupts on Timer 1.
- * The reason being, to set up a periodic interrupt in HPET, we need to
- * stop the main counter. And if we do that everytime someone diables/enables
- * RTC, we will have adverse effect on main kernel timer running on Timer 0.
- * So, for the time being, simulate the periodic interrupt in software.
- *
- * hpet_rtc_timer_init() is called for the first time and during subsequent
- * interuppts reinit happens through hpet_rtc_timer_reinit().
- */
-int hpet_rtc_timer_init(void)
-{
-       unsigned int cfg, cnt;
-       unsigned long flags;
-
-       if (!is_hpet_enabled())
-               return 0;
-       /*
-        * Set the counter 1 and enable the interrupts.
-        */
-       if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-               hpet_rtc_int_freq = PIE_freq;
-       else
-               hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-       local_irq_save(flags);
-
-       cnt = hpet_readl(HPET_COUNTER);
-       cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
-       hpet_writel(cnt, HPET_T1_CMP);
-       hpet_t1_cmp = cnt;
-
-       cfg = hpet_readl(HPET_T1_CFG);
-       cfg &= ~HPET_TN_PERIODIC;
-       cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-       hpet_writel(cfg, HPET_T1_CFG);
-
-       local_irq_restore(flags);
-
-       return 1;
-}
-
-static void hpet_rtc_timer_reinit(void)
-{
-       unsigned int cfg, cnt, ticks_per_int, lost_ints;
-
-       if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
-               cfg = hpet_readl(HPET_T1_CFG);
-               cfg &= ~HPET_TN_ENABLE;
-               hpet_writel(cfg, HPET_T1_CFG);
-               return;
-       }
-
-       if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-               hpet_rtc_int_freq = PIE_freq;
-       else
-               hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-       /* It is more accurate to use the comparator value than current count.*/
-       ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
-       hpet_t1_cmp += ticks_per_int;
-       hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-       /*
-        * If the interrupt handler was delayed too long, the write above tries
-        * to schedule the next interrupt in the past and the hardware would
-        * not interrupt until the counter had wrapped around.
-        * So we have to check that the comparator wasn't set to a past time.
-        */
-       cnt = hpet_readl(HPET_COUNTER);
-       if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
-               lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
-               /* Make sure that, even with the time needed to execute
-                * this code, the next scheduled interrupt has been moved
-                * back to the future: */
-               lost_ints++;
-
-               hpet_t1_cmp += lost_ints * ticks_per_int;
-               hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-               if (PIE_on)
-                       PIE_count += lost_ints;
-
-               printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-                      hpet_rtc_int_freq);
-       }
-}
-
-/*
- * The functions below are called from rtc driver.
- * Return 0 if HPET is not being used.
- * Otherwise do the necessary changes and return 1.
- */
-int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
-{
-       if (!is_hpet_enabled())
-               return 0;
-
-       if (bit_mask & RTC_UIE)
-               UIE_on = 0;
-       if (bit_mask & RTC_PIE)
-               PIE_on = 0;
-       if (bit_mask & RTC_AIE)
-               AIE_on = 0;
-
-       return 1;
-}
-
-int hpet_set_rtc_irq_bit(unsigned long bit_mask)
-{
-       int timer_init_reqd = 0;
-
-       if (!is_hpet_enabled())
-               return 0;
-
-       if (!(PIE_on | AIE_on | UIE_on))
-               timer_init_reqd = 1;
-
-       if (bit_mask & RTC_UIE) {
-               UIE_on = 1;
-       }
-       if (bit_mask & RTC_PIE) {
-               PIE_on = 1;
-               PIE_count = 0;
-       }
-       if (bit_mask & RTC_AIE) {
-               AIE_on = 1;
-       }
-
-       if (timer_init_reqd)
-               hpet_rtc_timer_init();
-
-       return 1;
-}
-
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
-{
-       if (!is_hpet_enabled())
-               return 0;
-
-       alarm_time.tm_hour = hrs;
-       alarm_time.tm_min = min;
-       alarm_time.tm_sec = sec;
-
-       return 1;
-}
-
-int hpet_set_periodic_freq(unsigned long freq)
-{
-       if (!is_hpet_enabled())
-               return 0;
-
-       PIE_freq = freq;
-       PIE_count = 0;
-
-       return 1;
-}
-
-int hpet_rtc_dropped_irq(void)
-{
-       if (!is_hpet_enabled())
-               return 0;
-
-       return 1;
-}
-
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct rtc_time curr_time;
-       unsigned long rtc_int_flag = 0;
-       int call_rtc_interrupt = 0;
-
-       hpet_rtc_timer_reinit();
-
-       if (UIE_on | AIE_on) {
-               rtc_get_rtc_time(&curr_time);
-       }
-       if (UIE_on) {
-               if (curr_time.tm_sec != prev_update_sec) {
-                       /* Set update int info, call real rtc int routine */
-                       call_rtc_interrupt = 1;
-                       rtc_int_flag = RTC_UF;
-                       prev_update_sec = curr_time.tm_sec;
-               }
-       }
-       if (PIE_on) {
-               PIE_count++;
-               if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
-                       /* Set periodic int info, call real rtc int routine */
-                       call_rtc_interrupt = 1;
-                       rtc_int_flag |= RTC_PF;
-                       PIE_count = 0;
-               }
-       }
-       if (AIE_on) {
-               if ((curr_time.tm_sec == alarm_time.tm_sec) &&
-                   (curr_time.tm_min == alarm_time.tm_min) &&
-                   (curr_time.tm_hour == alarm_time.tm_hour)) {
-                       /* Set alarm int info, call real rtc int routine */
-                       call_rtc_interrupt = 1;
-                       rtc_int_flag |= RTC_AF;
-               }
-       }
-       if (call_rtc_interrupt) {
-               rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-               rtc_interrupt(rtc_int_flag, dev_id);
-       }
-       return IRQ_HANDLED;
-}
-#endif
-
-static int __init nohpet_setup(char *s) 
-{ 
-       nohpet = 1;
-       return 1;
-} 
-
-__setup("nohpet", nohpet_setup);
-
-int __init notsc_setup(char *s)
-{
-       notsc = 1;
-       return 1;
-}
-
-__setup("notsc", notsc_setup);
diff --git a/arch/x86_64/kernel/tsc.c b/arch/x86_64/kernel/tsc.c
new file mode 100644 (file)
index 0000000..8958318
--- /dev/null
@@ -0,0 +1,226 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/acpi.h>
+#include <linux/cpufreq.h>
+
+#include <asm/timex.h>
+
+static int notsc __initdata = 0;
+
+unsigned int cpu_khz;          /* TSC clocks / usec, not used here */
+EXPORT_SYMBOL(cpu_khz);
+
+static unsigned int cyc2ns_scale __read_mostly;
+
+void set_cyc2ns_scale(unsigned long khz)
+{
+       cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz;
+}
+
+static unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+       return (cyc * cyc2ns_scale) >> NS_SCALE;
+}
+
+unsigned long long sched_clock(void)
+{
+       unsigned long a = 0;
+
+       /* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
+        * which means it is not completely exact and may not be monotonous
+        * between CPUs. But the errors should be too small to matter for
+        * scheduling purposes.
+        */
+
+       rdtscll(a);
+       return cycles_2_ns(a);
+}
+
+static int tsc_unstable;
+
+static inline int check_tsc_unstable(void)
+{
+       return tsc_unstable;
+}
+#ifdef CONFIG_CPU_FREQ
+
+/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
+ * changes.
+ *
+ * RED-PEN: On SMP we assume all CPUs run with the same frequency.  It's
+ * not that important because current Opteron setups do not support
+ * scaling on SMP anyroads.
+ *
+ * Should fix up last_tsc too. Currently gettimeofday in the
+ * first tick after the change will be slightly wrong.
+ */
+
+#include <linux/workqueue.h>
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(struct work_struct *v)
+{
+       unsigned int cpu;
+       for_each_online_cpu(cpu) {
+               cpufreq_get(cpu);
+       }
+       cpufreq_delayed_issched = 0;
+}
+
+static unsigned int  ref_freq = 0;
+static unsigned long loops_per_jiffy_ref = 0;
+
+static unsigned long cpu_khz_ref = 0;
+
+static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+                                void *data)
+{
+       struct cpufreq_freqs *freq = data;
+       unsigned long *lpj, dummy;
+
+       if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+               return 0;
+
+       lpj = &dummy;
+       if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+#ifdef CONFIG_SMP
+               lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+#else
+               lpj = &boot_cpu_data.loops_per_jiffy;
+#endif
+
+       if (!ref_freq) {
+               ref_freq = freq->old;
+               loops_per_jiffy_ref = *lpj;
+               cpu_khz_ref = cpu_khz;
+       }
+       if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+               (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+               (val == CPUFREQ_RESUMECHANGE)) {
+               *lpj =
+               cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
+
+               cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
+               if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+                       mark_tsc_unstable();
+       }
+
+       set_cyc2ns_scale(cpu_khz_ref);
+
+       return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+       .notifier_call  = time_cpufreq_notifier
+};
+
+static int __init cpufreq_tsc(void)
+{
+       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
+       if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+                                      CPUFREQ_TRANSITION_NOTIFIER))
+               cpufreq_init = 1;
+       return 0;
+}
+
+core_initcall(cpufreq_tsc);
+
+#endif
+
+static int tsc_unstable = 0;
+
+/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+__cpuinit int unsynchronized_tsc(void)
+{
+       if (tsc_unstable)
+               return 1;
+
+#ifdef CONFIG_SMP
+       if (apic_is_clustered_box())
+               return 1;
+#endif
+       /* Most intel systems have synchronized TSCs except for
+          multi node systems */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+#ifdef CONFIG_ACPI
+               /* But TSC doesn't tick in C3 so don't use it there */
+               if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000)
+                       return 1;
+#endif
+               return 0;
+       }
+
+       /* Assume multi socket systems are not synchronized */
+       return num_present_cpus() > 1;
+}
+
+int __init notsc_setup(char *s)
+{
+       notsc = 1;
+       return 1;
+}
+
+__setup("notsc", notsc_setup);
+
+
+/* clock source code: */
+static cycle_t read_tsc(void)
+{
+       cycle_t ret = (cycle_t)get_cycles_sync();
+       return ret;
+}
+
+static cycle_t __vsyscall_fn vread_tsc(void)
+{
+       cycle_t ret = (cycle_t)get_cycles_sync();
+       return ret;
+}
+
+static struct clocksource clocksource_tsc = {
+       .name                   = "tsc",
+       .rating                 = 300,
+       .read                   = read_tsc,
+       .mask                   = CLOCKSOURCE_MASK(64),
+       .shift                  = 22,
+       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
+                                 CLOCK_SOURCE_MUST_VERIFY,
+       .vread                  = vread_tsc,
+};
+
+void mark_tsc_unstable(void)
+{
+       if (!tsc_unstable) {
+               tsc_unstable = 1;
+               /* Change only the rating, when not registered */
+               if (clocksource_tsc.mult)
+                       clocksource_change_rating(&clocksource_tsc, 0);
+               else
+                       clocksource_tsc.rating = 0;
+       }
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
+static int __init init_tsc_clocksource(void)
+{
+       if (!notsc) {
+               clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
+                                                       clocksource_tsc.shift);
+               if (check_tsc_unstable())
+                       clocksource_tsc.rating = 0;
+
+               return clocksource_register(&clocksource_tsc);
+       }
+       return 0;
+}
+
+module_init(init_tsc_clocksource);
diff --git a/arch/x86_64/kernel/tsc_sync.c b/arch/x86_64/kernel/tsc_sync.c
new file mode 100644 (file)
index 0000000..014f0db
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * arch/x86_64/kernel/tsc_sync.c: check TSC synchronization.
+ *
+ * Copyright (C) 2006, Red Hat, Inc., Ingo Molnar
+ *
+ * We check whether all boot CPUs have their TSC's synchronized,
+ * print a warning if not and turn off the TSC clock-source.
+ *
+ * The warp-check is point-to-point between two CPUs, the CPU
+ * initiating the bootup is the 'source CPU', the freshly booting
+ * CPU is the 'target CPU'.
+ *
+ * Only two CPUs may participate - they can enter in any order.
+ * ( The serial nature of the boot logic and the CPU hotplug lock
+ *   protects against more than 2 CPUs entering this code. )
+ */
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/nmi.h>
+#include <asm/tsc.h>
+
+/*
+ * Entry/exit counters that make sure that both CPUs
+ * run the measurement code at once:
+ */
+static __cpuinitdata atomic_t start_count;
+static __cpuinitdata atomic_t stop_count;
+
+/*
+ * We use a raw spinlock in this exceptional case, because
+ * we want to have the fastest, inlined, non-debug version
+ * of a critical section, to be able to prove TSC time-warps:
+ */
+static __cpuinitdata raw_spinlock_t sync_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static __cpuinitdata cycles_t last_tsc;
+static __cpuinitdata cycles_t max_warp;
+static __cpuinitdata int nr_warps;
+
+/*
+ * TSC-warp measurement loop running on both CPUs:
+ */
+static __cpuinit void check_tsc_warp(void)
+{
+       cycles_t start, now, prev, end;
+       int i;
+
+       start = get_cycles_sync();
+       /*
+        * The measurement runs for 20 msecs:
+        */
+       end = start + cpu_khz * 20ULL;
+       now = start;
+
+       for (i = 0; ; i++) {
+               /*
+                * We take the global lock, measure TSC, save the
+                * previous TSC that was measured (possibly on
+                * another CPU) and update the previous TSC timestamp.
+                */
+               __raw_spin_lock(&sync_lock);
+               prev = last_tsc;
+               now = get_cycles_sync();
+               last_tsc = now;
+               __raw_spin_unlock(&sync_lock);
+
+               /*
+                * Be nice every now and then (and also check whether
+                * measurement is done [we also insert a 100 million
+                * loops safety exit, so we dont lock up in case the
+                * TSC readout is totally broken]):
+                */
+               if (unlikely(!(i & 7))) {
+                       if (now > end || i > 100000000)
+                               break;
+                       cpu_relax();
+                       touch_nmi_watchdog();
+               }
+               /*
+                * Outside the critical section we can now see whether
+                * we saw a time-warp of the TSC going backwards:
+                */
+               if (unlikely(prev > now)) {
+                       __raw_spin_lock(&sync_lock);
+                       max_warp = max(max_warp, prev - now);
+                       nr_warps++;
+                       __raw_spin_unlock(&sync_lock);
+               }
+
+       }
+}
+
+/*
+ * Source CPU calls into this - it waits for the freshly booted
+ * target CPU to arrive and then starts the measurement:
+ */
+void __cpuinit check_tsc_sync_source(int cpu)
+{
+       int cpus = 2;
+
+       /*
+        * No need to check if we already know that the TSC is not
+        * synchronized:
+        */
+       if (unsynchronized_tsc())
+               return;
+
+       printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
+                         smp_processor_id(), cpu);
+
+       /*
+        * Reset it - in case this is a second bootup:
+        */
+       atomic_set(&stop_count, 0);
+
+       /*
+        * Wait for the target to arrive:
+        */
+       while (atomic_read(&start_count) != cpus-1)
+               cpu_relax();
+       /*
+        * Trigger the target to continue into the measurement too:
+        */
+       atomic_inc(&start_count);
+
+       check_tsc_warp();
+
+       while (atomic_read(&stop_count) != cpus-1)
+               cpu_relax();
+
+       /*
+        * Reset it - just in case we boot another CPU later:
+        */
+       atomic_set(&start_count, 0);
+
+       if (nr_warps) {
+               printk("\n");
+               printk(KERN_WARNING "Measured %Ld cycles TSC warp between CPUs,"
+                                   " turning off TSC clock.\n", max_warp);
+               mark_tsc_unstable();
+               nr_warps = 0;
+               max_warp = 0;
+               last_tsc = 0;
+       } else {
+               printk(" passed.\n");
+       }
+
+       /*
+        * Let the target continue with the bootup:
+        */
+       atomic_inc(&stop_count);
+}
+
+/*
+ * Freshly booted CPUs call into this:
+ */
+void __cpuinit check_tsc_sync_target(void)
+{
+       int cpus = 2;
+
+       if (unsynchronized_tsc())
+               return;
+
+       /*
+        * Register this CPU's participation and wait for the
+        * source CPU to start the measurement:
+        */
+       atomic_inc(&start_count);
+       while (atomic_read(&start_count) != cpus)
+               cpu_relax();
+
+       check_tsc_warp();
+
+       /*
+        * Ok, we are done:
+        */
+       atomic_inc(&stop_count);
+
+       /*
+        * Wait for the source CPU to print stuff:
+        */
+       while (atomic_read(&stop_count) != cpus)
+               cpu_relax();
+}
+#undef NR_LOOPS
+
index c360c42252444ad83eb20165b4d5ae8967dd06c5..b73212c0a55001d0c24df52442a9b027879e3183 100644 (file)
@@ -88,31 +88,25 @@ SECTIONS
   __vsyscall_0 = VSYSCALL_VIRT_ADDR;
 
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .xtime_lock : AT(VLOAD(.xtime_lock)) { *(.xtime_lock) }
-  xtime_lock = VVIRT(.xtime_lock);
-
-  .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
-  vxtime = VVIRT(.vxtime);
+  .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { *(.vsyscall_fn) }
+  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+  .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data))
+               { *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
 
   .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
   vgetcpu_mode = VVIRT(.vgetcpu_mode);
 
-  .sys_tz : AT(VLOAD(.sys_tz)) { *(.sys_tz) }
-  sys_tz = VVIRT(.sys_tz);
-
-  .sysctl_vsyscall : AT(VLOAD(.sysctl_vsyscall)) { *(.sysctl_vsyscall) }
-  sysctl_vsyscall = VVIRT(.sysctl_vsyscall);
-
-  .xtime : AT(VLOAD(.xtime)) { *(.xtime) }
-  xtime = VVIRT(.xtime);
-
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
   jiffies = VVIRT(.jiffies);
 
-  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
-  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
-  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
+               { *(.vsyscall_1) }
+  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
+               { *(.vsyscall_2) }
+  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
+               { *(.vsyscall_3) }
 
   . = VSYSCALL_VIRT_ADDR + 4096;
 
index 2433d6fc68b14faa4f51b9e841a0b1f9d755f3af..180ff919eaf91a85fd0e39f9146ed49aa7d1933b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/seqlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
+#include <linux/clocksource.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
@@ -34,6 +35,7 @@
 #include <asm/vsyscall.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/unistd.h>
 #include <asm/fixmap.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
 #define __syscall_clobber "r11","rcx","memory"
 
-int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
-seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
+struct vsyscall_gtod_data_t {
+       seqlock_t lock;
+       int sysctl_enabled;
+       struct timeval wall_time_tv;
+       struct timezone sys_tz;
+       cycle_t offset_base;
+       struct clocksource clock;
+};
 int __vgetcpu_mode __section_vgetcpu_mode;
 
-#include <asm/unistd.h>
-
-static __always_inline void timeval_normalize(struct timeval * tv)
+struct vsyscall_gtod_data_t __vsyscall_gtod_data __section_vsyscall_gtod_data =
 {
-       time_t __sec;
-
-       __sec = tv->tv_usec / 1000000;
-       if (__sec) {
-               tv->tv_usec %= 1000000;
-               tv->tv_sec += __sec;
-       }
-}
+       .lock = SEQLOCK_UNLOCKED,
+       .sysctl_enabled = 1,
+};
 
-static __always_inline void do_vgettimeofday(struct timeval * tv)
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
 {
-       long sequence, t;
-       unsigned long sec, usec;
-
-       do {
-               sequence = read_seqbegin(&__xtime_lock);
-               
-               sec = __xtime.tv_sec;
-               usec = __xtime.tv_nsec / 1000;
-
-               if (__vxtime.mode != VXTIME_HPET) {
-                       t = get_cycles_sync();
-                       if (t < __vxtime.last_tsc)
-                               t = __vxtime.last_tsc;
-                       usec += ((t - __vxtime.last_tsc) *
-                                __vxtime.tsc_quot) >> 32;
-                       /* See comment in x86_64 do_gettimeofday. */
-               } else {
-                       usec += ((readl((void __iomem *)
-                                  fix_to_virt(VSYSCALL_HPET) + 0xf0) -
-                                 __vxtime.last) * __vxtime.quot) >> 32;
-               }
-       } while (read_seqretry(&__xtime_lock, sequence));
-
-       tv->tv_sec = sec + usec / 1000000;
-       tv->tv_usec = usec % 1000000;
+       unsigned long flags;
+
+       write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+       /* copy vsyscall data */
+       vsyscall_gtod_data.clock = *clock;
+       vsyscall_gtod_data.wall_time_tv.tv_sec = wall_time->tv_sec;
+       vsyscall_gtod_data.wall_time_tv.tv_usec = wall_time->tv_nsec/1000;
+       vsyscall_gtod_data.sys_tz = sys_tz;
+       write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
 
-/* RED-PEN may want to readd seq locking, but then the variable should be write-once. */
+/* RED-PEN may want to readd seq locking, but then the variable should be
+ * write-once.
+ */
 static __always_inline void do_get_tz(struct timezone * tz)
 {
-       *tz = __sys_tz;
+       *tz = __vsyscall_gtod_data.sys_tz;
 }
 
 static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
@@ -101,7 +88,8 @@ static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
        int ret;
        asm volatile("vsysc2: syscall"
                : "=a" (ret)
-               : "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber );
+               : "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
+               : __syscall_clobber );
        return ret;
 }
 
@@ -114,10 +102,44 @@ static __always_inline long time_syscall(long *t)
        return secs;
 }
 
+static __always_inline void do_vgettimeofday(struct timeval * tv)
+{
+       cycle_t now, base, mask, cycle_delta;
+       unsigned long seq, mult, shift, nsec_delta;
+       cycle_t (*vread)(void);
+       do {
+               seq = read_seqbegin(&__vsyscall_gtod_data.lock);
+
+               vread = __vsyscall_gtod_data.clock.vread;
+               if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) {
+                       gettimeofday(tv,0);
+                       return;
+               }
+               now = vread();
+               base = __vsyscall_gtod_data.clock.cycle_last;
+               mask = __vsyscall_gtod_data.clock.mask;
+               mult = __vsyscall_gtod_data.clock.mult;
+               shift = __vsyscall_gtod_data.clock.shift;
+
+               *tv = __vsyscall_gtod_data.wall_time_tv;
+
+       } while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
+
+       /* calculate interval: */
+       cycle_delta = (now - base) & mask;
+       /* convert to nsecs: */
+       nsec_delta = (cycle_delta * mult) >> shift;
+
+       /* convert to usecs and add to timespec: */
+       tv->tv_usec += nsec_delta / NSEC_PER_USEC;
+       while (tv->tv_usec > USEC_PER_SEC) {
+               tv->tv_sec += 1;
+               tv->tv_usec -= USEC_PER_SEC;
+       }
+}
+
 int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
-       if (!__sysctl_vsyscall)
-               return gettimeofday(tv,tz);
        if (tv)
                do_vgettimeofday(tv);
        if (tz)
@@ -129,11 +151,11 @@ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
-       if (!__sysctl_vsyscall)
+       if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
                return time_syscall(t);
        else if (t)
-               *t = __xtime.tv_sec;            
-       return __xtime.tv_sec;
+               *t = __vsyscall_gtod_data.wall_time_tv.tv_sec;
+       return __vsyscall_gtod_data.wall_time_tv.tv_sec;
 }
 
 /* Fast way to get current CPU and node.
@@ -210,7 +232,7 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
                ret = -ENOMEM;
                goto out;
        }
-       if (!sysctl_vsyscall) {
+       if (!vsyscall_gtod_data.sysctl_enabled) {
                writew(SYSCALL, map1);
                writew(SYSCALL, map2);
        } else {
@@ -232,16 +254,17 @@ static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
 
 static ctl_table kernel_table2[] = {
        { .ctl_name = 99, .procname = "vsyscall64",
-         .data = &sysctl_vsyscall, .maxlen = sizeof(int), .mode = 0644,
+         .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
+         .mode = 0644,
          .strategy = vsyscall_sysctl_nostrat,
          .proc_handler = vsyscall_sysctl_change },
-       { 0, }
+       {}
 };
 
 static ctl_table kernel_root_table2[] = {
        { .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
          .child = kernel_table2 },
-       { 0 },
+       {}
 };
 
 #endif
@@ -301,7 +324,7 @@ static int __init vsyscall_init(void)
        BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
        map_vsyscall();
 #ifdef CONFIG_SYSCTL
-       register_sysctl_table(kernel_root_table2, 0);
+       register_sysctl_table(kernel_root_table2);
 #endif
        on_each_cpu(cpu_vsyscall_init, NULL, 0, 1);
        hotcpu_notifier(cpu_vsyscall_notifier, 0);
index 6d77e4797a471035978e04e4307a71d034918cbc..0dffae69f4ad89a52e0deb67688d1648f3f32c21 100644 (file)
@@ -26,6 +26,7 @@ EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(copy_user_generic);
+EXPORT_SYMBOL(__copy_user_nocache);
 EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_to_user);
 EXPORT_SYMBOL(__copy_from_user_inatomic);
@@ -34,8 +35,8 @@ EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
 
 #ifdef CONFIG_SMP
-extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
+extern void  __write_lock_failed(rwlock_t *rw);
+extern void  __read_lock_failed(rwlock_t *rw);
 EXPORT_SYMBOL(__write_lock_failed);
 EXPORT_SYMBOL(__read_lock_failed);
 #endif
index b78d4170fce230ea2d1797295a9248d1efdc66ea..8d5f835af4819bdcba182705d8c1e1b450c8fa87 100644 (file)
@@ -9,4 +9,4 @@ obj-y := io.o iomap_copy.o
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
        usercopy.o getuser.o putuser.o  \
        thunk.o clear_page.o copy_page.o bitstr.o bitops.o
-lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o
+lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o copy_user_nocache.o
diff --git a/arch/x86_64/lib/copy_user_nocache.S b/arch/x86_64/lib/copy_user_nocache.S
new file mode 100644 (file)
index 0000000..4620efb
--- /dev/null
@@ -0,0 +1,217 @@
+/* Copyright 2002 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License v2.
+ *
+ * Functions to copy from and to user space.
+ */
+
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+#define FIX_ALIGNMENT 1
+
+#include <asm/current.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpufeature.h>
+
+/*
+ * copy_user_nocache - Uncached memory copy with exception handling
+ * This will force destination/source out of cache for more performance.
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
+ * rcx zero flag       when 1 zero on exception
+ *
+ * Output:
+ * eax uncopied bytes or 0 if successful.
+ */
+ENTRY(__copy_user_nocache)
+       CFI_STARTPROC
+       pushq %rbx
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rbx, 0
+       pushq %rcx              /* save zero flag */
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rcx, 0
+
+       xorl %eax,%eax          /* zero for the exception handler */
+
+#ifdef FIX_ALIGNMENT
+       /* check for bad alignment of destination */
+       movl %edi,%ecx
+       andl $7,%ecx
+       jnz  .Lbad_alignment
+.Lafter_bad_alignment:
+#endif
+
+       movq %rdx,%rcx
+
+       movl $64,%ebx
+       shrq $6,%rdx
+       decq %rdx
+       js   .Lhandle_tail
+
+       .p2align 4
+.Lloop:
+.Ls1:  movq (%rsi),%r11
+.Ls2:  movq 1*8(%rsi),%r8
+.Ls3:  movq 2*8(%rsi),%r9
+.Ls4:  movq 3*8(%rsi),%r10
+.Ld1:  movnti %r11,(%rdi)
+.Ld2:  movnti %r8,1*8(%rdi)
+.Ld3:  movnti %r9,2*8(%rdi)
+.Ld4:  movnti %r10,3*8(%rdi)
+
+.Ls5:  movq 4*8(%rsi),%r11
+.Ls6:  movq 5*8(%rsi),%r8
+.Ls7:  movq 6*8(%rsi),%r9
+.Ls8:  movq 7*8(%rsi),%r10
+.Ld5:  movnti %r11,4*8(%rdi)
+.Ld6:  movnti %r8,5*8(%rdi)
+.Ld7:  movnti %r9,6*8(%rdi)
+.Ld8:  movnti %r10,7*8(%rdi)
+
+       dec  %rdx
+
+       leaq 64(%rsi),%rsi
+       leaq 64(%rdi),%rdi
+
+       jns  .Lloop
+
+       .p2align 4
+.Lhandle_tail:
+       movl %ecx,%edx
+       andl $63,%ecx
+       shrl $3,%ecx
+       jz   .Lhandle_7
+       movl $8,%ebx
+       .p2align 4
+.Lloop_8:
+.Ls9:  movq (%rsi),%r8
+.Ld9:  movnti %r8,(%rdi)
+       decl %ecx
+       leaq 8(%rdi),%rdi
+       leaq 8(%rsi),%rsi
+       jnz .Lloop_8
+
+.Lhandle_7:
+       movl %edx,%ecx
+       andl $7,%ecx
+       jz   .Lende
+       .p2align 4
+.Lloop_1:
+.Ls10: movb (%rsi),%bl
+.Ld10: movb %bl,(%rdi)
+       incq %rdi
+       incq %rsi
+       decl %ecx
+       jnz .Lloop_1
+
+       CFI_REMEMBER_STATE
+.Lende:
+       popq %rcx
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_RESTORE %rcx
+       popq %rbx
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_RESTORE rbx
+       ret
+       CFI_RESTORE_STATE
+
+#ifdef FIX_ALIGNMENT
+       /* align destination */
+       .p2align 4
+.Lbad_alignment:
+       movl $8,%r9d
+       subl %ecx,%r9d
+       movl %r9d,%ecx
+       cmpq %r9,%rdx
+       jz   .Lhandle_7
+       js   .Lhandle_7
+.Lalign_1:
+.Ls11: movb (%rsi),%bl
+.Ld11: movb %bl,(%rdi)
+       incq %rsi
+       incq %rdi
+       decl %ecx
+       jnz .Lalign_1
+       subq %r9,%rdx
+       jmp .Lafter_bad_alignment
+#endif
+
+       /* table sorted by exception address */
+       .section __ex_table,"a"
+       .align 8
+       .quad .Ls1,.Ls1e
+       .quad .Ls2,.Ls2e
+       .quad .Ls3,.Ls3e
+       .quad .Ls4,.Ls4e
+       .quad .Ld1,.Ls1e
+       .quad .Ld2,.Ls2e
+       .quad .Ld3,.Ls3e
+       .quad .Ld4,.Ls4e
+       .quad .Ls5,.Ls5e
+       .quad .Ls6,.Ls6e
+       .quad .Ls7,.Ls7e
+       .quad .Ls8,.Ls8e
+       .quad .Ld5,.Ls5e
+       .quad .Ld6,.Ls6e
+       .quad .Ld7,.Ls7e
+       .quad .Ld8,.Ls8e
+       .quad .Ls9,.Le_quad
+       .quad .Ld9,.Le_quad
+       .quad .Ls10,.Le_byte
+       .quad .Ld10,.Le_byte
+#ifdef FIX_ALIGNMENT
+       .quad .Ls11,.Lzero_rest
+       .quad .Ld11,.Lzero_rest
+#endif
+       .quad .Le5,.Le_zero
+       .previous
+
+       /* compute 64-offset for main loop. 8 bytes accuracy with error on the
+          pessimistic side. this is gross. it would be better to fix the
+          interface. */
+       /* eax: zero, ebx: 64 */
+.Ls1e:         addl $8,%eax
+.Ls2e:         addl $8,%eax
+.Ls3e:         addl $8,%eax
+.Ls4e:         addl $8,%eax
+.Ls5e:         addl $8,%eax
+.Ls6e:         addl $8,%eax
+.Ls7e:         addl $8,%eax
+.Ls8e:         addl $8,%eax
+       addq %rbx,%rdi  /* +64 */
+       subq %rax,%rdi  /* correct destination with computed offset */
+
+       shlq $6,%rdx    /* loop counter * 64 (stride length) */
+       addq %rax,%rdx  /* add offset to loopcnt */
+       andl $63,%ecx   /* remaining bytes */
+       addq %rcx,%rdx  /* add them */
+       jmp .Lzero_rest
+
+       /* exception on quad word loop in tail handling */
+       /* ecx: loopcnt/8, %edx: length, rdi: correct */
+.Le_quad:
+       shll $3,%ecx
+       andl $7,%edx
+       addl %ecx,%edx
+       /* edx: bytes to zero, rdi: dest, eax:zero */
+.Lzero_rest:
+       cmpl $0,(%rsp)  /* zero flag set? */
+       jz   .Le_zero
+       movq %rdx,%rcx
+.Le_byte:
+       xorl %eax,%eax
+.Le5:  rep
+       stosb
+       /* when there is another exception while zeroing the rest just return */
+.Le_zero:
+       movq %rdx,%rax
+       jmp .Lende
+       CFI_ENDPROC
+ENDPROC(__copy_user_nocache)
+
+
index 49e8cf2e06f8eca9d016386d8e91ec95c3de26b4..6ada7231f3abd11953e1bdd89c4101eac9ebe8db 100644 (file)
@@ -56,17 +56,17 @@ int unregister_page_fault_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
 
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
        struct die_args args = {
                .regs = regs,
-               .str = str,
+               .str = "page fault",
                .err = err,
-               .trapnr = trap,
-               .signr = sig
+               .trapnr = 14,
+               .signr = SIGSEGV
        };
-       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+       return atomic_notifier_call_chain(&notify_page_fault_chain,
+                                         DIE_PAGE_FAULT, &args);
 }
 
 /* Sometimes the CPU reports invalid exceptions on prefetch.
@@ -355,8 +355,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                        if (vmalloc_fault(address) >= 0)
                                return;
                }
-               if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-                                               SIGSEGV) == NOTIFY_STOP)
+               if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
                        return;
                /*
                 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -365,8 +364,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                goto bad_area_nosemaphore;
        }
 
-       if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-                                       SIGSEGV) == NOTIFY_STOP)
+       if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
                return;
 
        if (likely(regs->eflags & X86_EFLAGS_IF))
index 2968b90ef8adfec3d0316a3ef7b8d8e49628284d..ec31534eb104875649847948c32f816c6951d5a8 100644 (file)
@@ -711,20 +711,30 @@ int kern_addr_valid(unsigned long addr)
 extern int exception_trace, page_fault_trace;
 
 static ctl_table debug_table2[] = {
-       { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,
-         proc_dointvec },
-       { 0, }
+       {
+               .ctl_name       = 99,
+               .procname       = "exception-trace",
+               .data           = &exception_trace,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {}
 }; 
 
 static ctl_table debug_root_table2[] = { 
-       { .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, 
-          .child = debug_table2 }, 
-       { 0 }, 
+       {
+               .ctl_name = CTL_DEBUG,
+               .procname = "debug",
+               .mode = 0555,
+               .child = debug_table2
+       },
+       {}
 }; 
 
 static __init int x8664_sysctl_init(void)
 { 
-       register_sysctl_table(debug_root_table2, 1);
+       register_sysctl_table(debug_root_table2);
        return 0;
 }
 __initcall(x8664_sysctl_init);
index 2ee2e003606cad9cc727042af6ed435dadc45a53..41b8fb069924d9a6b26582688f9421aa44e80d8d 100644 (file)
@@ -36,6 +36,8 @@ unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
 cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
+unsigned long __initdata nodemap_addr;
+unsigned long __initdata nodemap_size;
 
 
 /*
@@ -52,34 +54,88 @@ populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift)
        int res = -1;
        unsigned long addr, end;
 
-       if (shift >= 64)
-               return -1;
-       memset(memnodemap, 0xff, sizeof(memnodemap));
+       memset(memnodemap, 0xff, memnodemapsize);
        for (i = 0; i < numnodes; i++) {
                addr = nodes[i].start;
                end = nodes[i].end;
                if (addr >= end)
                        continue;
-               if ((end >> shift) >= NODEMAPSIZE)
+               if ((end >> shift) >= memnodemapsize)
                        return 0;
                do {
                        if (memnodemap[addr >> shift] != 0xff)
                                return -1;
                        memnodemap[addr >> shift] = i;
-                       addr += (1UL << shift);
+                       addr += (1UL << shift);
                } while (addr < end);
                res = 1;
        } 
        return res;
 }
 
-int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
+static int __init allocate_cachealigned_memnodemap(void)
 {
-       int shift = 20;
+       unsigned long pad, pad_addr;
+
+       memnodemap = memnode.embedded_map;
+       if (memnodemapsize <= 48)
+               return 0;
+
+       pad = L1_CACHE_BYTES - 1;
+       pad_addr = 0x8000;
+       nodemap_size = pad + memnodemapsize;
+       nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT,
+                                     nodemap_size);
+       if (nodemap_addr == -1UL) {
+               printk(KERN_ERR
+                      "NUMA: Unable to allocate Memory to Node hash map\n");
+               nodemap_addr = nodemap_size = 0;
+               return -1;
+       }
+       pad_addr = (nodemap_addr + pad) & ~pad;
+       memnodemap = phys_to_virt(pad_addr);
+
+       printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
+              nodemap_addr, nodemap_addr + nodemap_size);
+       return 0;
+}
 
-       while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0)
-               shift++;
+/*
+ * The LSB of all start and end addresses in the node map is the value of the
+ * maximum possible shift.
+ */
+static int __init
+extract_lsb_from_nodes (const struct bootnode *nodes, int numnodes)
+{
+       int i, nodes_used = 0;
+       unsigned long start, end;
+       unsigned long bitfield = 0, memtop = 0;
+
+       for (i = 0; i < numnodes; i++) {
+               start = nodes[i].start;
+               end = nodes[i].end;
+               if (start >= end)
+                       continue;
+               bitfield |= start;
+               nodes_used++;
+               if (end > memtop)
+                       memtop = end;
+       }
+       if (nodes_used <= 1)
+               i = 63;
+       else
+               i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
+       memnodemapsize = (memtop >> i)+1;
+       return i;
+}
+
+int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
+{
+       int shift;
 
+       shift = extract_lsb_from_nodes(nodes, numnodes);
+       if (allocate_cachealigned_memnodemap())
+               return -1;
        printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
                shift);
 
@@ -216,31 +272,113 @@ void __init numa_init_array(void)
 }
 
 #ifdef CONFIG_NUMA_EMU
+/* Numa emulation */
 int numa_fake __initdata = 0;
 
-/* Numa emulation */
+/*
+ * This function is used to find out if the start and end correspond to
+ * different zones.
+ */
+int zone_cross_over(unsigned long start, unsigned long end)
+{
+       if ((start < (MAX_DMA32_PFN << PAGE_SHIFT)) &&
+                       (end >= (MAX_DMA32_PFN << PAGE_SHIFT)))
+               return 1;
+       return 0;
+}
+
 static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
 {
-       int i;
+       int i, big;
        struct bootnode nodes[MAX_NUMNODES];
-       unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
+       unsigned long sz, old_sz;
+       unsigned long hole_size;
+       unsigned long start, end;
+       unsigned long max_addr = (end_pfn << PAGE_SHIFT);
+
+       start = (start_pfn << PAGE_SHIFT);
+       hole_size = e820_hole_size(start, max_addr);
+       sz = (max_addr - start - hole_size) / numa_fake;
 
        /* Kludge needed for the hash function */
-       if (hweight64(sz) > 1) {
-               unsigned long x = 1;
-               while ((x << 1) < sz)
-                       x <<= 1;
-               if (x < sz/2)
-                       printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n");
-               sz = x;
-       }
 
+       old_sz = sz;
+       /*
+        * Round down to the nearest FAKE_NODE_MIN_SIZE.
+        */
+       sz &= FAKE_NODE_MIN_HASH_MASK;
+
+       /*
+        * We ensure that each node is at least 64MB big.  Smaller than this
+        * size can cause VM hiccups.
+        */
+       if (sz == 0) {
+               printk(KERN_INFO "Not enough memory for %d nodes.  Reducing "
+                               "the number of nodes\n", numa_fake);
+               numa_fake = (max_addr - start - hole_size) / FAKE_NODE_MIN_SIZE;
+               printk(KERN_INFO "Number of fake nodes will be = %d\n",
+                               numa_fake);
+               sz = FAKE_NODE_MIN_SIZE;
+       }
+       /*
+        * Find out how many nodes can get an extra NODE_MIN_SIZE granule.
+        * This logic ensures the extra memory gets distributed among as many
+        * nodes as possible (as compared to one single node getting all that
+        * extra memory.
+        */
+       big = ((old_sz - sz) * numa_fake) / FAKE_NODE_MIN_SIZE;
+       printk(KERN_INFO "Fake node Size: %luMB hole_size: %luMB big nodes: "
+                       "%d\n",
+                       (sz >> 20), (hole_size >> 20), big);
        memset(&nodes,0,sizeof(nodes));
+       end = start;
        for (i = 0; i < numa_fake; i++) {
-               nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
+               /*
+                * In case we are not able to allocate enough memory for all
+                * the nodes, we reduce the number of fake nodes.
+                */
+               if (end >= max_addr) {
+                       numa_fake = i - 1;
+                       break;
+               }
+               start = nodes[i].start = end;
+               /*
+                * Final node can have all the remaining memory.
+                */
                if (i == numa_fake-1)
-                       sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
-               nodes[i].end = nodes[i].start + sz;
+                       sz = max_addr - start;
+               end = nodes[i].start + sz;
+               /*
+                * Fir "big" number of nodes get extra granule.
+                */
+               if (i < big)
+                       end += FAKE_NODE_MIN_SIZE;
+               /*
+                * Iterate over the range to ensure that this node gets at
+                * least sz amount of RAM (excluding holes)
+                */
+               while ((end - start - e820_hole_size(start, end)) < sz) {
+                       end += FAKE_NODE_MIN_SIZE;
+                       if (end >= max_addr)
+                               break;
+               }
+               /*
+                * Look at the next node to make sure there is some real memory
+                * to map.  Bad things happen when the only memory present
+                * in a zone on a fake node is IO hole.
+                */
+               while (e820_hole_size(end, end + FAKE_NODE_MIN_SIZE) > 0) {
+                       if (zone_cross_over(start, end + sz)) {
+                               end = (MAX_DMA32_PFN << PAGE_SHIFT);
+                               break;
+                       }
+                       if (end >= max_addr)
+                               break;
+                       end += FAKE_NODE_MIN_SIZE;
+               }
+               if (end > max_addr)
+                       end = max_addr;
+               nodes[i].end = end;
                printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n",
                       i,
                       nodes[i].start, nodes[i].end,
@@ -290,6 +428,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
               end_pfn << PAGE_SHIFT); 
                /* setup dummy node covering all memory */ 
        memnode_shift = 63; 
+       memnodemap = memnode.embedded_map;
        memnodemap[0] = 0;
        nodes_clear(node_online_map);
        node_set_online(0);
@@ -321,20 +460,6 @@ unsigned long __init numa_free_all_bootmem(void)
        return pages;
 } 
 
-#ifdef CONFIG_SPARSEMEM
-static void __init arch_sparse_init(void)
-{
-       int i;
-
-       for_each_online_node(i)
-               memory_present(i, node_start_pfn(i), node_end_pfn(i));
-
-       sparse_init();
-}
-#else
-#define arch_sparse_init() do {} while (0)
-#endif
-
 void __init paging_init(void)
 { 
        int i;
@@ -344,7 +469,8 @@ void __init paging_init(void)
        max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
        max_zone_pfns[ZONE_NORMAL] = end_pfn;
 
-       arch_sparse_init();
+       sparse_memory_present_with_active_regions(MAX_NUMNODES);
+       sparse_init();
 
        for_each_online_node(i) {
                setup_node_zones(i); 
index ccb91dd996a957c1dc26f183e095c3a8edbd30f1..65c5eaa5990563048b1ac59e04e3dcd645441b5c 100644 (file)
@@ -107,6 +107,7 @@ static void revert_page(unsigned long address, pgprot_t ref_prot)
        pud_t *pud;
        pmd_t *pmd;
        pte_t large_pte;
+       unsigned long pfn;
 
        pgd = pgd_offset_k(address);
        BUG_ON(pgd_none(*pgd));
@@ -114,7 +115,8 @@ static void revert_page(unsigned long address, pgprot_t ref_prot)
        BUG_ON(pud_none(*pud));
        pmd = pmd_offset(pud, address);
        BUG_ON(pmd_val(*pmd) & _PAGE_PSE);
-       large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
+       pfn = (__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT;
+       large_pte = pfn_pte(pfn, ref_prot);
        large_pte = pte_mkhuge(large_pte);
        set_pte((pte_t *)pmd, large_pte);
 }      
index 149aba05a5b8e70c6abb22dd17e21b1f1994adf4..c9eddc8859c0f797818c81dbaed75d4618a605d2 100644 (file)
@@ -11,7 +11,7 @@ obj-y         += fixup.o init.o
 obj-$(CONFIG_ACPI)     += acpi.o
 obj-y                  += legacy.o irq.o common.o early.o
 # mmconfig has a 64bit special
-obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
+obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
 
 obj-$(CONFIG_NUMA)     += k8-bus.o
 
@@ -24,3 +24,4 @@ fixup-y  += ../../i386/pci/fixup.o
 i386-y  += ../../i386/pci/i386.o
 init-y += ../../i386/pci/init.o
 early-y += ../../i386/pci/early.o
+mmconfig-shared-y += ../../i386/pci/mmconfig-shared.o
index faabb6e87f12461de8c25bf4ec4f14f75216edaa..65d82736987e600b642646f4d14e515b4fc020fc 100644 (file)
 
 #include "pci.h"
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN      (2 * 1024*1024)
-#define MMCONFIG_APER_MAX      (256 * 1024*1024)
-
-/* Verify the first 16 busses. We assume that systems with more busses
-   get MCFG right. */
-#define MAX_CHECK_BUS 16
-
-static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
-
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
        struct acpi_mcfg_allocation *cfg;
@@ -32,30 +22,17 @@ static struct mmcfg_virt *pci_mmcfg_virt;
 
 static char __iomem *get_virt(unsigned int seg, unsigned bus)
 {
-       int cfg_num = -1;
        struct acpi_mcfg_allocation *cfg;
+       int cfg_num;
 
-       while (1) {
-               ++cfg_num;
-               if (cfg_num >= pci_mmcfg_config_num)
-                       break;
+       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
                cfg = pci_mmcfg_virt[cfg_num].cfg;
-               if (cfg->pci_segment != seg)
-                       continue;
-               if ((cfg->start_bus_number <= bus) &&
+               if (cfg->pci_segment == seg &&
+                   (cfg->start_bus_number <= bus) &&
                    (cfg->end_bus_number >= bus))
                        return pci_mmcfg_virt[cfg_num].virt;
        }
 
-       /* Handle more broken MCFG tables on Asus etc.
-          They only contain a single entry for bus 0-0. Assume
-          this applies to all busses. */
-       cfg = &pci_mmcfg_config[0];
-       if (pci_mmcfg_config_num == 1 &&
-               cfg->pci_segment == 0 &&
-               (cfg->start_bus_number | cfg->end_bus_number) == 0)
-               return pci_mmcfg_virt[0].virt;
-
        /* Fall back to type 0 */
        return NULL;
 }
@@ -63,8 +40,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
        char __iomem *addr;
-       if (seg == 0 && bus < MAX_CHECK_BUS &&
-               test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
+       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
+               test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
                return NULL;
        addr = get_virt(seg, bus);
        if (!addr)
@@ -135,79 +112,46 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   Normally this can be expressed in the MCFG by not listing them
-   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
-   Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them. */
-static __init void unreachable_devices(void)
+static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
 {
-       int i, k;
-       /* Use the max bus number from ACPI here? */
-       for (k = 0; k < MAX_CHECK_BUS; k++) {
-               for (i = 0; i < 32; i++) {
-                       u32 val1;
-                       char __iomem *addr;
-
-                       pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-                       addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
-                       if (addr == NULL|| readl(addr) != val1) {
-                               set_bit(i + 32*k, fallback_slots);
-                               printk(KERN_NOTICE "PCI: No mmconfig possible"
-                                      " on device %02x:%02x\n", k, i);
-                       }
-               }
+       void __iomem *addr;
+       u32 size;
+
+       size = (cfg->end_bus_number + 1) << 20;
+       addr = ioremap_nocache(cfg->address, size);
+       if (addr) {
+               printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n",
+                      cfg->address, cfg->address + size - 1);
        }
+       return addr;
 }
 
-void __init pci_mmcfg_init(int type)
+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+                                   unsigned int devfn)
 {
-       int i;
-
-       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-               return;
-
-       acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return;
-
-       /* Only do this check when type 1 works. If it doesn't work
-           assume we run on a Mac and always use MCFG */
-       if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
-                       pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
-                       E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
-                               (unsigned long)pci_mmcfg_config[0].address);
-               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-               return;
-       }
+       return pci_dev_base(seg, bus, devfn) != NULL;
+}
 
-       pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
+int __init pci_mmcfg_arch_init(void)
+{
+       int i;
+       pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
+                                pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
                printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
-               return;
+               return 0;
        }
+
        for (i = 0; i < pci_mmcfg_config_num; ++i) {
                pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
-               pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address,
-                                                        MMCONFIG_APER_MAX);
+               pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
                if (!pci_mmcfg_virt[i].virt) {
                        printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
                                        "segment %d\n",
                                pci_mmcfg_config[i].pci_segment);
-                       return;
+                       return 0;
                }
-               printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n",
-                       (unsigned long)pci_mmcfg_config[i].address);
        }
-
-       unreachable_devices();
-
        raw_pci_ops = &pci_mmcfg;
-       pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+       return 1;
 }
index 903f0d3b68520a94a5a76222b31c6860ba57de20..7e803fc887700604b47401b7d82512c48e95e6e1 100644 (file)
@@ -16,10 +16,10 @@ config IOSCHED_AS
        tristate "Anticipatory I/O scheduler"
        default y
        ---help---
-         The anticipatory I/O scheduler is the default disk scheduler. It is
-         generally a good choice for most environments, but is quite large and
-         complex when compared to the deadline I/O scheduler, it can also be
-         slower in some cases especially some database loads.
+         The anticipatory I/O scheduler is generally a good choice for most
+         environments, but is quite large and complex when compared to the
+         deadline I/O scheduler, it can also be slower in some cases
+         especially some database loads.
 
 config IOSCHED_DEADLINE
        tristate "Deadline I/O scheduler"
@@ -38,6 +38,7 @@ config IOSCHED_CFQ
          The CFQ I/O scheduler tries to distribute bandwidth equally
          among all processes in the system. It should provide a fair
          working environment, suitable for desktop systems.
+         This is the default I/O scheduler.
 
 choice
        prompt "Default I/O scheduler"
index 7fde8f4daebfff867e688e275c09a735634c9292..689a4c3542babc00e385699fe1caf4b02c0f9103 100644 (file)
@@ -99,7 +99,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
index 157d8b73bb64784fb90ecd1d9ec1bffd22321ada..d276fd14d63a05ff63f529bd5a4525584e580a85 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/capability.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/miscdevice.h>
 #include <linux/rtc.h>
index 20eacc2c9e0e5223f27d9f979672a5ed031b350b..e942ffe8b57ee4c9a13a447bf205e3939815dfcc 100644 (file)
@@ -13,6 +13,7 @@ config ACPI
        depends on IA64 || X86
        depends on PCI
        depends on PM
+       select PNP
        default y
        ---help---
          Advanced Configuration and Power Interface (ACPI) support for 
@@ -132,15 +133,6 @@ config ACPI_VIDEO
          Note that this is an ref. implementation only.  It may or may not work
          for your integrated video device.
 
-config ACPI_HOTKEY
-       tristate "Generic Hotkey (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       depends on X86
-       default n
-       help
-         Experimental consolidated hotkey driver.
-         If you are unsure, say N.
-
 config ACPI_FAN
        tristate "Fan"
        default y
index 856c32bccacb04024b7036282bed0c865ef7395e..5956e9f64a8bfd682754999267f99f80ba9a7558 100644 (file)
@@ -46,7 +46,6 @@ obj-$(CONFIG_ACPI_FAN)                += fan.o
 obj-$(CONFIG_ACPI_DOCK)                += dock.o
 obj-$(CONFIG_ACPI_BAY)         += bay.o
 obj-$(CONFIG_ACPI_VIDEO)       += video.o
-obj-$(CONFIG_ACPI_HOTKEY)      += hotkey.o
 obj-y                          += pci_root.o pci_link.o pci_irq.o pci_bind.o
 obj-$(CONFIG_ACPI_POWER)       += power.o
 obj-$(CONFIG_ACPI_PROCESSOR)   += processor.o
index 6daeace796a86c2b3e7892c517b5bab107ceb8a7..37c7dc4f9fe5db6d15b7bba43803790f0c0ee588 100644 (file)
@@ -35,7 +35,6 @@
 #define ACPI_AC_COMPONENT              0x00020000
 #define ACPI_AC_CLASS                  "ac_adapter"
 #define ACPI_AC_HID                    "ACPI0003"
-#define ACPI_AC_DRIVER_NAME            "ACPI AC Adapter Driver"
 #define ACPI_AC_DEVICE_NAME            "AC Adapter"
 #define ACPI_AC_FILE_STATE             "state"
 #define ACPI_AC_NOTIFY_STATUS          0x80
 #define ACPI_AC_STATUS_UNKNOWN         0xFF
 
 #define _COMPONENT             ACPI_AC_COMPONENT
-ACPI_MODULE_NAME("acpi_ac")
+ACPI_MODULE_NAME("ac");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI AC Adapter Driver");
 MODULE_LICENSE("GPL");
 
 extern struct proc_dir_entry *acpi_lock_ac_dir(void);
@@ -58,7 +57,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type);
 static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_ac_driver = {
-       .name = ACPI_AC_DRIVER_NAME,
+       .name = "ac",
        .class = ACPI_AC_CLASS,
        .ids = ACPI_AC_HID,
        .ops = {
index cd946ed192d3e38a1539fcd58abfcfaf06258c26..c26172671fd882a175eb04cba40d6a8d1db8c304 100644 (file)
 #define ACPI_MEMORY_DEVICE_COMPONENT           0x08000000UL
 #define ACPI_MEMORY_DEVICE_CLASS               "memory"
 #define ACPI_MEMORY_DEVICE_HID                 "PNP0C80"
-#define ACPI_MEMORY_DEVICE_DRIVER_NAME         "Hotplug Mem Driver"
 #define ACPI_MEMORY_DEVICE_NAME                        "Hotplug Mem Device"
 
 #define _COMPONENT             ACPI_MEMORY_DEVICE_COMPONENT
 
-ACPI_MODULE_NAME("acpi_memory")
-    MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
+ACPI_MODULE_NAME("acpi_memhotplug");
+MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+MODULE_DESCRIPTION("Hotplug Mem Driver");
 MODULE_LICENSE("GPL");
 
 /* ACPI _STA method values */
@@ -60,7 +59,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type);
 static int acpi_memory_device_start(struct acpi_device *device);
 
 static struct acpi_driver acpi_memory_device_driver = {
-       .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+       .name = "acpi_memhotplug",
        .class = ACPI_MEMORY_DEVICE_CLASS,
        .ids = ACPI_MEMORY_DEVICE_HID,
        .ops = {
index 31ad70a6e22eb3074261b757fc7d831b841c9bed..772299fb5f9d97e54078f549e8241a852bbf181b 100644 (file)
@@ -141,6 +141,7 @@ struct asus_hotk {
                W5A,            //W5A
                W3V,            //W3030V
                xxN,            //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
+               A4S,            //Z81sp
                //(Centrino)
                END_MODEL
        } model;                //Models currently supported
@@ -397,7 +398,16 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_set = "SPLV",
         .brightness_get = "GPLV",
         .display_set = "SDSP",
-        .display_get = "\\ADVG"}
+       .display_get = "\\ADVG"},
+
+       {
+               .name              = "A4S",
+               .brightness_set    = "SPLV",
+               .brightness_get    = "GPLV",
+               .mt_bt_switch      = "BLED",
+               .mt_wled           = "WLED"
+       }
+
 };
 
 /* procdir we use */
@@ -421,7 +431,7 @@ static struct asus_hotk *hotk;
 static int asus_hotk_add(struct acpi_device *device);
 static int asus_hotk_remove(struct acpi_device *device, int type);
 static struct acpi_driver asus_hotk_driver = {
-       .name = ACPI_HOTK_NAME,
+       .name = "asus_acpi",
        .class = ACPI_HOTK_CLASS,
        .ids = ACPI_HOTK_HID,
        .ops = {
@@ -1117,6 +1127,8 @@ static int asus_model_match(char *model)
                return W3V;
        else if (strncmp(model, "W5A", 3) == 0)
                return W5A;
+       else if (strncmp(model, "A4S", 3) == 0)
+               return A4S;
        else
                return END_MODEL;
 }
@@ -1365,10 +1377,6 @@ static int __init asus_acpi_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-       if (!acpi_specific_hotkey_enabled) {
-               printk(KERN_ERR "Using generic hotkey driver\n");
-               return -ENODEV;
-       }
        asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
        if (!asus_proc_dir) {
                printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
index 2f4521a48fe7b6e3f66726d389cbe5c436540ef6..e64c76c8b7268a56562969d48b6c940bbda09bfc 100644 (file)
@@ -42,7 +42,6 @@
 #define ACPI_BATTERY_COMPONENT         0x00040000
 #define ACPI_BATTERY_CLASS             "battery"
 #define ACPI_BATTERY_HID               "PNP0C0A"
-#define ACPI_BATTERY_DRIVER_NAME       "ACPI Battery Driver"
 #define ACPI_BATTERY_DEVICE_NAME       "Battery"
 #define ACPI_BATTERY_FILE_INFO         "info"
 #define ACPI_BATTERY_FILE_STATUS       "state"
 #define ACPI_BATTERY_UNITS_AMPS                "mA"
 
 #define _COMPONENT             ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME("acpi_battery")
+ACPI_MODULE_NAME("battery");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
@@ -67,7 +66,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type);
 static int acpi_battery_resume(struct acpi_device *device);
 
 static struct acpi_driver acpi_battery_driver = {
-       .name = ACPI_BATTERY_DRIVER_NAME,
+       .name = "battery",
        .class = ACPI_BATTERY_CLASS,
        .ids = ACPI_BATTERY_HID,
        .ops = {
@@ -324,6 +323,13 @@ static int acpi_battery_check(struct acpi_battery *battery)
        return result;
 }
 
+static void acpi_battery_check_present(struct acpi_battery *battery)
+{
+       if (!battery->flags.present) {
+               acpi_battery_check(battery);
+       }
+}
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -340,6 +346,8 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
        if (!battery)
                goto end;
 
+       acpi_battery_check_present(battery);
+
        if (battery->flags.present)
                seq_printf(seq, "present:                 yes\n");
        else {
@@ -424,6 +432,8 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
        if (!battery)
                goto end;
 
+       acpi_battery_check_present(battery);
+
        if (battery->flags.present)
                seq_printf(seq, "present:                 yes\n");
        else {
@@ -499,6 +509,8 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
        if (!battery)
                goto end;
 
+       acpi_battery_check_present(battery);
+
        if (!battery->flags.present) {
                seq_printf(seq, "present:                 no\n");
                goto end;
@@ -536,6 +548,8 @@ acpi_battery_write_alarm(struct file *file,
        if (!battery || (count > sizeof(alarm_string) - 1))
                return -EINVAL;
 
+       acpi_battery_check_present(battery);
+
        if (!battery->flags.present)
                return -ENODEV;
 
index 91082ce6f5d1de0e158704401c45d46590336afa..fb3f31b5e69f6587ff4c7cada15b2291c64fad40 100644 (file)
 #include <asm/uaccess.h>
 #include <linux/platform_device.h>
 
-#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver"
-
-ACPI_MODULE_NAME("bay")
+ACPI_MODULE_NAME("bay");
 MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
 MODULE_LICENSE("GPL");
 #define ACPI_BAY_CLASS "bay"
 #define ACPI_BAY_COMPONENT     0x10000000
@@ -47,18 +45,6 @@ MODULE_LICENSE("GPL");
        acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
        printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
 static void bay_notify(acpi_handle handle, u32 event, void *data);
-static int acpi_bay_add(struct acpi_device *device);
-static int acpi_bay_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver acpi_bay_driver = {
-       .name = ACPI_BAY_DRIVER_NAME,
-       .class = ACPI_BAY_CLASS,
-       .ids = ACPI_BAY_HID,
-       .ops = {
-               .add = acpi_bay_add,
-               .remove = acpi_bay_remove,
-               },
-};
 
 struct bay {
        acpi_handle handle;
@@ -234,14 +220,6 @@ int eject_removable_drive(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(eject_removable_drive);
 
-static int acpi_bay_add(struct acpi_device *device)
-{
-       bay_dprintk(device->handle, "adding bay device");
-       strcpy(acpi_device_name(device), "Dockable Bay");
-       strcpy(acpi_device_class(device), "bay");
-       return 0;
-}
-
 static int acpi_bay_add_fs(struct bay *bay)
 {
        int ret;
@@ -303,7 +281,7 @@ static int bay_add(acpi_handle handle, int id)
 
        /* initialize platform device stuff */
        pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
-       if (pdev == NULL) {
+       if (IS_ERR(pdev)) {
                printk(KERN_ERR PREFIX "Error registering bay device\n");
                goto bay_add_err;
        }
@@ -339,52 +317,6 @@ bay_add_err:
        return -ENODEV;
 }
 
-static int acpi_bay_remove(struct acpi_device *device, int type)
-{
-       /*** FIXME: do something here */
-       return 0;
-}
-
-/**
- * bay_create_acpi_device - add new devices to acpi
- * @handle - handle of the device to add
- *
- *  This function will create a new acpi_device for the given
- *  handle if one does not exist already.  This should cause
- *  acpi to scan for drivers for the given devices, and call
- *  matching driver's add routine.
- *
- *  Returns a pointer to the acpi_device corresponding to the handle.
- */
-static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
-{
-       struct acpi_device *device = NULL;
-       struct acpi_device *parent_device;
-       acpi_handle parent;
-       int ret;
-
-       bay_dprintk(handle, "Trying to get device");
-       if (acpi_bus_get_device(handle, &device)) {
-               /*
-                * no device created for this object,
-                * so we should create one.
-                */
-               bay_dprintk(handle, "No device for handle");
-               acpi_get_parent(handle, &parent);
-               if (acpi_bus_get_device(parent, &parent_device))
-                       parent_device = NULL;
-
-               ret = acpi_bus_add(&device, parent_device, handle,
-                       ACPI_BUS_TYPE_DEVICE);
-               if (ret) {
-                       pr_debug("error adding bus, %x\n",
-                               -ret);
-                       return NULL;
-               }
-       }
-       return device;
-}
-
 /**
  * bay_notify - act upon an acpi bay notification
  * @handle: the bay handle
@@ -394,38 +326,19 @@ static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
  */
 static void bay_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_device *dev;
+       struct bay *bay_dev = (struct bay *)data;
+       struct device *dev = &bay_dev->pdev->dev;
 
        bay_dprintk(handle, "Bay event");
 
        switch(event) {
        case ACPI_NOTIFY_BUS_CHECK:
-               printk("Bus Check\n");
        case ACPI_NOTIFY_DEVICE_CHECK:
-               printk("Device Check\n");
-               dev = bay_create_acpi_device(handle);
-               if (dev)
-                       acpi_bus_generate_event(dev, event, 0);
-               else
-                       printk("No device for generating event\n");
-               /* wouldn't it be a good idea to just rescan SATA
-                * right here?
-                */
-               break;
        case ACPI_NOTIFY_EJECT_REQUEST:
-               printk("Eject request\n");
-               dev = bay_create_acpi_device(handle);
-               if (dev)
-                       acpi_bus_generate_event(dev, event, 0);
-               else
-                       printk("No device for generating eventn");
-
-               /* wouldn't it be a good idea to just call the
-                * eject_device here if we were a SATA device?
-                */
+               kobject_uevent(&dev->kobj, KOBJ_CHANGE);
                break;
        default:
-               printk("unknown event %d\n", event);
+               printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event);
        }
 }
 
@@ -457,10 +370,6 @@ static int __init bay_init(void)
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, find_bay, &bays, NULL);
 
-       if (bays)
-               if ((acpi_bus_register_driver(&acpi_bay_driver) < 0))
-                       printk(KERN_ERR "Unable to register bay driver\n");
-
        if (!bays)
                return -ENODEV;
 
@@ -481,8 +390,6 @@ static void __exit bay_exit(void)
                kfree(bay->name);
                kfree(bay);
        }
-
-       acpi_bus_unregister_driver(&acpi_bay_driver);
 }
 
 postcore_initcall(bay_init);
index c26468da429507be4ccef20e3f1b57165d860d85..dd49ea0d0ed3606a69dfc2a9580b64768ced7cb9 100644 (file)
@@ -39,7 +39,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_bus")
+ACPI_MODULE_NAME("bus");
 #ifdef CONFIG_X86
 extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
 #endif
@@ -147,7 +147,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
                        *state = ACPI_STATE_D0;
        } else {
                /*
-                * Get the device's power state either directly (via _PSC) or 
+                * Get the device's power state either directly (via _PSC) or
                 * indirectly (via power resources).
                 */
                if (device->power.flags.explicit_get) {
@@ -199,15 +199,14 @@ int acpi_bus_set_power(acpi_handle handle, int state)
         * Get device's current power state if it's unknown
         * This means device power state isn't initialized or previous setting failed
         */
-       if (!device->flags.force_power_state) {
-               if (device->power.state == ACPI_STATE_UNKNOWN)
-                       acpi_bus_get_power(device->handle, &device->power.state);
-               if (state == device->power.state) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
-                                         state));
-                       return 0;
-               }
+       if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state)
+               acpi_bus_get_power(device->handle, &device->power.state);
+       if ((state == device->power.state) && !device->flags.force_power_state) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+                                 state));
+               return 0;
        }
+
        if (!device->power.states[state].flags.valid) {
                printk(KERN_WARNING PREFIX "Device does not support D%d\n", state);
                return -ENODEV;
@@ -462,7 +461,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
                                  "Received BUS CHECK notification for device [%s]\n",
                                  device->pnp.bus_id));
                result = acpi_bus_check_scope(device);
-               /* 
+               /*
                 * TBD: We'll need to outsource certain events to non-ACPI
                 *      drivers via the device manager (device.c).
                 */
@@ -473,7 +472,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
                                  "Received DEVICE CHECK notification for device [%s]\n",
                                  device->pnp.bus_id));
                result = acpi_bus_check_device(device, NULL);
-               /* 
+               /*
                 * TBD: We'll need to outsource certain events to non-ACPI
                 *      drivers via the device manager (device.c).
                 */
@@ -543,7 +542,7 @@ static int __init acpi_bus_init_irq(void)
        char *message = NULL;
 
 
-       /* 
+       /*
         * Let the system know what interrupt model we are using by
         * evaluating the \_PIC object, if exists.
         */
@@ -684,7 +683,7 @@ static int __init acpi_bus_init(void)
         * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
         * is called).
         *
-        * This is accomplished by looking for the ECDT table, and getting 
+        * This is accomplished by looking for the ECDT table, and getting
         * the EC parameters out of that.
         */
        status = acpi_ec_ecdt_probe();
@@ -699,6 +698,9 @@ static int __init acpi_bus_init(void)
 
        printk(KERN_INFO PREFIX "Interpreter enabled\n");
 
+       /* Initialize sleep structures */
+       acpi_sleep_init();
+
        /*
         * Get the system interrupt model and evaluate \_PIC.
         */
index c726612fafb606a6c7869666c7cd4af9dcd374c7..cb4110b50cd0f19f15b0f6c6d124861bd62a82ef 100644 (file)
@@ -34,7 +34,6 @@
 #include <acpi/acpi_drivers.h>
 
 #define ACPI_BUTTON_COMPONENT          0x00080000
-#define ACPI_BUTTON_DRIVER_NAME                "ACPI Button Driver"
 #define ACPI_BUTTON_CLASS              "button"
 #define ACPI_BUTTON_FILE_INFO          "info"
 #define ACPI_BUTTON_FILE_STATE         "state"
 #define ACPI_BUTTON_TYPE_LID           0x05
 
 #define _COMPONENT             ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME("acpi_button")
+ACPI_MODULE_NAME("button");
 
 MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Button Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_button_add(struct acpi_device *device);
@@ -73,7 +72,7 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
 static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_button_driver = {
-       .name = ACPI_BUTTON_DRIVER_NAME,
+       .name = "button",
        .class = ACPI_BUTTON_CLASS,
        .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E",
        .ops = {
index 4a9b7bf6f44ed79a3fff799c3a5245ed49f273a6..f9db4f444bd0f814fe4ffbec8252e4227df981dc 100644 (file)
@@ -31,7 +31,7 @@
 #include <acpi/actypes.h>
 #include <acpi/acutils.h>
 
-ACPI_MODULE_NAME("cm_sbs")
+ACPI_MODULE_NAME("cm_sbs");
 #define ACPI_AC_CLASS          "ac_adapter"
 #define ACPI_BATTERY_CLASS     "battery"
 #define ACPI_SBS_COMPONENT     0x00080000
index 69a68fd394cf6861c5e8bb9618604523fa08785d..0930d9413dfa31768e889e7150e9dd55a0691670 100644 (file)
@@ -35,7 +35,6 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/container.h>
 
-#define ACPI_CONTAINER_DRIVER_NAME     "ACPI container driver"
 #define ACPI_CONTAINER_DEVICE_NAME     "ACPI container device"
 #define ACPI_CONTAINER_CLASS           "container"
 
 
 #define ACPI_CONTAINER_COMPONENT       0x01000000
 #define _COMPONENT                     ACPI_CONTAINER_COMPONENT
-ACPI_MODULE_NAME("acpi_container")
+ACPI_MODULE_NAME("container");
 
-    MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
+MODULE_AUTHOR("Anil S Keshavamurthy");
+MODULE_DESCRIPTION("ACPI container driver");
 MODULE_LICENSE("GPL");
 
 #define ACPI_STA_PRESENT               (0x00000001)
@@ -56,7 +55,7 @@ static int acpi_container_add(struct acpi_device *device);
 static int acpi_container_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_container_driver = {
-       .name = ACPI_CONTAINER_DRIVER_NAME,
+       .name = "container",
        .class = ACPI_CONTAINER_CLASS,
        .ids = "ACPI0004,PNP0A05,PNP0A06",
        .ops = {
index d48f65a8f6587122be909ff286280203011f6bf5..bf513e07b7735738c0099171443ac05e6fcc917e 100644 (file)
@@ -12,7 +12,7 @@
 #include <acpi/acglobal.h>
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("debug")
+ACPI_MODULE_NAME("debug");
 
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
index 1cbe6190582494ed9f3557c58a17b659644f4979..1683e5c5b94c5febc942d191489f0f30634cbe04 100644 (file)
@@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
                 * Obtain the method mutex if necessary. Do not acquire mutex for a
                 * recursive call.
                 */
-               if (!walk_state ||
-                   !obj_desc->method.mutex->mutex.owner_thread ||
-                   (walk_state->thread !=
-                    obj_desc->method.mutex->mutex.owner_thread)) {
+               if (acpi_os_get_thread_id() !=
+                   obj_desc->method.mutex->mutex.owner_thread_id) {
                        /*
                         * Acquire the method mutex. This releases the interpreter if we
                         * block (and reacquires it before it returns)
@@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
                        }
 
                        /* Update the mutex and walk info and save the original sync_level */
+                       obj_desc->method.mutex->mutex.owner_thread_id =
+                               acpi_os_get_thread_id();
 
                        if (walk_state) {
                                obj_desc->method.mutex->mutex.
                                    original_sync_level =
                                    walk_state->thread->current_sync_level;
 
-                               obj_desc->method.mutex->mutex.owner_thread =
-                                   walk_state->thread;
                                walk_state->thread->current_sync_level =
                                    obj_desc->method.sync_level;
                        } else {
@@ -569,7 +567,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
 
                        acpi_os_release_mutex(method_desc->method.mutex->mutex.
                                              os_mutex);
-                       method_desc->method.mutex->mutex.owner_thread = NULL;
+                       method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
                }
        }
 
index 688e83a169068836c9546564bce5c8e669f8f55b..54a697f9aa1873400cd2ad1237b786e4f3f9550e 100644 (file)
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
+#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
 
-ACPI_MODULE_NAME("dock")
+ACPI_MODULE_NAME("dock");
 MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
+MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
 MODULE_LICENSE("GPL");
 
 static struct atomic_notifier_head dock_notifier_list;
@@ -741,7 +741,7 @@ static int dock_add(acpi_handle handle)
                goto dock_add_err;
        }
 
-       printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME);
+       printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
 
        return 0;
 
index 743ce27fa0bbf2915c78f4d18fdefecb1fdf133a..ab688837379534b46ab194dacb41925215c3670b 100644 (file)
 #include <acpi/actypes.h>
 
 #define _COMPONENT             ACPI_EC_COMPONENT
-ACPI_MODULE_NAME("acpi_ec")
+ACPI_MODULE_NAME("ec");
 #define ACPI_EC_COMPONENT              0x00100000
 #define ACPI_EC_CLASS                  "embedded_controller"
 #define ACPI_EC_HID                    "PNP0C09"
-#define ACPI_EC_DRIVER_NAME            "ACPI Embedded Controller Driver"
 #define ACPI_EC_DEVICE_NAME            "Embedded Controller"
 #define ACPI_EC_FILE_INFO              "info"
 #undef PREFIX
@@ -80,7 +79,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type);
 static int acpi_ec_add(struct acpi_device *device);
 
 static struct acpi_driver acpi_ec_driver = {
-       .name = ACPI_EC_DRIVER_NAME,
+       .name = "ec",
        .class = ACPI_EC_CLASS,
        .ids = ACPI_EC_HID,
        .ops = {
@@ -280,8 +279,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
        mutex_lock(&ec->lock);
        if (ec->global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-               if (ACPI_FAILURE(status))
+               if (ACPI_FAILURE(status)) {
+                       mutex_unlock(&ec->lock);
                        return -ENODEV;
+               }
        }
 
        /* Make sure GPE is enabled before doing transaction */
index 959a893c8d1fdbd45d415c4a8a50c954ac498050..3b23562e6f92d195ea24dad4b1eb24131b6f519a 100644 (file)
@@ -13,7 +13,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("event")
+ACPI_MODULE_NAME("event");
 
 /* Global vars for handling event proc entry */
 static DEFINE_SPINLOCK(acpi_system_event_lock);
index dfac3ecc596ebfd9314148d3a54ba80648c9d8b0..635ba449ebc2c97e98c2bc615f44e87bcaaf3092 100644 (file)
@@ -636,17 +636,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
                }
        }
 
-       if (!acpi_gbl_system_awake_and_running) {
-               /*
-                * We just woke up because of a wake GPE. Disable any further GPEs
-                * until we are fully up and running (Only wake GPEs should be enabled
-                * at this time, but we just brute-force disable them all.)
-                * 1) We must disable this particular wake GPE so it won't fire again
-                * 2) We want to disable all wake GPEs, since we are now awake
-                */
-               (void)acpi_hw_disable_all_gpes();
-       }
-
        /*
         * Dispatch the GPE to either an installed handler, or the control method
         * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
index 1b784ffe54c3d3c5976a28c1fac2301bb9f47e3d..d572700197f309d118ff302fde56c29a2c25fb1a 100644 (file)
@@ -196,12 +196,11 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
                notify_info->notify.value = (u16) notify_value;
                notify_info->notify.handler_obj = handler_obj;
 
-               status =
-                   acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
-                                   notify_info);
-               if (ACPI_FAILURE(status)) {
-                       acpi_ut_delete_generic_state(notify_info);
-               }
+               acpi_ex_relinquish_interpreter();
+
+               acpi_ev_notify_dispatch(notify_info);
+
+               acpi_ex_reacquire_interpreter();
        }
 
        if (!handler_obj) {
index 68d283fd60e7d254d936b0850a63950a948dbad3..1a73c14df2c5aa7d7f7cdd1c195bb1e202747139 100644 (file)
@@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = {
 static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
        {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
        {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
-       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"},
        {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
         "Acquire Depth"},
        {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"}
index 5101bad5baf8b3074d29156b8a47444b286e90f8..4eb883bda6ae7f23800decda4a549042c64c8a94 100644 (file)
@@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
  *
  ******************************************************************************/
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+                         struct acpi_thread_state *thread)
 {
-       struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
        if (!thread) {
                return;
        }
@@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
 
        /* Support for multiple acquires by the owning thread */
 
-       if (obj_desc->mutex.owner_thread) {
-               if (obj_desc->mutex.owner_thread->thread_id ==
-                   walk_state->thread->thread_id) {
-                       /*
-                        * The mutex is already owned by this thread, just increment the
-                        * acquisition depth
-                        */
-                       obj_desc->mutex.acquisition_depth++;
-                       return_ACPI_STATUS(AE_OK);
-               }
+       if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) {
+               /*
+                * The mutex is already owned by this thread, just increment the
+                * acquisition depth
+                */
+               obj_desc->mutex.acquisition_depth++;
+               return_ACPI_STATUS(AE_OK);
        }
 
        /* Acquire the mutex, wait if necessary. Special case for Global Lock */
@@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
 
        /* Have the mutex: update mutex and walk info and save the sync_level */
 
-       obj_desc->mutex.owner_thread = walk_state->thread;
+       obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id();
        obj_desc->mutex.acquisition_depth = 1;
        obj_desc->mutex.original_sync_level =
            walk_state->thread->current_sync_level;
@@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* The mutex must have been previously acquired in order to release it */
 
-       if (!obj_desc->mutex.owner_thread) {
+       if (!obj_desc->mutex.owner_thread_id) {
                ACPI_ERROR((AE_INFO,
                            "Cannot release Mutex [%4.4s], not acquired",
                            acpi_ut_get_node_name(obj_desc->mutex.node)));
@@ -266,14 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
         * The Mutex is owned, but this thread must be the owner.
         * Special case for Global Lock, any thread can release
         */
-       if ((obj_desc->mutex.owner_thread->thread_id !=
+       if ((obj_desc->mutex.owner_thread_id !=
             walk_state->thread->thread_id)
            && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
                ACPI_ERROR((AE_INFO,
                            "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
                            (unsigned long)walk_state->thread->thread_id,
                            acpi_ut_get_node_name(obj_desc->mutex.node),
-                           (unsigned long)obj_desc->mutex.owner_thread->thread_id));
+                           (unsigned long)obj_desc->mutex.owner_thread_id));
                return_ACPI_STATUS(AE_AML_NOT_OWNER);
        }
 
@@ -300,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* Unlink the mutex from the owner's list */
 
-       acpi_ex_unlink_mutex(obj_desc);
+       acpi_ex_unlink_mutex(obj_desc, walk_state->thread);
 
        /* Release the mutex, special case for Global Lock */
 
@@ -312,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* Update the mutex and restore sync_level */
 
-       obj_desc->mutex.owner_thread = NULL;
+       obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
        walk_state->thread->current_sync_level =
            obj_desc->mutex.original_sync_level;
 
@@ -367,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
 
                /* Mark mutex unowned */
 
-               obj_desc->mutex.owner_thread = NULL;
+               obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 
                /* Update Thread sync_level (Last mutex is the important one) */
 
index af22fdf73413a5c342b7ac5ae8f1aae9234a5254..ec655c53949225080bd90c76143831994f40444e 100644 (file)
 
 #define ACPI_FAN_COMPONENT             0x00200000
 #define ACPI_FAN_CLASS                 "fan"
-#define ACPI_FAN_DRIVER_NAME           "ACPI Fan Driver"
 #define ACPI_FAN_FILE_STATE            "state"
 
 #define _COMPONENT             ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME("acpi_fan")
+ACPI_MODULE_NAME("fan");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Fan Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
@@ -52,7 +51,7 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
 static int acpi_fan_resume(struct acpi_device *device);
 
 static struct acpi_driver acpi_fan_driver = {
-       .name = ACPI_FAN_DRIVER_NAME,
+       .name = "fan",
        .class = ACPI_FAN_CLASS,
        .ids = "PNP0C0B",
        .ops = {
index 7b6c9ff9bebe17d92cb954bc1e6d34e2fac1d946..4334c208841a3f06586ba3693b10d8437fff5b12 100644 (file)
@@ -241,3 +241,65 @@ static int __init init_acpi_device_notify(void)
 }
 
 arch_initcall(init_acpi_device_notify);
+
+
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+
+/* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
+ * its device node and pass extra config data.  This helps its driver use
+ * capabilities that the now-obsolete mc146818 didn't have, and informs it
+ * that this board's RTC is wakeup-capable (per ACPI spec).
+ */
+#include <linux/mc146818rtc.h>
+
+static struct cmos_rtc_board_info rtc_info;
+
+
+/* PNP devices are registered in a subsys_initcall();
+ * ACPI specifies the PNP IDs to use.
+ */
+#include <linux/pnp.h>
+
+static int __init pnp_match(struct device *dev, void *data)
+{
+       static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
+       struct pnp_dev *pnp = to_pnp_dev(dev);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ids); i++) {
+               if (compare_pnp_id(pnp->id, ids[i]) != 0)
+                       return 1;
+       }
+       return 0;
+}
+
+static struct device *__init get_rtc_dev(void)
+{
+       return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
+}
+
+static int __init acpi_rtc_init(void)
+{
+       struct device *dev = get_rtc_dev();
+
+       if (dev) {
+               rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
+               rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
+               rtc_info.rtc_century = acpi_gbl_FADT.century;
+
+               /* NOTE:  acpi_gbl_FADT->rtcs4 is NOT currently useful */
+
+               dev->platform_data = &rtc_info;
+
+               /* RTC always wakes from S1/S2/S3, and often S4/STD */
+               device_init_wakeup(dev, 1);
+
+               put_device(dev);
+       } else
+               pr_debug("ACPI: RTC unavailable?\n");
+       return 0;
+}
+/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
+fs_initcall(acpi_rtc_init);
+
+#endif
index 57901ca3ade911fea9ae132dd7aa77844025372b..8fa93125fd4c94af822bf9b6dd1863511de16b7a 100644 (file)
@@ -235,6 +235,14 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
                                "While executing method _SST"));
        }
 
+       /*
+        * 1) Disable/Clear all GPEs
+        */
+       status = acpi_hw_disable_all_gpes();
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
        return_ACPI_STATUS(AE_OK);
 }
 
@@ -290,13 +298,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
        }
 
        /*
-        * 1) Disable/Clear all GPEs
         * 2) Enable all wakeup GPEs
         */
-       status = acpi_hw_disable_all_gpes();
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
        acpi_gbl_system_awake_and_running = FALSE;
 
        status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
deleted file mode 100644 (file)
index 8edfb92..0000000
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- *  hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $)
- *
- *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <linux/kmod.h>
-#include <linux/seq_file.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-
-#define HOTKEY_ACPI_VERSION "0.1"
-
-#define HOTKEY_PROC "hotkey"
-#define HOTKEY_EV_CONFIG    "event_config"
-#define HOTKEY_PL_CONFIG    "poll_config"
-#define HOTKEY_ACTION   "action"
-#define HOTKEY_INFO "info"
-
-#define ACPI_HOTK_NAME          "Generic Hotkey Driver"
-#define ACPI_HOTK_CLASS         "Hotkey"
-#define ACPI_HOTK_DEVICE_NAME   "Hotkey"
-#define ACPI_HOTK_HID           "Unknown?"
-#define ACPI_HOTKEY_COMPONENT   0x20000000
-
-#define ACPI_HOTKEY_EVENT   0x1
-#define ACPI_HOTKEY_POLLING 0x2
-#define ACPI_UNDEFINED_EVENT    0xf
-
-#define RESULT_STR_LEN     80
-
-#define ACTION_METHOD  0
-#define POLL_METHOD    1
-
-#define IS_EVENT(e)            ((e) <= 10000 && (e) >0)
-#define IS_POLL(e)             ((e) > 10000)
-#define IS_OTHERS(e)           ((e)<=0 || (e)>=20000)
-#define _COMPONENT              ACPI_HOTKEY_COMPONENT
-ACPI_MODULE_NAME("acpi_hotkey")
-
-    MODULE_AUTHOR("luming.yu@intel.com");
-MODULE_DESCRIPTION(ACPI_HOTK_NAME);
-MODULE_LICENSE("GPL");
-
-/*  standardized internal hotkey number/event  */
-enum {
-       /* Video Extension event */
-       HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80,
-       HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE,
-       HK_EVENT_CYCLE_DISPLAY_OUTPUT,
-       HK_EVENT_NEXT_DISPLAY_OUTPUT,
-       HK_EVENT_PREVIOUS_DISPLAY_OUTPUT,
-       HK_EVENT_CYCLE_BRIGHTNESS,
-       HK_EVENT_INCREASE_BRIGHTNESS,
-       HK_EVENT_DECREASE_BRIGHTNESS,
-       HK_EVENT_ZERO_BRIGHTNESS,
-       HK_EVENT_DISPLAY_DEVICE_OFF,
-
-       /* Snd Card event */
-       HK_EVENT_VOLUME_MUTE,
-       HK_EVENT_VOLUME_INCLREASE,
-       HK_EVENT_VOLUME_DECREASE,
-
-       /* running state control */
-       HK_EVENT_ENTERRING_S3,
-       HK_EVENT_ENTERRING_S4,
-       HK_EVENT_ENTERRING_S5,
-};
-
-enum conf_entry_enum {
-       bus_handle = 0,
-       bus_method = 1,
-       action_handle = 2,
-       method = 3,
-       LAST_CONF_ENTRY
-};
-
-/*  procdir we use */
-static struct proc_dir_entry *hotkey_proc_dir;
-static struct proc_dir_entry *hotkey_config;
-static struct proc_dir_entry *hotkey_poll_config;
-static struct proc_dir_entry *hotkey_action;
-static struct proc_dir_entry *hotkey_info;
-
-/* linkage for all type of hotkey */
-struct acpi_hotkey_link {
-       struct list_head entries;
-       int hotkey_type;        /* event or polling based hotkey  */
-       int hotkey_standard_num;        /* standardized hotkey(event) number */
-};
-
-/* event based hotkey */
-struct acpi_event_hotkey {
-       struct acpi_hotkey_link hotkey_link;
-       int flag;
-       acpi_handle bus_handle; /* bus to install notify handler */
-       int external_hotkey_num;        /* external hotkey/event number */
-       acpi_handle action_handle;      /* acpi handle attached aml action method */
-       char *action_method;    /* action method */
-};
-
-/*
- * There are two ways to poll status
- * 1. directy call read_xxx method, without any arguments passed in
- * 2. call write_xxx method, with arguments passed in, you need
- * the result is saved in acpi_polling_hotkey.poll_result.
- * anthoer read command through polling interface.
- *
- */
-
-/* polling based hotkey */
-struct acpi_polling_hotkey {
-       struct acpi_hotkey_link hotkey_link;
-       int flag;
-       acpi_handle poll_handle;        /* acpi handle attached polling method */
-       char *poll_method;      /* poll method */
-       acpi_handle action_handle;      /* acpi handle attached action method */
-       char *action_method;    /* action method */
-       union acpi_object *poll_result; /* polling_result */
-       struct proc_dir_entry *proc;
-};
-
-/* hotkey object union */
-union acpi_hotkey {
-       struct list_head entries;
-       struct acpi_hotkey_link link;
-       struct acpi_event_hotkey event_hotkey;
-       struct acpi_polling_hotkey poll_hotkey;
-};
-
-/* hotkey object list */
-struct acpi_hotkey_list {
-       struct list_head *entries;
-       int count;
-};
-
-static int auto_hotkey_add(struct acpi_device *device);
-static int auto_hotkey_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver hotkey_driver = {
-       .name = ACPI_HOTK_NAME,
-       .class = ACPI_HOTK_CLASS,
-       .ids = ACPI_HOTK_HID,
-       .ops = {
-               .add = auto_hotkey_add,
-               .remove = auto_hotkey_remove,
-               },
-};
-
-static void free_hotkey_device(union acpi_hotkey *key);
-static void free_hotkey_buffer(union acpi_hotkey *key);
-static void free_poll_hotkey_buffer(union acpi_hotkey *key);
-static int hotkey_open_config(struct inode *inode, struct file *file);
-static int hotkey_poll_open_config(struct inode *inode, struct file *file);
-static ssize_t hotkey_write_config(struct file *file,
-                                  const char __user * buffer,
-                                  size_t count, loff_t * data);
-static int hotkey_info_open_fs(struct inode *inode, struct file *file);
-static int hotkey_action_open_fs(struct inode *inode, struct file *file);
-static ssize_t hotkey_execute_aml_method(struct file *file,
-                                        const char __user * buffer,
-                                        size_t count, loff_t * data);
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
-static union acpi_hotkey *get_hotkey_by_event(struct
-                                             acpi_hotkey_list
-                                             *hotkey_list, int event);
-
-/* event based config */
-static const struct file_operations hotkey_config_fops = {
-       .open = hotkey_open_config,
-       .read = seq_read,
-       .write = hotkey_write_config,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-/* polling based config */
-static const struct file_operations hotkey_poll_config_fops = {
-       .open = hotkey_poll_open_config,
-       .read = seq_read,
-       .write = hotkey_write_config,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-/* hotkey driver info */
-static const struct file_operations hotkey_info_fops = {
-       .open = hotkey_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-/* action */
-static const struct file_operations hotkey_action_fops = {
-       .open = hotkey_action_open_fs,
-       .read = seq_read,
-       .write = hotkey_execute_aml_method,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-/* polling results */
-static const struct file_operations hotkey_polling_fops = {
-       .open = hotkey_polling_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-struct acpi_hotkey_list global_hotkey_list;    /* link all ev or pl hotkey  */
-struct list_head hotkey_entries;       /* head of the list of hotkey_list */
-
-static int hotkey_info_seq_show(struct seq_file *seq, void *offset)
-{
-
-       seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION);
-
-       return 0;
-}
-
-static int hotkey_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-static char *format_result(union acpi_object *object)
-{
-       char *buf;
-
-       buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
-       if (!buf)
-               return NULL;
-       /* Now, just support integer type */
-       if (object->type == ACPI_TYPE_INTEGER)
-               sprintf(buf, "%d\n", (u32) object->integer.value);
-       return buf;
-}
-
-static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_polling_hotkey *poll_hotkey = seq->private;
-       char *buf;
-
-
-       if (poll_hotkey->poll_result) {
-               buf = format_result(poll_hotkey->poll_result);
-               if (buf)
-                       seq_printf(seq, "%s", buf);
-               kfree(buf);
-       }
-       return 0;
-}
-
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, hotkey_polling_seq_show, PDE(inode)->data);
-}
-
-static int hotkey_action_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-/* Mapping external hotkey number to standardized hotkey event num */
-static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
-{
-       struct list_head *entries;
-       int val = -1;
-
-
-       list_for_each(entries, list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
-                   && key->event_hotkey.external_hotkey_num == event) {
-                       val = key->link.hotkey_standard_num;
-                       break;
-               }
-       }
-
-       return val;
-}
-
-static void
-acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data)
-{
-       struct acpi_device *device = NULL;
-       u32 internal_event;
-
-
-       if (acpi_bus_get_device(handle, &device))
-               return;
-
-       internal_event = hotkey_get_internal_event(event, &global_hotkey_list);
-       acpi_bus_generate_event(device, internal_event, 0);
-
-       return;
-}
-
-/* Need to invent automatically hotkey add method */
-static int auto_hotkey_add(struct acpi_device *device)
-{
-       /* Implement me */
-       return 0;
-}
-
-/* Need to invent automatically hotkey remove method */
-static int auto_hotkey_remove(struct acpi_device *device, int type)
-{
-       /* Implement me */
-       return 0;
-}
-
-/* Create a proc file for each polling method */
-static int create_polling_proc(union acpi_hotkey *device)
-{
-       struct proc_dir_entry *proc;
-       char proc_name[80];
-       mode_t mode;
-
-       mode = S_IFREG | S_IRUGO | S_IWUGO;
-
-       sprintf(proc_name, "%d", device->link.hotkey_standard_num);
-       /*
-          strcat(proc_name, device->poll_hotkey.poll_method);
-        */
-       proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
-
-       if (!proc) {
-               return -ENODEV;
-       } else {
-               proc->proc_fops = &hotkey_polling_fops;
-               proc->owner = THIS_MODULE;
-               proc->data = device;
-               proc->uid = 0;
-               proc->gid = 0;
-               device->poll_hotkey.proc = proc;
-       }
-       return 0;
-}
-
-static int hotkey_add(union acpi_hotkey *device)
-{
-       int status = 0;
-       struct acpi_device *dev = NULL;
-
-
-       if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-               acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
-               status = acpi_install_notify_handler(dev->handle,
-                                                    ACPI_DEVICE_NOTIFY,
-                                                    acpi_hotkey_notify_handler,
-                                                    dev);
-       } else                  /* Add polling hotkey */
-               create_polling_proc(device);
-
-       global_hotkey_list.count++;
-
-       list_add_tail(&device->link.entries, global_hotkey_list.entries);
-
-       return status;
-}
-
-static int hotkey_remove(union acpi_hotkey *device)
-{
-       struct list_head *entries, *next;
-
-
-       list_for_each_safe(entries, next, global_hotkey_list.entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_standard_num ==
-                   device->link.hotkey_standard_num) {
-                       list_del(&key->link.entries);
-                       free_hotkey_device(key);
-                       global_hotkey_list.count--;
-                       break;
-               }
-       }
-       kfree(device);
-       return 0;
-}
-
-static int hotkey_update(union acpi_hotkey *key)
-{
-       struct list_head *entries;
-
-
-       list_for_each(entries, global_hotkey_list.entries) {
-               union acpi_hotkey *tmp =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (tmp->link.hotkey_standard_num ==
-                   key->link.hotkey_standard_num) {
-                       if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-                               free_hotkey_buffer(tmp);
-                               tmp->event_hotkey.bus_handle =
-                                   key->event_hotkey.bus_handle;
-                               tmp->event_hotkey.external_hotkey_num =
-                                   key->event_hotkey.external_hotkey_num;
-                               tmp->event_hotkey.action_handle =
-                                   key->event_hotkey.action_handle;
-                               tmp->event_hotkey.action_method =
-                                   key->event_hotkey.action_method;
-                               kfree(key);
-                       } else {
-                               /*
-                                  char  proc_name[80];
-
-                                  sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
-                                  strcat(proc_name, tmp->poll_hotkey.poll_method);
-                                  remove_proc_entry(proc_name,hotkey_proc_dir);
-                                */
-                               free_poll_hotkey_buffer(tmp);
-                               tmp->poll_hotkey.poll_handle =
-                                   key->poll_hotkey.poll_handle;
-                               tmp->poll_hotkey.poll_method =
-                                   key->poll_hotkey.poll_method;
-                               tmp->poll_hotkey.action_handle =
-                                   key->poll_hotkey.action_handle;
-                               tmp->poll_hotkey.action_method =
-                                   key->poll_hotkey.action_method;
-                               tmp->poll_hotkey.poll_result =
-                                   key->poll_hotkey.poll_result;
-                               /*
-                                  create_polling_proc(tmp);
-                                */
-                               kfree(key);
-                       }
-                       return 0;
-                       break;
-               }
-       }
-
-       return -ENODEV;
-}
-
-static void free_hotkey_device(union acpi_hotkey *key)
-{
-       struct acpi_device *dev;
-
-
-       if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-               acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
-               if (dev->handle)
-                       acpi_remove_notify_handler(dev->handle,
-                                                  ACPI_DEVICE_NOTIFY,
-                                                  acpi_hotkey_notify_handler);
-               free_hotkey_buffer(key);
-       } else {
-               char proc_name[80];
-
-               sprintf(proc_name, "%d", key->link.hotkey_standard_num);
-               /*
-                  strcat(proc_name, key->poll_hotkey.poll_method);
-                */
-               remove_proc_entry(proc_name, hotkey_proc_dir);
-               free_poll_hotkey_buffer(key);
-       }
-       kfree(key);
-       return;
-}
-
-static void free_hotkey_buffer(union acpi_hotkey *key)
-{
-       /* key would never be null, action method could be */
-       kfree(key->event_hotkey.action_method);
-}
-
-static void free_poll_hotkey_buffer(union acpi_hotkey *key)
-{
-       /* key would never be null, others could be*/
-       kfree(key->poll_hotkey.action_method);
-       kfree(key->poll_hotkey.poll_method);
-       kfree(key->poll_hotkey.poll_result);
-}
-static int
-init_hotkey_device(union acpi_hotkey *key, char **config_entry,
-                  int std_num, int external_num)
-{
-       acpi_handle tmp_handle;
-       acpi_status status = AE_OK;
-
-       if (std_num < 0 || IS_POLL(std_num) || !key)
-               goto do_fail;
-
-       if (!config_entry[bus_handle] || !config_entry[action_handle]
-                       || !config_entry[method])
-               goto do_fail;
-
-       key->link.hotkey_type = ACPI_HOTKEY_EVENT;
-       key->link.hotkey_standard_num = std_num;
-       key->event_hotkey.flag = 0;
-       key->event_hotkey.action_method = config_entry[method];
-
-       status = acpi_get_handle(NULL, config_entry[bus_handle],
-                          &(key->event_hotkey.bus_handle));
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       key->event_hotkey.external_hotkey_num = external_num;
-       status = acpi_get_handle(NULL, config_entry[action_handle],
-                           &(key->event_hotkey.action_handle));
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       status = acpi_get_handle(key->event_hotkey.action_handle,
-                                config_entry[method], &tmp_handle);
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       return AE_OK;
-do_fail_zero:
-       key->event_hotkey.action_method = NULL;
-do_fail:
-       return -ENODEV;
-}
-
-static int
-init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
-                       int std_num)
-{
-       acpi_status status = AE_OK;
-       acpi_handle tmp_handle;
-
-       if (std_num < 0 || IS_EVENT(std_num) || !key)
-               goto do_fail;
-       if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
-               !config_entry[action_handle] || !config_entry[method])
-               goto do_fail;
-
-       key->link.hotkey_type = ACPI_HOTKEY_POLLING;
-       key->link.hotkey_standard_num = std_num;
-       key->poll_hotkey.flag = 0;
-       key->poll_hotkey.poll_method = config_entry[bus_method];
-       key->poll_hotkey.action_method = config_entry[method];
-
-       status = acpi_get_handle(NULL, config_entry[bus_handle],
-                     &(key->poll_hotkey.poll_handle));
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       status = acpi_get_handle(key->poll_hotkey.poll_handle,
-                                config_entry[bus_method], &tmp_handle);
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       status =
-           acpi_get_handle(NULL, config_entry[action_handle],
-                           &(key->poll_hotkey.action_handle));
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       status = acpi_get_handle(key->poll_hotkey.action_handle,
-                                config_entry[method], &tmp_handle);
-       if (ACPI_FAILURE(status))
-               goto do_fail_zero;
-       key->poll_hotkey.poll_result =
-           kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-       if (!key->poll_hotkey.poll_result)
-               goto do_fail_zero;
-       return AE_OK;
-
-do_fail_zero:
-       key->poll_hotkey.poll_method = NULL;
-       key->poll_hotkey.action_method = NULL;
-do_fail:
-       return -ENODEV;
-}
-
-static int hotkey_open_config(struct inode *inode, struct file *file)
-{
-       return (single_open
-                    (file, hotkey_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_poll_open_config(struct inode *inode, struct file *file)
-{
-       return (single_open
-                    (file, hotkey_poll_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       struct list_head *entries;
-       char bus_name[ACPI_PATHNAME_MAX] = { 0 };
-       char action_name[ACPI_PATHNAME_MAX] = { 0 };
-       struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
-       struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
-       list_for_each(entries, hotkey_list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-                       acpi_get_name(key->event_hotkey.bus_handle,
-                                     ACPI_NAME_TYPE_MAX, &bus);
-                       acpi_get_name(key->event_hotkey.action_handle,
-                                     ACPI_NAME_TYPE_MAX, &act);
-                       seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name,
-                                  action_name,
-                                  key->event_hotkey.action_method,
-                                  key->link.hotkey_standard_num,
-                                  key->event_hotkey.external_hotkey_num);
-               }
-       }
-       seq_puts(seq, "\n");
-       return 0;
-}
-
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       struct list_head *entries;
-       char bus_name[ACPI_PATHNAME_MAX] = { 0 };
-       char action_name[ACPI_PATHNAME_MAX] = { 0 };
-       struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
-       struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
-       list_for_each(entries, hotkey_list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) {
-                       acpi_get_name(key->poll_hotkey.poll_handle,
-                                     ACPI_NAME_TYPE_MAX, &bus);
-                       acpi_get_name(key->poll_hotkey.action_handle,
-                                     ACPI_NAME_TYPE_MAX, &act);
-                       seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name,
-                                  key->poll_hotkey.poll_method,
-                                  action_name,
-                                  key->poll_hotkey.action_method,
-                                  key->link.hotkey_standard_num);
-               }
-       }
-       seq_puts(seq, "\n");
-       return 0;
-}
-
-static int
-get_parms(char *config_record, int *cmd, char **config_entry,
-              int *internal_event_num, int *external_event_num)
-{
-/* the format of *config_record =
- * "1:\d+:*" : "cmd:internal_event_num"
- * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
- * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
- */
-       char *tmp, *tmp1, count;
-       int i;
-
-       sscanf(config_record, "%d", cmd);
-       if (*cmd == 1) {
-               if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
-                   2)
-                       goto do_fail;
-               else
-                       return (6);
-       }
-       tmp = strchr(config_record, ':');
-       if (!tmp)
-               goto do_fail;
-       tmp++;
-       for (i = 0; i < LAST_CONF_ENTRY; i++) {
-               tmp1 = strchr(tmp, ':');
-               if (!tmp1) {
-                       goto do_fail;
-               }
-               count = tmp1 - tmp;
-               config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
-               if (!config_entry[i])
-                       goto handle_failure;
-               strncpy(config_entry[i], tmp, count);
-               tmp = tmp1 + 1;
-       }
-       if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
-               goto handle_failure;
-       if (!IS_OTHERS(*internal_event_num)) {
-               return 6;
-       }
-handle_failure:
-       while (i-- > 0)
-               kfree(config_entry[i]);
-do_fail:
-       return -1;
-}
-
-/*  count is length for one input record */
-static ssize_t hotkey_write_config(struct file *file,
-                                  const char __user * buffer,
-                                  size_t count, loff_t * data)
-{
-       char *config_record = NULL;
-       char *config_entry[LAST_CONF_ENTRY];
-       int cmd, internal_event_num, external_event_num;
-       int ret = 0;
-       union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-
-       if (!key)
-               return -ENOMEM;
-
-       config_record = kzalloc(count + 1, GFP_KERNEL);
-       if (!config_record) {
-               kfree(key);
-               return -ENOMEM;
-       }
-
-       if (copy_from_user(config_record, buffer, count)) {
-               kfree(config_record);
-               kfree(key);
-               printk(KERN_ERR PREFIX "Invalid data\n");
-               return -EINVAL;
-       }
-       ret = get_parms(config_record, &cmd, config_entry,
-                      &internal_event_num, &external_event_num);
-       kfree(config_record);
-       if (ret != 6) {
-               printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
-               return -EINVAL;
-       }
-
-       if (cmd == 1) {
-               union acpi_hotkey *tmp = NULL;
-               tmp = get_hotkey_by_event(&global_hotkey_list,
-                                         internal_event_num);
-               if (!tmp)
-                       printk(KERN_ERR PREFIX "Invalid key\n");
-               else
-                       memcpy(key, tmp, sizeof(union acpi_hotkey));
-               goto cont_cmd;
-       }
-       if (IS_EVENT(internal_event_num)) {
-               if (init_hotkey_device(key, config_entry,
-                       internal_event_num, external_event_num))
-                       goto init_hotkey_fail;
-       } else {
-               if (init_poll_hotkey_device(key, config_entry,
-                              internal_event_num))
-                       goto init_poll_hotkey_fail;
-       }
-cont_cmd:
-       switch (cmd) {
-       case 0:
-               if (get_hotkey_by_event(&global_hotkey_list,
-                               key->link.hotkey_standard_num))
-                       goto fail_out;
-               else
-                       hotkey_add(key);
-               break;
-       case 1:
-               hotkey_remove(key);
-               break;
-       case 2:
-               /* key is kfree()ed if matched*/
-               if (hotkey_update(key))
-                       goto fail_out;
-               break;
-       default:
-               goto fail_out;
-               break;
-       }
-       return count;
-
-init_poll_hotkey_fail:         /* failed init_poll_hotkey_device */
-       kfree(config_entry[bus_method]);
-       config_entry[bus_method] = NULL;
-init_hotkey_fail:              /* failed init_hotkey_device */
-       kfree(config_entry[method]);
-fail_out:
-       kfree(config_entry[bus_handle]);
-       kfree(config_entry[action_handle]);
-       /* No double free since elements =NULL for error cases */
-       if (IS_EVENT(internal_event_num)) {
-               if (config_entry[bus_method])
-                       kfree(config_entry[bus_method]);
-               free_hotkey_buffer(key);        /* frees [method] */
-       } else
-               free_poll_hotkey_buffer(key);  /* frees [bus_method]+[method] */
-       kfree(key);
-       printk(KERN_ERR PREFIX "invalid key\n");
-       return -EINVAL;
-}
-
-/*
- * This function evaluates an ACPI method, given an int as parameter, the
- * method is searched within the scope of the handle, can be NULL. The output
- * of the method is written is output, which can also be NULL
- *
- * returns 1 if write is successful, 0 else.
- */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-                         struct acpi_buffer *output)
-{
-       struct acpi_object_list params; /* list of input parameters (an int here) */
-       union acpi_object in_obj;       /* the only param we use */
-       acpi_status status;
-
-       params.count = 1;
-       params.pointer = &in_obj;
-       in_obj.type = ACPI_TYPE_INTEGER;
-       in_obj.integer.value = val;
-
-       status = acpi_evaluate_object(handle, (char *)method, &params, output);
-
-       return (status == AE_OK);
-}
-
-static int read_acpi_int(acpi_handle handle, const char *method,
-                        union acpi_object *val)
-{
-       struct acpi_buffer output;
-       union acpi_object out_obj;
-       acpi_status status;
-
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
-       if (val) {
-               val->integer.value = out_obj.integer.value;
-               val->type = out_obj.type;
-       } else
-               printk(KERN_ERR PREFIX "null val pointer\n");
-       return ((status == AE_OK)
-                    && (out_obj.type == ACPI_TYPE_INTEGER));
-}
-
-static union acpi_hotkey *get_hotkey_by_event(struct
-                                             acpi_hotkey_list
-                                             *hotkey_list, int event)
-{
-       struct list_head *entries;
-
-       list_for_each(entries, hotkey_list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_standard_num == event) {
-                       return (key);
-               }
-       }
-       return (NULL);
-}
-
-/*
- * user call AML method interface:
- * Call convention:
- * echo "event_num: arg type : value"
- * example: echo "1:1:30" > /proc/acpi/action
- * Just support 1 integer arg passing to AML method
- */
-
-static ssize_t hotkey_execute_aml_method(struct file *file,
-                                        const char __user * buffer,
-                                        size_t count, loff_t * data)
-{
-       struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       char *arg;
-       int event, method_type, type, value;
-       union acpi_hotkey *key;
-
-
-       arg = kzalloc(count + 1, GFP_KERNEL);
-       if (!arg)
-               return -ENOMEM;
-
-       if (copy_from_user(arg, buffer, count)) {
-               kfree(arg);
-               printk(KERN_ERR PREFIX "Invalid argument 2\n");
-               return -EINVAL;
-       }
-
-       if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) !=
-           4) {
-               kfree(arg);
-               printk(KERN_ERR PREFIX "Invalid argument 3\n");
-               return -EINVAL;
-       }
-       kfree(arg);
-       if (type == ACPI_TYPE_INTEGER) {
-               key = get_hotkey_by_event(hotkey_list, event);
-               if (!key)
-                       goto do_fail;
-               if (IS_EVENT(event))
-                       write_acpi_int(key->event_hotkey.action_handle,
-                                      key->event_hotkey.action_method, value,
-                                      NULL);
-               else if (IS_POLL(event)) {
-                       if (method_type == POLL_METHOD)
-                               read_acpi_int(key->poll_hotkey.poll_handle,
-                                             key->poll_hotkey.poll_method,
-                                             key->poll_hotkey.poll_result);
-                       else if (method_type == ACTION_METHOD)
-                               write_acpi_int(key->poll_hotkey.action_handle,
-                                              key->poll_hotkey.action_method,
-                                              value, NULL);
-                       else
-                               goto do_fail;
-
-               }
-       } else {
-               printk(KERN_WARNING "Not supported\n");
-               return -EINVAL;
-       }
-       return count;
-      do_fail:
-       return -EINVAL;
-
-}
-
-static int __init hotkey_init(void)
-{
-       int result;
-       mode_t mode = S_IFREG | S_IRUGO | S_IWUGO;
-
-
-       if (acpi_disabled)
-               return -ENODEV;
-
-       if (acpi_specific_hotkey_enabled) {
-               printk("Using specific hotkey driver\n");
-               return -ENODEV;
-       }
-
-       hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir);
-       if (!hotkey_proc_dir) {
-               return (-ENODEV);
-       }
-       hotkey_proc_dir->owner = THIS_MODULE;
-
-       hotkey_config =
-           create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir);
-       if (!hotkey_config) {
-               goto do_fail1;
-       } else {
-               hotkey_config->proc_fops = &hotkey_config_fops;
-               hotkey_config->data = &global_hotkey_list;
-               hotkey_config->owner = THIS_MODULE;
-               hotkey_config->uid = 0;
-               hotkey_config->gid = 0;
-       }
-
-       hotkey_poll_config =
-           create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir);
-       if (!hotkey_poll_config) {
-               goto do_fail2;
-       } else {
-               hotkey_poll_config->proc_fops = &hotkey_poll_config_fops;
-               hotkey_poll_config->data = &global_hotkey_list;
-               hotkey_poll_config->owner = THIS_MODULE;
-               hotkey_poll_config->uid = 0;
-               hotkey_poll_config->gid = 0;
-       }
-
-       hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir);
-       if (!hotkey_action) {
-               goto do_fail3;
-       } else {
-               hotkey_action->proc_fops = &hotkey_action_fops;
-               hotkey_action->owner = THIS_MODULE;
-               hotkey_action->uid = 0;
-               hotkey_action->gid = 0;
-       }
-
-       hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir);
-       if (!hotkey_info) {
-               goto do_fail4;
-       } else {
-               hotkey_info->proc_fops = &hotkey_info_fops;
-               hotkey_info->owner = THIS_MODULE;
-               hotkey_info->uid = 0;
-               hotkey_info->gid = 0;
-       }
-
-       result = acpi_bus_register_driver(&hotkey_driver);
-       if (result < 0)
-               goto do_fail5;
-       global_hotkey_list.count = 0;
-       global_hotkey_list.entries = &hotkey_entries;
-
-       INIT_LIST_HEAD(&hotkey_entries);
-
-       return (0);
-
-      do_fail5:
-       remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-      do_fail4:
-       remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-      do_fail3:
-       remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-      do_fail2:
-       remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-      do_fail1:
-       remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
-       return (-ENODEV);
-}
-
-static void __exit hotkey_exit(void)
-{
-       struct list_head *entries, *next;
-
-
-       list_for_each_safe(entries, next, global_hotkey_list.entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-
-               acpi_os_wait_events_complete(NULL);
-               list_del(&key->link.entries);
-               global_hotkey_list.count--;
-               free_hotkey_device(key);
-       }
-       acpi_bus_unregister_driver(&hotkey_driver);
-       remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-       remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-       remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-       remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-       remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
-       return;
-}
-
-module_init(hotkey_init);
-module_exit(hotkey_exit);
index bb54b6cdb30b8a1ed42bfe0f9b9f78cb3739ed2f..acab4a4818974df5487cdc27efcc3fad7d084308 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/acpi.h>
 #define ACPI_EC_HC_COMPONENT   0x00080000
 #define ACPI_EC_HC_CLASS       "ec_hc_smbus"
 #define ACPI_EC_HC_HID         "ACPI0001"
-#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver"
 #define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
 
 #define _COMPONENT             ACPI_EC_HC_COMPONENT
 
-ACPI_MODULE_NAME("acpi_smbus")
+ACPI_MODULE_NAME("i2c_ec");
 
 static int acpi_ec_hc_add(struct acpi_device *device);
 static int acpi_ec_hc_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_ec_hc_driver = {
-       .name = ACPI_EC_HC_DRIVER_NAME,
+       .name = "i2c_ec",
        .class = ACPI_EC_HC_CLASS,
        .ids = ACPI_EC_HC_HID,
        .ops = {
index c6144ca6663861529a65d1f7f5c5d618be1f43f3..1a0ed3dc409c8426d1e79f084a1ce0e38451bac7 100644 (file)
@@ -496,6 +496,10 @@ static int ibm_acpi_driver_init(void)
        printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
        printk(IBM_INFO "%s\n", IBM_URL);
 
+       if (ibm_thinkpad_ec_found)
+               printk(IBM_INFO "ThinkPad EC firmware %s\n",
+                      ibm_thinkpad_ec_found);
+
        return 0;
 }
 
@@ -2617,7 +2621,7 @@ static void __init ibm_handle_init(char *name,
        ibm_handle_init(#object, &object##_handle, *object##_parent,    \
                object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
 
-static int set_ibm_param(const char *val, struct kernel_param *kp)
+static int __init set_ibm_param(const char *val, struct kernel_param *kp)
 {
        unsigned int i;
 
@@ -2659,7 +2663,8 @@ static void acpi_ibm_exit(void)
        for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
                ibm_exit(&ibms[i]);
 
-       remove_proc_entry(IBM_DIR, acpi_root_dir);
+       if (proc_dir)
+               remove_proc_entry(IBM_DIR, acpi_root_dir);
 
        if (ibm_thinkpad_ec_found)
                kfree(ibm_thinkpad_ec_found);
@@ -2696,11 +2701,6 @@ static int __init acpi_ibm_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-       if (!acpi_specific_hotkey_enabled) {
-               printk(IBM_ERR "using generic hotkey driver\n");
-               return -ENODEV;
-       }
-
        /* ec is required because many other handles are relative to it */
        IBM_HANDLE_INIT(ec);
        if (!ec_handle) {
@@ -2710,9 +2710,6 @@ static int __init acpi_ibm_init(void)
 
        /* Models with newer firmware report the EC in DMI */
        ibm_thinkpad_ec_found = check_dmi_for_ec();
-       if (ibm_thinkpad_ec_found)
-               printk(IBM_INFO "ThinkPad EC firmware %s\n",
-                      ibm_thinkpad_ec_found);
 
        /* these handles are not required */
        IBM_HANDLE_INIT(vid);
@@ -2742,6 +2739,7 @@ static int __init acpi_ibm_init(void)
        proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
        if (!proc_dir) {
                printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
+               acpi_ibm_exit();
                return -ENODEV;
        }
        proc_dir->owner = THIS_MODULE;
index 326af8fc0ce7e83fd91d9d7fee21f6d854f25694..33db2241044e5930430c5091f6580c9013721f15 100644 (file)
@@ -45,6 +45,7 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acdispat.h>
 #include <acpi/acinterp.h>
+#include <linux/nmi.h>
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsinit")
@@ -534,7 +535,15 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
        info->parameter_type = ACPI_PARAM_ARGS;
        info->flags = ACPI_IGNORE_RETURN_VALUE;
 
+       /*
+        * Some hardware relies on this being executed as atomically
+        * as possible (without an NMI being received in the middle of
+        * this) - so disable NMIs and initialize the device:
+        */
+       acpi_nmi_disable();
        status = acpi_ns_evaluate(info);
+       acpi_nmi_enable();
+
        if (ACPI_SUCCESS(status)) {
                walk_info->num_INI++;
 
index 4a9faff4c01dc897bd113dabd50ec961024125a8..8fcd6a15517f5810ee6b2b6f98ba33d01d8d707a 100644 (file)
@@ -33,7 +33,7 @@
 
 #define ACPI_NUMA      0x80000000
 #define _COMPONENT     ACPI_NUMA
-ACPI_MODULE_NAME("numa")
+ACPI_MODULE_NAME("numa");
 
 static nodemask_t nodes_found_map = NODE_MASK_NONE;
 #define PXM_INVAL      -1
@@ -45,12 +45,6 @@ int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
 int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
                                = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
-extern int __init acpi_table_parse_madt_family(char *id,
-                                              unsigned long madt_size,
-                                              int entry_id,
-                                              acpi_madt_entry_handler handler,
-                                              unsigned int max_entries);
-
 int __cpuinit pxm_to_node(int pxm)
 {
        if (pxm < 0)
@@ -208,9 +202,9 @@ static int __init acpi_parse_srat(struct acpi_table_header *table)
 
 int __init
 acpi_table_parse_srat(enum acpi_srat_type id,
-                     acpi_madt_entry_handler handler, unsigned int max_entries)
+                     acpi_table_entry_handler handler, unsigned int max_entries)
 {
-       return acpi_table_parse_madt_family(ACPI_SIG_SRAT,
+       return acpi_table_parse_entries(ACPI_SIG_SRAT,
                                            sizeof(struct acpi_table_srat), id,
                                            handler, max_entries);
 }
@@ -220,9 +214,7 @@ int __init acpi_numa_init(void)
        int result;
 
        /* SRAT: Static Resource Affinity Table */
-       result = acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat);
-
-       if (result > 0) {
+       if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
                result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
                                               acpi_parse_processor_affinity,
                                               NR_CPUS);
@@ -230,7 +222,7 @@ int __init acpi_numa_init(void)
        }
 
        /* SLIT: System Locality Information Table */
-       result = acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+       acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
        acpi_numa_arch_fixup();
        return 0;
index 0f6f3bcbc8ebc2d4b0c06cb8f1443d1fb5e6e9b6..971eca4864fab3223bc68d97cd032a56d428f4ea 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/efi.h>
 
 #define _COMPONENT             ACPI_OS_SERVICES
-ACPI_MODULE_NAME("osl")
+ACPI_MODULE_NAME("osl");
 #define PREFIX         "ACPI: "
 struct acpi_os_dpc {
        acpi_osd_exec_callback function;
@@ -68,9 +68,6 @@ EXPORT_SYMBOL(acpi_in_debugger);
 extern char line_buf[80];
 #endif                         /*ENABLE_DEBUGGER */
 
-int acpi_specific_hotkey_enabled = TRUE;
-EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
-
 static unsigned int acpi_irq_irq;
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
@@ -205,7 +202,7 @@ void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
        if (phys > ULONG_MAX) {
                printk(KERN_ERR PREFIX "Cannot map memory that high\n");
-               return 0;
+               return NULL;
        }
        if (acpi_gbl_permanent_mmap)
                /*
@@ -890,26 +887,6 @@ u32 acpi_os_get_line(char *buffer)
 }
 #endif                         /*  ACPI_FUTURE_USAGE  */
 
-/* Assumes no unreadable holes inbetween */
-u8 acpi_os_readable(void *ptr, acpi_size len)
-{
-#if defined(__i386__) || defined(__x86_64__)
-       char tmp;
-       return !__get_user(tmp, (char __user *)ptr)
-           && !__get_user(tmp, (char __user *)ptr + len - 1);
-#endif
-       return 1;
-}
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *ptr, acpi_size len)
-{
-       /* could do dummy write (racy) or a kernel page table lookup.
-          The later may be difficult at early boot when kmap doesn't work yet. */
-       return 1;
-}
-#endif
-
 acpi_status acpi_os_signal(u32 function, void *info)
 {
        switch (function) {
@@ -1012,14 +989,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
 
 __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
 
-static int __init acpi_hotkey_setup(char *str)
-{
-       acpi_specific_hotkey_enabled = FALSE;
-       return 1;
-}
-
-__setup("acpi_generic_hotkey", acpi_hotkey_setup);
-
 /*
  * max_cstate is defined in the base kernel so modules can
  * change it w/o depending on the state of the processor module.
index 55f57a61c55e19bab562c331473ea9abee9bc89f..028969370bbf821d9c015353f5d0d69b0cebc2c9 100644 (file)
@@ -36,7 +36,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_bind")
+ACPI_MODULE_NAME("pci_bind");
 
 struct acpi_pci_data {
        struct acpi_pci_id id;
index fe7d007833ade1b03ba2660269bcd10d42440c54..dd3186abe07a9c464df616aae6fb05454fb53085 100644 (file)
@@ -38,7 +38,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_irq")
+ACPI_MODULE_NAME("pci_irq");
 
 static struct acpi_prt_list acpi_prt;
 static DEFINE_SPINLOCK(acpi_prt_lock);
index 0f683c8c6fbc76676b193241e5af457118c7915f..acc594771379af521ef06a5f7a549ca781583d8d 100644 (file)
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_link")
+ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_CLASS            "pci_irq_routing"
 #define ACPI_PCI_LINK_HID              "PNP0C0F"
-#define ACPI_PCI_LINK_DRIVER_NAME      "ACPI PCI Interrupt Link Driver"
 #define ACPI_PCI_LINK_DEVICE_NAME      "PCI Interrupt Link"
 #define ACPI_PCI_LINK_FILE_INFO                "info"
 #define ACPI_PCI_LINK_FILE_STATUS      "state"
@@ -56,7 +55,7 @@ static int acpi_pci_link_add(struct acpi_device *device);
 static int acpi_pci_link_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_pci_link_driver = {
-       .name = ACPI_PCI_LINK_DRIVER_NAME,
+       .name = "pci_link",
        .class = ACPI_PCI_LINK_CLASS,
        .ids = ACPI_PCI_LINK_HID,
        .ops = {
index 4ecf701687e8768d23135796f3c818b0b68a213f..ad4145a37786d93a974455575a411b080c4aad63 100644 (file)
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_root")
+ACPI_MODULE_NAME("pci_root");
 #define ACPI_PCI_ROOT_CLASS            "pci_bridge"
 #define ACPI_PCI_ROOT_HID              "PNP0A03"
-#define ACPI_PCI_ROOT_DRIVER_NAME      "ACPI PCI Root Bridge Driver"
 #define ACPI_PCI_ROOT_DEVICE_NAME      "PCI Root Bridge"
 static int acpi_pci_root_add(struct acpi_device *device);
 static int acpi_pci_root_remove(struct acpi_device *device, int type);
 static int acpi_pci_root_start(struct acpi_device *device);
 
 static struct acpi_driver acpi_pci_root_driver = {
-       .name = ACPI_PCI_ROOT_DRIVER_NAME,
+       .name = "pci_root",
        .class = ACPI_PCI_ROOT_CLASS,
        .ids = ACPI_PCI_ROOT_HID,
        .ops = {
index 0ba7dfbbb2eebe47ad9f673d6151f605b503ef3a..1ef338545dfef977034a490d56ae9c5f043eb948 100644 (file)
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_POWER_COMPONENT
-ACPI_MODULE_NAME("acpi_power")
+ACPI_MODULE_NAME("power");
 #define ACPI_POWER_COMPONENT           0x00800000
 #define ACPI_POWER_CLASS               "power_resource"
-#define ACPI_POWER_DRIVER_NAME         "ACPI Power Resource Driver"
 #define ACPI_POWER_DEVICE_NAME         "Power Resource"
 #define ACPI_POWER_FILE_INFO           "info"
 #define ACPI_POWER_FILE_STATUS         "state"
@@ -57,25 +56,33 @@ ACPI_MODULE_NAME("acpi_power")
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
+static int acpi_power_resume(struct acpi_device *device);
 static int acpi_power_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_power_driver = {
-       .name = ACPI_POWER_DRIVER_NAME,
+       .name = "power",
        .class = ACPI_POWER_CLASS,
        .ids = ACPI_POWER_HID,
        .ops = {
                .add = acpi_power_add,
                .remove = acpi_power_remove,
+               .resume = acpi_power_resume,
                },
 };
 
+struct acpi_power_reference {
+       struct list_head node;
+       struct acpi_device *device;
+};
+
 struct acpi_power_resource {
        struct acpi_device * device;
        acpi_bus_id name;
        u32 system_level;
        u32 order;
        int state;
-       int references;
+       struct mutex resource_lock;
+       struct list_head reference;
 };
 
 static struct list_head acpi_power_resource_list;
@@ -171,22 +178,47 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
        return result;
 }
 
-static int acpi_power_on(acpi_handle handle)
+static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
 {
        int result = 0;
+       int found = 0;
        acpi_status status = AE_OK;
-       struct acpi_device *device = NULL;
        struct acpi_power_resource *resource = NULL;
+       struct list_head *node, *next;
+       struct acpi_power_reference *ref;
 
 
        result = acpi_power_get_context(handle, &resource);
        if (result)
                return result;
 
-       resource->references++;
+       mutex_lock(&resource->resource_lock);
+       list_for_each_safe(node, next, &resource->reference) {
+               ref = container_of(node, struct acpi_power_reference, node);
+               if (dev->handle == ref->device->handle) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
+                                 dev->pnp.bus_id, resource->name));
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               ref = kmalloc(sizeof (struct acpi_power_reference),
+                   irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+               if (!ref) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
+                       mutex_unlock(&resource->resource_lock);
+                       return -ENOMEM;
+               }
+               list_add_tail(&ref->node, &resource->reference);
+               ref->device = dev;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
+                         dev->pnp.bus_id, resource->name));
+       }
+       mutex_unlock(&resource->resource_lock);
 
-       if ((resource->references > 1)
-           || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
+       if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
                                  resource->name));
                return 0;
@@ -203,38 +235,49 @@ static int acpi_power_on(acpi_handle handle)
                return -ENOEXEC;
 
        /* Update the power resource's _device_ power state */
-       device = resource->device;
        resource->device->power.state = ACPI_STATE_D0;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
                          resource->name));
-
        return 0;
 }
 
-static int acpi_power_off_device(acpi_handle handle)
+static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
 {
        int result = 0;
        acpi_status status = AE_OK;
        struct acpi_power_resource *resource = NULL;
+       struct list_head *node, *next;
+       struct acpi_power_reference *ref;
+
 
        result = acpi_power_get_context(handle, &resource);
        if (result)
                return result;
 
-       if (resource->references)
-               resource->references--;
+       mutex_lock(&resource->resource_lock);
+       list_for_each_safe(node, next, &resource->reference) {
+               ref = container_of(node, struct acpi_power_reference, node);
+               if (dev->handle == ref->device->handle) {
+                       list_del(&ref->node);
+                       kfree(ref);
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
+                           dev->pnp.bus_id, resource->name));
+                       break;
+               }
+       }
 
-       if (resource->references) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Resource [%s] is still in use, dereferencing\n",
-                                 resource->device->pnp.bus_id));
+       if (!list_empty(&resource->reference)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
+                   resource->name));
+               mutex_unlock(&resource->resource_lock);
                return 0;
        }
+       mutex_unlock(&resource->resource_lock);
 
        if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
-                                 resource->device->pnp.bus_id));
+                                 resource->name));
                return 0;
        }
 
@@ -276,7 +319,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
        arg.integer.value = 1;
        /* Open power resource */
        for (i = 0; i < dev->wakeup.resources.count; i++) {
-               ret = acpi_power_on(dev->wakeup.resources.handles[i]);
+               ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
                if (ret) {
                        printk(KERN_ERR PREFIX "Transition power state\n");
                        dev->wakeup.flags.valid = 0;
@@ -323,7 +366,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
 
        /* Close power resource */
        for (i = 0; i < dev->wakeup.resources.count; i++) {
-               ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
+               ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
                if (ret) {
                        printk(KERN_ERR PREFIX "Transition power state\n");
                        dev->wakeup.flags.valid = 0;
@@ -407,16 +450,20 @@ int acpi_power_transition(struct acpi_device *device, int state)
         * (e.g. so the device doesn't lose power while transitioning).
         */
        for (i = 0; i < tl->count; i++) {
-               result = acpi_power_on(tl->handles[i]);
+               result = acpi_power_on(tl->handles[i], device);
                if (result)
                        goto end;
        }
 
+       if (device->power.state == state) {
+               goto end;
+       }
+
        /*
         * Then we dereference all power resources used in the current list.
         */
        for (i = 0; i < cl->count; i++) {
-               result = acpi_power_off_device(cl->handles[i]);
+               result = acpi_power_off_device(cl->handles[i], device);
                if (result)
                        goto end;
        }
@@ -439,7 +486,11 @@ static struct proc_dir_entry *acpi_power_dir;
 
 static int acpi_power_seq_show(struct seq_file *seq, void *offset)
 {
+       int count = 0;
+       int result = 0;
        struct acpi_power_resource *resource = NULL;
+       struct list_head *node, *next;
+       struct acpi_power_reference *ref;
 
 
        resource = seq->private;
@@ -447,6 +498,10 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
        if (!resource)
                goto end;
 
+       result = acpi_power_get_state(resource);
+       if (result)
+               goto end;
+
        seq_puts(seq, "state:                   ");
        switch (resource->state) {
        case ACPI_POWER_RESOURCE_STATE_ON:
@@ -460,11 +515,18 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
                break;
        }
 
+       mutex_lock(&resource->resource_lock);
+       list_for_each_safe(node, next, &resource->reference) {
+               ref = container_of(node, struct acpi_power_reference, node);
+               count++;
+       }
+       mutex_unlock(&resource->resource_lock);
+
        seq_printf(seq, "system level:            S%d\n"
                   "order:                   %d\n"
                   "reference count:         %d\n",
                   resource->system_level,
-                  resource->order, resource->references);
+                  resource->order, count);
 
       end:
        return 0;
@@ -537,6 +599,8 @@ static int acpi_power_add(struct acpi_device *device)
                return -ENOMEM;
 
        resource->device = device;
+       mutex_init(&resource->resource_lock);
+       INIT_LIST_HEAD(&resource->reference);
        strcpy(resource->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
@@ -584,6 +648,7 @@ static int acpi_power_add(struct acpi_device *device)
 static int acpi_power_remove(struct acpi_device *device, int type)
 {
        struct acpi_power_resource *resource = NULL;
+       struct list_head *node, *next;
 
 
        if (!device || !acpi_driver_data(device))
@@ -593,11 +658,54 @@ static int acpi_power_remove(struct acpi_device *device, int type)
 
        acpi_power_remove_fs(device);
 
+       mutex_lock(&resource->resource_lock);
+       list_for_each_safe(node, next, &resource->reference) {
+               struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
+               list_del(&ref->node);
+               kfree(ref);
+       }
+       mutex_unlock(&resource->resource_lock);
+
        kfree(resource);
 
        return 0;
 }
 
+static int acpi_power_resume(struct acpi_device *device)
+{
+       int result = 0;
+       struct acpi_power_resource *resource = NULL;
+       struct acpi_power_reference *ref;
+
+       if (!device || !acpi_driver_data(device))
+               return -EINVAL;
+
+       resource = (struct acpi_power_resource *)acpi_driver_data(device);
+
+       result = acpi_power_get_state(resource);
+       if (result)
+               return result;
+
+       mutex_lock(&resource->resource_lock);
+       if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
+           list_empty(&resource->reference)) {
+               mutex_unlock(&resource->resource_lock);
+               result = acpi_power_off_device(device->handle, NULL);
+               return result;
+       }
+
+       if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
+           !list_empty(&resource->reference)) {
+               ref = container_of(resource->reference.next, struct acpi_power_reference, node);
+               mutex_unlock(&resource->resource_lock);
+               result = acpi_power_on(device->handle, ref->device);
+               return result;
+       }
+
+       mutex_unlock(&resource->resource_lock);
+       return 0;
+}
+
 static int __init acpi_power_init(void)
 {
        int result = 0;
index 0079bc51082c723eb35ee5098159f1acf3574ba2..99d1516d1e7023c067b8485272440dab43111485 100644 (file)
@@ -60,7 +60,6 @@
 
 #define ACPI_PROCESSOR_COMPONENT       0x01000000
 #define ACPI_PROCESSOR_CLASS           "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME     "ACPI Processor Driver"
 #define ACPI_PROCESSOR_DEVICE_NAME     "Processor"
 #define ACPI_PROCESSOR_FILE_INFO       "info"
 #define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
 #define ACPI_STA_PRESENT 0x00000001
 
 #define _COMPONENT             ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_core");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Processor Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_processor_add(struct acpi_device *device);
@@ -89,7 +88,7 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
 static int acpi_processor_handle_eject(struct acpi_processor *pr);
 
 static struct acpi_driver acpi_processor_driver = {
-       .name = ACPI_PROCESSOR_DRIVER_NAME,
+       .name = "processor",
        .class = ACPI_PROCESSOR_CLASS,
        .ids = ACPI_PROCESSOR_HID,
        .ops = {
@@ -404,7 +403,7 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
        if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
                /* First check against id */
                if (lsapic->processor_id == acpi_id) {
-                       *apic_id = lsapic->id;
+                       *apic_id = (lsapic->id << 8) | lsapic->eid;
                        return 1;
                /* Check against optional uid */
                } else if (entry->length >= 16 &&
@@ -1005,7 +1004,7 @@ static int __init acpi_processor_init(void)
 #ifdef CONFIG_SMP
        if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
                                (struct acpi_table_header **)&madt)))
-               madt = 0;
+               madt = NULL;
 #endif
 
        acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
index 6c6751b1405be5d7547a0e7f9010bc7dbaa82593..60773005b8afacbe24024a9ea33e96cc578ac59d 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/sched.h>       /* need_resched() */
 #include <linux/latency.h>
+#include <linux/clockchips.h>
+
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ * asm/acpi.h is not an option, as it would require more include magic. Also
+ * creating an empty asm-ia64/apic.h would just trade pest vs. cholera.
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
+
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -48,9 +67,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_idle");
 #define ACPI_PROCESSOR_FILE_POWER      "power"
 #define US_TO_PM_TIMER_TICKS(t)                ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define C2_OVERHEAD                    4       /* 1us (3.579 ticks per us) */
@@ -238,6 +256,81 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
        }
 }
 
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+
+/*
+ * Some BIOS implementations switch to C3 in the published C2 state.
+ * This seems to be a common problem on AMD boxen, but other vendors
+ * are affected too. We pick the most conservative approach: we assume
+ * that the local APIC stops in both C2 and C3.
+ */
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+                                  struct acpi_processor_cx *cx)
+{
+       struct acpi_processor_power *pwr = &pr->power;
+
+       /*
+        * Check, if one of the previous states already marked the lapic
+        * unstable
+        */
+       if (pwr->timer_broadcast_on_state < state)
+               return;
+
+       if (cx->type >= ACPI_STATE_C2)
+               pr->power.timer_broadcast_on_state = state;
+}
+
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
+{
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+       unsigned long reason;
+
+       reason = pr->power.timer_broadcast_on_state < INT_MAX ?
+               CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+
+       clockevents_notify(reason, &pr->id);
+#else
+       cpumask_t mask = cpumask_of_cpu(pr->id);
+
+       if (pr->power.timer_broadcast_on_state < INT_MAX)
+               on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
+       else
+               on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
+#endif
+}
+
+/* Power(C) State timer broadcast control */
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+                                      struct acpi_processor_cx *cx,
+                                      int broadcast)
+{
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+       int state = cx - pr->power.states;
+
+       if (state >= pr->power.timer_broadcast_on_state) {
+               unsigned long reason;
+
+               reason = broadcast ?  CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
+                       CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
+               clockevents_notify(reason, &pr->id);
+       }
+#endif
+}
+
+#else
+
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+                                  struct acpi_processor_cx *cstate) { }
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+                                      struct acpi_processor_cx *cx,
+                                      int broadcast)
+{
+}
+
+#endif
+
 static void acpi_processor_idle(void)
 {
        struct acpi_processor *pr = NULL;
@@ -382,6 +475,7 @@ static void acpi_processor_idle(void)
                /* Get start time (ticks) */
                t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
                /* Invoke C2 */
+               acpi_state_timer_broadcast(pr, cx, 1);
                acpi_cstate_enter(cx);
                /* Get end time (ticks) */
                t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -396,6 +490,7 @@ static void acpi_processor_idle(void)
                /* Compute time (ticks) that we were actually asleep */
                sleep_ticks =
                    ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+               acpi_state_timer_broadcast(pr, cx, 0);
                break;
 
        case ACPI_STATE_C3:
@@ -417,6 +512,7 @@ static void acpi_processor_idle(void)
                /* Get start time (ticks) */
                t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
                /* Invoke C3 */
+               acpi_state_timer_broadcast(pr, cx, 1);
                acpi_cstate_enter(cx);
                /* Get end time (ticks) */
                t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -436,6 +532,7 @@ static void acpi_processor_idle(void)
                /* Compute time (ticks) that we were actually asleep */
                sleep_ticks =
                    ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+               acpi_state_timer_broadcast(pr, cx, 0);
                break;
 
        default:
@@ -904,11 +1001,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
        unsigned int i;
        unsigned int working = 0;
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-       int timer_broadcast = 0;
-       cpumask_t mask = cpumask_of_cpu(pr->id);
-       on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
-#endif
+       pr->power.timer_broadcast_on_state = INT_MAX;
 
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
                struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -920,21 +1013,14 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
 
                case ACPI_STATE_C2:
                        acpi_processor_power_verify_c2(cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-                       /* Some AMD systems fake C3 as C2, but still
-                          have timer troubles */
-                       if (cx->valid && 
-                               boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-                               timer_broadcast++;
-#endif
+                       if (cx->valid)
+                               acpi_timer_check_state(i, pr, cx);
                        break;
 
                case ACPI_STATE_C3:
                        acpi_processor_power_verify_c3(pr, cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
                        if (cx->valid)
-                               timer_broadcast++;
-#endif
+                               acpi_timer_check_state(i, pr, cx);
                        break;
                }
 
@@ -942,10 +1028,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                        working++;
        }
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-       if (timer_broadcast)
-               on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
-#endif
+       acpi_propagate_timer_broadcast(pr);
 
        return (working);
 }
index 058f13cf3b796208da3a801c7e81d5c6edd82e14..2f2e7964226dcc59840cec2b0e1942a251d64880 100644 (file)
 
 #define ACPI_PROCESSOR_COMPONENT       0x01000000
 #define ACPI_PROCESSOR_CLASS           "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME     "ACPI Processor Driver"
 #define ACPI_PROCESSOR_FILE_PERFORMANCE        "performance"
 #define _COMPONENT             ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_perflib");
 
 static DEFINE_MUTEX(performance_mutex);
 
index 40fecd67ad8371674372a77c73e9e3b0fb991cdd..06e6f3fb88254d61dda243f390a7eabc509696aa 100644 (file)
@@ -41,9 +41,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_thermal");
 
 /* --------------------------------------------------------------------------
                                  Limit Interface
index 89dff3639abef84e8880590d4eb1c8e742bd71b2..b33486009f41c690f1b6bed87f4818beb17a27d6 100644 (file)
@@ -41,9 +41,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_throttling");
 
 /* --------------------------------------------------------------------------
                               Throttling Control
index f58fc7447ab4ee8757885d869505a629ff4efa7a..59640d9a0acceefe1ee8a4e6d9495edb4f5c5431 100644 (file)
@@ -59,7 +59,6 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
 #define ACPI_AC_CLASS                  "ac_adapter"
 #define ACPI_BATTERY_CLASS             "battery"
 #define ACPI_SBS_HID                   "ACPI0002"
-#define ACPI_SBS_DRIVER_NAME           "ACPI Smart Battery System Driver"
 #define ACPI_SBS_DEVICE_NAME           "Smart Battery System"
 #define ACPI_SBS_FILE_INFO             "info"
 #define ACPI_SBS_FILE_STATE            "state"
@@ -78,7 +77,7 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
 #define        MAX_SBS_BAT                     4
 #define        MAX_SMBUS_ERR                   1
 
-ACPI_MODULE_NAME("acpi_sbs");
+ACPI_MODULE_NAME("sbs");
 
 MODULE_AUTHOR("Rich Townsend");
 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
@@ -110,7 +109,7 @@ static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
 static void acpi_sbs_update_queue(void *data);
 
 static struct acpi_driver acpi_sbs_driver = {
-       .name = ACPI_SBS_DRIVER_NAME,
+       .name = "sbs",
        .class = ACPI_SBS_CLASS,
        .ids = ACPI_SBS_HID,
        .ops = {
@@ -1034,21 +1033,19 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
        } else {
                seq_printf(seq, "capacity state:          ok\n");
        }
+
+       foo = (s16) battery->state.amperage * battery->info.ipscale;
+       if (battery->info.capacity_mode) {
+               foo = foo * battery->info.design_voltage / 1000;
+       }
        if (battery->state.amperage < 0) {
                seq_printf(seq, "charging state:          discharging\n");
-               foo = battery->state.remaining_capacity * cscale * 60 /
-                   (battery->state.average_time_to_empty == 0 ? 1 :
-                    battery->state.average_time_to_empty);
-               seq_printf(seq, "present rate:            %i%s\n",
-                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+               seq_printf(seq, "present rate:            %d %s\n",
+                          -foo, battery->info.capacity_mode ? "mW" : "mA");
        } else if (battery->state.amperage > 0) {
                seq_printf(seq, "charging state:          charging\n");
-               foo = (battery->info.full_charge_capacity -
-                      battery->state.remaining_capacity) * cscale * 60 /
-                   (battery->state.average_time_to_full == 0 ? 1 :
-                    battery->state.average_time_to_full);
-               seq_printf(seq, "present rate:            %i%s\n",
-                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+               seq_printf(seq, "present rate:            %d %s\n",
+                          foo, battery->info.capacity_mode ? "mW" : "mA");
        } else {
                seq_printf(seq, "charging state:          charged\n");
                seq_printf(seq, "present rate:            0 %s\n",
index 64f26db10c8efd765fcde8e8d0eb821b3a06efc2..bb0e0da39fb15d355be664e5ae23f1dc5e632441 100644 (file)
 #include <acpi/acinterp.h>     /* for acpi_ex_eisa_id_to_string() */
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("scan")
+ACPI_MODULE_NAME("scan");
 #define STRUCT_TO_INT(s)       (*((int*)&s))
 extern struct acpi_device *acpi_root;
 
 #define ACPI_BUS_CLASS                 "system_bus"
 #define ACPI_BUS_HID                   "ACPI_BUS"
-#define ACPI_BUS_DRIVER_NAME           "ACPI Bus Driver"
 #define ACPI_BUS_DEVICE_NAME           "System Bus"
 
 static LIST_HEAD(acpi_device_list);
index 62ce87d7165101078aa829b73294dd6922e1519a..37a0930fc0a6ac538fbb2407e3ebb6f71a203753 100644 (file)
@@ -200,7 +200,7 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
        {},
 };
 
-static int __init acpi_sleep_init(void)
+int __init acpi_sleep_init(void)
 {
        int i = 0;
 
@@ -229,4 +229,3 @@ static int __init acpi_sleep_init(void)
        return 0;
 }
 
-late_initcall(acpi_sleep_init);
index 47fb4b394eec568636b2a7da421e12210e96acc6..d9801eff6489c1448e2e33c20650c21f0e399469 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <acpi/acpi_bus.h>
-#include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <asm/io.h>
 #include "sleep.h"
index 7147b0bdab0a83f8581d79bf192ea986deea10f5..83a8d3097904e99dbb825736ee84294bd4739de5 100644 (file)
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("acpi_system")
+ACPI_MODULE_NAME("system");
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
 #endif
 #define MODULE_PARAM_PREFIX "acpi."
 
 #define ACPI_SYSTEM_CLASS              "system"
-#define ACPI_SYSTEM_DRIVER_NAME                "ACPI System Driver"
 #define ACPI_SYSTEM_DEVICE_NAME                "System"
 #define ACPI_SYSTEM_FILE_INFO          "info"
 #define ACPI_SYSTEM_FILE_EVENT         "event"
index ba4cb200314a12f50b66527140e7abada696fe91..849e2c361804bd91fbba7279e149469e1848f56f 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -170,40 +169,40 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header)
 
 
 int __init
-acpi_table_parse_madt_family(char *id,
-                            unsigned long madt_size,
+acpi_table_parse_entries(char *id,
+                            unsigned long table_size,
                             int entry_id,
-                            acpi_madt_entry_handler handler,
+                            acpi_table_entry_handler handler,
                             unsigned int max_entries)
 {
-       struct acpi_table_header *madt = NULL;
+       struct acpi_table_header *table_header = NULL;
        struct acpi_subtable_header *entry;
        unsigned int count = 0;
-       unsigned long madt_end;
+       unsigned long table_end;
 
        if (!handler)
                return -EINVAL;
 
-       /* Locate the MADT (if exists). There should only be one. */
-       acpi_get_table(id, 0, &madt);
+       /* Locate the table (if exists). There should only be one. */
+       acpi_get_table(id, 0, &table_header);
 
-       if (!madt) {
+       if (!table_header) {
                printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
                return -ENODEV;
        }
 
-       madt_end = (unsigned long)madt + madt->length;
+       table_end = (unsigned long)table_header + table_header->length;
 
        /* Parse all entries looking for a match. */
 
        entry = (struct acpi_subtable_header *)
-           ((unsigned long)madt + madt_size);
+           ((unsigned long)table_header + table_size);
 
        while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
-              madt_end) {
+              table_end) {
                if (entry->type == entry_id
                    && (!max_entries || count++ < max_entries))
-                       if (handler(entry, madt_end))
+                       if (handler(entry, table_end))
                                return -EINVAL;
 
                entry = (struct acpi_subtable_header *)
@@ -219,13 +218,22 @@ acpi_table_parse_madt_family(char *id,
 
 int __init
 acpi_table_parse_madt(enum acpi_madt_type id,
-                     acpi_madt_entry_handler handler, unsigned int max_entries)
+                     acpi_table_entry_handler handler, unsigned int max_entries)
 {
-       return acpi_table_parse_madt_family(ACPI_SIG_MADT,
+       return acpi_table_parse_entries(ACPI_SIG_MADT,
                                            sizeof(struct acpi_table_madt), id,
                                            handler, max_entries);
 }
 
+/**
+ * acpi_table_parse - find table with @id, run @handler on it
+ *
+ * @id: table id to find
+ * @handler: handler to run
+ *
+ * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
+ * run @handler on it.  Return 0 if table found, return on if not.
+ */
 int __init acpi_table_parse(char *id, acpi_table_handler handler)
 {
        struct acpi_table_header *table = NULL;
@@ -235,9 +243,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
        acpi_get_table(id, 0, &table);
        if (table) {
                handler(table);
-               return 1;
-       } else
                return 0;
+       } else
+               return 1;
 }
 
 /*
index 807978d5381abb34767687de505600b0e8d6aa8a..417ef5fa7666e4a09b49f25a764778778de84cd4 100644 (file)
@@ -338,9 +338,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id)
        int i;
        acpi_status status = AE_NOT_EXIST;
 
-       ACPI_FUNCTION_TRACE(acpi_unload_table);
+       ACPI_FUNCTION_TRACE(acpi_unload_table_id);
 
-       /* Find table from the requested type list */
+       /* Find table in the global table list */
        for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
                if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
                        continue;
@@ -352,8 +352,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id)
                * simply a position within the hierarchy
                */
                acpi_tb_delete_namespace_by_owner(i);
-               acpi_tb_release_owner_id(i);
+               status = acpi_tb_release_owner_id(i);
                acpi_tb_set_table_loaded_flag(i, FALSE);
+               break;
        }
        return_ACPI_STATUS(status);
 }
@@ -408,7 +409,7 @@ acpi_get_table(char *signature,
                }
 
                if (!acpi_gbl_permanent_mmap) {
-                       acpi_gbl_root_table_list.tables[i].pointer = 0;
+                       acpi_gbl_root_table_list.tables[i].pointer = NULL;
                }
 
                return (status);
index f76d3168c2b2d3e098ba0ca14883853dc6917b19..0ae8b9310cbf98d2320dc40800f08b12bb0f7f48 100644 (file)
@@ -36,7 +36,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
@@ -46,7 +47,6 @@
 
 #define ACPI_THERMAL_COMPONENT         0x04000000
 #define ACPI_THERMAL_CLASS             "thermal_zone"
-#define ACPI_THERMAL_DRIVER_NAME       "ACPI Thermal Zone Driver"
 #define ACPI_THERMAL_DEVICE_NAME       "Thermal Zone"
 #define ACPI_THERMAL_FILE_STATE                "state"
 #define ACPI_THERMAL_FILE_TEMPERATURE  "temperature"
 #define CELSIUS_TO_KELVIN(t)   ((t+273)*10)
 
 #define _COMPONENT             ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME("acpi_thermal")
+ACPI_MODULE_NAME("thermal");
 
 MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
 MODULE_LICENSE("GPL");
 
 static int tzp;
@@ -98,7 +98,7 @@ static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
                                          size_t, loff_t *);
 
 static struct acpi_driver acpi_thermal_driver = {
-       .name = ACPI_THERMAL_DRIVER_NAME,
+       .name = "thermal",
        .class = ACPI_THERMAL_CLASS,
        .ids = ACPI_THERMAL_HID,
        .ops = {
@@ -269,7 +269,7 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "Polling frequency set to %lu seconds\n",
-                         tz->polling_frequency));
+                         tz->polling_frequency/10));
 
        return 0;
 }
@@ -1356,28 +1356,32 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
 static int acpi_thermal_resume(struct acpi_device *device)
 {
        struct acpi_thermal *tz = NULL;
-       int i;
+       int i, j, power_state, result;
+
 
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
        tz = acpi_driver_data(device);
 
-       acpi_thermal_get_temperature(tz);
-
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (tz->trips.active[i].flags.valid) {
-                       tz->temperature = tz->trips.active[i].temperature;
-                       tz->trips.active[i].flags.enabled = 0;
-
-                       acpi_thermal_active(tz);
-
-                       tz->state.active |= tz->trips.active[i].flags.enabled;
-                       tz->state.active_index = i;
+               if (!(&tz->trips.active[i]))
+                       break;
+               if (!tz->trips.active[i].flags.valid)
+                       break;
+               tz->trips.active[i].flags.enabled = 1;
+               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
+                       result = acpi_bus_get_power(tz->trips.active[i].devices.
+                           handles[j], &power_state);
+                       if (result || (power_state != ACPI_STATE_D0)) {
+                               tz->trips.active[i].flags.enabled = 0;
+                               break;
+                       }
                }
+               tz->state.active |= tz->trips.active[i].flags.enabled;
        }
 
-       acpi_thermal_check(tz);
+       acpi_thermal_check(tz);
 
        return AE_OK;
 }
index d9b651ffcdc0c21335f1c15e1e7ef7e3d86361cf..faf8a5232d8e5d94d285f7c92bc4b6856ace05bb 100644 (file)
@@ -125,7 +125,7 @@ static int write_acpi_int(const char *methodName, int val)
        union acpi_object in_objs[1];
        acpi_status status;
 
-       params.count = sizeof(in_objs) / sizeof(in_objs[0]);
+       params.count = ARRAY_SIZE(in_objs);
        params.pointer = in_objs;
        in_objs[0].type = ACPI_TYPE_INTEGER;
        in_objs[0].integer.value = val;
@@ -561,10 +561,6 @@ static int __init toshiba_acpi_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-       if (!acpi_specific_hotkey_enabled) {
-               printk(MY_INFO "Using generic hotkey driver\n");
-               return -ENODEV;
-       }
        /* simple device detection: look for HCI method */
        if (is_valid_acpi_path(METHOD_HCI_1))
                method_hci = METHOD_HCI_1;
index f777cebdc46dd85f8ec66b491096f9d2f20af1a3..673a0caa4073438f3f22af2dcad6a6e9f4bdc029 100644 (file)
@@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
                        acpi_os_delete_mutex(object->mutex.os_mutex);
                        acpi_gbl_global_lock_mutex = NULL;
                } else {
-                       acpi_ex_unlink_mutex(object);
                        acpi_os_delete_mutex(object->mutex.os_mutex);
                }
                break;
index 68a809fa7b19d06ef9f9457120d05fdbbecdb9b2..34f1575710807eada4cfd4ff8162b9753b4cfd1b 100644 (file)
@@ -31,7 +31,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_utils")
+ACPI_MODULE_NAME("utils");
 
 /* --------------------------------------------------------------------------
                             Object Evaluation Helpers
index e0b97add8c6355274cb220b04352c9927263b5d2..bf525cca3b637160a3c1b28f95269ea108c1dfd3 100644 (file)
@@ -40,7 +40,6 @@
 
 #define ACPI_VIDEO_COMPONENT           0x08000000
 #define ACPI_VIDEO_CLASS               "video"
-#define ACPI_VIDEO_DRIVER_NAME         "ACPI Video Driver"
 #define ACPI_VIDEO_BUS_NAME            "Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME         "Video Device"
 #define ACPI_VIDEO_NOTIFY_SWITCH       0x80
 #define ACPI_VIDEO_DISPLAY_LCD 4
 
 #define _COMPONENT             ACPI_VIDEO_COMPONENT
-ACPI_MODULE_NAME("acpi_video")
+ACPI_MODULE_NAME("video");
 
-    MODULE_AUTHOR("Bruno Ducrot");
-MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
+MODULE_AUTHOR("Bruno Ducrot");
+MODULE_DESCRIPTION("ACPI Video Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_video_bus = {
-       .name = ACPI_VIDEO_DRIVER_NAME,
+       .name = "video",
        .class = ACPI_VIDEO_CLASS,
        .ids = ACPI_VIDEO_HID,
        .ops = {
index 3747457fee7a1f2180dbf0abf96281494c3ff050..4af0a4bb578042fc7c58c6e4448ec01e88a1622c 100644 (file)
@@ -161,6 +161,19 @@ config SATA_INTEL_COMBINED
        depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX)
        default y
 
+config SATA_ACPI
+       bool
+       depends on ACPI && PCI
+       default y
+       help
+         This option adds support for SATA-related ACPI objects.
+         These ACPI objects add the ability to retrieve taskfiles
+         from the ACPI BIOS and write them to the disk controller.
+         These objects may be related to performance, security,
+         power management, or other areas.
+         You can disable this at kernel boot time by using the
+         option libata.noacpi=1
+
 config PATA_ALI
        tristate "ALi PATA support (Experimental)"
        depends on PCI && EXPERIMENTAL
index cd096f0c78a105c2e9a9e605e0acdc3aed82af89..74298afbbaa7c354dd21fc9067a883f4326599e6 100644 (file)
@@ -66,4 +66,4 @@ obj-$(CONFIG_ATA_GENERIC)     += ata_generic.o
 obj-$(CONFIG_PATA_LEGACY)      += pata_legacy.o
 
 libata-objs    := libata-core.o libata-scsi.o libata-sff.o libata-eh.o
-
+libata-$(CONFIG_SATA_ACPI) += libata-acpi.o
index 92cdb0c5171f3a35fe347e02bf36bc60c12e2135..6a3543e062415cfa733e728fd327d3cbe851be14 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
new file mode 100644 (file)
index 0000000..b4e8be5
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * libata-acpi.c
+ * Provides ACPI support for PATA/SATA.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ * Copyright (C) 2006 Randy Dunlap
+ */
+
+#include <linux/ata.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/libata.h>
+#include <linux/pci.h>
+#include "libata.h"
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acnames.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+#include <acpi/acexcep.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+
+#define SATA_ROOT_PORT(x)      (((x) >> 16) & 0xffff)
+#define SATA_PORT_NUMBER(x)    ((x) & 0xffff)  /* or NO_PORT_MULT */
+#define NO_PORT_MULT           0xffff
+#define SATA_ADR_RSVD          0xffffffff
+
+#define REGS_PER_GTF           7
+struct taskfile_array {
+       u8      tfa[REGS_PER_GTF];      /* regs. 0x1f1 - 0x1f7 */
+};
+
+
+/**
+ * sata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * This function is somewhat SATA-specific.  Or at least the
+ * PATA & SATA versions of this function are different,
+ * so it's not entirely generic code.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
+                                       acpi_integer *pcidevfn)
+{
+       struct pci_dev  *pci_dev;
+       acpi_integer    addr;
+
+       pci_dev = to_pci_dev(dev);      /* NOTE: PCI-specific */
+       /* Please refer to the ACPI spec for the syntax of _ADR. */
+       addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+       *pcidevfn = addr;
+       *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+       if (!*handle)
+               return -ENODEV;
+       return 0;
+}
+
+/**
+ * pata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * The PATA and SATA versions of this function are different.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
+                               acpi_integer *pcidevfn)
+{
+       unsigned int bus, devnum, func;
+       acpi_integer addr;
+       acpi_handle dev_handle, parent_handle;
+       struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
+                                       .pointer = NULL};
+       acpi_status status;
+       struct acpi_device_info *dinfo = NULL;
+       int ret = -ENODEV;
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       bus = pdev->bus->number;
+       devnum = PCI_SLOT(pdev->devfn);
+       func = PCI_FUNC(pdev->devfn);
+
+       dev_handle = DEVICE_ACPI_HANDLE(dev);
+       parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
+
+       status = acpi_get_object_info(parent_handle, &buffer);
+       if (ACPI_FAILURE(status))
+               goto err;
+
+       dinfo = buffer.pointer;
+       if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+           dinfo->address == bus) {
+               /* ACPI spec for _ADR for PCI bus: */
+               addr = (acpi_integer)(devnum << 16 | func);
+               *pcidevfn = addr;
+               *handle = dev_handle;
+       } else {
+               goto err;
+       }
+
+       if (!*handle)
+               goto err;
+       ret = 0;
+err:
+       kfree(dinfo);
+       return ret;
+}
+
+struct walk_info {             /* can be trimmed some */
+       struct device   *dev;
+       struct acpi_device *adev;
+       acpi_handle     handle;
+       acpi_integer    pcidevfn;
+       unsigned int    drivenum;
+       acpi_handle     obj_handle;
+       struct ata_port *ataport;
+       struct ata_device *atadev;
+       u32             sata_adr;
+       int             status;
+       char            basepath[ACPI_PATHNAME_MAX];
+       int             basepath_len;
+};
+
+static acpi_status get_devices(acpi_handle handle,
+                               u32 level, void *context, void **return_value)
+{
+       acpi_status             status;
+       struct walk_info        *winfo = context;
+       struct acpi_buffer      namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
+       char                    *pathname;
+       struct acpi_buffer      buffer;
+       struct acpi_device_info *dinfo;
+
+       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
+       if (status)
+               goto ret;
+       pathname = namebuf.pointer;
+
+       buffer.length = ACPI_ALLOCATE_BUFFER;
+       buffer.pointer = NULL;
+       status = acpi_get_object_info(handle, &buffer);
+       if (ACPI_FAILURE(status))
+               goto out2;
+
+       dinfo = buffer.pointer;
+
+       /* find full device path name for pcidevfn */
+       if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+           dinfo->address == winfo->pcidevfn) {
+               if (ata_msg_probe(winfo->ataport))
+                       ata_dev_printk(winfo->atadev, KERN_DEBUG,
+                               ":%s: matches pcidevfn (0x%llx)\n",
+                               pathname, winfo->pcidevfn);
+               strlcpy(winfo->basepath, pathname,
+                       sizeof(winfo->basepath));
+               winfo->basepath_len = strlen(pathname);
+               goto out;
+       }
+
+       /* if basepath is not yet known, ignore this object */
+       if (!winfo->basepath_len)
+               goto out;
+
+       /* if this object is in scope of basepath, maybe use it */
+       if (strncmp(pathname, winfo->basepath,
+           winfo->basepath_len) == 0) {
+               if (!(dinfo->valid & ACPI_VALID_ADR))
+                       goto out;
+               if (ata_msg_probe(winfo->ataport))
+                       ata_dev_printk(winfo->atadev, KERN_DEBUG,
+                               "GOT ONE: (%s) root_port = 0x%llx,"
+                               " port_num = 0x%llx\n", pathname,
+                               SATA_ROOT_PORT(dinfo->address),
+                               SATA_PORT_NUMBER(dinfo->address));
+               /* heuristics: */
+               if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
+                       if (ata_msg_probe(winfo->ataport))
+                               ata_dev_printk(winfo->atadev,
+                                       KERN_DEBUG, "warning: don't"
+                                       " know how to handle SATA port"
+                                       " multiplier\n");
+               if (SATA_ROOT_PORT(dinfo->address) ==
+                       winfo->ataport->port_no &&
+                   SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
+                       if (ata_msg_probe(winfo->ataport))
+                               ata_dev_printk(winfo->atadev,
+                                       KERN_DEBUG,
+                                       "THIS ^^^^^ is the requested"
+                                       " SATA drive (handle = 0x%p)\n",
+                                       handle);
+                       winfo->sata_adr = dinfo->address;
+                       winfo->obj_handle = handle;
+               }
+       }
+out:
+       kfree(dinfo);
+out2:
+       kfree(pathname);
+
+ret:
+       return status;
+}
+
+/* Get the SATA drive _ADR object. */
+static int get_sata_adr(struct device *dev, acpi_handle handle,
+                       acpi_integer pcidevfn, unsigned int drive,
+                       struct ata_port *ap,
+                       struct ata_device *atadev, u32 *dev_adr)
+{
+       acpi_status     status;
+       struct walk_info *winfo;
+       int             err = -ENOMEM;
+
+       winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
+       if (!winfo)
+               goto out;
+
+       winfo->dev = dev;
+       winfo->atadev = atadev;
+       winfo->ataport = ap;
+       if (acpi_bus_get_device(handle, &winfo->adev) < 0)
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(winfo->atadev, KERN_DEBUG,
+                               "acpi_bus_get_device failed\n");
+       winfo->handle = handle;
+       winfo->pcidevfn = pcidevfn;
+       winfo->drivenum = drive;
+
+       status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+       if (ACPI_FAILURE(status)) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(winfo->atadev, KERN_DEBUG,
+                               "%s: acpi_get_devices failed\n",
+                               __FUNCTION__);
+               err = -ENODEV;
+       } else {
+               *dev_adr = winfo->sata_adr;
+               atadev->obj_handle = winfo->obj_handle;
+               err = 0;
+       }
+       kfree(winfo);
+out:
+       return err;
+}
+
+/**
+ * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * @ap: the ata_port for the drive
+ * @ix: target ata_device (drive) index
+ * @gtf_length: number of bytes of _GTF data returned at @gtf_address
+ * @gtf_address: buffer containing _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * The _GTF method has no input parameters.
+ * It returns a variable number of register set values (registers
+ * hex 1F1..1F7, taskfiles).
+ * The <variable number> is not known in advance, so have ACPI-CA
+ * allocate the buffer as needed and return it, then free it later.
+ *
+ * The returned @gtf_length and @gtf_address are only valid if the
+ * function return value is 0.
+ */
+static int do_drive_get_GTF(struct ata_port *ap, int ix,
+                       unsigned int *gtf_length, unsigned long *gtf_address,
+                       unsigned long *obj_loc)
+{
+       acpi_status                     status;
+       acpi_handle                     dev_handle = NULL;
+       acpi_handle                     chan_handle, drive_handle;
+       acpi_integer                    pcidevfn = 0;
+       u32                             dev_adr;
+       struct acpi_buffer              output;
+       union acpi_object               *out_obj;
+       struct device                   *dev = ap->host->dev;
+       struct ata_device               *atadev = &ap->device[ix];
+       int                             err = -ENODEV;
+
+       *gtf_length = 0;
+       *gtf_address = 0UL;
+       *obj_loc = 0UL;
+
+       if (noacpi)
+               return 0;
+
+       if (ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_DEBUG,
+                       "%s: ENTER: ap->id: %d, port#: %d\n",
+                       __FUNCTION__, ap->id, ap->port_no);
+
+       if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: "
+                               "ata_dev_present: %d, PORT_DISABLED: %lu\n",
+                               __FUNCTION__, ata_dev_enabled(atadev),
+                               ap->flags & ATA_FLAG_DISABLED);
+               goto out;
+       }
+
+       /* Don't continue if device has no _ADR method.
+        * _GTF is intended for known motherboard devices. */
+       if (!(ap->cbl == ATA_CBL_SATA)) {
+               err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+               if (err < 0) {
+                       if (ata_msg_probe(ap))
+                               ata_dev_printk(atadev, KERN_DEBUG,
+                                       "%s: pata_get_dev_handle failed (%d)\n",
+                                       __FUNCTION__, err);
+                       goto out;
+               }
+       } else {
+               err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+               if (err < 0) {
+                       if (ata_msg_probe(ap))
+                               ata_dev_printk(atadev, KERN_DEBUG,
+                                       "%s: sata_get_dev_handle failed (%d\n",
+                                       __FUNCTION__, err);
+                       goto out;
+               }
+       }
+
+       /* Get this drive's _ADR info. if not already known. */
+       if (!atadev->obj_handle) {
+               if (!(ap->cbl == ATA_CBL_SATA)) {
+                       /* get child objects of dev_handle == channel objects,
+                        * + _their_ children == drive objects */
+                       /* channel is ap->port_no */
+                       chan_handle = acpi_get_child(dev_handle,
+                                               ap->port_no);
+                       if (ata_msg_probe(ap))
+                               ata_dev_printk(atadev, KERN_DEBUG,
+                                       "%s: chan adr=%d: chan_handle=0x%p\n",
+                                       __FUNCTION__, ap->port_no,
+                                       chan_handle);
+                       if (!chan_handle) {
+                               err = -ENODEV;
+                               goto out;
+                       }
+                       /* TBD: could also check ACPI object VALID bits */
+                       drive_handle = acpi_get_child(chan_handle, ix);
+                       if (!drive_handle) {
+                               err = -ENODEV;
+                               goto out;
+                       }
+                       dev_adr = ix;
+                       atadev->obj_handle = drive_handle;
+               } else {        /* for SATA mode */
+                       dev_adr = SATA_ADR_RSVD;
+                       err = get_sata_adr(dev, dev_handle, pcidevfn, 0,
+                                       ap, atadev, &dev_adr);
+               }
+               if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+                   !atadev->obj_handle) {
+                       if (ata_msg_probe(ap))
+                               ata_dev_printk(atadev, KERN_DEBUG,
+                                       "%s: get_sata/pata_adr failed: "
+                                       "err=%d, dev_adr=%u, obj_handle=0x%p\n",
+                                       __FUNCTION__, err, dev_adr,
+                                       atadev->obj_handle);
+                       goto out;
+               }
+       }
+
+       /* Setting up output buffer */
+       output.length = ACPI_ALLOCATE_BUFFER;
+       output.pointer = NULL;  /* ACPI-CA sets this; save/free it later */
+
+       /* _GTF has no input parameters */
+       err = -EIO;
+       status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
+                                       NULL, &output);
+       if (ACPI_FAILURE(status)) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG,
+                               "%s: Run _GTF error: status = 0x%x\n",
+                               __FUNCTION__, status);
+               goto out;
+       }
+
+       if (!output.length || !output.pointer) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+                               "length or ptr is NULL (0x%llx, 0x%p)\n",
+                               __FUNCTION__,
+                               (unsigned long long)output.length,
+                               output.pointer);
+               kfree(output.pointer);
+               goto out;
+       }
+
+       out_obj = output.pointer;
+       if (out_obj->type != ACPI_TYPE_BUFFER) {
+               kfree(output.pointer);
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+                               "error: expected object type of "
+                               " ACPI_TYPE_BUFFER, got 0x%x\n",
+                               __FUNCTION__, out_obj->type);
+               err = -ENOENT;
+               goto out;
+       }
+
+       if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
+           out_obj->buffer.length % REGS_PER_GTF) {
+               if (ata_msg_drv(ap))
+                       ata_dev_printk(atadev, KERN_ERR,
+                               "%s: unexpected GTF length (%d) or addr (0x%p)\n",
+                               __FUNCTION__, out_obj->buffer.length,
+                               out_obj->buffer.pointer);
+               err = -ENOENT;
+               goto out;
+       }
+
+       *gtf_length = out_obj->buffer.length;
+       *gtf_address = (unsigned long)out_obj->buffer.pointer;
+       *obj_loc = (unsigned long)out_obj;
+       if (ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_DEBUG, "%s: returning "
+                       "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
+                       __FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
+       err = 0;
+out:
+       return err;
+}
+
+/**
+ * taskfile_load_raw - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
+ *
+ * Outputs ATA taskfile to standard ATA host controller using MMIO
+ * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ * hob_lbal, hob_lbam, and hob_lbah.
+ *
+ * This function waits for idle (!BUSY and !DRQ) after writing
+ * registers.  If the control register has a new value, this
+ * function also waits for idle after writing control and before
+ * writing the remaining registers.
+ *
+ * LOCKING: TBD:
+ * Inherited from caller.
+ */
+static void taskfile_load_raw(struct ata_port *ap,
+                               struct ata_device *atadev,
+                               const struct taskfile_array *gtf)
+{
+       if (ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
+                       "%02x %02x %02x %02x %02x %02x %02x\n",
+                       __FUNCTION__,
+                       gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
+                       gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+
+       if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
+           && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
+           && (gtf->tfa[6] == 0))
+               return;
+
+       if (ap->ops->qc_issue) {
+               struct ata_taskfile tf;
+               unsigned int err;
+
+               ata_tf_init(atadev, &tf);
+
+               /* convert gtf to tf */
+               tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+               tf.protocol = atadev->class == ATA_DEV_ATAPI ?
+                       ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
+               tf.feature = gtf->tfa[0];       /* 0x1f1 */
+               tf.nsect   = gtf->tfa[1];       /* 0x1f2 */
+               tf.lbal    = gtf->tfa[2];       /* 0x1f3 */
+               tf.lbam    = gtf->tfa[3];       /* 0x1f4 */
+               tf.lbah    = gtf->tfa[4];       /* 0x1f5 */
+               tf.device  = gtf->tfa[5];       /* 0x1f6 */
+               tf.command = gtf->tfa[6];       /* 0x1f7 */
+
+               err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0);
+               if (err && ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_ERR,
+                               "%s: ata_exec_internal failed: %u\n",
+                               __FUNCTION__, err);
+       } else
+               if (ata_msg_warn(ap))
+                       ata_dev_printk(atadev, KERN_WARNING,
+                               "%s: SATA driver is missing qc_issue function"
+                               " entry points\n",
+                               __FUNCTION__);
+}
+
+/**
+ * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ * @gtf_length: total number of bytes of _GTF taskfiles
+ * @gtf_address: location of _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * Write {gtf_address, length gtf_length} in groups of
+ * REGS_PER_GTF bytes.
+ */
+static int do_drive_set_taskfiles(struct ata_port *ap,
+               struct ata_device *atadev, unsigned int gtf_length,
+               unsigned long gtf_address)
+{
+       int                     err = -ENODEV;
+       int                     gtf_count = gtf_length / REGS_PER_GTF;
+       int                     ix;
+       struct taskfile_array   *gtf;
+
+       if (ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_DEBUG,
+                       "%s: ENTER: ap->id: %d, port#: %d\n",
+                       __FUNCTION__, ap->id, ap->port_no);
+
+       if (noacpi || !(ap->cbl == ATA_CBL_SATA))
+               return 0;
+
+       if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED))
+               goto out;
+       if (!gtf_count)         /* shouldn't be here */
+               goto out;
+
+       if (gtf_length % REGS_PER_GTF) {
+               if (ata_msg_drv(ap))
+                       ata_dev_printk(atadev, KERN_ERR,
+                               "%s: unexpected GTF length (%d)\n",
+                               __FUNCTION__, gtf_length);
+               goto out;
+       }
+
+       for (ix = 0; ix < gtf_count; ix++) {
+               gtf = (struct taskfile_array *)
+                       (gtf_address + ix * REGS_PER_GTF);
+
+               /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
+               taskfile_load_raw(ap, atadev, gtf);
+       }
+
+       err = 0;
+out:
+       return err;
+}
+
+/**
+ * ata_acpi_exec_tfs - get then write drive taskfile settings
+ * @ap: the ata_port for the drive
+ *
+ * This applies to both PATA and SATA drives.
+ */
+int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+       int             ix;
+       int             ret =0;
+       unsigned int    gtf_length;
+       unsigned long   gtf_address;
+       unsigned long   obj_loc;
+
+       if (noacpi)
+               return 0;
+
+       for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
+               if (!ata_dev_enabled(&ap->device[ix]))
+                       continue;
+
+               ret = do_drive_get_GTF(ap, ix,
+                               &gtf_length, &gtf_address, &obj_loc);
+               if (ret < 0) {
+                       if (ata_msg_probe(ap))
+                               ata_port_printk(ap, KERN_DEBUG,
+                                       "%s: get_GTF error (%d)\n",
+                                       __FUNCTION__, ret);
+                       break;
+               }
+
+               ret = do_drive_set_taskfiles(ap, &ap->device[ix],
+                               gtf_length, gtf_address);
+               kfree((void *)obj_loc);
+               if (ret < 0) {
+                       if (ata_msg_probe(ap))
+                               ata_port_printk(ap, KERN_DEBUG,
+                                       "%s: set_taskfiles error (%d)\n",
+                                       __FUNCTION__, ret);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+/**
+ * ata_acpi_push_id - send Identify data to drive
+ * @ap: the ata_port for the drive
+ * @ix: drive index
+ *
+ * _SDD ACPI object: for SATA mode only
+ * Must be after Identify (Packet) Device -- uses its data
+ * ATM this function never returns a failure.  It is an optional
+ * method and if it fails for whatever reason, we should still
+ * just keep going.
+ */
+int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+       acpi_handle                     handle;
+       acpi_integer                    pcidevfn;
+       int                             err;
+       struct device                   *dev = ap->host->dev;
+       struct ata_device               *atadev = &ap->device[ix];
+       u32                             dev_adr;
+       acpi_status                     status;
+       struct acpi_object_list         input;
+       union acpi_object               in_params[1];
+
+       if (noacpi)
+               return 0;
+
+       if (ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_DEBUG,
+                       "%s: ap->id: %d, ix = %d, port#: %d\n",
+                       __FUNCTION__, ap->id, ix, ap->port_no);
+
+       /* Don't continue if not a SATA device. */
+       if (!(ap->cbl == ATA_CBL_SATA)) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG,
+                               "%s: Not a SATA device\n", __FUNCTION__);
+               goto out;
+       }
+
+       /* Don't continue if device has no _ADR method.
+        * _SDD is intended for known motherboard devices. */
+       err = sata_get_dev_handle(dev, &handle, &pcidevfn);
+       if (err < 0) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG,
+                               "%s: sata_get_dev_handle failed (%d\n",
+                               __FUNCTION__, err);
+               goto out;
+       }
+
+       /* Get this drive's _ADR info, if not already known */
+       if (!atadev->obj_handle) {
+               dev_adr = SATA_ADR_RSVD;
+               err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev,
+                                       &dev_adr);
+               if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+                       !atadev->obj_handle) {
+                       if (ata_msg_probe(ap))
+                               ata_dev_printk(atadev, KERN_DEBUG,
+                                       "%s: get_sata_adr failed: "
+                                       "err=%d, dev_adr=%u, obj_handle=0x%p\n",
+                                       __FUNCTION__, err, dev_adr,
+                                       atadev->obj_handle);
+                       goto out;
+               }
+       }
+
+       /* Give the drive Identify data to the drive via the _SDD method */
+       /* _SDD: set up input parameters */
+       input.count = 1;
+       input.pointer = in_params;
+       in_params[0].type = ACPI_TYPE_BUFFER;
+       in_params[0].buffer.length = sizeof(atadev->id[0]) * ATA_ID_WORDS;
+       in_params[0].buffer.pointer = (u8 *)atadev->id;
+       /* Output buffer: _SDD has no output */
+
+       /* It's OK for _SDD to be missing too. */
+       swap_buf_le16(atadev->id, ATA_ID_WORDS);
+       status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
+       swap_buf_le16(atadev->id, ATA_ID_WORDS);
+
+       err = ACPI_FAILURE(status) ? -EIO : 0;
+       if (err < 0) {
+               if (ata_msg_probe(ap))
+                       ata_dev_printk(atadev, KERN_DEBUG,
+                               "ata%u(%u): %s _SDD error: status = 0x%x\n",
+                               ap->id, ap->device->devno,
+                               __FUNCTION__, status);
+       }
+
+       /* always return success */
+out:
+       return 0;
+}
+
+
index 25d8d3f778a1c980f5537f64648ef69d0d3a911b..e900c5edefc4a55af483513dddbfdbc1129d7101 100644 (file)
@@ -93,6 +93,10 @@ static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
 module_param(ata_probe_timeout, int, 0444);
 MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
 
+int noacpi;
+module_param(noacpi, int, 0444);
+MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -1410,7 +1414,16 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
        }
 
        tf.protocol = ATA_PROT_PIO;
-       tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */
+
+       /* Some devices choke if TF registers contain garbage.  Make
+        * sure those are properly initialized.
+        */
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+       /* Device presence detection is unreliable on some
+        * controllers.  Always poll IDENTIFY if available.
+        */
+       tf.flags |= ATA_TFLAG_POLLING;
 
        err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
                                     id, sizeof(id[0]) * ATA_ID_WORDS);
@@ -1555,6 +1568,16 @@ int ata_dev_configure(struct ata_device *dev)
                ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
                               __FUNCTION__, ap->id, dev->devno);
 
+       /* set _SDD */
+       rc = ata_acpi_push_id(ap, dev->devno);
+       if (rc) {
+               ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
+                       rc);
+       }
+
+       /* retrieve and execute the ATA task file of _GTF */
+       ata_acpi_exec_tfs(ap);
+
        /* print device capabilities */
        if (ata_msg_probe(ap))
                ata_dev_printk(dev, KERN_DEBUG,
index 06ccf230e3c2b97308879b87ef93b98d504902b4..0ad7781d72a3b0f4e282da04dc606f48032d60cf 100644 (file)
@@ -47,6 +47,7 @@ extern struct workqueue_struct *ata_aux_wq;
 extern int atapi_enabled;
 extern int atapi_dmadir;
 extern int libata_fua;
+extern int noacpi;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
                           u64 block, u32 n_block, unsigned int tf_flags,
@@ -87,6 +88,20 @@ extern void ata_port_init(struct ata_port *ap, struct ata_host *host,
 extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
                                                 const struct ata_port_info *port);
 
+/* libata-acpi.c */
+#ifdef CONFIG_SATA_ACPI
+extern int ata_acpi_exec_tfs(struct ata_port *ap);
+extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix);
+#else
+static inline int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+       return 0;
+}
+static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+       return 0;
+}
+#endif
 
 /* libata-scsi.c */
 extern struct scsi_transport_template ata_scsi_transport_template;
index 4223e10de6a0aed4ecf8c4f3cba57e179901910a..98c1fee4b305a92f3d92f08506010d861ee027c4 100644 (file)
@@ -89,9 +89,10 @@ static int probe_all;                        /* Set to check all ISA port ranges */
 static int ht6560a;                    /* HT 6560A on primary 1, secondary 2, both 3 */
 static int ht6560b;                    /* HT 6560A on primary 1, secondary 2, both 3 */
 static int opti82c611a;                        /* Opti82c611A on primary 1, secondary 2, both 3 */
-static int opti82c46x;         /* Opti 82c465MV present (pri/sec autodetect) */
+static int opti82c46x;                 /* Opti 82c465MV present (pri/sec autodetect) */
 static int autospeed;                  /* Chip present which snoops speed changes */
 static int pio_mask = 0x1F;            /* PIO range for autospeed devices */
+static int iordy_mask = 0xFFFFFFFF;    /* Use iordy if available */
 
 /**
  *     legacy_set_mode         -       mode setting
@@ -113,6 +114,7 @@ static int legacy_set_mode(struct ata_port *ap, struct ata_device **unused)
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
                if (ata_dev_enabled(dev)) {
+                       ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                        dev->pio_mode = XFER_PIO_0;
                        dev->xfer_mode = XFER_PIO_0;
                        dev->xfer_shift = ATA_SHIFT_PIO;
@@ -695,6 +697,7 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
        void __iomem *io_addr, *ctrl_addr;
        int pio_modes = pio_mask;
        u32 mask = (1 << port);
+       u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
        int ret;
 
        pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
@@ -715,6 +718,7 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
        if (ht6560a & mask) {
                ops = &ht6560a_port_ops;
                pio_modes = 0x07;
+               iordy = ATA_FLAG_NO_IORDY;
        }
        if (ht6560b & mask) {
                ops = &ht6560b_port_ops;
@@ -750,6 +754,7 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
                        printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
                                pio_modes = 0x07;
                        ops = &pdc20230_port_ops;
+                       iordy = ATA_FLAG_NO_IORDY;
                        udelay(100);
                        inb(0x1F5);
                } else {
@@ -767,6 +772,7 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
        /* Chip does mode setting by command snooping */
        if (ops == &legacy_port_ops && (autospeed & mask))
                ops = &simple_port_ops;
+
        memset(&ae, 0, sizeof(struct ata_probe_ent));
        INIT_LIST_HEAD(&ae.node);
        ae.dev = &pdev->dev;
@@ -776,7 +782,7 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
        ae.pio_mask = pio_modes;
        ae.irq = irq;
        ae.irq_flags = 0;
-       ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
+       ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST|iordy;
        ae.port[0].cmd_addr = io_addr;
        ae.port[0].altstatus_addr = ctrl_addr;
        ae.port[0].ctl_addr = ctrl_addr;
@@ -945,6 +951,7 @@ module_param(ht6560b, int, 0);
 module_param(opti82c611a, int, 0);
 module_param(opti82c46x, int, 0);
 module_param(pio_mask, int, 0);
+module_param(iordy_mask, int, 0);
 
 module_init(legacy_init);
 module_exit(legacy_exit);
index ca8c965179b13a05f308e5bae65d7efc1ff798fc..f2e7115f7ab9de2aba9b0a9426e7155916c2f26f 100644 (file)
@@ -241,7 +241,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        probe.port_ops = &mpiix_port_ops;
        probe.sht = &mpiix_sht;
        probe.pio_mask = 0x1F;
-       probe.irq_flags = SA_SHIRQ;
+       probe.irq_flags = IRQF_SHARED;
        probe.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
        probe.n_ports = 1;
 
index acfc09f9abd9cc8b56b2cf8d6adc73878dbd6d77..36468ec6454cad8606a7908bb3df959997647b48 100644 (file)
@@ -264,7 +264,7 @@ next_entry:
        ae.n_ports = 1;
        ae.pio_mask = 1;                /* ISA so PIO 0 cycles */
        ae.irq = pdev->irq.AssignedIRQ;
-       ae.irq_flags = SA_SHIRQ;
+       ae.irq_flags = IRQF_SHARED;
        ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
        ae.port[0].cmd_addr = io_addr;
        ae.port[0].altstatus_addr = ctl_addr;
index ffa7f47fbb2086357f7028edab9d43000b021add..61537873d28ef133d4dc5efab882b7efc2c3714c 100644 (file)
@@ -796,7 +796,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
        probe_ent->port_ops     = pdc2027x_port_info[board_idx].port_ops;
 
                probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = SA_SHIRQ;
+               probe_ent->irq_flags = IRQF_SHARED;
        probe_ent->iomap = pcim_iomap_table(pdev);
 
        mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
index 1b3b4ed8eb194b22a606007561e7bc6e0a2fab69..4362141976adfa41af697adcbede81f4b1fdb44d 100644 (file)
@@ -264,16 +264,18 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
        if (type == 6580) {
                ae.port_ops = &qdi6580_port_ops;
                ae.pio_mask = 0x1F;
+               ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
        } else {
                ae.port_ops = &qdi6500_port_ops;
                ae.pio_mask = 0x07;     /* Actually PIO3 !IORDY is possible */
+               ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+                               ATA_FLAG_NO_IORDY;
        }
 
        ae.sht = &qdi_sht;
        ae.n_ports = 1;
        ae.irq = irq;
        ae.irq_flags = 0;
-       ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
        ae.port[0].cmd_addr = io_addr;
        ae.port[0].altstatus_addr = ctl_addr;
        ae.port[0].ctl_addr = ctl_addr;
index f2fa158d07ca3fc57f9daa7388707d42ab52cf3e..96e890fd645b671247069881385de1c36d0abdb0 100644 (file)
@@ -187,7 +187,9 @@ static void sl82c105_bmdma_start(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
+       udelay(100);
        sl82c105_reset_engine(ap);
+       udelay(100);
 
        /* Set the clocks for DMA */
        sl82c105_configure_dmamode(ap, qc->dev);
@@ -216,6 +218,7 @@ static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc)
 
        ata_bmdma_stop(qc);
        sl82c105_reset_engine(ap);
+       udelay(100);
 
        /* This will redo the initial setup of the DMA device to matching
           PIO timings */
index b4ed8ce553e6845156cb0bb0b2fb542cb2b471e8..857ac23217ab0895f095700b5db9c529a9f67fb5 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
index c5335f422801f85200003812ba82aa0f9a9b23a4..31b636fac98e6fa366dcc3f756d3b5e70a66ecb7 100644 (file)
@@ -710,7 +710,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->n_ports              = NR_PORTS;
 
        probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = SA_SHIRQ;
+       probe_ent->irq_flags = IRQF_SHARED;
 
        probe_ent->iomap = iomap;
 
index 769eca52442c73706d1eda322f8859352d9df423..d689df52eae3790a8027aaa21bc140bd3112d3ae 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
index 095ef1b2cd0e92b1e7dc3dd75a1a4f3760438c2f..ab92f208dae2f955b9aef79d214707e90c1b10f0 100644 (file)
@@ -827,7 +827,8 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                        /* freeze if hotplugged or controller error */
                        if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
                                               NV_ADMA_STAT_HOTUNPLUG |
-                                              NV_ADMA_STAT_TIMEOUT))) {
+                                              NV_ADMA_STAT_TIMEOUT |
+                                              NV_ADMA_STAT_SERROR))) {
                                struct ata_eh_info *ehi = &ap->eh_info;
 
                                ata_ehi_clear_desc(ehi);
@@ -841,6 +842,9 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                                } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
                                        ata_ehi_hotplugged(ehi);
                                        ata_ehi_push_desc(ehi, ": hot unplug");
+                               } else if (status & NV_ADMA_STAT_SERROR) {
+                                       /* let libata analyze SError and figure out the cause */
+                                       ata_ehi_push_desc(ehi, ": SError");
                                }
                                ata_port_freeze(ap);
                                continue;
index 3be4cc338d7bd6b6265a3d9aad5d75caab68df2d..cf9ed8c3930155bf87cd0d08c63c1ee84d977539 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -120,9 +119,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance);
-static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
-static void pdc_pata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
@@ -216,12 +213,12 @@ static const struct ata_port_operations pdc_pata_ops = {
        .dev_select             = ata_std_dev_select,
        .check_atapi_dma        = pdc_check_atapi_dma,
 
-       .phy_reset              = pdc_pata_phy_reset,
-
        .qc_prep                = pdc_qc_prep,
        .qc_issue               = pdc_qc_issue_prot,
+       .freeze                 = pdc_freeze,
+       .thaw                   = pdc_thaw,
+       .error_handler          = pdc_error_handler,
        .data_xfer              = ata_data_xfer,
-       .eng_timeout            = pdc_eng_timeout,
        .irq_handler            = pdc_interrupt,
        .irq_clear              = pdc_irq_clear,
        .irq_on                 = ata_irq_on,
@@ -254,7 +251,7 @@ static const struct ata_port_info pdc_port_info[] = {
        /* board_20619 */
        {
                .sht            = &pdc_ata_sht,
-               .flags          = PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+               .flags          = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
@@ -390,14 +387,6 @@ static void pdc_pata_cbl_detect(struct ata_port *ap)
                ap->cbl = ATA_CBL_PATA80;
 }
 
-static void pdc_pata_phy_reset(struct ata_port *ap)
-{
-       pdc_pata_cbl_detect(ap);
-       pdc_reset_port(ap);
-       ata_port_probe(ap);
-       ata_bus_reset(ap);
-}
-
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
        if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
@@ -565,6 +554,13 @@ static void pdc_thaw(struct ata_port *ap)
        readl(mmio + PDC_CTLSTAT); /* flush */
 }
 
+static int pdc_pre_reset(struct ata_port *ap)
+{
+       if (!sata_scr_valid(ap))
+               pdc_pata_cbl_detect(ap);
+       return ata_std_prereset(ap);
+}
+
 static void pdc_error_handler(struct ata_port *ap)
 {
        ata_reset_fn_t hardreset;
@@ -577,7 +573,7 @@ static void pdc_error_handler(struct ata_port *ap)
                hardreset = sata_std_hardreset;
 
        /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+       ata_do_eh(ap, pdc_pre_reset, ata_std_softreset, hardreset,
                  ata_std_postreset);
 }
 
@@ -593,43 +589,6 @@ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
                pdc_reset_port(ap);
 }
 
-static void pdc_eng_timeout(struct ata_port *ap)
-{
-       struct ata_host *host = ap->host;
-       u8 drv_stat;
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               ata_port_printk(ap, KERN_ERR, "command timeout\n");
-               drv_stat = ata_wait_idle(ap);
-               qc->err_mask |= __ac_err_mask(drv_stat);
-               break;
-
-       default:
-               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-               ata_port_printk(ap, KERN_ERR,
-                               "unknown timeout, cmd 0x%x stat 0x%x\n",
-                               qc->tf.command, drv_stat);
-
-               qc->err_mask |= ac_err_mask(drv_stat);
-               break;
-       }
-
-       spin_unlock_irqrestore(&host->lock, flags);
-       ata_eh_qc_complete(qc);
-       DPRINTK("EXIT\n");
-}
-
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
index bfa35ede655178d5cabb13e3d07ea602a705321d..6097d8f2a0c0aea71891bbff9c9c7b5b1fa11e47 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
index 06e87a37738239d7b8b427673cf1ac005fa00f27..0ebd77b080d68396b4bc37987b45037004374a8e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
index 3d9daf231115b46c1e7385d2c41ac1b00da31d4a..2fd037bde090d92641a954d82d2017ce3aa375ca 100644 (file)
@@ -346,6 +346,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
        struct ata_probe_ent *probe_ent;
        void __iomem *mmio_base;
        int rc;
+       u8 cls;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -383,9 +384,12 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
        INIT_LIST_HEAD(&probe_ent->node);
 
        /*
-        * Due to a bug in the chip, the default cache line size can't be used
+        * Due to a bug in the chip, the default cache line size can't be
+        * used (unless the default is non-zero).
         */
-       pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls);
+       if (cls == 0x00)
+               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
 
        if (pci_enable_msi(pdev) == 0)
                pci_intx(pdev, 0);
index ac2c10822be07c41e5f3995dee1f260099ce3bc2..8d60c4eb54fe4967e238d648ade98fa174800707 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
index 4aeb3d062ff6d52630834147015e1c33c039e314..a7c0ed3107e32ee29e9aee14637fbf9f4ace5808 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/pci.h>
index db33f6f4dd2a5517302e22fc5575c43c1a28413e..8510026b690a587b175427b1508970e6492f3a5d 100644 (file)
@@ -3017,7 +3017,7 @@ read_prom_byte(struct he_dev *he_dev, int addr)
        he_writel(he_dev, val, HOST_CNTL);
        
        /* Send READ instruction */
-       for (i = 0; i < sizeof(readtab)/sizeof(readtab[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(readtab); i++) {
                he_writel(he_dev, val | readtab[i], HOST_CNTL);
                udelay(EEPROM_DELAY);
        }
index 325325afabec839302521e16c09ec78532bdfeba..0bd657f5dd2a4554134e15c92b59b404c95a073b 100644 (file)
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
index f40786121948c4bc1cbd7cea1c14291704e1c982..b4b80140c3985a25271bc82bd47be24f41893aff 100644 (file)
@@ -388,7 +388,7 @@ idt77252_eeprom_read_status(struct idt77252_dev *card)
 
        gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-       for (i = 0; i < sizeof(rdsrtab)/sizeof(rdsrtab[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
                idt77252_write_gp(card, gp | rdsrtab[i]);
                udelay(5);
        }
@@ -422,7 +422,7 @@ idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
 
        gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-       for (i = 0; i < sizeof(rdtab)/sizeof(rdtab[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
                idt77252_write_gp(card, gp | rdtab[i]);
                udelay(5);
        }
@@ -469,14 +469,14 @@ idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
 
        gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-       for (i = 0; i < sizeof(wrentab)/sizeof(wrentab[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
                idt77252_write_gp(card, gp | wrentab[i]);
                udelay(5);
        }
        idt77252_write_gp(card, gp | SAR_GP_EECS);
        udelay(5);
 
-       for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
                idt77252_write_gp(card, gp | wrtab[i]);
                udelay(5);
        }
index 2c5e3ae77503bdbefc32714b88b82c2e7b50376c..480947f4e01e8ded8b84f243e065dcf40c423524 100644 (file)
@@ -7,6 +7,8 @@
  * Read this ForeRunner's MAC address from eprom/eeprom
  */
 
+#include <linux/kernel.h>
+
 typedef void __iomem *virt_addr_t;
 
 #define CYCLE_DELAY 5
@@ -176,7 +178,7 @@ read_eprom_byte(virt_addr_t base, u_int8_t offset)
    val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
 
    /* Send READ instruction */
-   for (i=0; i<sizeof readtab/sizeof readtab[0]; i++)
+   for (i=0; i<ARRAY_SIZE(readtab); i++)
    {
        NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
                (val | readtab[i]) );
index 9504cce51bfb372654e2dec26fbadc95ce093b73..fc8cb07c24779033dd95bfa1e7d3c343bd50836c 100644 (file)
@@ -4,7 +4,6 @@
  
 
 #include <linux/module.h>
-#include <linux/sched.h> /* for jiffies */
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/atmdev.h>
index 756d4f760da3b11f901ccbcedba6fc14d6bf18ad..0d7091e2077fcbc2043612d088c373ef077ca5f2 100644 (file)
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
index 472810f8e6e7332f13127b31a299f5712e4ffbc9..253868e03c705bbda2eec97180719597b081daf0 100644 (file)
@@ -324,27 +324,25 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
        return error;
 }
 
-static int device_add_attrs(struct bus_type * bus, struct device * dev)
+static int device_add_attrs(struct bus_type *bus, struct device *dev)
 {
        int error = 0;
        int i;
 
-       if (bus->dev_attrs) {
-               for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
-                       error = device_create_file(dev,&bus->dev_attrs[i]);
-                       if (error)
-                               goto Err;
+       if (!bus->dev_attrs)
+               return 0;
+
+       for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+               error = device_create_file(dev,&bus->dev_attrs[i]);
+               if (error) {
+                       while (--i >= 0)
+                               device_remove_file(dev, &bus->dev_attrs[i]);
+                       break;
                }
        }
- Done:
        return error;
- Err:
-       while (--i >= 0)
-               device_remove_file(dev,&bus->dev_attrs[i]);
-       goto Done;
 }
 
-
 static void device_remove_attrs(struct bus_type * bus, struct device * dev)
 {
        int i;
index 96def1ddba194b50347b171f221fbdfadbd896f5..1417e5cd4c6f539544ebc686a81d7b51592e0331 100644 (file)
@@ -163,8 +163,7 @@ int class_register(struct class * cls)
 void class_unregister(struct class * cls)
 {
        pr_debug("device class '%s': unregistering\n", cls->name);
-       if (cls->virtual_dir)
-               kobject_unregister(cls->virtual_dir);
+       kobject_unregister(cls->virtual_dir);
        remove_class_attrs(cls);
        subsystem_unregister(&cls->subsys);
 }
index 7fd095efaebd75d3d6e1446b7bfdee12c64e31df..fe7ef339414441afc3592994d00dc97a99e0d0d5 100644 (file)
@@ -103,7 +103,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
 #endif
 
 /*
- * register_cpu - Setup a driverfs device for a CPU.
+ * register_cpu - Setup a sysfs device for a CPU.
  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
  *       sysfs for this CPU.
  * @num - CPU number to use when creating the device.
index 475e33f76e0d3cefa8690e56ad046c17574c1231..cae346ef1b205c3a9554d85751fef6ffb5a287b7 100644 (file)
@@ -133,7 +133,7 @@ static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
 
 
 /*
- * register_node - Setup a driverfs device for a node.
+ * register_node - Setup a sysfs device for a node.
  * @num - Node number to use when creating the device.
  *
  * Initialize and register the node device.
index 706cdc6a69eca719c856bc3c65575e77804036a7..e3d9152e231a11902e5d40aba2295e9c415ad369 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
index 9d9bff23f426d815420ee1110d44c79a5e5f7fd1..99e2c8ce1cc4f7b98cc56289580530c644b003c8 100644 (file)
@@ -153,7 +153,6 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 
 static DEFINE_SPINLOCK(pd_lock);
index 30f16bd836505f2900050f4f484b59d0346fe8b3..dff3766f117f3307fdc52fbb46a9126db32d4a14 100644 (file)
@@ -35,7 +35,6 @@
  */
 
 //#define DEBUG /* uncomment if you want debugging info (pr_debug) */
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/bio.h>
 #include <linux/kernel.h>
index 31ade991aa913893e088fb69923be3c86e0d3e12..27cceb6f5652ca4f0a694411273966fbfcfb09a4 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 
index aae3abace586ff59ce0ac769ec1b6058b745fe0d..34e5555cb917d999b33f54815b7baf4d2426c8fa 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
index 92648ef2f5d02bf37e15dee1f64cd9bbd4319f89..c1bce75148febb9bb94f8d547a632243c8823570 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
index 77b99eecbc49cd9d0a81472f19f3932d0a6bc122..459aa97937ab65e25eae168406d9782ad1b14245 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
index 5e2c31882003e785f630597d0ba8451d0e195e3a..d66064ccb31c49ce57315b53d0449c773c076ab7 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index ad62abbbb739ae797560fa26391d6afa2a04a2ff..34f0afc42407961d51b1833e53990c0c9b87fcb1 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 420b645c4c9f0d20db0e5790e44a3c854890f6c8..0f4203b499af65771ccb63bac79cae5ec2ad4f80 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 6bdf593081d8d23f20dc0a5692c8dfec6d29390a..406af579ac3adc58c55ed42f0ef1cbe2a711c832 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/unistd.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
index ec469497c10ff46abbb5818d8ea8726284f05d4a..1f9fb7a9670314403d6981166f2544e22ceac9a5 100644 (file)
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
index 3105dddf59f19a9409807370ebfce41b7a9167f1..b36f44d4d1bf6c3d97e1682ff7611fb87e0044f1 100644 (file)
@@ -3553,9 +3553,7 @@ static void cdrom_sysctl_register(void)
        if (initialized == 1)
                return;
 
-       cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
-       if (cdrom_root_table->ctl_name && cdrom_root_table->child->de)
-               cdrom_root_table->child->de->owner = THIS_MODULE;
+       cdrom_sysctl_header = register_sysctl_table(cdrom_root_table);
 
        /* set the defaults */
        cdrom_sysctl_settings.autoclose = autoclose;
index b6c61bbb20e135adbba310b0d4f7cb5ea54d41d8..230131163240532cdfa34f3861e74aef87531bdd 100644 (file)
@@ -183,7 +183,6 @@ History:
 #include <linux/errno.h>       /* These include what we really need */
 #include <linux/delay.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/cdrom.h>
index fa70824897651b15e1f9e9f5c78691fc63951172..b3ab6e9b8df182ac4017940140edc456cb029a25 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
index bf5aef4e555b2d71696e8540a3840bb1258d5f27..5409fca5bbfcaa5fd346fd32428ae02e089806aa 100644 (file)
@@ -60,7 +60,6 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
index 3e581603d0a822b9bab9a95b2f55ae056ffb3b05..a0d04a23dacd2f3c809118244c60d7a1bd9ec969 100644 (file)
@@ -1,6 +1,7 @@
 agpgart-y := backend.o frontend.o generic.o isoch.o
 
 obj-$(CONFIG_AGP)              += agpgart.o
+obj-$(CONFIG_COMPAT)           += compat_ioctl.o
 obj-$(CONFIG_AGP_ALI)          += ali-agp.o
 obj-$(CONFIG_AGP_ATI)          += ati-agp.o
 obj-$(CONFIG_AGP_AMD)          += amd-k7-agp.o
index 1d59e2a5b9aabeb666704cfecb5eb8301d719051..9bd68d9f0f5989105b6349ba98004d9cff381b2e 100644 (file)
@@ -114,6 +114,7 @@ struct agp_bridge_driver {
        void (*free_by_type)(struct agp_memory *);
        void *(*agp_alloc_page)(struct agp_bridge_data *);
        void (*agp_destroy_page)(void *);
+        int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
 };
 
 struct agp_bridge_data {
@@ -218,6 +219,7 @@ struct agp_bridge_data {
 #define I810_PTE_MAIN_UNCACHED 0x00000000
 #define I810_PTE_LOCAL         0x00000002
 #define I810_PTE_VALID         0x00000001
+#define I830_PTE_SYSTEM_CACHED  0x00000006
 #define I810_SMRAM_MISCC       0x70
 #define I810_GFX_MEM_WIN_SIZE  0x00010000
 #define I810_GFX_MEM_WIN_32M   0x00010000
@@ -270,8 +272,16 @@ void global_cache_flush(void);
 void get_agp_version(struct agp_bridge_data *bridge);
 unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
        unsigned long addr, int type);
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+                                 int type);
 struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
 
+/* generic functions for user-populated AGP memory types */
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type);
+void agp_alloc_page_array(size_t size, struct agp_memory *mem);
+void agp_free_page_array(struct agp_memory *mem);
+
+
 /* generic routines for agp>=3 */
 int agp3_generic_fetch_size(void);
 void agp3_generic_tlbflush(struct agp_memory *mem);
@@ -288,6 +298,8 @@ extern struct aper_size_info_16 agp3_generic_sizes[];
 extern int agp_off;
 extern int agp_try_unsupported_boot;
 
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
 /* Chipset independant registers (from AGP Spec) */
 #define AGP_APBASE     0x10
 
index 5a31ec7c62fc40bd8fc213fd5fb69961971d82db..98177a93076f5c7d4f7959b93b37ae0b99617120 100644 (file)
@@ -214,6 +214,7 @@ static struct agp_bridge_driver ali_generic_bridge = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = ali_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver ali_m1541_bridge = {
@@ -237,6 +238,7 @@ static struct agp_bridge_driver ali_m1541_bridge = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = m1541_alloc_page,
        .agp_destroy_page       = m1541_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 
index b4e00a343da9162e559f305794ae31cc99842285..b0acf41c0db9d5f7997783371ac501d55ca89b8f 100644 (file)
@@ -91,6 +91,9 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
        int num_entries, status;
        void *temp;
 
+       if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+               return -EINVAL;
+
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
        if ((pg_start + mem->page_count) > num_entries)
@@ -142,6 +145,7 @@ struct agp_bridge_driver alpha_core_agp_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 struct agp_bridge_data *alpha_bridge;
index c85c8cadb6dfd67b9531eb849f140e9095deec9a..3d8d448bf394a181afcd4fc7319b87471aede4a7 100644 (file)
@@ -381,6 +381,7 @@ static struct agp_bridge_driver amd_irongate_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
index 93d2209fee4cfdda3539e0a36a9de177dfffcab2..636d984ed4a62598dc1e11f174f9e9a90262bfee 100644 (file)
@@ -62,12 +62,18 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        int i, j, num_entries;
        long long tmp;
+       int mask_type;
+       struct agp_bridge_data *bridge = mem->bridge;
        u32 pte;
 
        num_entries = agp_num_entries();
 
-       if (type != 0 || mem->type != 0)
+       if (type != mem->type)
                return -EINVAL;
+       mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+       if (mask_type != 0)
+               return -EINVAL;
+
 
        /* Make sure we can fit the range in the gatt table. */
        /* FIXME: could wrap */
@@ -90,7 +96,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                tmp = agp_bridge->driver->mask_memory(agp_bridge,
-                       mem->memory[i], mem->type);
+                       mem->memory[i], mask_type);
 
                BUG_ON(tmp & 0xffffff0000000ffcULL);
                pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -247,6 +253,7 @@ static struct agp_bridge_driver amd_8151_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 /* Some basic sanity checks for the aperture. */
index 9987dc2e0c3f02474ba75994b9bc7d675e9904db..77c9ad68fba919b09cd72013639622149164d382 100644 (file)
@@ -431,6 +431,7 @@ static struct agp_bridge_driver ati_generic_bridge = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 
index d59e037ddd1234e395b2a277f0c34c45cacb03b1..ebdd6dd66edb6b27931061a3ea732014f58bb31e 100644 (file)
@@ -43,7 +43,7 @@
  * fix some real stupidity. It's only by chance we can bump
  * past 0.99 at all due to some boolean logic error. */
 #define AGPGART_VERSION_MAJOR 0
-#define AGPGART_VERSION_MINOR 101
+#define AGPGART_VERSION_MINOR 102
 static const struct agp_version agp_current_version =
 {
        .major = AGPGART_VERSION_MAJOR,
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
new file mode 100644 (file)
index 0000000..fcb4b1b
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * AGPGART driver frontend compatibility ioctls
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Copyright (C) 2002-2003 Dave Jones
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/agpgart.h>
+#include <asm/uaccess.h>
+#include "agp.h"
+#include "compat_ioctl.h"
+
+static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
+{
+       struct agp_info32 userinfo;
+       struct agp_kern_info kerninfo;
+
+       agp_copy_info(agp_bridge, &kerninfo);
+
+       userinfo.version.major = kerninfo.version.major;
+       userinfo.version.minor = kerninfo.version.minor;
+       userinfo.bridge_id = kerninfo.device->vendor |
+           (kerninfo.device->device << 16);
+       userinfo.agp_mode = kerninfo.mode;
+       userinfo.aper_base = (compat_long_t)kerninfo.aper_base;
+       userinfo.aper_size = kerninfo.aper_size;
+       userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
+       userinfo.pg_used = kerninfo.current_memory;
+
+       if (copy_to_user(arg, &userinfo, sizeof(userinfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
+{
+       struct agp_region32 ureserve;
+       struct agp_region kreserve;
+       struct agp_client *client;
+       struct agp_file_private *client_priv;
+
+       DBG("");
+       if (copy_from_user(&ureserve, arg, sizeof(ureserve)))
+               return -EFAULT;
+
+       if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32))
+               return -EFAULT;
+
+       kreserve.pid = ureserve.pid;
+       kreserve.seg_count = ureserve.seg_count;
+
+       client = agp_find_client_by_pid(kreserve.pid);
+
+       if (kreserve.seg_count == 0) {
+               /* remove a client */
+               client_priv = agp_find_private(kreserve.pid);
+
+               if (client_priv != NULL) {
+                       set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+                       set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+               }
+               if (client == NULL) {
+                       /* client is already removed */
+                       return 0;
+               }
+               return agp_remove_client(kreserve.pid);
+       } else {
+               struct agp_segment32 *usegment;
+               struct agp_segment *ksegment;
+               int seg;
+
+               if (ureserve.seg_count >= 16384)
+                       return -EINVAL;
+
+               usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
+               if (!usegment)
+                       return -ENOMEM;
+
+               ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
+               if (!ksegment) {
+                       kfree(usegment);
+                       return -ENOMEM;
+               }
+
+               if (copy_from_user(usegment, (void __user *) ureserve.seg_list,
+                                  sizeof(*usegment) * ureserve.seg_count)) {
+                       kfree(usegment);
+                       kfree(ksegment);
+                       return -EFAULT;
+               }
+
+               for (seg = 0; seg < ureserve.seg_count; seg++) {
+                       ksegment[seg].pg_start = usegment[seg].pg_start;
+                       ksegment[seg].pg_count = usegment[seg].pg_count;
+                       ksegment[seg].prot = usegment[seg].prot;
+               }
+
+               kfree(usegment);
+               kreserve.seg_list = ksegment;
+
+               if (client == NULL) {
+                       /* Create the client and add the segment */
+                       client = agp_create_client(kreserve.pid);
+
+                       if (client == NULL) {
+                               kfree(ksegment);
+                               return -ENOMEM;
+                       }
+                       client_priv = agp_find_private(kreserve.pid);
+
+                       if (client_priv != NULL) {
+                               set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+                               set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+                       }
+               }
+               return agp_create_segment(client, &kreserve);
+       }
+       /* Will never really happen */
+       return -EINVAL;
+}
+
+static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
+{
+       struct agp_memory *memory;
+       struct agp_allocate32 alloc;
+
+       DBG("");
+       if (copy_from_user(&alloc, arg, sizeof(alloc)))
+               return -EFAULT;
+
+       memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
+
+       if (memory == NULL)
+               return -ENOMEM;
+
+       alloc.key = memory->key;
+       alloc.physical = memory->physical;
+
+       if (copy_to_user(arg, &alloc, sizeof(alloc))) {
+               agp_free_memory_wrap(memory);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+       struct agp_bind32 bind_info;
+       struct agp_memory *memory;
+
+       DBG("");
+       if (copy_from_user(&bind_info, arg, sizeof(bind_info)))
+               return -EFAULT;
+
+       memory = agp_find_mem_by_key(bind_info.key);
+
+       if (memory == NULL)
+               return -EINVAL;
+
+       return agp_bind_memory(memory, bind_info.pg_start);
+}
+
+static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+       struct agp_memory *memory;
+       struct agp_unbind32 unbind;
+
+       DBG("");
+       if (copy_from_user(&unbind, arg, sizeof(unbind)))
+               return -EFAULT;
+
+       memory = agp_find_mem_by_key(unbind.key);
+
+       if (memory == NULL)
+               return -EINVAL;
+
+       return agp_unbind_memory(memory);
+}
+
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct agp_file_private *curr_priv = file->private_data;
+       int ret_val = -ENOTTY;
+
+       mutex_lock(&(agp_fe.agp_mutex));
+
+       if ((agp_fe.current_controller == NULL) &&
+           (cmd != AGPIOC_ACQUIRE32)) {
+               ret_val = -EINVAL;
+               goto ioctl_out;
+       }
+       if ((agp_fe.backend_acquired != TRUE) &&
+           (cmd != AGPIOC_ACQUIRE32)) {
+               ret_val = -EBUSY;
+               goto ioctl_out;
+       }
+       if (cmd != AGPIOC_ACQUIRE32) {
+               if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
+                       ret_val = -EPERM;
+                       goto ioctl_out;
+               }
+               /* Use the original pid of the controller,
+                * in case it's threaded */
+
+               if (agp_fe.current_controller->pid != curr_priv->my_pid) {
+                       ret_val = -EBUSY;
+                       goto ioctl_out;
+               }
+       }
+
+       switch (cmd) {
+       case AGPIOC_INFO32:
+               ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg);
+               break;
+
+       case AGPIOC_ACQUIRE32:
+               ret_val = agpioc_acquire_wrap(curr_priv);
+               break;
+
+       case AGPIOC_RELEASE32:
+               ret_val = agpioc_release_wrap(curr_priv);
+               break;
+
+       case AGPIOC_SETUP32:
+               ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
+               break;
+
+       case AGPIOC_RESERVE32:
+               ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg);
+               break;
+
+       case AGPIOC_PROTECT32:
+               ret_val = agpioc_protect_wrap(curr_priv);
+               break;
+
+       case AGPIOC_ALLOCATE32:
+               ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg);
+               break;
+
+       case AGPIOC_DEALLOCATE32:
+               ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
+               break;
+
+       case AGPIOC_BIND32:
+               ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg);
+               break;
+
+       case AGPIOC_UNBIND32:
+               ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg);
+               break;
+       }
+
+ioctl_out:
+       DBG("ioctl returns %d\n", ret_val);
+       mutex_unlock(&(agp_fe.agp_mutex));
+       return ret_val;
+}
+
diff --git a/drivers/char/agp/compat_ioctl.h b/drivers/char/agp/compat_ioctl.h
new file mode 100644 (file)
index 0000000..71939d6
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _AGP_COMPAT_IOCTL_H
+#define _AGP_COMPAT_IOCTL_H
+
+#include <linux/compat.h>
+#include <linux/agpgart.h>
+
+#define AGPIOC_INFO32       _IOR (AGPIOC_BASE, 0, compat_uptr_t)
+#define AGPIOC_ACQUIRE32    _IO  (AGPIOC_BASE, 1)
+#define AGPIOC_RELEASE32    _IO  (AGPIOC_BASE, 2)
+#define AGPIOC_SETUP32      _IOW (AGPIOC_BASE, 3, compat_uptr_t)
+#define AGPIOC_RESERVE32    _IOW (AGPIOC_BASE, 4, compat_uptr_t)
+#define AGPIOC_PROTECT32    _IOW (AGPIOC_BASE, 5, compat_uptr_t)
+#define AGPIOC_ALLOCATE32   _IOWR(AGPIOC_BASE, 6, compat_uptr_t)
+#define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t)
+#define AGPIOC_BIND32       _IOW (AGPIOC_BASE, 8, compat_uptr_t)
+#define AGPIOC_UNBIND32     _IOW (AGPIOC_BASE, 9, compat_uptr_t)
+
+struct agp_info32 {
+       struct agp_version version;     /* version of the driver        */
+       u32 bridge_id;          /* bridge vendor/device         */
+       u32 agp_mode;           /* mode info of bridge          */
+       compat_long_t aper_base;        /* base of aperture             */
+       compat_size_t aper_size;        /* size of aperture             */
+       compat_size_t pg_total; /* max pages (swap + system)    */
+       compat_size_t pg_system;        /* max pages (system)           */
+       compat_size_t pg_used;          /* current pages used           */
+};
+
+/*
+ * The "prot" down below needs still a "sleep" flag somehow ...
+ */
+struct agp_segment32 {
+       compat_off_t pg_start;          /* starting page to populate    */
+       compat_size_t pg_count; /* number of pages              */
+       compat_int_t prot;              /* prot flags for mmap          */
+};
+
+struct agp_region32 {
+       compat_pid_t pid;               /* pid of process               */
+       compat_size_t seg_count;        /* number of segments           */
+       struct agp_segment32 *seg_list;
+};
+
+struct agp_allocate32 {
+       compat_int_t key;               /* tag of allocation            */
+       compat_size_t pg_count; /* number of pages              */
+       u32 type;               /* 0 == normal, other devspec   */
+       u32 physical;           /* device specific (some devices
+                                * need a phys address of the
+                                * actual page behind the gatt
+                                * table)                        */
+};
+
+struct agp_bind32 {
+       compat_int_t key;               /* tag of allocation            */
+       compat_off_t pg_start;          /* starting page to populate    */
+};
+
+struct agp_unbind32 {
+       compat_int_t key;               /* tag of allocation            */
+       u32 priority;           /* priority for paging out      */
+};
+
+extern struct agp_front_data agp_fe;
+
+int agpioc_acquire_wrap(struct agp_file_private *priv);
+int agpioc_release_wrap(struct agp_file_private *priv);
+int agpioc_protect_wrap(struct agp_file_private *priv);
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg);
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg);
+struct agp_file_private *agp_find_private(pid_t pid);
+struct agp_client *agp_create_client(pid_t id);
+int agp_remove_client(pid_t id);
+int agp_create_segment(struct agp_client *client, struct agp_region *region);
+void agp_free_memory_wrap(struct agp_memory *memory);
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
+struct agp_memory *agp_find_mem_by_key(int key);
+struct agp_client *agp_find_client_by_pid(pid_t id);
+
+#endif /* _AGP_COMPAT_H */
index 30f730ff81c1717c82eb3f50a8d94a1194255350..658cb1a72d2cf65d9c5244775ecdf1b696313b02 100644 (file)
@@ -335,6 +335,7 @@ static struct agp_bridge_driver efficeon_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
index 0f2ed2aa2d815039d7cd6cd3dc26a20a4e15791e..679d7f972439b43cb511fedf77d334af08928833 100644 (file)
@@ -41,9 +41,9 @@
 #include <asm/pgtable.h>
 #include "agp.h"
 
-static struct agp_front_data agp_fe;
+struct agp_front_data agp_fe;
 
-static struct agp_memory *agp_find_mem_by_key(int key)
+struct agp_memory *agp_find_mem_by_key(int key)
 {
        struct agp_memory *curr;
 
@@ -159,7 +159,7 @@ static pgprot_t agp_convert_mmap_flags(int prot)
        return vm_get_page_prot(prot_bits);
 }
 
-static int agp_create_segment(struct agp_client *client, struct agp_region *region)
+int agp_create_segment(struct agp_client *client, struct agp_region *region)
 {
        struct agp_segment_priv **ret_seg;
        struct agp_segment_priv *seg;
@@ -211,7 +211,7 @@ static void agp_insert_into_pool(struct agp_memory * temp)
 
 /* File private list routines */
 
-static struct agp_file_private *agp_find_private(pid_t pid)
+struct agp_file_private *agp_find_private(pid_t pid)
 {
        struct agp_file_private *curr;
 
@@ -266,13 +266,13 @@ static void agp_remove_file_private(struct agp_file_private * priv)
  * Wrappers for agp_free_memory & agp_allocate_memory
  * These make sure that internal lists are kept updated.
  */
-static void agp_free_memory_wrap(struct agp_memory *memory)
+void agp_free_memory_wrap(struct agp_memory *memory)
 {
        agp_remove_from_pool(memory);
        agp_free_memory(memory);
 }
 
-static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
 {
        struct agp_memory *memory;
 
@@ -484,7 +484,7 @@ static struct agp_controller *agp_find_controller_for_client(pid_t id)
        return NULL;
 }
 
-static struct agp_client *agp_find_client_by_pid(pid_t id)
+struct agp_client *agp_find_client_by_pid(pid_t id)
 {
        struct agp_client *temp;
 
@@ -509,7 +509,7 @@ static void agp_insert_client(struct agp_client *client)
        agp_fe.current_controller->num_clients++;
 }
 
-static struct agp_client *agp_create_client(pid_t id)
+struct agp_client *agp_create_client(pid_t id)
 {
        struct agp_client *new_client;
 
@@ -522,7 +522,7 @@ static struct agp_client *agp_create_client(pid_t id)
        return new_client;
 }
 
-static int agp_remove_client(pid_t id)
+int agp_remove_client(pid_t id)
 {
        struct agp_client *client;
        struct agp_client *prev_client;
@@ -746,7 +746,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
        return 0;
 }
 
-static int agpioc_acquire_wrap(struct agp_file_private *priv)
+int agpioc_acquire_wrap(struct agp_file_private *priv)
 {
        struct agp_controller *controller;
 
@@ -789,14 +789,14 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
        return 0;
 }
 
-static int agpioc_release_wrap(struct agp_file_private *priv)
+int agpioc_release_wrap(struct agp_file_private *priv)
 {
        DBG("");
        agp_controller_release_current(agp_fe.current_controller, priv);
        return 0;
 }
 
-static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
 {
        struct agp_setup mode;
 
@@ -876,7 +876,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
        return -EINVAL;
 }
 
-static int agpioc_protect_wrap(struct agp_file_private *priv)
+int agpioc_protect_wrap(struct agp_file_private *priv)
 {
        DBG("");
        /* This function is not currently implemented */
@@ -892,6 +892,9 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
        if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
                return -EFAULT;
 
+       if (alloc.type >= AGP_USER_TYPES)
+               return -EINVAL;
+
        memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
 
        if (memory == NULL)
@@ -907,7 +910,7 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
        return 0;
 }
 
-static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
 {
        struct agp_memory *memory;
 
@@ -1043,6 +1046,9 @@ static const struct file_operations agp_fops =
        .read           = agp_read,
        .write          = agp_write,
        .ioctl          = agp_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = compat_agp_ioctl,
+#endif
        .mmap           = agp_mmap,
        .open           = agp_open,
        .release        = agp_release,
index 3491d6f84bc6098b321965edacf416c7a0d277ac..7923337c3d26ae3db5a3aea6496eae8dd4836df6 100644 (file)
@@ -101,6 +101,63 @@ static int agp_get_key(void)
        return -1;
 }
 
+/*
+ * Use kmalloc if possible for the page list. Otherwise fall back to
+ * vmalloc. This speeds things up and also saves memory for small AGP
+ * regions.
+ */
+
+void agp_alloc_page_array(size_t size, struct agp_memory *mem)
+{
+       mem->memory = NULL;
+       mem->vmalloc_flag = 0;
+
+       if (size <= 2*PAGE_SIZE)
+               mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+       if (mem->memory == NULL) {
+               mem->memory = vmalloc(size);
+               mem->vmalloc_flag = 1;
+       }
+}
+EXPORT_SYMBOL(agp_alloc_page_array);
+
+void agp_free_page_array(struct agp_memory *mem)
+{
+       if (mem->vmalloc_flag) {
+               vfree(mem->memory);
+       } else {
+               kfree(mem->memory);
+       }
+}
+EXPORT_SYMBOL(agp_free_page_array);
+
+
+static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
+{
+       struct agp_memory *new;
+       unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
+
+       new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
+       if (new == NULL)
+               return NULL;
+
+       new->key = agp_get_key();
+
+       if (new->key < 0) {
+               kfree(new);
+               return NULL;
+       }
+
+       agp_alloc_page_array(alloc_size, new);
+
+       if (new->memory == NULL) {
+               agp_free_key(new->key);
+               kfree(new);
+               return NULL;
+       }
+       new->num_scratch_pages = 0;
+       return new;
+}
 
 struct agp_memory *agp_create_memory(int scratch_pages)
 {
@@ -116,7 +173,8 @@ struct agp_memory *agp_create_memory(int scratch_pages)
                kfree(new);
                return NULL;
        }
-       new->memory = vmalloc(PAGE_SIZE * scratch_pages);
+
+       agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
 
        if (new->memory == NULL) {
                agp_free_key(new->key);
@@ -124,6 +182,7 @@ struct agp_memory *agp_create_memory(int scratch_pages)
                return NULL;
        }
        new->num_scratch_pages = scratch_pages;
+       new->type = AGP_NORMAL_MEMORY;
        return new;
 }
 EXPORT_SYMBOL(agp_create_memory);
@@ -146,6 +205,11 @@ void agp_free_memory(struct agp_memory *curr)
        if (curr->is_bound == TRUE)
                agp_unbind_memory(curr);
 
+       if (curr->type >= AGP_USER_TYPES) {
+               agp_generic_free_by_type(curr);
+               return;
+       }
+
        if (curr->type != 0) {
                curr->bridge->driver->free_by_type(curr);
                return;
@@ -157,7 +221,7 @@ void agp_free_memory(struct agp_memory *curr)
                flush_agp_mappings();
        }
        agp_free_key(curr->key);
-       vfree(curr->memory);
+       agp_free_page_array(curr);
        kfree(curr);
 }
 EXPORT_SYMBOL(agp_free_memory);
@@ -188,6 +252,13 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
        if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
                return NULL;
 
+       if (type >= AGP_USER_TYPES) {
+               new = agp_generic_alloc_user(page_count, type);
+               if (new)
+                       new->bridge = bridge;
+               return new;
+       }
+
        if (type != 0) {
                new = bridge->driver->alloc_by_type(page_count, type);
                if (new)
@@ -960,6 +1031,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
        off_t j;
        void *temp;
        struct agp_bridge_data *bridge;
+       int mask_type;
 
        bridge = mem->bridge;
        if (!bridge)
@@ -995,7 +1067,11 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
        num_entries -= agp_memory_reserved/PAGE_SIZE;
        if (num_entries < 0) num_entries = 0;
 
-       if (type != 0 || mem->type != 0) {
+       if (type != mem->type)
+               return -EINVAL;
+
+       mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+       if (mask_type != 0) {
                /* The generic routines know nothing of memory types */
                return -EINVAL;
        }
@@ -1018,7 +1094,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
        }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
+               writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
+                      bridge->gatt_table+j);
        }
        readl(bridge->gatt_table+j-1);  /* PCI Posting. */
 
@@ -1032,6 +1109,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        size_t i;
        struct agp_bridge_data *bridge;
+       int mask_type;
 
        bridge = mem->bridge;
        if (!bridge)
@@ -1040,7 +1118,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
        if (mem->page_count == 0)
                return 0;
 
-       if (type != 0 || mem->type != 0) {
+       if (type != mem->type)
+               return -EINVAL;
+
+       mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+       if (mask_type != 0) {
                /* The generic routines know nothing of memory types */
                return -EINVAL;
        }
@@ -1056,22 +1138,40 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 }
 EXPORT_SYMBOL(agp_generic_remove_memory);
 
-
 struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type)
 {
        return NULL;
 }
 EXPORT_SYMBOL(agp_generic_alloc_by_type);
 
-
 void agp_generic_free_by_type(struct agp_memory *curr)
 {
-       vfree(curr->memory);
+       agp_free_page_array(curr);
        agp_free_key(curr->key);
        kfree(curr);
 }
 EXPORT_SYMBOL(agp_generic_free_by_type);
 
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
+{
+       struct agp_memory *new;
+       int i;
+       int pages;
+
+       pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
+       new = agp_create_user_memory(page_count);
+       if (new == NULL)
+               return NULL;
+
+       for (i = 0; i < page_count; i++)
+               new->memory[i] = 0;
+       new->page_count = 0;
+       new->type = type;
+       new->num_scratch_pages = pages;
+
+       return new;
+}
+EXPORT_SYMBOL(agp_generic_alloc_user);
 
 /*
  * Basic Page Allocation Routines -
@@ -1165,6 +1265,15 @@ unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
 }
 EXPORT_SYMBOL(agp_generic_mask_memory);
 
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+                                 int type)
+{
+       if (type >= AGP_USER_TYPES)
+               return 0;
+       return type;
+}
+EXPORT_SYMBOL(agp_generic_type_to_mask_type);
+
 /*
  * These functions are implemented according to the AGPv3 spec,
  * which covers implementation details that had previously been
index 907fb66ec4a98f12212b181099e39700eb797513..847deabf7f9b6b110f694d68856cb82c7fab9f56 100644 (file)
@@ -438,6 +438,7 @@ struct agp_bridge_driver hp_zx1_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = 1,
 };
 
index 91769443d8fe2d30cf010ef55318a51b43d82e81..3e7618653abd05ca4f74b12788e018251dd88b74 100644 (file)
@@ -293,6 +293,9 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
        pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
                 mem, pg_start, type, mem->memory[0]);
 
+       if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+               return -EINVAL;
+
        io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
 
        temp = agp_bridge->current_size;
@@ -396,6 +399,9 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
        struct lp_desc *start, *end, *lp;
        void *temp;
 
+       if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+               return -EINVAL;
+
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_8(temp)->num_entries;
 
@@ -572,6 +578,7 @@ struct agp_bridge_driver intel_i460_driver = {
 #endif
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = 1,
 };
 
index a3011de51f7c049438ae51fae97f3652522cf9a4..06b0bb6d982fca6486a928b98f7e84898a515579 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
 #include "agp.h"
@@ -24,6 +25,9 @@
                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
 
 
+extern int agp_memory_reserved;
+
+
 /* Intel 815 register */
 #define INTEL_815_APCONT       0x51
 #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
@@ -68,12 +72,15 @@ static struct aper_size_info_fixed intel_i810_sizes[] =
 
 #define AGP_DCACHE_MEMORY      1
 #define AGP_PHYS_MEMORY                2
+#define INTEL_AGP_CACHED_MEMORY 3
 
 static struct gatt_mask intel_i810_masks[] =
 {
        {.mask = I810_PTE_VALID, .type = 0},
        {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
-       {.mask = I810_PTE_VALID, .type = 0}
+       {.mask = I810_PTE_VALID, .type = 0},
+       {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
+        .type = INTEL_AGP_CACHED_MEMORY}
 };
 
 static struct _intel_i810_private {
@@ -117,13 +124,15 @@ static int intel_i810_configure(void)
 
        current_size = A_SIZE_FIX(agp_bridge->current_size);
 
-       pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
-       temp &= 0xfff80000;
-
-       intel_i810_private.registers = ioremap(temp, 128 * 4096);
        if (!intel_i810_private.registers) {
-               printk(KERN_ERR PFX "Unable to remap memory.\n");
-               return -ENOMEM;
+               pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+               temp &= 0xfff80000;
+
+               intel_i810_private.registers = ioremap(temp, 128 * 4096);
+               if (!intel_i810_private.registers) {
+                       printk(KERN_ERR PFX "Unable to remap memory.\n");
+                       return -ENOMEM;
+               }
        }
 
        if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
@@ -201,62 +210,79 @@ static void i8xx_destroy_pages(void *addr)
        atomic_dec(&agp_bridge->current_memory_agp);
 }
 
+static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
+                                       int type)
+{
+       if (type < AGP_USER_TYPES)
+               return type;
+       else if (type == AGP_USER_CACHED_MEMORY)
+               return INTEL_AGP_CACHED_MEMORY;
+       else
+               return 0;
+}
+
 static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
                                int type)
 {
        int i, j, num_entries;
        void *temp;
+       int ret = -EINVAL;
+       int mask_type;
 
        if (mem->page_count == 0)
-               return 0;
+               goto out;
 
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
 
        if ((pg_start + mem->page_count) > num_entries)
-               return -EINVAL;
+               goto out_err;
 
-       for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-               if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
-                       return -EBUSY;
-       }
 
-       if (type != 0 || mem->type != 0) {
-               if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
-                       /* special insert */
-                       if (!mem->is_flushed) {
-                               global_cache_flush();
-                               mem->is_flushed = TRUE;
-                       }
-
-                       for (i = pg_start; i < (pg_start + mem->page_count); i++) {
-                               writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
-                       }
-                       readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));    /* PCI Posting. */
-
-                       agp_bridge->driver->tlb_flush(mem);
-                       return 0;
+       for (j = pg_start; j < (pg_start + mem->page_count); j++) {
+               if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
+                       ret = -EBUSY;
+                       goto out_err;
                }
-               if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
-                       goto insert;
-               return -EINVAL;
        }
 
-insert:
-       if (!mem->is_flushed) {
-               global_cache_flush();
-               mem->is_flushed = TRUE;
-       }
+       if (type != mem->type)
+               goto out_err;
 
-       for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               writel(agp_bridge->driver->mask_memory(agp_bridge,
-                       mem->memory[i], mem->type),
-                       intel_i810_private.registers+I810_PTE_BASE+(j*4));
+       mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+
+       switch (mask_type) {
+       case AGP_DCACHE_MEMORY:
+               if (!mem->is_flushed)
+                       global_cache_flush();
+               for (i = pg_start; i < (pg_start + mem->page_count); i++) {
+                       writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
+                              intel_i810_private.registers+I810_PTE_BASE+(i*4));
+               }
+               readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+               break;
+       case AGP_PHYS_MEMORY:
+       case AGP_NORMAL_MEMORY:
+               if (!mem->is_flushed)
+                       global_cache_flush();
+               for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+                       writel(agp_bridge->driver->mask_memory(agp_bridge,
+                                                              mem->memory[i],
+                                                              mask_type),
+                              intel_i810_private.registers+I810_PTE_BASE+(j*4));
+               }
+               readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
+               break;
+       default:
+               goto out_err;
        }
-       readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));    /* PCI Posting. */
 
        agp_bridge->driver->tlb_flush(mem);
-       return 0;
+out:
+       ret = 0;
+out_err:
+       mem->is_flushed = 1;
+       return ret;
 }
 
 static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
@@ -337,12 +363,11 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
                new->type = AGP_DCACHE_MEMORY;
                new->page_count = pg_count;
                new->num_scratch_pages = 0;
-               vfree(new->memory);
+               agp_free_page_array(new);
                return new;
        }
        if (type == AGP_PHYS_MEMORY)
                return alloc_agpphysmem_i8xx(pg_count, type);
-
        return NULL;
 }
 
@@ -357,7 +382,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
                                 gart_to_virt(curr->memory[0]));
                        global_flush_tlb();
                }
-               vfree(curr->memory);
+               agp_free_page_array(curr);
        }
        kfree(curr);
 }
@@ -619,9 +644,11 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
 {
        int i,j,num_entries;
        void *temp;
+       int ret = -EINVAL;
+       int mask_type;
 
        if (mem->page_count == 0)
-               return 0;
+               goto out;
 
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -631,34 +658,41 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
                                pg_start,intel_i830_private.gtt_entries);
 
                printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-               return -EINVAL;
+               goto out_err;
        }
 
        if ((pg_start + mem->page_count) > num_entries)
-               return -EINVAL;
+               goto out_err;
 
        /* The i830 can't check the GTT for entries since its read only,
         * depend on the caller to make the correct offset decisions.
         */
 
-       if ((type != 0 && type != AGP_PHYS_MEMORY) ||
-               (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-               return -EINVAL;
+       if (type != mem->type)
+               goto out_err;
+
+       mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-       if (!mem->is_flushed) {
+       if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+           mask_type != INTEL_AGP_CACHED_MEMORY)
+               goto out_err;
+
+       if (!mem->is_flushed)
                global_cache_flush();
-               mem->is_flushed = TRUE;
-       }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
-                       mem->memory[i], mem->type),
-                       intel_i830_private.registers+I810_PTE_BASE+(j*4));
+                                                      mem->memory[i], mask_type),
+                      intel_i830_private.registers+I810_PTE_BASE+(j*4));
        }
        readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
-
        agp_bridge->driver->tlb_flush(mem);
-       return 0;
+
+out:
+       ret = 0;
+out_err:
+       mem->is_flushed = 1;
+       return ret;
 }
 
 static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -687,7 +721,6 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
 {
        if (type == AGP_PHYS_MEMORY)
                return alloc_agpphysmem_i8xx(pg_count, type);
-
        /* always return NULL for other allocation types for now */
        return NULL;
 }
@@ -734,9 +767,11 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
 {
        int i,j,num_entries;
        void *temp;
+       int ret = -EINVAL;
+       int mask_type;
 
        if (mem->page_count == 0)
-               return 0;
+               goto out;
 
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -746,33 +781,41 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
                                pg_start,intel_i830_private.gtt_entries);
 
                printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-               return -EINVAL;
+               goto out_err;
        }
 
        if ((pg_start + mem->page_count) > num_entries)
-               return -EINVAL;
+               goto out_err;
 
-       /* The i830 can't check the GTT for entries since its read only,
+       /* The i915 can't check the GTT for entries since its read only,
         * depend on the caller to make the correct offset decisions.
         */
 
-       if ((type != 0 && type != AGP_PHYS_MEMORY) ||
-               (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-               return -EINVAL;
+       if (type != mem->type)
+               goto out_err;
+
+       mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-       if (!mem->is_flushed) {
+       if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+           mask_type != INTEL_AGP_CACHED_MEMORY)
+               goto out_err;
+
+       if (!mem->is_flushed)
                global_cache_flush();
-               mem->is_flushed = TRUE;
-       }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
-                       mem->memory[i], mem->type), intel_i830_private.gtt+j);
+                       mem->memory[i], mask_type), intel_i830_private.gtt+j);
        }
-       readl(intel_i830_private.gtt+j-1);
 
+       readl(intel_i830_private.gtt+j-1);
        agp_bridge->driver->tlb_flush(mem);
-       return 0;
+
+ out:
+       ret = 0;
+ out_err:
+       mem->is_flushed = 1;
+       return ret;
 }
 
 static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -803,7 +846,7 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
  */
 static int intel_i9xx_fetch_size(void)
 {
-       int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
+       int num_sizes = ARRAY_SIZE(intel_i830_sizes);
        int aper_size; /* size in megabytes */
        int i;
 
@@ -1384,6 +1427,7 @@ static struct agp_bridge_driver intel_generic_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_810_driver = {
@@ -1408,6 +1452,7 @@ static struct agp_bridge_driver intel_810_driver = {
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_815_driver = {
@@ -1431,6 +1476,7 @@ static struct agp_bridge_driver intel_815_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_830_driver = {
@@ -1455,6 +1501,7 @@ static struct agp_bridge_driver intel_830_driver = {
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_820_driver = {
@@ -1478,6 +1525,7 @@ static struct agp_bridge_driver intel_820_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_830mp_driver = {
@@ -1501,6 +1549,7 @@ static struct agp_bridge_driver intel_830mp_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_840_driver = {
@@ -1524,6 +1573,7 @@ static struct agp_bridge_driver intel_840_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_845_driver = {
@@ -1547,6 +1597,7 @@ static struct agp_bridge_driver intel_845_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_850_driver = {
@@ -1570,6 +1621,7 @@ static struct agp_bridge_driver intel_850_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_860_driver = {
@@ -1593,6 +1645,7 @@ static struct agp_bridge_driver intel_860_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_915_driver = {
@@ -1617,6 +1670,7 @@ static struct agp_bridge_driver intel_915_driver = {
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_i965_driver = {
@@ -1641,6 +1695,7 @@ static struct agp_bridge_driver intel_i965_driver = {
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
 static struct agp_bridge_driver intel_7505_driver = {
@@ -1664,6 +1719,7 @@ static struct agp_bridge_driver intel_7505_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int find_i810(u16 device)
index df7f37b2739abe007a9f9f629f301941f65cadf7..2563286b2fcf3db9a112a986147cd0d23c2c5ed0 100644 (file)
@@ -310,6 +310,7 @@ static struct agp_bridge_driver nvidia_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
index 17c50b0f83f0ab5514ca768a9c97bc6a262f360e..b7b4590673ae977d67231ffb5eeb381b2243bcfb 100644 (file)
@@ -228,6 +228,7 @@ struct agp_bridge_driver parisc_agp_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = 1,
 };
 
index 902648db7efaddb4a526eab1e56b70633bba8d9a..92d1dc45b9be05d53fa04fde3c21c2dae4097488 100644 (file)
@@ -265,6 +265,7 @@ struct agp_bridge_driver sgi_tioca_driver = {
        .free_by_type = agp_generic_free_by_type,
        .agp_alloc_page = sgi_tioca_alloc_page,
        .agp_destroy_page = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture = 1,
        .needs_scratch_page = 0,
        .num_aperture_sizes = 1,
index a00fd48a6f05cc55fdd66451d425e1f7ae1aaddc..60342b708152d25ccd06bbf097b438f179017bb3 100644 (file)
@@ -140,6 +140,7 @@ static struct agp_bridge_driver sis_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
index 4f2d7d99902f1cfc21ad988846d1176609b3ccf2..9f5ae7714f85e1c8e30e7ff3ae2440f24e5ea91e 100644 (file)
@@ -444,6 +444,7 @@ static struct agp_bridge_driver sworks_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
index dffc19382f7eb828f73426e91b7524f5ffce3305..6c45702e542cc7394ee5596b0d06ef3a2d49047b 100644 (file)
@@ -510,6 +510,7 @@ struct agp_bridge_driver uninorth_agp_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = 1,
 };
 
@@ -534,6 +535,7 @@ struct agp_bridge_driver u3_agp_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = 1,
        .needs_scratch_page     = 1,
 };
index 2ded7a280d7f784eeb0c5ead3a3b55a2e1927c04..2e7c04370cd9e16340ed51da02f38ac30cbce086 100644 (file)
@@ -191,6 +191,7 @@ static struct agp_bridge_driver via_agp3_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_bridge_driver via_driver = {
@@ -214,6 +215,7 @@ static struct agp_bridge_driver via_driver = {
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids via_agp_device_ids[] __devinitdata =
index 7f60a18ef76beca074c8c489fc76ca12846f6436..8dcf9d20f44985be7cbf707bee14e5e20af6a077 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
index 1383727b443ad98fb28795b1f71c7ecd02ff0d46..ac9ab40d57aa23b1d4b16a3f66ca38746c5c6b53 100644 (file)
@@ -7,7 +7,6 @@
  * for authors.
  */
 
-#include <linux/sched.h>
 #include <asm/upa.h>
 
 #include "ffb.h"
index dd45111a48547619063d30dfdadd2eb2c78a81ba..9a19879e3b688fa7f3924bad6e624846148dc7be 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "ffb_drv.h"
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/shmparam.h>
 #include <asm/oplib.h>
index 48cb8f0e8ebf8000e5dcc697d1d20383ae7cfd50..3d7efc26aad61338818a1416ff4d344ad4227a76 100644 (file)
@@ -3,7 +3,6 @@
  *   thermometer driver (as used in the Rebel.com NetWinder)
  */
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
index 06f2dbf17710770e5829d464e81cfb48d5e8367c..db984e481d4ca42908fffee5fb426528d119e82b 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>        /* for kmalloc() and kfree() */
-#include <linux/sched.h>       /* for struct wait_queue etc */
 #include <linux/major.h>
 #include <linux/types.h>
 #include <linux/errno.h>
index 1aa93a752a9c0c636bf6945224c7ea6aa787bf48..ae76a9ffe89f56481dc0cb851e3e0687b66b8694 100644 (file)
@@ -117,7 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_S390)
+#if defined(CONFIG_S390)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
 #elif defined(CONFIG_IA64)
index 20dc3be5ecfcf8fe987e41313902f41acdc4a2e0..0be700f4e8fd7acdceaec7dd3acf0acdf63a00d3 100644 (file)
@@ -703,7 +703,7 @@ int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
 
 static ctl_table hpet_table[] = {
        {
-        .ctl_name = 1,
+        .ctl_name = CTL_UNNUMBERED,
         .procname = "max-user-freq",
         .data = &hpet_max_freq,
         .maxlen = sizeof(int),
@@ -715,7 +715,7 @@ static ctl_table hpet_table[] = {
 
 static ctl_table hpet_root[] = {
        {
-        .ctl_name = 1,
+        .ctl_name = CTL_UNNUMBERED,
         .procname = "hpet",
         .maxlen = 0,
         .mode = 0555,
@@ -1018,7 +1018,7 @@ static int __init hpet_init(void)
        if (result < 0)
                return -ENODEV;
 
-       sysctl_header = register_sysctl_table(dev_root, 0);
+       sysctl_header = register_sysctl_table(dev_root);
 
        result = acpi_bus_register_driver(&hpet_acpi_driver);
        if (result < 0) {
index d7806834fc171ad07f08c90f0e5b20a30c000987..50315d6364fdd98727133c9fa7930ea0aa755d0f 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/module.h>
 #include <linux/major.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
index ff2d052177cb9250c17198b66e5f510db1b52267..c2aa44ee6eb6d89848e68ee42e1b3cba4a799ab7 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <asm/system.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index 3aff5e99b674360bad4fa42407d70a9d594656e4..8e222f2b80cc4bb2ee28535e936fcd83d6fb397c 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <asm/system.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
index 9d23136e598a74ce54c4a52d6a250f8f8a6202b5..e02893b7b300907e8a1d18555c155c3b7283c8dc 100644 (file)
@@ -686,7 +686,7 @@ static int ipmi_poweroff_init (void)
                printk(KERN_INFO PFX "Power cycle is enabled.\n");
 
 #ifdef CONFIG_PROC_FS
-       ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
+       ipmi_table_header = register_sysctl_table(ipmi_root_table);
        if (!ipmi_table_header) {
                printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
                rv = -ENOMEM;
index a39f19c35a6a8bd6fa2673f916069039f6142b6a..204deaa0de80edb9f16ca0fd55923b13950924e0 100644 (file)
@@ -37,7 +37,6 @@
 #define NVRAM_VERSION  "1.2"
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/nvram.h>
 
index 206cf6f50695699be3fe865a5f024c1df9e640fe..ba012c2bdf7a3b8ceb136f32d0d24cede5037725 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
index c07a1b5cd05d3f31204fab9eb7810e9704d96e08..de14aea34e11f215765c8b718efe65ff595e795a 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>      /* For EXPORT_SYMBOL */
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
index 85c1618452605819fa2110f9a68cb208dc46df84..294e9cb0c449424cdb47761712cf2db51b7fb259 100644 (file)
@@ -1146,7 +1146,7 @@ static int __init rio_init(void)
                                rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
                                hp->Mode |= RIO_PCI_INT_ENABLE;
                        } else
-                               hp->Mode &= !RIO_PCI_INT_ENABLE;
+                               hp->Mode &= ~RIO_PCI_INT_ENABLE;
                        rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
                        rio_start_card_running(hp);
                }
index b6d3072dce5aabd956c5eef07c010f7ec8db7c7c..c7dac9b13351d2585aa6e911f7bf873cd89c0547 100644 (file)
@@ -282,7 +282,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id)
  */
 static ctl_table rtc_table[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "max-user-freq",
                .data           = &rtc_max_user_freq,
                .maxlen         = sizeof(int),
@@ -294,9 +294,8 @@ static ctl_table rtc_table[] = {
 
 static ctl_table rtc_root[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "rtc",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_table,
        },
@@ -307,7 +306,6 @@ static ctl_table dev_root[] = {
        {
                .ctl_name       = CTL_DEV,
                .procname       = "dev",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_root,
        },
@@ -318,7 +316,7 @@ static struct ctl_table_header *sysctl_header;
 
 static int __init init_sysctl(void)
 {
-    sysctl_header = register_sysctl_table(dev_root, 0);
+    sysctl_header = register_sysctl_table(dev_root);
     return 0;
 }
 
index 75de5f66517aeb81bf3cec37db24baebaa03379a..3c869145bfdcb1169ab41c4a49633051212ab964 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 17d54e1331b2ea61475534e8b294cd6e2ebb7e3d..78237577b05ac57790ac34aee0f601b8aae23aa7 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
index be73c80d699d5edc4570a5e09c83af3727bc333d..1d8c4ae615513e9d6dd54875ba2dbae57a87e0fb 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/workqueue.h>
 #include <linux/kexec.h>
 #include <linux/irq.h>
+#include <linux/hrtimer.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -158,6 +159,17 @@ static struct sysrq_key_op sysrq_sync_op = {
        .enable_mask    = SYSRQ_ENABLE_SYNC,
 };
 
+static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
+{
+       sysrq_timer_list_show();
+}
+
+static struct sysrq_key_op sysrq_show_timers_op = {
+       .handler        = sysrq_handle_show_timers,
+       .help_msg       = "show-all-timers(Q)",
+       .action_msg     = "Show Pending Timers",
+};
+
 static void sysrq_handle_mountro(int key, struct tty_struct *tty)
 {
        emergency_remount();
@@ -335,7 +347,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        /* o: This will often be registered as 'Off' at init time */
        NULL,                           /* o */
        &sysrq_showregs_op,             /* p */
-       NULL,                           /* q */
+       &sysrq_show_timers_op,          /* q */
        &sysrq_unraw_op,                /* r */
        &sysrq_sync_op,                 /* s */
        &sysrq_showstate_op,            /* t */
index 4fac2bdf62156e48fa036c2516ae42b2019aac33..35e58030d2968d38e7a039ef36a58bdf9fd4b3df 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>      /* printk() */
 #include <linux/fs.h>          /* everything... */
 #include <linux/errno.h>       /* error codes */
index c346ec5a3dc9e3eff49a992cc074f61a6bef9786..5422f999636fffff6e499a9b7242d52f9e733fa9 100644 (file)
@@ -58,7 +58,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/miscdevice.h>
index 2f572b97c16d94390adb7507b4cc4befc1f95adc..e5a254a434f8345696c806b35a8d4b2539ed44fe 100644 (file)
@@ -23,7 +23,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include "tpm.h"
index 26776517f04c7eaa0e705ec83aee988452fa4c6e..791930320a13c21e2a33c2f81b0c18b233463dba 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
index e01317cb1a0e08d4799582f5d7ecbad49765ef22..bef6d886d4fb2f6e3e2ea3b69ee1da3e29673b0c 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kdev_t.h>
 #include <asm/io.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
index b4678839d3bbaf4ca7dbb7f17968a0944c712369..5c921e471564778aeffcafe7c3b7afeb37757018 100644 (file)
@@ -192,7 +192,7 @@ static int wdt_gpi_open(struct inode *inode, struct file *file)
                locked = 0;
        }
 
-       res = request_irq(wd_irq, wdt_gpi_irqhdl, SA_SHIRQ | SA_INTERRUPT,
+       res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
                          wdt_gpi_name, &miscdev);
        if (unlikely(res))
                return res;
index b6bcdbbf57b3fe5ab0810fc6221fcab1d9b744ed..ccaa6a39cb4b8195a9f30dafc38a41f6de821028 100644 (file)
  * This file is licensed under the GPL v2.
  */
 
+#include <linux/acpi_pmtmr.h>
 #include <linux/clocksource.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 
-/* Number of PMTMR ticks expected during calibration run */
-#define PMTMR_TICKS_PER_SEC 3579545
-
 /*
  * The I/O port the PMTMR resides at.
  * The location is detected during setup_arch(),
  */
 u32 pmtmr_ioport __read_mostly;
 
-#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */
-
 static inline u32 read_pmtmr(void)
 {
        /* mask the output to 24 bits */
        return inl(pmtmr_ioport) & ACPI_PM_MASK;
 }
 
-static cycle_t acpi_pm_read_verified(void)
+u32 acpi_pm_read_verified(void)
 {
        u32 v1 = 0, v2 = 0, v3 = 0;
 
@@ -57,7 +53,12 @@ static cycle_t acpi_pm_read_verified(void)
        } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
                          || (v3 > v1 && v3 < v2)));
 
-       return (cycle_t)v2;
+       return v2;
+}
+
+static cycle_t acpi_pm_read_slow(void)
+{
+       return (cycle_t)acpi_pm_read_verified();
 }
 
 static cycle_t acpi_pm_read(void)
@@ -72,7 +73,8 @@ static struct clocksource clocksource_acpi_pm = {
        .mask           = (cycle_t)ACPI_PM_MASK,
        .mult           = 0, /*to be caluclated*/
        .shift          = 22,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+
 };
 
 
@@ -87,7 +89,7 @@ __setup("acpi_pm_good", acpi_pm_good_setup);
 
 static inline void acpi_pm_need_workaround(void)
 {
-       clocksource_acpi_pm.read = acpi_pm_read_verified;
+       clocksource_acpi_pm.read = acpi_pm_read_slow;
        clocksource_acpi_pm.rating = 110;
 }
 
index bf4d3d50d1c4e9a7c76c05f9b8476ebf3896f8c2..4f3925ceb36041a8cdbdaab80b0c330eebb28a61 100644 (file)
@@ -31,7 +31,7 @@ static struct clocksource clocksource_cyclone = {
        .mask           = CYCLONE_TIMER_MASK,
        .mult           = 10,
        .shift          = 0,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_cyclone_clocksource(void)
index 22915cc46ba7fbe56ef7e52896ce74c9490b8e7a..b92da677aa5d8e23673e192a8c5bcdf67ae46de0 100644 (file)
@@ -57,7 +57,7 @@ static struct clocksource cs_hrt = {
        .rating         = 250,
        .read           = read_hrt,
        .mask           = CLOCKSOURCE_MASK(32),
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
        /* mult, shift are set based on mhz27 flag */
 };
 
index 491779af8d556963e4e86a742af828bd6ea347e0..d155e81b5c97d5b6dc267d57897eada5a23ecf51 100644 (file)
@@ -16,7 +16,7 @@ config CPU_FREQ
 if CPU_FREQ
 
 config CPU_FREQ_TABLE
-       def_tristate m
+       tristate
 
 config CPU_FREQ_DEBUG
        bool "Enable CPUfreq debugging"
index a45cc89e387a3ee14ba2afcda2cb09ac5303b1f0..f52facc570f57c97841b7a4bd809f6929bbe88a8 100644 (file)
@@ -41,8 +41,67 @@ static struct cpufreq_driver *cpufreq_driver;
 static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
+/*
+ * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
+ * all cpufreq/hotplug/workqueue/etc related lock issues.
+ *
+ * The rules for this semaphore:
+ * - Any routine that wants to read from the policy structure will
+ *   do a down_read on this semaphore.
+ * - Any routine that will write to the policy structure and/or may take away
+ *   the policy altogether (eg. CPU hotplug), will hold this lock in write
+ *   mode before doing so.
+ *
+ * Additional rules:
+ * - All holders of the lock should check to make sure that the CPU they
+ *   are concerned with are online after they get the lock.
+ * - Governor routines that can be called in cpufreq hotplug path should not
+ *   take this sem as top level hotplug notifier handler takes this.
+ */
+static DEFINE_PER_CPU(int, policy_cpu);
+static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
+
+#define lock_policy_rwsem(mode, cpu)                                   \
+int lock_policy_rwsem_##mode                                           \
+(int cpu)                                                              \
+{                                                                      \
+       int policy_cpu = per_cpu(policy_cpu, cpu);                      \
+       BUG_ON(policy_cpu == -1);                                       \
+       down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));            \
+       if (unlikely(!cpu_online(cpu))) {                               \
+               up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));      \
+               return -1;                                              \
+       }                                                               \
+                                                                       \
+       return 0;                                                       \
+}
+
+lock_policy_rwsem(read, cpu);
+EXPORT_SYMBOL_GPL(lock_policy_rwsem_read);
+
+lock_policy_rwsem(write, cpu);
+EXPORT_SYMBOL_GPL(lock_policy_rwsem_write);
+
+void unlock_policy_rwsem_read(int cpu)
+{
+       int policy_cpu = per_cpu(policy_cpu, cpu);
+       BUG_ON(policy_cpu == -1);
+       up_read(&per_cpu(cpu_policy_rwsem, policy_cpu));
+}
+EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read);
+
+void unlock_policy_rwsem_write(int cpu)
+{
+       int policy_cpu = per_cpu(policy_cpu, cpu);
+       BUG_ON(policy_cpu == -1);
+       up_write(&per_cpu(cpu_policy_rwsem, policy_cpu));
+}
+EXPORT_SYMBOL_GPL(unlock_policy_rwsem_write);
+
+
 /* internal prototypes */
 static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
+static unsigned int __cpufreq_get(unsigned int cpu);
 static void handle_update(struct work_struct *work);
 
 /**
@@ -415,12 +474,8 @@ static ssize_t store_##file_name                                   \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
-       lock_cpu_hotplug();                                             \
-       mutex_lock(&policy->lock);                                      \
        ret = __cpufreq_set_policy(policy, &new_policy);                \
        policy->user_policy.object = policy->object;                    \
-       mutex_unlock(&policy->lock);                                    \
-       unlock_cpu_hotplug();                                           \
                                                                        \
        return ret ? ret : count;                                       \
 }
@@ -434,7 +489,7 @@ store_one(scaling_max_freq,max);
 static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
                                                        char *buf)
 {
-       unsigned int cur_freq = cpufreq_get(policy->cpu);
+       unsigned int cur_freq = __cpufreq_get(policy->cpu);
        if (!cur_freq)
                return sprintf(buf, "<unknown>");
        return sprintf(buf, "%u\n", cur_freq);
@@ -479,18 +534,12 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
                                                &new_policy.governor))
                return -EINVAL;
 
-       lock_cpu_hotplug();
-
        /* Do not use cpufreq_set_policy here or the user_policy.max
           will be wrongly overridden */
-       mutex_lock(&policy->lock);
        ret = __cpufreq_set_policy(policy, &new_policy);
 
        policy->user_policy.policy = policy->policy;
        policy->user_policy.governor = policy->governor;
-       mutex_unlock(&policy->lock);
-
-       unlock_cpu_hotplug();
 
        if (ret)
                return ret;
@@ -595,11 +644,17 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
                return -EINVAL;
+
+       if (lock_policy_rwsem_read(policy->cpu) < 0)
+               return -EINVAL;
+
        if (fattr->show)
                ret = fattr->show(policy, buf);
        else
                ret = -EIO;
 
+       unlock_policy_rwsem_read(policy->cpu);
+
        cpufreq_cpu_put(policy);
        return ret;
 }
@@ -613,11 +668,17 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
                return -EINVAL;
+
+       if (lock_policy_rwsem_write(policy->cpu) < 0)
+               return -EINVAL;
+
        if (fattr->store)
                ret = fattr->store(policy, buf, count);
        else
                ret = -EIO;
 
+       unlock_policy_rwsem_write(policy->cpu);
+
        cpufreq_cpu_put(policy);
        return ret;
 }
@@ -691,8 +752,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        policy->cpu = cpu;
        policy->cpus = cpumask_of_cpu(cpu);
 
-       mutex_init(&policy->lock);
-       mutex_lock(&policy->lock);
+       /* Initially set CPU itself as the policy_cpu */
+       per_cpu(policy_cpu, cpu) = cpu;
+       lock_policy_rwsem_write(cpu);
+
        init_completion(&policy->kobj_unregister);
        INIT_WORK(&policy->update, handle_update);
 
@@ -702,7 +765,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        ret = cpufreq_driver->init(policy);
        if (ret) {
                dprintk("initialization failed\n");
-               mutex_unlock(&policy->lock);
+               unlock_policy_rwsem_write(cpu);
                goto err_out;
        }
 
@@ -716,6 +779,14 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                 */
                managed_policy = cpufreq_cpu_get(j);
                if (unlikely(managed_policy)) {
+
+                       /* Set proper policy_cpu */
+                       unlock_policy_rwsem_write(cpu);
+                       per_cpu(policy_cpu, cpu) = managed_policy->cpu;
+
+                       if (lock_policy_rwsem_write(cpu) < 0)
+                               goto err_out_driver_exit;
+
                        spin_lock_irqsave(&cpufreq_driver_lock, flags);
                        managed_policy->cpus = policy->cpus;
                        cpufreq_cpu_data[cpu] = managed_policy;
@@ -726,13 +797,13 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                                                &managed_policy->kobj,
                                                "cpufreq");
                        if (ret) {
-                               mutex_unlock(&policy->lock);
+                               unlock_policy_rwsem_write(cpu);
                                goto err_out_driver_exit;
                        }
 
                        cpufreq_debug_enable_ratelimit();
-                       mutex_unlock(&policy->lock);
                        ret = 0;
+                       unlock_policy_rwsem_write(cpu);
                        goto err_out_driver_exit; /* call driver->exit() */
                }
        }
@@ -746,7 +817,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
 
        ret = kobject_register(&policy->kobj);
        if (ret) {
-               mutex_unlock(&policy->lock);
+               unlock_policy_rwsem_write(cpu);
                goto err_out_driver_exit;
        }
        /* set up files for this cpu device */
@@ -761,8 +832,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
 
        spin_lock_irqsave(&cpufreq_driver_lock, flags);
-       for_each_cpu_mask(j, policy->cpus)
+       for_each_cpu_mask(j, policy->cpus) {
                cpufreq_cpu_data[j] = policy;
+               per_cpu(policy_cpu, j) = policy->cpu;
+       }
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
        /* symlink affected CPUs */
@@ -778,14 +851,14 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
                                        "cpufreq");
                if (ret) {
-                       mutex_unlock(&policy->lock);
+                       unlock_policy_rwsem_write(cpu);
                        goto err_out_unregister;
                }
        }
 
        policy->governor = NULL; /* to assure that the starting sequence is
                                  * run in cpufreq_set_policy */
-       mutex_unlock(&policy->lock);
+       unlock_policy_rwsem_write(cpu);
 
        /* set default policy */
        ret = cpufreq_set_policy(&new_policy);
@@ -826,11 +899,13 @@ module_out:
 
 
 /**
- * cpufreq_remove_dev - remove a CPU device
+ * __cpufreq_remove_dev - remove a CPU device
  *
  * Removes the cpufreq interface for a CPU device.
+ * Caller should already have policy_rwsem in write mode for this CPU.
+ * This routine frees the rwsem before returning.
  */
-static int cpufreq_remove_dev (struct sys_device * sys_dev)
+static int __cpufreq_remove_dev (struct sys_device * sys_dev)
 {
        unsigned int cpu = sys_dev->id;
        unsigned long flags;
@@ -849,6 +924,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
        if (!data) {
                spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
                cpufreq_debug_enable_ratelimit();
+               unlock_policy_rwsem_write(cpu);
                return -EINVAL;
        }
        cpufreq_cpu_data[cpu] = NULL;
@@ -865,6 +941,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
                sysfs_remove_link(&sys_dev->kobj, "cpufreq");
                cpufreq_cpu_put(data);
                cpufreq_debug_enable_ratelimit();
+               unlock_policy_rwsem_write(cpu);
                return 0;
        }
 #endif
@@ -873,6 +950,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
        if (!kobject_get(&data->kobj)) {
                spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
                cpufreq_debug_enable_ratelimit();
+               unlock_policy_rwsem_write(cpu);
                return -EFAULT;
        }
 
@@ -906,10 +984,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       mutex_lock(&data->lock);
        if (cpufreq_driver->target)
                __cpufreq_governor(data, CPUFREQ_GOV_STOP);
-       mutex_unlock(&data->lock);
+
+       unlock_policy_rwsem_write(cpu);
 
        kobject_unregister(&data->kobj);
 
@@ -933,6 +1011,18 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
 }
 
 
+static int cpufreq_remove_dev (struct sys_device * sys_dev)
+{
+       unsigned int cpu = sys_dev->id;
+       int retval;
+       if (unlikely(lock_policy_rwsem_write(cpu)))
+               BUG();
+
+       retval = __cpufreq_remove_dev(sys_dev);
+       return retval;
+}
+
+
 static void handle_update(struct work_struct *work)
 {
        struct cpufreq_policy *policy =
@@ -980,9 +1070,12 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
        unsigned int ret_freq = 0;
 
        if (policy) {
-               mutex_lock(&policy->lock);
+               if (unlikely(lock_policy_rwsem_read(cpu)))
+                       return ret_freq;
+
                ret_freq = policy->cur;
-               mutex_unlock(&policy->lock);
+
+               unlock_policy_rwsem_read(cpu);
                cpufreq_cpu_put(policy);
        }
 
@@ -991,24 +1084,13 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
 EXPORT_SYMBOL(cpufreq_quick_get);
 
 
-/**
- * cpufreq_get - get the current CPU frequency (in kHz)
- * @cpu: CPU number
- *
- * Get the CPU current (static) CPU frequency
- */
-unsigned int cpufreq_get(unsigned int cpu)
+static unsigned int __cpufreq_get(unsigned int cpu)
 {
-       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       struct cpufreq_policy *policy = cpufreq_cpu_data[cpu];
        unsigned int ret_freq = 0;
 
-       if (!policy)
-               return 0;
-
        if (!cpufreq_driver->get)
-               goto out;
-
-       mutex_lock(&policy->lock);
+               return (ret_freq);
 
        ret_freq = cpufreq_driver->get(cpu);
 
@@ -1022,11 +1104,33 @@ unsigned int cpufreq_get(unsigned int cpu)
                }
        }
 
-       mutex_unlock(&policy->lock);
+       return (ret_freq);
+}
 
-out:
-       cpufreq_cpu_put(policy);
+/**
+ * cpufreq_get - get the current CPU frequency (in kHz)
+ * @cpu: CPU number
+ *
+ * Get the CPU current (static) CPU frequency
+ */
+unsigned int cpufreq_get(unsigned int cpu)
+{
+       unsigned int ret_freq = 0;
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+
+       if (!policy)
+               goto out;
+
+       if (unlikely(lock_policy_rwsem_read(cpu)))
+               goto out_policy;
+
+       ret_freq = __cpufreq_get(cpu);
 
+       unlock_policy_rwsem_read(cpu);
+
+out_policy:
+       cpufreq_cpu_put(policy);
+out:
        return (ret_freq);
 }
 EXPORT_SYMBOL(cpufreq_get);
@@ -1278,7 +1382,6 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
  *********************************************************************/
 
 
-/* Must be called with lock_cpu_hotplug held */
 int __cpufreq_driver_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
@@ -1304,20 +1407,19 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
        if (!policy)
                return -EINVAL;
 
-       lock_cpu_hotplug();
-       mutex_lock(&policy->lock);
+       if (unlikely(lock_policy_rwsem_write(policy->cpu)))
+               return -EINVAL;
 
        ret = __cpufreq_driver_target(policy, target_freq, relation);
 
-       mutex_unlock(&policy->lock);
-       unlock_cpu_hotplug();
+       unlock_policy_rwsem_write(policy->cpu);
 
        cpufreq_cpu_put(policy);
        return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-int cpufreq_driver_getavg(struct cpufreq_policy *policy)
+int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
 {
        int ret = 0;
 
@@ -1325,20 +1427,15 @@ int cpufreq_driver_getavg(struct cpufreq_policy *policy)
        if (!policy)
                return -EINVAL;
 
-       mutex_lock(&policy->lock);
-
        if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
                ret = cpufreq_driver->getavg(policy->cpu);
 
-       mutex_unlock(&policy->lock);
-
        cpufreq_cpu_put(policy);
        return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_driver_getavg);
+EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
 
 /*
- * Locking: Must be called with the lock_cpu_hotplug() lock held
  * when "event" is CPUFREQ_GOV_LIMITS
  */
 
@@ -1420,9 +1517,7 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
        if (!cpu_policy)
                return -EINVAL;
 
-       mutex_lock(&cpu_policy->lock);
        memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
-       mutex_unlock(&cpu_policy->lock);
 
        cpufreq_cpu_put(cpu_policy);
        return 0;
@@ -1433,7 +1528,6 @@ EXPORT_SYMBOL(cpufreq_get_policy);
 /*
  * data   : current policy.
  * policy : policy to be set.
- * Locking: Must be called with the lock_cpu_hotplug() lock held
  */
 static int __cpufreq_set_policy(struct cpufreq_policy *data,
                                struct cpufreq_policy *policy)
@@ -1539,10 +1633,9 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
        if (!data)
                return -EINVAL;
 
-       lock_cpu_hotplug();
+       if (unlikely(lock_policy_rwsem_write(policy->cpu)))
+               return -EINVAL;
 
-       /* lock this CPU */
-       mutex_lock(&data->lock);
 
        ret = __cpufreq_set_policy(data, policy);
        data->user_policy.min = data->min;
@@ -1550,9 +1643,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
        data->user_policy.policy = data->policy;
        data->user_policy.governor = data->governor;
 
-       mutex_unlock(&data->lock);
+       unlock_policy_rwsem_write(policy->cpu);
 
-       unlock_cpu_hotplug();
        cpufreq_cpu_put(data);
 
        return ret;
@@ -1576,8 +1668,8 @@ int cpufreq_update_policy(unsigned int cpu)
        if (!data)
                return -ENODEV;
 
-       lock_cpu_hotplug();
-       mutex_lock(&data->lock);
+       if (unlikely(lock_policy_rwsem_write(cpu)))
+               return -EINVAL;
 
        dprintk("updating policy for CPU %u\n", cpu);
        memcpy(&policy, data, sizeof(struct cpufreq_policy));
@@ -1602,8 +1694,8 @@ int cpufreq_update_policy(unsigned int cpu)
 
        ret = __cpufreq_set_policy(data, &policy);
 
-       mutex_unlock(&data->lock);
-       unlock_cpu_hotplug();
+       unlock_policy_rwsem_write(cpu);
+
        cpufreq_cpu_put(data);
        return ret;
 }
@@ -1613,31 +1705,28 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
-       struct cpufreq_policy *policy;
        struct sys_device *sys_dev;
+       struct cpufreq_policy *policy;
 
        sys_dev = get_cpu_sysdev(cpu);
-
        if (sys_dev) {
                switch (action) {
                case CPU_ONLINE:
                        cpufreq_add_dev(sys_dev);
                        break;
                case CPU_DOWN_PREPARE:
-                       /*
-                        * We attempt to put this cpu in lowest frequency
-                        * possible before going down. This will permit
-                        * hardware-managed P-State to switch other related
-                        * threads to min or higher speeds if possible.
-                        */
+                       if (unlikely(lock_policy_rwsem_write(cpu)))
+                               BUG();
+
                        policy = cpufreq_cpu_data[cpu];
                        if (policy) {
-                               cpufreq_driver_target(policy, policy->min,
+                               __cpufreq_driver_target(policy, policy->min,
                                                CPUFREQ_RELATION_H);
                        }
+                       __cpufreq_remove_dev(sys_dev);
                        break;
-               case CPU_DEAD:
-                       cpufreq_remove_dev(sys_dev);
+               case CPU_DOWN_FAILED:
+                       cpufreq_add_dev(sys_dev);
                        break;
                }
        }
@@ -1751,3 +1840,16 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
        return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
+
+static int __init cpufreq_core_init(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               per_cpu(policy_cpu, cpu) = -1;
+               init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
+       }
+       return 0;
+}
+
+core_initcall(cpufreq_core_init);
index eef0270c6f3ddf98b23b3495628a60894199ec10..26f440ccc3fb358e9525ecabee819ae52b7afa26 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/cpu.h>
-#include <linux/sched.h>
 #include <linux/kmod.h>
 #include <linux/workqueue.h>
 #include <linux/jiffies.h>
@@ -430,14 +429,12 @@ static void dbs_check_cpu(int cpu)
 static void do_dbs_timer(struct work_struct *work)
 { 
        int i;
-       lock_cpu_hotplug();
        mutex_lock(&dbs_mutex);
        for_each_online_cpu(i)
                dbs_check_cpu(i);
        schedule_delayed_work(&dbs_work, 
                        usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
        mutex_unlock(&dbs_mutex);
-       unlock_cpu_hotplug();
 } 
 
 static inline void dbs_timer_init(void)
index f697449327c6fca54f856189801965861855f6a6..d60bcb9d14ccd811c72fee221ebf894e8c695efc 100644 (file)
@@ -52,19 +52,20 @@ static unsigned int def_sampling_rate;
 static void do_dbs_timer(struct work_struct *work);
 
 /* Sampling types */
-enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
+enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
 
 struct cpu_dbs_info_s {
        cputime64_t prev_cpu_idle;
        cputime64_t prev_cpu_wall;
        struct cpufreq_policy *cur_policy;
        struct delayed_work work;
-       enum dbs_sample sample_type;
-       unsigned int enable;
        struct cpufreq_frequency_table *freq_table;
        unsigned int freq_lo;
        unsigned int freq_lo_jiffies;
        unsigned int freq_hi_jiffies;
+       int cpu;
+       unsigned int enable:1,
+                    sample_type:1;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
@@ -402,7 +403,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
        if (load < (dbs_tuners_ins.up_threshold - 10)) {
                unsigned int freq_next, freq_cur;
 
-               freq_cur = cpufreq_driver_getavg(policy);
+               freq_cur = __cpufreq_driver_getavg(policy);
                if (!freq_cur)
                        freq_cur = policy->cur;
 
@@ -423,9 +424,11 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 
 static void do_dbs_timer(struct work_struct *work)
 {
-       unsigned int cpu = smp_processor_id();
-       struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
-       enum dbs_sample sample_type = dbs_info->sample_type;
+       struct cpu_dbs_info_s *dbs_info =
+               container_of(work, struct cpu_dbs_info_s, work.work);
+       unsigned int cpu = dbs_info->cpu;
+       int sample_type = dbs_info->sample_type;
+
        /* We want all CPUs to do sampling nearly on same jiffy */
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 
@@ -434,15 +437,19 @@ static void do_dbs_timer(struct work_struct *work)
 
        delay -= jiffies % delay;
 
-       if (!dbs_info->enable)
+       if (lock_policy_rwsem_write(cpu) < 0)
+               return;
+
+       if (!dbs_info->enable) {
+               unlock_policy_rwsem_write(cpu);
                return;
+       }
+
        /* Common NORMAL_SAMPLE setup */
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        if (!dbs_tuners_ins.powersave_bias ||
            sample_type == DBS_NORMAL_SAMPLE) {
-               lock_cpu_hotplug();
                dbs_check_cpu(dbs_info);
-               unlock_cpu_hotplug();
                if (dbs_info->freq_lo) {
                        /* Setup timer for SUB_SAMPLE */
                        dbs_info->sample_type = DBS_SUB_SAMPLE;
@@ -454,26 +461,27 @@ static void do_dbs_timer(struct work_struct *work)
                                        CPUFREQ_RELATION_H);
        }
        queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+       unlock_policy_rwsem_write(cpu);
 }
 
-static inline void dbs_timer_init(unsigned int cpu)
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 {
-       struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
        /* We want all CPUs to do sampling nearly on same jiffy */
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
        delay -= jiffies % delay;
 
+       dbs_info->enable = 1;
        ondemand_powersave_bias_init();
-       INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-       queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+       INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
+       queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
+                             delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
 {
        dbs_info->enable = 0;
        cancel_delayed_work(&dbs_info->work);
-       flush_workqueue(kondemand_wq);
 }
 
 static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -502,21 +510,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
                mutex_lock(&dbs_mutex);
                dbs_enable++;
-               if (dbs_enable == 1) {
-                       kondemand_wq = create_workqueue("kondemand");
-                       if (!kondemand_wq) {
-                               printk(KERN_ERR
-                                        "Creation of kondemand failed\n");
-                               dbs_enable--;
-                               mutex_unlock(&dbs_mutex);
-                               return -ENOSPC;
-                       }
-               }
 
                rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
                if (rc) {
-                       if (dbs_enable == 1)
-                               destroy_workqueue(kondemand_wq);
                        dbs_enable--;
                        mutex_unlock(&dbs_mutex);
                        return rc;
@@ -530,7 +526,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
                        j_dbs_info->prev_cpu_wall = get_jiffies_64();
                }
-               this_dbs_info->enable = 1;
+               this_dbs_info->cpu = cpu;
                /*
                 * Start the timerschedule work, when this governor
                 * is used for first time
@@ -550,7 +546,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
                        dbs_tuners_ins.sampling_rate = def_sampling_rate;
                }
-               dbs_timer_init(policy->cpu);
+               dbs_timer_init(this_dbs_info);
 
                mutex_unlock(&dbs_mutex);
                break;
@@ -560,9 +556,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                dbs_timer_exit(this_dbs_info);
                sysfs_remove_group(&policy->kobj, &dbs_attr_group);
                dbs_enable--;
-               if (dbs_enable == 0)
-                       destroy_workqueue(kondemand_wq);
-
                mutex_unlock(&dbs_mutex);
 
                break;
@@ -591,12 +584,18 @@ static struct cpufreq_governor cpufreq_gov_dbs = {
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+       kondemand_wq = create_workqueue("kondemand");
+       if (!kondemand_wq) {
+               printk(KERN_ERR "Creation of kondemand failed\n");
+               return -EFAULT;
+       }
        return cpufreq_register_governor(&cpufreq_gov_dbs);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
        cpufreq_unregister_governor(&cpufreq_gov_dbs);
+       destroy_workqueue(kondemand_wq);
 }
 
 
@@ -608,3 +607,4 @@ MODULE_LICENSE("GPL");
 
 module_init(cpufreq_gov_dbs_init);
 module_exit(cpufreq_gov_dbs_exit);
+
index 91ad342a6051f19e64f5e00478cf2a5f8ab7e9a7..d1c7cac9316cc4e7729f8445c9ba8ebc07d858b7 100644 (file)
@@ -370,12 +370,10 @@ __exit cpufreq_stats_exit(void)
        cpufreq_unregister_notifier(&notifier_trans_block,
                        CPUFREQ_TRANSITION_NOTIFIER);
        unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
-       lock_cpu_hotplug();
        for_each_online_cpu(cpu) {
                cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier,
                                                CPU_DEAD, (void *)(long)cpu);
        }
-       unlock_cpu_hotplug();
 }
 
 MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
index 2a4eb0bfaf30d2cd6698a2c72d9e67468e6d08b5..860345c7799ab1188c21945756ec6e696019b10e 100644 (file)
@@ -71,7 +71,6 @@ static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
 
        dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
-       lock_cpu_hotplug();
        mutex_lock(&userspace_mutex);
        if (!cpu_is_managed[policy->cpu])
                goto err;
@@ -94,7 +93,6 @@ static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
 
  err:
        mutex_unlock(&userspace_mutex);
-       unlock_cpu_hotplug();
        return ret;
 }
 
index 31ea405f2eeb5fbe8d8fdb94b0f785f58729208f..0eb62841e9b0bd6f207bdb0c159709318919bff4 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/crypto.h>
index 8700a8076d0482df55c2cd8e379d603e7873e918..bd3918ddf7ac00619046d5d0550428a801f41392 100644 (file)
@@ -6,7 +6,6 @@
 
 #ifdef CONFIG_MODULES
 
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
index b09dfc78e5a2b10d34965ede7329ed7a8a311652..d517734462e6c3cf9bcd23e67d93db029054a4bc 100644 (file)
@@ -22,7 +22,6 @@ static char *version =
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index a6b1ae256e16b4006373233bb18afdce83d09d98..c903ebfab526e6416bbb915654fcc3f391a4575f 100644 (file)
@@ -17,7 +17,6 @@ static char *version =
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 8c7d48eff7b7a6339db159b901987e5ca12c3815..7452399501b42a0fe006eb5d438126e4ec966933 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
index 0b0a87b8d1079f2755a3bfd902d1cb6e4a130f53..1e277ba5a9f34aaa3f2f6beee5704c447d79edd0 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
@@ -495,7 +494,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
                return -ENODEV;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        ali1535_adapter.dev.parent = &dev->dev;
 
        snprintf(ali1535_adapter.name, I2C_NAME_SIZE, 
index c537441ac0383ca825ca60b15bfae9d8bcd08b47..e47fe01bf42ae5c0bd73fcf215e8a1c01d361e66 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -490,7 +489,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
                return -ENODEV;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        ali15x3_adapter.dev.parent = &dev->dev;
 
        snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,
index 91fbc0ee439cc85b94b30fb3818b53790a164bb3..7490dc1771ae11f4e1335d53aff103549f0515c5 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -375,7 +374,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
        dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
        dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport);
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        amd756_smbus.dev.parent = &pdev->dev;
 
        sprintf(amd756_smbus.name, "SMBus %s adapter at %04x",
index 14ad9912f204550e88624e7b643c782f1e2f6af8..e15f9e37716ada1b65ac7f4a2e3561e312dc097e 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -372,7 +371,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        smbus->adapter.dev.parent = &dev->dev;
 
        pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
index 8c3569a9775b79d1d9cb935c505abd07856a3669..6569a36985bdf19f8326e65237e567f3643c618e 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -523,7 +522,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
        else
                dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        i801_adapter.dev.parent = &dev->dev;
 
        snprintf(i801_adapter.name, I2C_NAME_SIZE,
index d108ab4974cc222bfb433b585868ba6b2f48b3af..90e2d9350c1bd12d390a2495872c837cc5959a5f 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 
@@ -84,7 +83,7 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
         * Every time unit enable is asserted, GPOD needs to be cleared
         * on IOP3XX to avoid data corruption on the bus.
         */
-#ifdef CONFIG_PLAT_IOP
+#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
        if (iop3xx_adap->id == 0) {
                gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
                gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
index 653555184a6467d19db716ca7cd4ff97a8ef71dc..1514ec5b77f8e82f72a66ffc27ff8dc3f8414f7b 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
index f28a76d1c0af2f0ee5bcc30f6dc65a363a0ac23d..e417c2c3ca22af0fa2520878ff07798a417ffad0 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
index 03d0aeea0189baadf42de61c5fecc44cb5de9087..21b180904085e433cd69923d49dc304b5c19497c 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -426,7 +425,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
        if (retval)
                return retval;
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        piix4_adapter.dev.parent = &dev->dev;
 
        snprintf(piix4_adapter.name, I2C_NAME_SIZE,
index c3b1567c852a711595c1dbd4ac2575afe7d83044..14e83d0aac8c8fcc94372710f53067bd5a4ddad9 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/arch/i2c.h>
 #include <asm/arch/pxa-regs.h>
 
@@ -54,8 +55,21 @@ struct pxa_i2c {
        unsigned int            irqlogidx;
        u32                     isrlog[32];
        u32                     icrlog[32];
+
+       void __iomem            *reg_base;
+
+       unsigned long           iobase;
+       unsigned long           iosize;
+
+       int                     irq;
 };
 
+#define _IBMR(i2c)     ((i2c)->reg_base + 0)
+#define _IDBR(i2c)     ((i2c)->reg_base + 8)
+#define _ICR(i2c)      ((i2c)->reg_base + 0x10)
+#define _ISR(i2c)      ((i2c)->reg_base + 0x18)
+#define _ISAR(i2c)     ((i2c)->reg_base + 0x20)
+
 /*
  * I2C Slave mode address
  */
@@ -130,7 +144,8 @@ static unsigned int i2c_debug = DEBUG;
 
 static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
 {
-       dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
+       dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno,
+               readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 }
 
 #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
@@ -153,7 +168,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
        printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
                i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
        printk("i2c: ICR: %08x ISR: %08x\n"
-              "i2c: log: ", ICR, ISR);
+              "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
        for (i = 0; i < i2c->irqlogidx; i++)
                printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
        printk("\n");
@@ -161,7 +176,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 
 static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
 {
-       return !(ICR & ICR_SCLE);
+       return !(readl(_ICR(i2c)) & ICR_SCLE);
 }
 
 static void i2c_pxa_abort(struct pxa_i2c *i2c)
@@ -173,28 +188,29 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c)
                return;
        }
 
-       while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) {
-               unsigned long icr = ICR;
+       while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) {
+               unsigned long icr = readl(_ICR(i2c));
 
                icr &= ~ICR_START;
                icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
 
-               ICR = icr;
+               writel(icr, _ICR(i2c));
 
                show_state(i2c);
 
                msleep(1);
        }
 
-       ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+       writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
+              _ICR(i2c));
 }
 
 static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 {
        int timeout = DEF_TIMEOUT;
 
-       while (timeout-- && ISR & (ISR_IBB | ISR_UB)) {
-               if ((ISR & ISR_SAD) != 0)
+       while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
+               if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
                        timeout += 4;
 
                msleep(2);
@@ -214,9 +230,9 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
        while (time_before(jiffies, timeout)) {
                if (i2c_debug > 1)
                        dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-                               __func__, (long)jiffies, ISR, ICR, IBMR);
+                               __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 
-               if (ISR & ISR_SAD) {
+               if (readl(_ISR(i2c)) & ISR_SAD) {
                        if (i2c_debug > 0)
                                dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
                        goto out;
@@ -226,7 +242,7 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
                 * quick check of the i2c lines themselves to ensure they've
                 * gone high...
                 */
-               if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) {
+               if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) {
                        if (i2c_debug > 0)
                                dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
                        return 1;
@@ -246,7 +262,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
        if (i2c_debug)
                dev_dbg(&i2c->adap.dev, "setting to bus master\n");
 
-       if ((ISR & (ISR_UB | ISR_IBB)) != 0) {
+       if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
                dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
                if (!i2c_pxa_wait_master(i2c)) {
                        dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
@@ -254,7 +270,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
                }
        }
 
-       ICR |= ICR_SCLE;
+       writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
        return 0;
 }
 
@@ -270,11 +286,11 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
        while (time_before(jiffies, timeout)) {
                if (i2c_debug > 1)
                        dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-                               __func__, (long)jiffies, ISR, ICR, IBMR);
+                               __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 
-               if ((ISR & (ISR_UB|ISR_IBB)) == 0 ||
-                   (ISR & ISR_SAD) != 0 ||
-                   (ICR & ICR_SCLE) == 0) {
+               if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
+                   (readl(_ISR(i2c)) & ISR_SAD) != 0 ||
+                   (readl(_ICR(i2c)) & ICR_SCLE) == 0) {
                        if (i2c_debug > 1)
                                dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
                        return 1;
@@ -302,9 +318,9 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
                /* we need to wait for the stop condition to end */
 
                /* if we where in stop, then clear... */
-               if (ICR & ICR_STOP) {
+               if (readl(_ICR(i2c)) & ICR_STOP) {
                        udelay(100);
-                       ICR &= ~ICR_STOP;
+                       writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c));
                }
 
                if (!i2c_pxa_wait_slave(i2c)) {
@@ -314,12 +330,12 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
                }
        }
 
-       ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA);
-       ICR &= ~ICR_SCLE;
+       writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c));
+       writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 
        if (i2c_debug) {
-               dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR);
-               decode_ICR(ICR);
+               dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c)));
+               decode_ICR(readl(_ICR(i2c)));
        }
 }
 #else
@@ -334,24 +350,24 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
        i2c_pxa_abort(i2c);
 
        /* reset according to 9.8 */
-       ICR = ICR_UR;
-       ISR = I2C_ISR_INIT;
-       ICR &= ~ICR_UR;
+       writel(ICR_UR, _ICR(i2c));
+       writel(I2C_ISR_INIT, _ISR(i2c));
+       writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
 
-       ISAR = i2c->slave_addr;
+       writel(i2c->slave_addr, _ISAR(i2c));
 
        /* set control register values */
-       ICR = I2C_ICR_INIT;
+       writel(I2C_ICR_INIT, _ICR(i2c));
 
 #ifdef CONFIG_I2C_PXA_SLAVE
        dev_info(&i2c->adap.dev, "Enabling slave mode\n");
-       ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE;
+       writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
 #endif
 
        i2c_pxa_set_slave(i2c, 0);
 
        /* enable unit */
-       ICR |= ICR_IUE;
+       writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
        udelay(100);
 }
 
@@ -371,19 +387,19 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
                if (i2c->slave != NULL)
                        ret = i2c->slave->read(i2c->slave->data);
 
-               IDBR = ret;
-               ICR |= ICR_TB;   /* allow next byte */
+               writel(ret, _IDBR(i2c));
+               writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));   /* allow next byte */
        }
 }
 
 static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-       unsigned int byte = IDBR;
+       unsigned int byte = readl(_IDBR(i2c));
 
        if (i2c->slave != NULL)
                i2c->slave->write(i2c->slave->data, byte);
 
-       ICR |= ICR_TB;
+       writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -403,13 +419,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
         * start condition... if this happens, we'd better back off
         * and stop holding the poor thing up
         */
-       ICR &= ~(ICR_START|ICR_STOP);
-       ICR |= ICR_TB;
+       writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+       writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
 
        timeout = 0x10000;
 
        while (1) {
-               if ((IBMR & 2) == 2)
+               if ((readl(_IBMR(i2c)) & 2) == 2)
                        break;
 
                timeout--;
@@ -420,7 +436,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
                }
        }
 
-       ICR &= ~ICR_SCLE;
+       writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -447,14 +463,14 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
        if (isr & ISR_BED) {
                /* what should we do here? */
        } else {
-               IDBR = 0;
-               ICR |= ICR_TB;
+               writel(0, _IDBR(i2c));
+               writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
        }
 }
 
 static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-       ICR |= ICR_TB | ICR_ACKNAK;
+       writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -466,13 +482,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
         * start condition... if this happens, we'd better back off
         * and stop holding the poor thing up
         */
-       ICR &= ~(ICR_START|ICR_STOP);
-       ICR |= ICR_TB | ICR_ACKNAK;
+       writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+       writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
 
        timeout = 0x10000;
 
        while (1) {
-               if ((IBMR & 2) == 2)
+               if ((readl(_IBMR(i2c)) & 2) == 2)
                        break;
 
                timeout--;
@@ -483,7 +499,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
                }
        }
 
-       ICR &= ~ICR_SCLE;
+       writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -514,13 +530,13 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
        /*
         * Step 1: target slave address into IDBR
         */
-       IDBR = i2c_pxa_addr_byte(i2c->msg);
+       writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
 
        /*
         * Step 2: initiate the write.
         */
-       icr = ICR & ~(ICR_STOP | ICR_ALDIE);
-       ICR = icr | ICR_START | ICR_TB;
+       icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
+       writel(icr | ICR_START | ICR_TB, _ICR(i2c));
 }
 
 /*
@@ -594,7 +610,7 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
 
 static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
 {
-       u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+       u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
 
  again:
        /*
@@ -645,7 +661,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
                /*
                 * Write mode.  Write the next data byte.
                 */
-               IDBR = i2c->msg->buf[i2c->msg_ptr++];
+               writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
 
                icr |= ICR_ALDIE | ICR_TB;
 
@@ -675,7 +691,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
                /*
                 * Write the next address.
                 */
-               IDBR = i2c_pxa_addr_byte(i2c->msg);
+               writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
 
                /*
                 * And trigger a repeated start, and send the byte.
@@ -696,18 +712,18 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
 
        i2c->icrlog[i2c->irqlogidx-1] = icr;
 
-       ICR = icr;
+       writel(icr, _ICR(i2c));
        show_state(i2c);
 }
 
 static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-       u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+       u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
 
        /*
         * Read the byte.
         */
-       i2c->msg->buf[i2c->msg_ptr++] = IDBR;
+       i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c));
 
        if (i2c->msg_ptr < i2c->msg->len) {
                /*
@@ -724,17 +740,17 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
 
        i2c->icrlog[i2c->irqlogidx-1] = icr;
 
-       ICR = icr;
+       writel(icr, _ICR(i2c));
 }
 
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 {
        struct pxa_i2c *i2c = dev_id;
-       u32 isr = ISR;
+       u32 isr = readl(_ISR(i2c));
 
        if (i2c_debug > 2 && 0) {
                dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-                       __func__, isr, ICR, IBMR);
+                       __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
                decode_ISR(isr);
        }
 
@@ -746,7 +762,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
        /*
         * Always clear all pending IRQs.
         */
-       ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED);
+       writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
 
        if (isr & ISR_SAD)
                i2c_pxa_slave_start(i2c, isr);
@@ -779,7 +795,7 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
        /* If the I2C controller is disabled we need to reset it (probably due
           to a suspend/resume destroying state). We do this here as we can then
           avoid worrying about resuming the controller before its users. */
-       if (!(ICR & ICR_IUE))
+       if (!(readl(_ICR(i2c)) & ICR_IUE))
                i2c_pxa_reset(i2c);
 
        for (i = adap->retries; i >= 0; i--) {
@@ -810,28 +826,53 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
 
 static struct pxa_i2c i2c_pxa = {
        .lock   = SPIN_LOCK_UNLOCKED,
-       .wait   = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
        .adap   = {
                .owner          = THIS_MODULE,
                .algo           = &i2c_pxa_algorithm,
-               .name           = "pxa2xx-i2c",
+               .name           = "pxa2xx-i2c.0",
                .retries        = 5,
        },
 };
 
+#define res_len(r)             ((r)->end - (r)->start + 1)
 static int i2c_pxa_probe(struct platform_device *dev)
 {
        struct pxa_i2c *i2c = &i2c_pxa;
+       struct resource *res;
 #ifdef CONFIG_I2C_PXA_SLAVE
        struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 #endif
        int ret;
+       int irq;
 
-#ifdef CONFIG_PXA27x
-       pxa_gpio_mode(GPIO117_I2CSCL_MD);
-       pxa_gpio_mode(GPIO118_I2CSDA_MD);
-       udelay(100);
-#endif
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(dev, 0);
+       if (res == NULL || irq < 0)
+               return -ENODEV;
+
+       if (!request_mem_region(res->start, res_len(res), res->name))
+               return -ENOMEM;
+
+       i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
+       if (!i2c) {
+               ret = -ENOMEM;
+               goto emalloc;
+       }
+
+       memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
+       init_waitqueue_head(&i2c->wait);
+       i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
+
+       i2c->reg_base = ioremap(res->start, res_len(res));
+       if (!i2c->reg_base) {
+               ret = -EIO;
+               goto eremap;
+       }
+
+       i2c->iobase = res->start;
+       i2c->iosize = res_len(res);
+
+       i2c->irq = irq;
 
        i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
 
@@ -842,11 +883,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
        }
 #endif
 
-       pxa_set_cken(CKEN14_I2C, 1);
-       ret = request_irq(IRQ_I2C, i2c_pxa_handler, IRQF_DISABLED,
-                         "pxa2xx-i2c", i2c);
+       switch (dev->id) {
+       case 0:
+#ifdef CONFIG_PXA27x
+               pxa_gpio_mode(GPIO117_I2CSCL_MD);
+               pxa_gpio_mode(GPIO118_I2CSDA_MD);
+#endif
+               pxa_set_cken(CKEN14_I2C, 1);
+               break;
+#ifdef CONFIG_PXA27x
+       case 1:
+               local_irq_disable();
+               PCFR |= PCFR_PI2CEN;
+               local_irq_enable();
+               pxa_set_cken(CKEN15_PWRI2C, 1);
+#endif
+       }
+
+       ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+                         i2c->adap.name, i2c);
        if (ret)
-               goto out;
+               goto ereqirq;
+
 
        i2c_pxa_reset(i2c);
 
@@ -856,7 +914,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
        ret = i2c_add_adapter(&i2c->adap);
        if (ret < 0) {
                printk(KERN_INFO "I2C: Failed to add bus\n");
-               goto err_irq;
+               goto eadapt;
        }
 
        platform_set_drvdata(dev, i2c);
@@ -870,9 +928,25 @@ static int i2c_pxa_probe(struct platform_device *dev)
 #endif
        return 0;
 
- err_irq:
-       free_irq(IRQ_I2C, i2c);
- out:
+eadapt:
+       free_irq(irq, i2c);
+ereqirq:
+       switch (dev->id) {
+       case 0:
+               pxa_set_cken(CKEN14_I2C, 0);
+               break;
+#ifdef CONFIG_PXA27x
+       case 1:
+               pxa_set_cken(CKEN15_PWRI2C, 0);
+               local_irq_disable();
+               PCFR &= ~PCFR_PI2CEN;
+               local_irq_enable();
+#endif
+       }
+eremap:
+       kfree(i2c);
+emalloc:
+       release_mem_region(res->start, res_len(res));
        return ret;
 }
 
@@ -883,8 +957,21 @@ static int i2c_pxa_remove(struct platform_device *dev)
        platform_set_drvdata(dev, NULL);
 
        i2c_del_adapter(&i2c->adap);
-       free_irq(IRQ_I2C, i2c);
-       pxa_set_cken(CKEN14_I2C, 0);
+       free_irq(i2c->irq, i2c);
+       switch (dev->id) {
+       case 0:
+               pxa_set_cken(CKEN14_I2C, 0);
+               break;
+#ifdef CONFIG_PXA27x
+       case 1:
+               pxa_set_cken(CKEN15_PWRI2C, 0);
+               local_irq_disable();
+               PCFR &= ~PCFR_PI2CEN;
+               local_irq_enable();
+#endif
+       }
+       release_mem_region(i2c->iobase, i2c->iosize);
+       kfree(i2c);
 
        return 0;
 }
index 4ca6de209b8b6225406f459f64969ef7db94fb25..556f244aae769e3b156a39900077dd5af279aa37 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/err.h>
index d333babe4ad36161a860967e5624519f4c1ec4ba..a6feed449dbe65756ee0016e93fc1be5859dd4f4 100644 (file)
@@ -384,7 +384,7 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
                return -ENODEV;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        sis5595_adapter.dev.parent = &dev->dev;
 
        sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
index 172bacf932a6807c21333f2cb3b594b8ed47b855..5fd734f99ee9df9f12ff5103fa13606c557d852f 100644 (file)
@@ -477,7 +477,7 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
                return -ENODEV;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        sis630_adapter.dev.parent = &dev->dev;
 
        sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
index 869a635d37e9d5d3a6da7e93f777609a61bc5f4a..4157b0cd604c5415c727f5c49113f68151b798db 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -298,7 +297,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
                return -EINVAL;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        sis96x_adapter.dev.parent = &dev->dev;
 
        snprintf(sis96x_adapter.name, I2C_NAME_SIZE,
index bbcc62151f7c4cf542478bcf6ee8768254aaba64..81520868797b84e8f3915a8c23360660c7291022 100644 (file)
@@ -138,7 +138,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
        outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR);
        outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT);
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        vt586b_adapter.dev.parent = &dev->dev;
 
        res = i2c_bit_add_bus(&vt586b_adapter);
index cec3a0c3894dda7912024c769e04057d2a47c5ad..bfce13c8f1ff764d9c6036a8b4cef9cb86cdf106 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
index ec03341d2bd8c2e934478c0cbc0826216cd2576c..49234e32fd167f0de6591584048568d582349bc7 100644 (file)
@@ -383,6 +383,9 @@ config BLK_DEV_OFFBOARD
 config BLK_DEV_GENERIC
        tristate "Generic PCI IDE Chipset Support"
        depends on BLK_DEV_IDEPCI
+        help
+          This option provides generic support for various PCI IDE Chipsets
+          which otherwise might not be supported.
 
 config BLK_DEV_OPTI621
        tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)"
@@ -797,6 +800,14 @@ config BLK_DEV_IDEDMA_PMAC
          to transfer data to and from memory.  Saying Y is safe and improves
          performance.
 
+config BLK_DEV_IDE_CELLEB
+       bool "Toshiba's Cell Reference Set IDE support"
+       depends on PPC_CELLEB
+       help
+         This driver provides support for the built-in IDE controller on
+         Toshiba Cell Reference Board.
+         If unsure, say Y.
+
 config BLK_DEV_IDE_SWARM
        tristate "IDE for Sibyte evaluation boards"
        depends on SIBYTE_SB1xxx_SOC
index d9f029e8ff7411cdb5827d5ed889bcbd5847402d..28feedfbd21dda41123e8c6066bcdfa47e1b477f 100644 (file)
@@ -37,6 +37,7 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE)     += legacy/q40ide.o
 # built-in only drivers from ppc/
 ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE)  += ppc/mpc8xx.o
 ide-core-$(CONFIG_BLK_DEV_IDE_PMAC)    += ppc/pmac.o
+ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB)  += ppc/scc_pata.o
 
 # built-in only drivers from h8300/
 ide-core-$(CONFIG_H8300)               += h8300/ide-h8300.o
index 8a1c27f28692c02c6fee0d43899eab4d000f126d..40e5c66b81ce58fea8c22c5d74b2d060cfc1c35c 100644 (file)
@@ -307,26 +307,24 @@ static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
        return on;
 }
 
-static int icside_dma_host_off(ide_drive_t *drive)
+static void icside_dma_host_off(ide_drive_t *drive)
 {
-       return 0;
 }
 
-static int icside_dma_off_quietly(ide_drive_t *drive)
+static void icside_dma_off_quietly(ide_drive_t *drive)
 {
        drive->using_dma = 0;
-       return icside_dma_host_off(drive);
 }
 
-static int icside_dma_host_on(ide_drive_t *drive)
+static void icside_dma_host_on(ide_drive_t *drive)
 {
-       return 0;
 }
 
 static int icside_dma_on(ide_drive_t *drive)
 {
        drive->using_dma = 1;
-       return icside_dma_host_on(drive);
+
+       return 0;
 }
 
 static int icside_dma_check(ide_drive_t *drive)
@@ -365,10 +363,7 @@ static int icside_dma_check(ide_drive_t *drive)
 out:
        on = icside_set_speed(drive, xfer_mode);
 
-       if (on)
-               return icside_dma_on(drive);
-       else
-               return icside_dma_off_quietly(drive);
+       return on ? 0 : -1;
 }
 
 static int icside_dma_end(ide_drive_t *drive)
@@ -497,9 +492,9 @@ static void icside_dma_init(ide_hwif_t *hwif)
        hwif->autodma           = autodma;
 
        hwif->ide_dma_check     = icside_dma_check;
-       hwif->ide_dma_host_off  = icside_dma_host_off;
-       hwif->ide_dma_off_quietly = icside_dma_off_quietly;
-       hwif->ide_dma_host_on   = icside_dma_host_on;
+       hwif->dma_host_off      = icside_dma_host_off;
+       hwif->dma_off_quietly   = icside_dma_off_quietly;
+       hwif->dma_host_on       = icside_dma_host_on;
        hwif->ide_dma_on        = icside_dma_on;
        hwif->dma_setup         = icside_dma_setup;
        hwif->dma_exec_cmd      = icside_dma_exec_cmd;
@@ -556,7 +551,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
                 * Ensure we're using MMIO
                 */
                default_hwif_mmiops(hwif);
-               hwif->mmio = 2;
+               hwif->mmio = 1;
 
                for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
                        hwif->hw.io_ports[i] = port;
index 3058217767d62eb644efdf6253e530564e3fcbb1..9c6c49fdd2b14997d51d441b3ca9399cfd1d1f08 100644 (file)
@@ -46,7 +46,7 @@ rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int
        hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
        hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
        hwif->hw.irq = hwif->irq = irq;
-       hwif->mmio = 2;
+       hwif->mmio = 1;
        default_hwif_mmiops(hwif);
 
        return hwif;
index 5797e0b5a1327f4e87a41e772bdd568d6180abce..6b2d152351b301f4243cb52843ed4b8e0fe7ffdb 100644 (file)
@@ -682,9 +682,12 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
 static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
 static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
 static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
-static int cris_dma_off (ide_drive_t *drive);
 static int cris_dma_on (ide_drive_t *drive);
 
+static void cris_dma_off(ide_drive_t *drive)
+{
+}
+
 static void tune_cris_ide(ide_drive_t *drive, u8 pio)
 {
        int setup, strobe, hold;
@@ -795,7 +798,7 @@ init_e100_ide (void)
                                0, 0, cris_ide_ack_intr,
                                ide_default_irq(0));
                ide_register_hw(&hw, &hwif);
-               hwif->mmio = 2;
+               hwif->mmio = 1;
                hwif->chipset = ide_etrax100;
                hwif->tuneproc = &tune_cris_ide;
                hwif->speedproc = &speed_cris_ide;
@@ -814,13 +817,16 @@ init_e100_ide (void)
                hwif->OUTBSYNC = &cris_ide_outbsync;
                hwif->INB = &cris_ide_inb;
                hwif->INW = &cris_ide_inw;
-               hwif->ide_dma_host_off = &cris_dma_off;
-               hwif->ide_dma_host_on = &cris_dma_on;
-               hwif->ide_dma_off_quietly = &cris_dma_off;
+               hwif->dma_host_off = &cris_dma_off;
+               hwif->dma_host_on = &cris_dma_on;
+               hwif->dma_off_quietly = &cris_dma_off;
                hwif->udma_four = 0;
                hwif->ultra_mask = cris_ultra_mask;
                hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
                hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */
+               hwif->autodma = 1;
+               hwif->drives[0].autodma = 1;
+               hwif->drives[1].autodma = 1;
        }
 
        /* Reset pulse */
@@ -835,11 +841,6 @@ init_e100_ide (void)
        cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
 }
 
-static int cris_dma_off (ide_drive_t *drive)
-{
-       return 0;
-}
-
 static int cris_dma_on (ide_drive_t *drive)
 {
        return 0;
@@ -1045,17 +1046,10 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
 
 static int cris_dma_check(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       struct hd_driveid* id = drive->id;
-
-       if (id && (id->capability & 1)) {
-               if (ide_use_dma(drive)) {
-                       if (cris_config_drive_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-       }
+       if (ide_use_dma(drive) && cris_config_drive_for_dma(drive))
+               return 0;
 
-       return hwif->ide_dma_off_quietly(drive);
+       return -1;
 }
 
 static int cris_dma_end(ide_drive_t *drive)
index 608ca871744b1a7e4ca81ec468e9fc8702343fe0..88750a300337dfd122509564363fcf14335f3d31 100644 (file)
@@ -76,13 +76,11 @@ static inline void hwif_setup(ide_hwif_t *hwif)
 {
        default_hwif_iops(hwif);
 
-       hwif->mmio  = 2;
+       hwif->mmio  = 1;
        hwif->OUTW  = mm_outw;
        hwif->OUTSW = mm_outsw;
        hwif->INW   = mm_inw;
        hwif->INSW  = mm_insw;
-       hwif->OUTL  = NULL;
-       hwif->INL   = NULL;
        hwif->OUTSL = NULL;
        hwif->INSL  = NULL;
 }
index 5969cec58dc155c2f21aea7e72c4b6d6aca9eb94..45a928c058cfb0b21c5b150127458d4fb9256773 100644 (file)
@@ -687,15 +687,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
        struct request *rq = HWGROUP(drive)->rq;
-       ide_hwif_t *hwif = HWIF(drive);
        int stat, err, sense_key;
        
-       /* We may have bogus DMA interrupts in PIO state here */
-       if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) {
-               stat = hwif->INB(hwif->dma_status);
-               /* Should we force the bit as well ? */
-               hwif->OUTB(stat, hwif->dma_status);
-       }
        /* Check for errors. */
        stat = HWIF(drive)->INB(IDE_STATUS_REG);
        if (stat_ret)
@@ -930,6 +923,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
  
        if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+               /* waiting for CDB interrupt, not DMA yet. */
+               if (info->dma)
+                       drive->waiting_for_dma = 0;
+
                /* packet command */
                ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
                return ide_started;
@@ -972,6 +969,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
                /* Check for errors. */
                if (cdrom_decode_status(drive, DRQ_STAT, NULL))
                        return ide_stopped;
+
+               /* Ok, next interrupt will be DMA interrupt. */
+               if (info->dma)
+                       drive->waiting_for_dma = 1;
        } else {
                /* Otherwise, we must wait for DRQ to get set. */
                if (ide_wait_stat(&startstop, drive, DRQ_STAT,
@@ -1103,7 +1104,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
        if (dma) {
                info->dma = 0;
                if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
        }
 
        if (cdrom_decode_status(drive, 0, &stat))
@@ -1699,7 +1700,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        if (dma) {
                if (dma_error) {
                        printk(KERN_ERR "ide-cd: dma error\n");
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
                        return ide_error(drive, "dma error", stat);
                }
 
@@ -1825,7 +1826,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
                info->dma = 0;
                if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
                        printk(KERN_ERR "ide-cd: write dma error\n");
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
                }
        }
 
@@ -3254,14 +3255,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
        if (drive->autotune == IDE_TUNE_DEFAULT ||
            drive->autotune == IDE_TUNE_AUTO)
                drive->dsc_overlap = (drive->next != drive);
-#if 0
-       drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
-       if (HWIF(drive)->no_dsc) {
-               printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n",
-                       drive->name);
-               drive->dsc_overlap = 0;
-       }
-#endif
 
        if (ide_cdrom_register(drive, nslots)) {
                printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -3360,21 +3353,16 @@ static int idecd_open(struct inode * inode, struct file * file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info;
-       ide_drive_t *drive;
        int rc = -ENOMEM;
 
        if (!(info = ide_cd_get(disk)))
                return -ENXIO;
 
-       drive = info->drive;
-
-       drive->usage++;
-
        if (!info->buffer)
-               info->buffer = kmalloc(SECTOR_BUFFER_SIZE,
-                                       GFP_KERNEL|__GFP_REPEAT);
-        if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
-               drive->usage--;
+               info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+
+       if (info->buffer)
+               rc = cdrom_open(&info->devinfo, inode, file);
 
        if (rc < 0)
                ide_cd_put(info);
@@ -3386,10 +3374,8 @@ static int idecd_release(struct inode * inode, struct file * file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info = ide_cd_g(disk);
-       ide_drive_t *drive = info->drive;
 
        cdrom_release (&info->devinfo, file);
-       drive->usage--;
 
        ide_cd_put(info);
 
index 0a05a377d66ac54a77056fd67cf484cf5bdf8fec..e2cea1889c4d350f4153146b64433cabbc72b620 100644 (file)
@@ -77,6 +77,7 @@ struct ide_disk_obj {
        ide_driver_t    *driver;
        struct gendisk  *disk;
        struct kref     kref;
+       unsigned int    openers;        /* protected by BKL for now */
 };
 
 static DEFINE_MUTEX(idedisk_ref_mutex);
@@ -1081,8 +1082,9 @@ static int idedisk_open(struct inode *inode, struct file *filp)
 
        drive = idkp->drive;
 
-       drive->usage++;
-       if (drive->removable && drive->usage == 1) {
+       idkp->openers++;
+
+       if (drive->removable && idkp->openers == 1) {
                ide_task_t args;
                memset(&args, 0, sizeof(ide_task_t));
                args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
@@ -1106,9 +1108,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
        struct ide_disk_obj *idkp = ide_disk_g(disk);
        ide_drive_t *drive = idkp->drive;
 
-       if (drive->usage == 1)
+       if (idkp->openers == 1)
                ide_cacheflush_p(drive);
-       if (drive->removable && drive->usage == 1) {
+
+       if (drive->removable && idkp->openers == 1) {
                ide_task_t args;
                memset(&args, 0, sizeof(ide_task_t));
                args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
@@ -1117,7 +1120,8 @@ static int idedisk_release(struct inode *inode, struct file *filp)
                if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
                        drive->doorlocking = 0;
        }
-       drive->usage--;
+
+       idkp->openers--;
 
        ide_disk_put(idkp);
 
index 56efed6742d4d32945a1072203fea57b833d1df5..08e7cd043bccc9f9a7937276431f25130b3d7509 100644 (file)
@@ -348,15 +348,14 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
 static int config_drive_for_dma (ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
-       ide_hwif_t *hwif = HWIF(drive);
 
-       if ((id->capability & 1) && hwif->autodma) {
+       if ((id->capability & 1) && drive->hwif->autodma) {
                /*
                 * Enable DMA on any drive that has
                 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
                 */
                if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
-                       return hwif->ide_dma_on(drive);
+                       return 0;
                /*
                 * Enable DMA on any drive that has mode2 DMA
                 * (multi or single) enabled
@@ -364,14 +363,14 @@ static int config_drive_for_dma (ide_drive_t *drive)
                if (id->field_valid & 2)        /* regular DMA */
                        if ((id->dma_mword & 0x404) == 0x404 ||
                            (id->dma_1word & 0x404) == 0x404)
-                               return hwif->ide_dma_on(drive);
+                               return 0;
 
                /* Consult the list of known "good" drives */
                if (__ide_dma_good_drive(drive))
-                       return hwif->ide_dma_on(drive);
+                       return 0;
        }
-//     if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255);
-       return hwif->ide_dma_off_quietly(drive);
+
+       return -1;
 }
 
 /**
@@ -415,72 +414,68 @@ static int dma_timer_expiry (ide_drive_t *drive)
 }
 
 /**
- *     __ide_dma_host_off      -       Generic DMA kill
+ *     ide_dma_host_off        -       Generic DMA kill
  *     @drive: drive to control
  *
  *     Perform the generic IDE controller DMA off operation. This
  *     works for most IDE bus mastering controllers
  */
 
-int __ide_dma_host_off (ide_drive_t *drive)
+void ide_dma_host_off(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        u8 unit                 = (drive->select.b.unit & 0x01);
        u8 dma_stat             = hwif->INB(hwif->dma_status);
 
        hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
-       return 0;
 }
 
-EXPORT_SYMBOL(__ide_dma_host_off);
+EXPORT_SYMBOL(ide_dma_host_off);
 
 /**
- *     __ide_dma_host_off_quietly      -       Generic DMA kill
+ *     ide_dma_off_quietly     -       Generic DMA kill
  *     @drive: drive to control
  *
  *     Turn off the current DMA on this IDE controller. 
  */
 
-int __ide_dma_off_quietly (ide_drive_t *drive)
+void ide_dma_off_quietly(ide_drive_t *drive)
 {
        drive->using_dma = 0;
        ide_toggle_bounce(drive, 0);
 
-       if (HWIF(drive)->ide_dma_host_off(drive))
-               return 1;
-
-       return 0;
+       drive->hwif->dma_host_off(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_off_quietly);
+EXPORT_SYMBOL(ide_dma_off_quietly);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 /**
- *     __ide_dma_off   -       disable DMA on a device
+ *     ide_dma_off     -       disable DMA on a device
  *     @drive: drive to disable DMA on
  *
  *     Disable IDE DMA for a device on this IDE controller.
  *     Inform the user that DMA has been disabled.
  */
 
-int __ide_dma_off (ide_drive_t *drive)
+void ide_dma_off(ide_drive_t *drive)
 {
        printk(KERN_INFO "%s: DMA disabled\n", drive->name);
-       return HWIF(drive)->ide_dma_off_quietly(drive);
+       drive->hwif->dma_off_quietly(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_off);
+EXPORT_SYMBOL(ide_dma_off);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
- *     __ide_dma_host_on       -       Enable DMA on a host
+ *     ide_dma_host_on -       Enable DMA on a host
  *     @drive: drive to enable for DMA
  *
  *     Enable DMA on an IDE controller following generic bus mastering
  *     IDE controller behaviour
  */
-int __ide_dma_host_on (ide_drive_t *drive)
+
+void ide_dma_host_on(ide_drive_t *drive)
 {
        if (drive->using_dma) {
                ide_hwif_t *hwif        = HWIF(drive);
@@ -488,12 +483,10 @@ int __ide_dma_host_on (ide_drive_t *drive)
                u8 dma_stat             = hwif->INB(hwif->dma_status);
 
                hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
-               return 0;
        }
-       return 1;
 }
 
-EXPORT_SYMBOL(__ide_dma_host_on);
+EXPORT_SYMBOL(ide_dma_host_on);
 
 /**
  *     __ide_dma_on            -       Enable DMA on a device
@@ -511,8 +504,7 @@ int __ide_dma_on (ide_drive_t *drive)
        drive->using_dma = 1;
        ide_toggle_bounce(drive, 1);
 
-       if (HWIF(drive)->ide_dma_host_on(drive))
-               return 1;
+       drive->hwif->dma_host_on(drive);
 
        return 0;
 }
@@ -565,7 +557,10 @@ int ide_dma_setup(ide_drive_t *drive)
        }
 
        /* PRD table */
-       hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);
+       if (hwif->mmio)
+               writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable);
+       else
+               outl(hwif->dmatable_dma, hwif->dma_prdtable);
 
        /* specify r/w */
        hwif->OUTB(reading, hwif->dma_command);
@@ -680,6 +675,9 @@ int ide_use_dma(ide_drive_t *drive)
        struct hd_driveid *id = drive->id;
        ide_hwif_t *hwif = drive->hwif;
 
+       if ((id->capability & 1) == 0 || drive->autodma == 0)
+               return 0;
+
        /* consult the list of known "bad" drives */
        if (__ide_dma_bad_drive(drive))
                return 0;
@@ -753,12 +751,37 @@ void ide_dma_verbose(ide_drive_t *drive)
        return;
 bug_dma_off:
        printk(", BUG DMA OFF");
-       hwif->ide_dma_off_quietly(drive);
+       hwif->dma_off_quietly(drive);
        return;
 }
 
 EXPORT_SYMBOL(ide_dma_verbose);
 
+int ide_set_dma(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       int rc;
+
+       rc = hwif->ide_dma_check(drive);
+
+       switch(rc) {
+       case -1: /* DMA needs to be disabled */
+               hwif->dma_off_quietly(drive);
+               return 0;
+       case  0: /* DMA needs to be enabled */
+               return hwif->ide_dma_on(drive);
+       case  1: /* DMA setting cannot be changed */
+               break;
+       default:
+               BUG();
+               break;
+       }
+
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(ide_set_dma);
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 int __ide_dma_lostirq (ide_drive_t *drive)
 {
@@ -809,7 +832,7 @@ int ide_release_dma(ide_hwif_t *hwif)
 {
        ide_release_dma_engine(hwif);
 
-       if (hwif->mmio == 2)
+       if (hwif->mmio)
                return 1;
        else
                return ide_release_iomio_dma(hwif);
@@ -878,9 +901,9 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
 
 static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
-       if (hwif->mmio == 2)
+       if (hwif->mmio)
                return ide_mapped_mmio_dma(hwif, base,ports);
-       BUG_ON(hwif->mmio == 1);
+
        return ide_iomio_dma(hwif, base, ports);
 }
 
@@ -908,14 +931,14 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
        if (!(hwif->dma_prdtable))
                hwif->dma_prdtable      = (hwif->dma_base + 4);
 
-       if (!hwif->ide_dma_off_quietly)
-               hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
-       if (!hwif->ide_dma_host_off)
-               hwif->ide_dma_host_off = &__ide_dma_host_off;
+       if (!hwif->dma_off_quietly)
+               hwif->dma_off_quietly = &ide_dma_off_quietly;
+       if (!hwif->dma_host_off)
+               hwif->dma_host_off = &ide_dma_host_off;
        if (!hwif->ide_dma_on)
                hwif->ide_dma_on = &__ide_dma_on;
-       if (!hwif->ide_dma_host_on)
-               hwif->ide_dma_host_on = &__ide_dma_host_on;
+       if (!hwif->dma_host_on)
+               hwif->dma_host_on = &ide_dma_host_on;
        if (!hwif->ide_dma_check)
                hwif->ide_dma_check = &__ide_dma_check;
        if (!hwif->dma_setup)
index d33717c8afd466731855e4a42f01d65c9ee85b2e..57cd21c5b2c1f0c0fdc7a79985f226f736a0da00 100644 (file)
@@ -279,6 +279,7 @@ typedef struct ide_floppy_obj {
        ide_driver_t    *driver;
        struct gendisk  *disk;
        struct kref     kref;
+       unsigned int    openers;        /* protected by BKL for now */
 
        /* Current packet command */
        idefloppy_pc_t *pc;
@@ -866,7 +867,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
        if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
                printk(KERN_ERR "ide-floppy: The floppy wants to issue "
                        "more interrupts in DMA mode\n");
-               (void)__ide_dma_off(drive);
+               ide_dma_off(drive);
                return ide_do_reset(drive);
        }
 
@@ -1096,9 +1097,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
        pc->current_position = pc->buffer;
        bcount.all = min(pc->request_transfer, 63 * 1024);
 
-       if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
-               (void)__ide_dma_off(drive);
-       }
+       if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
+               ide_dma_off(drive);
+
        feature.all = 0;
 
        if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
@@ -1433,7 +1434,8 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
        
        drive->bios_cyl = 0;
        drive->bios_head = drive->bios_sect = 0;
-       floppy->blocks = floppy->bs_factor = 0;
+       floppy->blocks = 0;
+       floppy->bs_factor = 1;
        set_capacity(floppy->disk, 0);
 
        idefloppy_create_read_capacity_cmd(&pc);
@@ -1949,9 +1951,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
 
        drive = floppy->drive;
 
-       drive->usage++;
+       floppy->openers++;
 
-       if (drive->usage == 1) {
+       if (floppy->openers == 1) {
                clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
                /* Just in case */
 
@@ -1969,13 +1971,11 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
                    ** capacity of the drive or begin the format - Sam
                    */
                    ) {
-                       drive->usage--;
                        ret = -EIO;
                        goto out_put_floppy;
                }
 
                if (floppy->wp && (filp->f_mode & 2)) {
-                       drive->usage--;
                        ret = -EROFS;
                        goto out_put_floppy;
                }
@@ -1987,13 +1987,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
                }
                check_disk_change(inode->i_bdev);
        } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
-               drive->usage--;
                ret = -EBUSY;
                goto out_put_floppy;
        }
        return 0;
 
 out_put_floppy:
+       floppy->openers--;
        ide_floppy_put(floppy);
        return ret;
 }
@@ -2007,7 +2007,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
        
        debug_log(KERN_INFO "Reached idefloppy_release\n");
 
-       if (drive->usage == 1) {
+       if (floppy->openers == 1) {
                /* IOMEGA Clik! drives do not support lock/unlock commands */
                 if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
                        idefloppy_create_prevent_cmd(&pc, 0);
@@ -2016,7 +2016,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
 
                clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
        }
-       drive->usage--;
+
+       floppy->openers--;
 
        ide_floppy_put(floppy);
 
@@ -2050,7 +2051,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
                prevent = 0;
                /* fall through */
        case CDROM_LOCKDOOR:
-               if (drive->usage > 1)
+               if (floppy->openers > 1)
                        return -EBUSY;
 
                /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
@@ -2072,7 +2073,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
                if (!(file->f_mode & 2))
                        return -EPERM;
 
-               if (drive->usage > 1) {
+               if (floppy->openers > 1) {
                        /* Don't format if someone is using the disk */
 
                        clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
index 2614f41b5074ea2d203767be2eefa6a4b5505f45..c193553f6fe749e88724e4a63f812179dde309c5 100644 (file)
@@ -226,7 +226,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                        break;
                if (drive->hwif->ide_dma_check == NULL)
                        break;
-               drive->hwif->ide_dma_check(drive);
+               ide_set_dma(drive);
                break;
        }
        pm->pm_step = ide_pm_state_completed;
@@ -1351,7 +1351,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
         */
        drive->retry_pio++;
        drive->state = DMA_PIO_RETRY;
-       (void) hwif->ide_dma_off_quietly(drive);
+       hwif->dma_off_quietly(drive);
 
        /*
         * un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1646,6 +1646,17 @@ irqreturn_t ide_intr (int irq, void *dev_id)
        del_timer(&hwgroup->timer);
        spin_unlock(&ide_lock);
 
+       /* Some controllers might set DMA INTR no matter DMA or PIO;
+        * bmdma status might need to be cleared even for
+        * PIO interrupts to prevent spurious/lost irq.
+        */
+       if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
+               /* ide_dma_end() needs bmdma status for error checking.
+                * So, skip clearing bmdma status here and leave it
+                * to ide_dma_end() if this is dma interrupt.
+                */
+               hwif->ide_dma_clear_irq(drive);
+
        if (drive->unmask)
                local_irq_enable_in_hardirq();
        /* service this interrupt, may set handler for next interrupt */
index badde6331775a12208c375fb68139b0e156d9606..c67b3b1e6f4c64b255d043220a8cdc8b72aff80b 100644 (file)
@@ -49,11 +49,6 @@ static void ide_insw (unsigned long port, void *addr, u32 count)
        insw(port, addr, count);
 }
 
-static u32 ide_inl (unsigned long port)
-{
-       return (u32) inl(port);
-}
-
 static void ide_insl (unsigned long port, void *addr, u32 count)
 {
        insl(port, addr, count);
@@ -79,11 +74,6 @@ static void ide_outsw (unsigned long port, void *addr, u32 count)
        outsw(port, addr, count);
 }
 
-static void ide_outl (u32 val, unsigned long port)
-{
-       outl(val, port);
-}
-
 static void ide_outsl (unsigned long port, void *addr, u32 count)
 {
        outsl(port, addr, count);
@@ -94,12 +84,10 @@ void default_hwif_iops (ide_hwif_t *hwif)
        hwif->OUTB      = ide_outb;
        hwif->OUTBSYNC  = ide_outbsync;
        hwif->OUTW      = ide_outw;
-       hwif->OUTL      = ide_outl;
        hwif->OUTSW     = ide_outsw;
        hwif->OUTSL     = ide_outsl;
        hwif->INB       = ide_inb;
        hwif->INW       = ide_inw;
-       hwif->INL       = ide_inl;
        hwif->INSW      = ide_insw;
        hwif->INSL      = ide_insl;
 }
@@ -123,11 +111,6 @@ static void ide_mm_insw (unsigned long port, void *addr, u32 count)
        __ide_mm_insw((void __iomem *) port, addr, count);
 }
 
-static u32 ide_mm_inl (unsigned long port)
-{
-       return (u32) readl((void __iomem *) port);
-}
-
 static void ide_mm_insl (unsigned long port, void *addr, u32 count)
 {
        __ide_mm_insl((void __iomem *) port, addr, count);
@@ -153,11 +136,6 @@ static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
        __ide_mm_outsw((void __iomem *) port, addr, count);
 }
 
-static void ide_mm_outl (u32 value, unsigned long port)
-{
-       writel(value, (void __iomem *) port);
-}
-
 static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
 {
        __ide_mm_outsl((void __iomem *) port, addr, count);
@@ -170,12 +148,10 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
           this one is controller specific! */
        hwif->OUTBSYNC  = ide_mm_outbsync;
        hwif->OUTW      = ide_mm_outw;
-       hwif->OUTL      = ide_mm_outl;
        hwif->OUTSW     = ide_mm_outsw;
        hwif->OUTSL     = ide_mm_outsl;
        hwif->INB       = ide_mm_inb;
        hwif->INW       = ide_mm_inw;
-       hwif->INL       = ide_mm_inl;
        hwif->INSW      = ide_mm_insw;
        hwif->INSL      = ide_mm_insl;
 }
@@ -777,7 +753,7 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (hwif->ide_dma_check)         /* check if host supports DMA */
-               hwif->ide_dma_host_off(drive);
+               hwif->dma_host_off(drive);
 #endif
 
        /*
@@ -854,9 +830,9 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (speed >= XFER_SW_DMA_0)
-               hwif->ide_dma_host_on(drive);
+               hwif->dma_host_on(drive);
        else if (hwif->ide_dma_check)   /* check if host supports DMA */
-               hwif->ide_dma_off_quietly(drive);
+               hwif->dma_off_quietly(drive);
 #endif
 
        switch(speed) {
@@ -1066,12 +1042,12 @@ static void check_dma_crc(ide_drive_t *drive)
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (drive->crc_count) {
-               (void) HWIF(drive)->ide_dma_off_quietly(drive);
+               drive->hwif->dma_off_quietly(drive);
                ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
                if (drive->current_speed >= XFER_SW_DMA_0)
                        (void) HWIF(drive)->ide_dma_on(drive);
        } else
-               (void)__ide_dma_off(drive);
+               ide_dma_off(drive);
 #endif
 }
 
index 8237d89eec6e2c3ddd735369ddef750c1ea4fad3..8afce4ceea310c6e47eea9ff1c715bdb39916591 100644 (file)
@@ -205,6 +205,21 @@ int ide_dma_enable (ide_drive_t *drive)
 
 EXPORT_SYMBOL(ide_dma_enable);
 
+int ide_use_fast_pio(ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+
+       if ((id->capability & 1) && drive->autodma)
+               return 1;
+
+       if ((id->capability & 8) || (id->field_valid & 2))
+               return 1;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_use_fast_pio);
+
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
  * These timings are for access to the IDE data port register *only*.
@@ -349,7 +364,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
        int use_iordy = 0;
        struct hd_driveid* id = drive->id;
        int overridden  = 0;
-       int blacklisted = 0;
 
        if (mode_wanted != 255) {
                pio_mode = mode_wanted;
@@ -357,7 +371,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
                pio_mode = 0;
        } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
                overridden = 1;
-               blacklisted = 1;
                use_iordy = (pio_mode > 2);
        } else {
                pio_mode = id->tPIO;
@@ -409,7 +422,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
                d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time;
                d->use_iordy = use_iordy;
                d->overridden = overridden;
-               d->blacklisted = blacklisted;
        }
        return pio_mode;
 }
@@ -462,8 +474,6 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
                return -1;
 }
 
-EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
-
 static void ide_dump_opcode(ide_drive_t *drive)
 {
        struct request *rq;
index 176bbc850d6ba8731bd5e8b89de627c5209208c2..8afbd6cb94be9ac50db17f3c62f03c4804791a1e 100644 (file)
@@ -853,11 +853,11 @@ static void probe_hwif(ide_hwif_t *hwif)
                                 * things, if not checked and cleared.
                                 *   PARANOIA!!!
                                 */
-                               hwif->ide_dma_off_quietly(drive);
+                               hwif->dma_off_quietly(drive);
 #ifdef CONFIG_IDEDMA_ONLYDISK
                                if (drive->media == ide_disk)
 #endif
-                                       hwif->ide_dma_check(drive);
+                                       ide_set_dma(drive);
                        }
                }
        }
index 30a5780f4185a7e6c4fe6ac65c79df25d822357c..afb71c66b6f3f94e0517cc641feb01db0a1715b6 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/uaccess.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
index c6eec0413a6c5f323bf67798554a6a794747773e..4e59239fef75e1ecd7638d0dcf3f7fdc6e4a2b7b 100644 (file)
@@ -1970,7 +1970,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
                printk(KERN_ERR "ide-tape: The tape wants to issue more "
                                "interrupts in DMA mode\n");
                printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
-               (void)__ide_dma_off(drive);
+               ide_dma_off(drive);
                return ide_do_reset(drive);
        }
        /* Get the number of bytes to transfer on this interrupt. */
@@ -2176,7 +2176,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
        if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
                printk(KERN_WARNING "ide-tape: DMA disabled, "
                                "reverting to PIO\n");
-               (void)__ide_dma_off(drive);
+               ide_dma_off(drive);
        }
        if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
                dma_ok = !hwif->dma_setup(drive);
@@ -4792,15 +4792,10 @@ static int idetape_open(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct ide_tape_obj *tape;
-       ide_drive_t *drive;
 
        if (!(tape = ide_tape_get(disk)))
                return -ENXIO;
 
-       drive = tape->drive;
-
-       drive->usage++;
-
        return 0;
 }
 
@@ -4808,9 +4803,6 @@ static int idetape_release(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct ide_tape_obj *tape = ide_tape_g(disk);
-       ide_drive_t *drive = tape->drive;
-
-       drive->usage--;
 
        ide_tape_put(tape);
 
index c750f6ce770a2ab053f1b4f515b6f81f2ed82a3e..b3c0818c5c6c592eefa9289b0e2cbe1492bf73a3 100644 (file)
@@ -389,9 +389,8 @@ int ide_hwif_request_regions(ide_hwif_t *hwif)
        unsigned long addr;
        unsigned int i;
 
-       if (hwif->mmio == 2)
+       if (hwif->mmio)
                return 0;
-       BUG_ON(hwif->mmio == 1);
        addr = hwif->io_ports[IDE_CONTROL_OFFSET];
        if (addr && !hwif_request_region(hwif, addr, 1))
                goto control_region_busy;
@@ -438,7 +437,7 @@ void ide_hwif_release_regions(ide_hwif_t *hwif)
 {
        u32 i = 0;
 
-       if (hwif->mmio == 2)
+       if (hwif->mmio)
                return;
        if (hwif->io_ports[IDE_CONTROL_OFFSET])
                release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
@@ -507,23 +506,22 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->ide_dma_end               = tmp_hwif->ide_dma_end;
        hwif->ide_dma_check             = tmp_hwif->ide_dma_check;
        hwif->ide_dma_on                = tmp_hwif->ide_dma_on;
-       hwif->ide_dma_off_quietly       = tmp_hwif->ide_dma_off_quietly;
+       hwif->dma_off_quietly           = tmp_hwif->dma_off_quietly;
        hwif->ide_dma_test_irq          = tmp_hwif->ide_dma_test_irq;
-       hwif->ide_dma_host_on           = tmp_hwif->ide_dma_host_on;
-       hwif->ide_dma_host_off          = tmp_hwif->ide_dma_host_off;
+       hwif->ide_dma_clear_irq         = tmp_hwif->ide_dma_clear_irq;
+       hwif->dma_host_on               = tmp_hwif->dma_host_on;
+       hwif->dma_host_off              = tmp_hwif->dma_host_off;
        hwif->ide_dma_lostirq           = tmp_hwif->ide_dma_lostirq;
        hwif->ide_dma_timeout           = tmp_hwif->ide_dma_timeout;
 
        hwif->OUTB                      = tmp_hwif->OUTB;
        hwif->OUTBSYNC                  = tmp_hwif->OUTBSYNC;
        hwif->OUTW                      = tmp_hwif->OUTW;
-       hwif->OUTL                      = tmp_hwif->OUTL;
        hwif->OUTSW                     = tmp_hwif->OUTSW;
        hwif->OUTSL                     = tmp_hwif->OUTSL;
 
        hwif->INB                       = tmp_hwif->INB;
        hwif->INW                       = tmp_hwif->INW;
-       hwif->INL                       = tmp_hwif->INL;
        hwif->INSW                      = tmp_hwif->INSW;
        hwif->INSL                      = tmp_hwif->INSL;
 
@@ -551,7 +549,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->extra_ports               = tmp_hwif->extra_ports;
        hwif->autodma                   = tmp_hwif->autodma;
        hwif->udma_four                 = tmp_hwif->udma_four;
-       hwif->no_dsc                    = tmp_hwif->no_dsc;
 
        hwif->hwif_data                 = tmp_hwif->hwif_data;
 }
@@ -1138,12 +1135,11 @@ static int set_using_dma (ide_drive_t *drive, int arg)
        if (HWIF(drive)->ide_dma_check == NULL)
                return -EPERM;
        if (arg) {
-               if (HWIF(drive)->ide_dma_check(drive)) return -EIO;
-               if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
-       } else {
-               if (__ide_dma_off(drive))
+               if (ide_set_dma(drive))
                        return -EIO;
-       }
+               if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
+       } else
+               ide_dma_off(drive);
        return 0;
 #else
        return -EPERM;
index 0391a3122878f14876c46e71e5ad403cd745348f..1ed224a01f79ddd24e371740cccc55a4065e26fc 100644 (file)
@@ -215,7 +215,7 @@ fail_base2:
                        
                        index = ide_register_hw(&hw, &hwif);
                        if (index != -1) {
-                               hwif->mmio = 2;
+                               hwif->mmio = 1;
                                printk("ide%d: ", index);
                                switch(type) {
                                case BOARD_BUDDHA:
index 64d42619ab06a1f7e4e4d576bd8f8ef329ff5ee8..dcfadbbf55d88e0ccbe56b0abc831a63d9ecaab8 100644 (file)
@@ -167,7 +167,7 @@ found:
 
        index = ide_register_hw(&hw, &hwif);
        if (index != -1) {
-           hwif->mmio = 2;
+           hwif->mmio = 1;
            switch (i) {
                case 0:
                    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
index c48e87e512d38298bdc15f358a2751217e1b1615..19ccd006f205ae1a329c16ad64a76e29adae7ac1 100644 (file)
@@ -143,16 +143,16 @@ static void ht6560b_selectproc (ide_drive_t *drive)
                current_timing = timing;
                if (drive->media != ide_disk || !drive->present)
                        select |= HT_PREFETCH_MODE;
-               (void) HWIF(drive)->INB(HT_CONFIG_PORT);
-               (void) HWIF(drive)->INB(HT_CONFIG_PORT);
-               (void) HWIF(drive)->INB(HT_CONFIG_PORT);
-               (void) HWIF(drive)->INB(HT_CONFIG_PORT);
-               HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               outb(select, HT_CONFIG_PORT);
                /*
                 * Set timing for this drive:
                 */
-               HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
-               (void) HWIF(drive)->INB(IDE_STATUS_REG);
+               outb(timing, IDE_SELECT_REG);
+               (void)inb(IDE_STATUS_REG);
 #ifdef DEBUG
                printk("ht6560b: %s: select=%#x timing=%#x\n",
                        drive->name, select, timing);
index 7efd28ac21ed41aa8a5363efeaf11079b04c321f..a5023cdbdc58ee1ec757f8ffc855ff791783fff6 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index b1730d7e414c3ec1f53ad1dfa71bf855d8131cc0..4c0079ad52ac16a9dd95df58e9afdde2a29239bf 100644 (file)
@@ -141,7 +141,7 @@ void macide_init(void)
        }
 
         if (index != -1) {
-               hwif->mmio = 2;
+               hwif->mmio = 1;
                if (macintosh_config->ide_type == MAC_IDE_QUADRA)
                        printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
                else if (macintosh_config->ide_type == MAC_IDE_PB)
index 434a94faa3b7202792ad5c05aa60144c3c59dbf3..74f08124eabb772f2d5f80abff23e4b11bfafecf 100644 (file)
@@ -145,7 +145,7 @@ void q40ide_init(void)
        index = ide_register_hw(&hw, &hwif);
        // **FIXME**
        if (index != -1)
-               hwif->mmio = 2;
+               hwif->mmio = 1;
     }
 }
 
index c7854ea57b52d42f346852f5ef8a7630306c4a4d..0a59d5ef1599e16d323bfadb051c6ae9491c9e6f 100644 (file)
@@ -181,12 +181,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
 {
        int mem_sttime;
        int mem_stcfg;
-       unsigned long mode;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       if (ide_use_dma(drive))
-               mode = ide_dma_speed(drive, 0);
-#endif
 
        mem_sttime = 0;
        mem_stcfg  = au_readl(MEM_STCFG2);
@@ -195,7 +189,7 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
                auide_tune_drive(drive, speed - XFER_PIO_0);
                return 0;
        }
-             
+
        switch(speed) {
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
        case XFER_MW_DMA_2:
@@ -207,7 +201,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
                mem_stcfg &= ~TOECS_MASK;
                mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
 
-               mode = XFER_MW_DMA_2;
                break;
        case XFER_MW_DMA_1:
                mem_sttime = SBC_IDE_TIMING(MDMA1);
@@ -218,7 +211,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
                mem_stcfg &= ~TOECS_MASK;
                mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
 
-               mode = XFER_MW_DMA_1;
                break;
        case XFER_MW_DMA_0:
                mem_sttime = SBC_IDE_TIMING(MDMA0);
@@ -229,14 +221,13 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
                mem_stcfg &= ~TOECS_MASK;
                mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
 
-               mode = XFER_MW_DMA_0;
                break;
 #endif
        default:
                return 1;
        }
-       
-       if (ide_config_drive_speed(drive, mode))
+
+       if (ide_config_drive_speed(drive, speed))
                return 1;
 
        au_writel(mem_sttime,MEM_STTIME2);
@@ -423,9 +414,9 @@ static int auide_dma_check(ide_drive_t *drive)
        speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
        
        if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-               return HWIF(drive)->ide_dma_on(drive);
+               return 0;
 
-       return HWIF(drive)->ide_dma_off_quietly(drive);
+       return -1;
 }
 
 static int auide_dma_test_irq(ide_drive_t *drive)
@@ -447,27 +438,24 @@ static int auide_dma_test_irq(ide_drive_t *drive)
        return 0;
 }
 
-static int auide_dma_host_on(ide_drive_t *drive)
+static void auide_dma_host_on(ide_drive_t *drive)
 {
-       return 0;
 }
 
 static int auide_dma_on(ide_drive_t *drive)
 {
        drive->using_dma = 1;
-       return auide_dma_host_on(drive);
-}
 
+       return 0;
+}
 
-static int auide_dma_host_off(ide_drive_t *drive)
+static void auide_dma_host_off(ide_drive_t *drive)
 {
-       return 0;
 }
 
-static int auide_dma_off_quietly(ide_drive_t *drive)
+static void auide_dma_off_quietly(ide_drive_t *drive)
 {
        drive->using_dma = 0;
-       return auide_dma_host_off(drive);
 }
 
 static int auide_dma_lostirq(ide_drive_t *drive)
@@ -717,7 +705,8 @@ static int au_ide_probe(struct device *dev)
 
        /* hold should be on in all cases */
        hwif->hold                      = 1;
-       hwif->mmio                      = 2;
+
+       hwif->mmio  = 1;
 
        /* If the user has selected DDMA assisted copies,
           then set up a few local I/O function entry points 
@@ -732,7 +721,7 @@ static int au_ide_probe(struct device *dev)
        hwif->speedproc                 = &auide_tune_chipset;
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       hwif->ide_dma_off_quietly       = &auide_dma_off_quietly;
+       hwif->dma_off_quietly           = &auide_dma_off_quietly;
        hwif->ide_dma_timeout           = &auide_dma_timeout;
 
        hwif->ide_dma_check             = &auide_dma_check;
@@ -741,8 +730,8 @@ static int au_ide_probe(struct device *dev)
        hwif->ide_dma_end               = &auide_dma_end;
        hwif->dma_setup                 = &auide_dma_setup;
        hwif->ide_dma_test_irq          = &auide_dma_test_irq;
-       hwif->ide_dma_host_off          = &auide_dma_host_off;
-       hwif->ide_dma_host_on           = &auide_dma_host_on;
+       hwif->dma_host_off              = &auide_dma_host_off;
+       hwif->dma_host_on               = &auide_dma_host_on;
        hwif->ide_dma_lostirq           = &auide_dma_lostirq;
        hwif->ide_dma_on                = &auide_dma_on;
 
index 09c9e7936b0dff79c5d44f84732a003f910ca2f5..81fa06851b27dadfd5c4d34c58aa38b6a276c5f4 100644 (file)
@@ -115,7 +115,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
        /* Setup MMIO ops.  */
        default_hwif_mmiops(hwif);
        /* Prevent resource map manipulation.  */
-       hwif->mmio = 2;
+       hwif->mmio = 1;
        hwif->noprobe = 0;
 
        for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
index d261bfbad2227206505ae2c52fa079bf2a0c6a25..990eafe5ea1171e599efe0908fb3d0ea22ea0131 100644 (file)
@@ -94,9 +94,9 @@ static u8 aec62xx_ratemask (ide_drive_t *drive)
        switch(hwif->pci_dev->device) {
                case PCI_DEVICE_ID_ARTOP_ATP865:
                case PCI_DEVICE_ID_ARTOP_ATP865R:
-                       mode = (hwif->INB(((hwif->channel) ?
-                                       hwif->mate->dma_status :
-                                       hwif->dma_status)) & 0x10) ? 4 : 3;
+                       mode = (inb(hwif->channel ?
+                                   hwif->mate->dma_status :
+                                   hwif->dma_status) & 0x10) ? 4 : 3;
                        break;
                case PCI_DEVICE_ID_ARTOP_ATP860:
                case PCI_DEVICE_ID_ARTOP_ATP860R:
@@ -209,25 +209,13 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                aec62xx_tune_drive(drive, 5);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 static int aec62xx_irq_timeout (ide_drive_t *drive)
@@ -286,10 +274,8 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
        hwif->tuneproc = &aec62xx_tune_drive;
        hwif->speedproc = &aec62xx_tune_chipset;
 
-       if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+       if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
                hwif->serialized = hwif->channel;
-               hwif->no_dsc = 1;
-       }
 
        if (hwif->mate)
                hwif->mate->serialized = hwif->serialized;
index 68df77ec502b8aec6d5b166893d24741bf1be0bb..4debd18d52f83da057dc1e73922d196a442ce2d5 100644 (file)
@@ -507,17 +507,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
  *
  *     Configure a drive for DMA operation. If DMA is not possible we
  *     drop the drive into PIO mode instead.
- *
- *     FIXME: exactly what are we trying to return here
  */
+
 static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct hd_driveid *id   = drive->id;
 
        if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
-               return hwif->ide_dma_off_quietly(drive);
+               goto no_dma_set;
 
        drive->init_speed = 0;
 
@@ -552,9 +550,10 @@ try_dma_modes:
 ata_pio:
                hwif->tuneproc(drive, 255);
 no_dma_set:
-               return hwif->ide_dma_off_quietly(drive);
+               return -1;
        }
-       return hwif->ide_dma_on(drive);
+
+       return 0;
 }
 
 /**
@@ -852,8 +851,8 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
 {
        if (m5229_revision < 0x20)
                return;
-       if (!(hwif->channel))
-               hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2);
+       if (!hwif->channel)
+               outb(inb(dmabase + 2) & 0x60, dmabase + 2);
        ide_setup_dma(hwif, dmabase, 8);
 }
 
index a4336995a4108675d4a2f73a9af6dcde1838be04..7989bdd842a2312ae0ca21640c1bbfcf029338fb 100644 (file)
@@ -304,8 +304,9 @@ static int amd74xx_ide_dma_check(ide_drive_t *drive)
        amd_set_drive(drive, speed);
 
        if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-               return HWIF(drive)->ide_dma_on(drive);
-       return HWIF(drive)->ide_dma_off_quietly(drive);
+               return 0;
+
+       return -1;
 }
 
 /*
index 982ac31fa9954bc09c30ede6e40a9e7f35dd1541..2d48af32e3f455dc7a67eed2e84418e4b6ae1234 100644 (file)
@@ -101,7 +101,7 @@ static u8 atiixp_dma_2_pio(u8 xfer_rate) {
        }
 }
 
-static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+static void atiixp_dma_host_on(ide_drive_t *drive)
 {
        struct pci_dev *dev = drive->hwif->pci_dev;
        unsigned long flags;
@@ -118,10 +118,10 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive)
 
        spin_unlock_irqrestore(&atiixp_lock, flags);
 
-       return __ide_dma_host_on(drive);
+       ide_dma_host_on(drive);
 }
 
-static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+static void atiixp_dma_host_off(ide_drive_t *drive)
 {
        struct pci_dev *dev = drive->hwif->pci_dev;
        unsigned long flags;
@@ -135,7 +135,7 @@ static int atiixp_ide_dma_host_off(ide_drive_t *drive)
 
        spin_unlock_irqrestore(&atiixp_lock, flags);
 
-       return __ide_dma_host_off(drive);
+       ide_dma_host_off(drive);
 }
 
 /**
@@ -235,11 +235,8 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive)
 {
        u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
 
-       /* If no DMA speed was available then disable DMA and use PIO. */
-       if (!speed) {
-               u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
-               speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
-       }
+       if (!speed)
+               return 0;
 
        (void) atiixp_speedproc(drive, speed);
        return ide_dma_enable(drive);
@@ -255,30 +252,20 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive)
 
 static int atiixp_dma_check(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
        u8 tspeed, speed;
 
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (atiixp_config_drive_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive)) {
                tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
                speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
-               hwif->speedproc(drive, speed);
-               return hwif->ide_dma_off_quietly(drive);
+               atiixp_speedproc(drive, speed);
        }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 /**
@@ -318,8 +305,8 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
        else
                hwif->udma_four = 0;
 
-       hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
-       hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+       hwif->dma_host_on = &atiixp_dma_host_on;
+       hwif->dma_host_off = &atiixp_dma_host_off;
        hwif->ide_dma_check = &atiixp_dma_check;
        if (!noautodma)
                hwif->autodma = 1;
index aee947e8fc389ebbb44bb91ffa786b210c8cfdbd..49df27513da7add4275f42bd71a33bdbdd3bc84f 100644 (file)
@@ -466,36 +466,21 @@ static int config_chipset_for_dma (ide_drive_t *drive)
        if (!speed)
                return 0;
 
-       if(ide_set_xfer_rate(drive, speed))
-               return 0; 
-
-       if (!drive->init_speed)
-               drive->init_speed = speed;
+       if (cmd64x_tune_chipset(drive, speed))
+               return 0;
 
        return ide_dma_enable(drive);
 }
 
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                config_chipset_for_pio(drive, 1);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 static int cmd64x_alt_dma_status (struct pci_dev *dev)
@@ -518,13 +503,13 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
 
        drive->waiting_for_dma = 0;
        /* read DMA command state */
-       dma_cmd = hwif->INB(hwif->dma_command);
+       dma_cmd = inb(hwif->dma_command);
        /* stop DMA */
-       hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+       outb(dma_cmd & ~1, hwif->dma_command);
        /* get DMA status */
-       dma_stat = hwif->INB(hwif->dma_status);
+       dma_stat = inb(hwif->dma_status);
        /* clear the INTR & ERROR bits */
-       hwif->OUTB(dma_stat|6, hwif->dma_status);
+       outb(dma_stat | 6, hwif->dma_status);
        if (cmd64x_alt_dma_status(dev)) {
                u8 dma_intr     = 0;
                u8 dma_mask     = (hwif->channel) ? ARTTIM23_INTR_CH1 :
@@ -546,7 +531,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
        struct pci_dev *dev             = hwif->pci_dev;
         u8 dma_alt_stat = 0, mask      = (hwif->channel) ? MRDMODE_INTR_CH1 :
                                                            MRDMODE_INTR_CH0;
-       u8 dma_stat = hwif->INB(hwif->dma_status);
+       u8 dma_stat = inb(hwif->dma_status);
 
        (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
 #ifdef DEBUG
@@ -576,13 +561,13 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
 
        drive->waiting_for_dma = 0;
        /* get DMA status */
-       dma_stat = hwif->INB(hwif->dma_status);
+       dma_stat = inb(hwif->dma_status);
        /* read DMA command state */
-       dma_cmd = hwif->INB(hwif->dma_command);
+       dma_cmd = inb(hwif->dma_command);
        /* stop DMA */
-       hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+       outb(dma_cmd & ~1, hwif->dma_command);
        /* clear the INTR & ERROR bits */
-       hwif->OUTB(dma_stat|6, hwif->dma_status);
+       outb(dma_stat | 6, hwif->dma_status);
        /* and free any DMA resources */
        ide_destroy_dmatable(drive);
        /* verify good DMA status */
index ba6786aabf3baaf937c351fe55884537d6e31d5a..400859a839f7dcd9b1fb4c25b1796a98e87a12cb 100644 (file)
@@ -132,12 +132,11 @@ static void cs5520_tune_drive(ide_drive_t *drive, u8 pio)
 
 static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-
        /* Tune the drive for PIO modes up to PIO 4 */  
        cs5520_tune_drive(drive, 4);
+
        /* Then tell the core to use DMA operations */
-       return hwif->ide_dma_on(drive);
+       return 0;
 }
 
 /*
index 9bf5fdfc5b1fc56cca63ca623ed252871e08aee9..b2d7c132ef4b8cd3a6188e25964cb25b434450c6 100644 (file)
@@ -81,8 +81,8 @@ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio)      /* pio=255 means "autot
 
        pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
        if (!cs5530_set_xfer_mode(drive, modes[pio])) {
-               format = (hwif->INL(basereg+4) >> 31) & 1;
-               hwif->OUTL(cs5530_pio_timings[format][pio],
+               format = (inl(basereg + 4) >> 31) & 1;
+               outl(cs5530_pio_timings[format][pio],
                        basereg+(drive->select.b.unit<<3));
        }
 }
@@ -103,16 +103,13 @@ static int cs5530_config_dma (ide_drive_t *drive)
        int                     unit = drive->select.b.unit;
        ide_drive_t             *mate = &hwif->drives[unit^1];
        struct hd_driveid       *id = drive->id;
-       unsigned int            reg, timings;
+       unsigned int            reg, timings = 0;
        unsigned long           basereg;
 
        /*
         * Default to DMA-off in case we run into trouble here.
         */
-       hwif->ide_dma_off_quietly(drive);
-       /* turn off DMA while we fiddle */
-       hwif->ide_dma_host_off(drive);
-       /* clear DMA_capable bit */
+       hwif->dma_off_quietly(drive);
 
        /*
         * The CS5530 specifies that two drives sharing a cable cannot
@@ -182,30 +179,24 @@ static int cs5530_config_dma (ide_drive_t *drive)
                case XFER_MW_DMA_1:     timings = 0x00012121; break;
                case XFER_MW_DMA_2:     timings = 0x00002020; break;
                default:
-                       printk(KERN_ERR "%s: cs5530_config_dma: huh? mode=%02x\n",
-                               drive->name, mode);
-                       return 1;       /* failure */
+                       BUG();
+                       break;
        }
        basereg = CS5530_BASEREG(hwif);
-       reg = hwif->INL(basereg+4);             /* get drive0 config register */
+       reg = inl(basereg + 4);                 /* get drive0 config register */
        timings |= reg & 0x80000000;            /* preserve PIO format bit */
        if (unit == 0) {                        /* are we configuring drive0? */
-               hwif->OUTL(timings, basereg+4); /* write drive0 config register */
+               outl(timings, basereg + 4);     /* write drive0 config register */
        } else {
                if (timings & 0x00100000)
                        reg |=  0x00100000;     /* enable UDMA timings for both drives */
                else
                        reg &= ~0x00100000;     /* disable UDMA timings for both drives */
-               hwif->OUTL(reg,     basereg+4); /* write drive0 config register */
-               hwif->OUTL(timings, basereg+12);        /* write drive1 config register */
+               outl(reg, basereg + 4);         /* write drive0 config register */
+               outl(timings, basereg + 12);    /* write drive1 config register */
        }
-       (void) hwif->ide_dma_host_on(drive);
-       /* set DMA_capable bit */
 
-       /*
-        * Finally, turn DMA on in software, and exit.
-        */
-       return hwif->ide_dma_on(drive); /* success */
+       return 0;       /* success */
 }
 
 /**
@@ -321,17 +312,17 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
 
        hwif->tuneproc = &cs5530_tuneproc;
        basereg = CS5530_BASEREG(hwif);
-       d0_timings = hwif->INL(basereg+0);
+       d0_timings = inl(basereg + 0);
        if (CS5530_BAD_PIO(d0_timings)) {
                /* PIO timings not initialized? */
-               hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
                if (!hwif->drives[0].autotune)
                        hwif->drives[0].autotune = 1;
                        /* needs autotuning later */
        }
-       if (CS5530_BAD_PIO(hwif->INL(basereg+8))) {
-       /* PIO timings not initialized? */
-               hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+       if (CS5530_BAD_PIO(inl(basereg + 8))) {
+               /* PIO timings not initialized? */
+               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
                if (!hwif->drives[1].autotune)
                        hwif->drives[1].autotune = 1;
                        /* needs autotuning later */
index 5c5aec28e6717f3d9e7c81d243bc711ebf8b455b..45f43efbf92c856b4aaabf967cbab9ee87d33c9f 100644 (file)
@@ -195,28 +195,19 @@ static int cs5535_config_drive_for_dma(ide_drive_t *drive)
 
 static int cs5535_dma_check(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct hd_driveid *id   = drive->id;
        u8 speed;
 
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-               if (ide_use_dma(drive)) {
-                       if (cs5535_config_drive_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive)) {
                speed = ide_get_best_pio_mode(drive, 255, 4, NULL);
                cs5535_set_drive(drive, speed);
-               return hwif->ide_dma_off_quietly(drive);
        }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
index 9eafcbf444f4d0cb629ae14e00f354544113444c..103b9db97853046d38550e7c496de20a47460113 100644 (file)
@@ -197,8 +197,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
 #if CY82C693_DEBUG_LOGS
        /* for debug let's show the previous values */
 
-       HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
-       data = HWIF(drive)->INB(CY82_DATA_PORT);
+       outb(index, CY82_INDEX_PORT);
+       data = inb(CY82_DATA_PORT);
 
        printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
                drive->name, HWIF(drive)->channel, drive->select.b.unit,
@@ -207,8 +207,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
 
        data = (u8)mode|(u8)(single<<2);
 
-       HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
-       HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+       outb(index, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
@@ -227,8 +227,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
         */
 
        data = BUSMASTER_TIMEOUT;
-       HWIF(drive)->OUTB(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
-       HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+       outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO        
        printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
@@ -478,21 +478,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
        }
 }
 
-static ide_pci_device_t cy82c693_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "CY82C693",
-               .init_chipset   = init_chipset_cy82c693,
-               .init_iops      = init_iops_cy82c693,
-               .init_hwif      = init_hwif_cy82c693,
-               .channels       = 1,
-               .autodma        = AUTODMA,
-               .bootable       = ON_BOARD,
-       }
+static ide_pci_device_t cy82c693_chipset __devinitdata = {
+       .name           = "CY82C693",
+       .init_chipset   = init_chipset_cy82c693,
+       .init_iops      = init_iops_cy82c693,
+       .init_hwif      = init_hwif_cy82c693,
+       .channels       = 1,
+       .autodma        = AUTODMA,
+       .bootable       = ON_BOARD,
 };
 
 static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data];
        struct pci_dev *dev2;
        int ret = -ENODEV;
 
@@ -501,7 +498,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
         if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
            PCI_FUNC(dev->devfn) == 1) {
                dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
-               ret = ide_setup_pci_devices(dev, dev2, d);
+               ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
                /* We leak pci refs here but thats ok - we can't be unloaded */
        }
        return ret;
index ce7b08f08a0959fe428cec32ff01e1b218ed3afc..924eaa3a5708890e592dce1d7d130b769c37f25b 100644 (file)
@@ -48,19 +48,6 @@ static u8 hpt34x_ratemask (ide_drive_t *drive)
        return 1;
 }
 
-static void hpt34x_clear_chipset (ide_drive_t *drive)
-{
-       struct pci_dev *dev     = HWIF(drive)->pci_dev;
-       u32 reg1 = 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
-
-       pci_read_config_dword(dev, 0x44, &reg1);
-       pci_read_config_dword(dev, 0x48, &reg2);
-       tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
-       tmp2 = (reg2 & ~(0x11 << drive->dn));
-       pci_write_config_dword(dev, 0x44, tmp1);
-       pci_write_config_dword(dev, 0x48, tmp2);
-}
-
 static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
@@ -81,7 +68,7 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        pci_read_config_dword(dev, 0x44, &reg1);
        pci_read_config_dword(dev, 0x48, &reg2);
        tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
-       tmp2 = ((hi_speed << drive->dn) | reg2);
+       tmp2 = ((hi_speed << drive->dn) | (reg2 & ~(0x11 << drive->dn)));
        pci_write_config_dword(dev, 0x44, tmp1);
        pci_write_config_dword(dev, 0x48, tmp2);
 
@@ -99,7 +86,6 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio)
 {
        pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-       hpt34x_clear_chipset(drive);
        (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
@@ -117,38 +103,25 @@ static int config_chipset_for_dma (ide_drive_t *drive)
        if (!(speed))
                return 0;
 
-       hpt34x_clear_chipset(drive);
        (void) hpt34x_tune_chipset(drive, speed);
        return ide_dma_enable(drive);
 }
 
 static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if (id && (id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
 #ifndef CONFIG_HPT34X_AUTODMA
-                               return hwif->ide_dma_off_quietly(drive);
+               return -1;
 #else
-                               return hwif->ide_dma_on(drive);
+               return 0;
 #endif
-               }
-
-               goto fast_ata_pio;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                hpt34x_tune_drive(drive, 255);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 /*
@@ -209,7 +182,6 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
 
        hwif->tuneproc = &hpt34x_tune_drive;
        hwif->speedproc = &hpt34x_tune_chipset;
-       hwif->no_dsc = 1;
        hwif->drives[0].autotune = 1;
        hwif->drives[1].autotune = 1;
 
index 05be8fadda7ad25c023b992c6002ec343bcf2517..60ecdc258c7cbc1272edff2082c0e97c17ba98d4 100644 (file)
@@ -736,24 +736,15 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
 
 static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-               if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                hpt3xx_tune_drive(drive, 255);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 /*
@@ -841,7 +832,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
                return 0;
        }
 
-       dma_stat = hwif->INB(hwif->dma_status);
+       dma_stat = inb(hwif->dma_status);
        /* return 1 if INTR asserted */
        if (dma_stat & 4)
                return 1;
@@ -1391,9 +1382,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
        u8 dma_new      = 0, dma_old    = 0;
        unsigned long flags;
 
-       if (!dmabase)
-               return;
-               
        dma_old = hwif->INB(dmabase + 2);
 
        local_irq_save(flags);
index 63248b6909faf0ce5cc2471da359441740fd5b12..424f00bb160d6210047805002b101ca7ba3bac21 100644 (file)
@@ -244,17 +244,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 
 static int it8213_config_drive_for_dma (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
+       u8 pio;
 
-       if (ide_use_dma(drive)) {
-               if (config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-       }
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       hwif->speedproc(drive, XFER_PIO_0
-                       + ide_get_best_pio_mode(drive, 255, 4, NULL));
+       pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
+       it8213_tune_chipset(drive, XFER_PIO_0 + pio);
 
-       return hwif->ide_dma_off_quietly(drive);
+       return -1;
 }
 
 /**
index e9bad185968a8e289cd28f2844ac2578b6727373..a132767f7d90cfb637e606be18a0940703932cfd 100644 (file)
@@ -520,14 +520,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 
 static int it821x_config_drive_for_dma (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       if (ide_use_dma(drive)) {
-               if (config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-       }
        config_it821x_chipset_for_pio(drive, 1);
-       return hwif->ide_dma_off_quietly(drive);
+
+       return -1;
 }
 
 /**
@@ -608,11 +606,11 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
                                printk(".\n");
                        /* Now the core code will have wrongly decided no DMA
                           so we need to fix this */
-                       hwif->ide_dma_off_quietly(drive);
+                       hwif->dma_off_quietly(drive);
 #ifdef CONFIG_IDEDMA_ONLYDISK
                        if (drive->media == ide_disk)
 #endif
-                               hwif->ide_dma_check(drive);
+                               ide_set_dma(drive);
                } else {
                        /* Non RAID volume. Fixups to stop the core code
                           doing unsupported things */
index f07bbbed17783322627df81caeadabb49fe8d448..53f25500c22b57afdb2cc54f1daa2cd510070000 100644 (file)
@@ -147,7 +147,9 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 {
        u8 speed        = ide_dma_speed(drive, jmicron_ratemask(drive));
 
-       config_jmicron_chipset_for_pio(drive, !speed);
+       if (!speed)
+               return 0;
+
        jmicron_tune_chipset(drive, speed);
        return ide_dma_enable(drive);
 }
@@ -162,14 +164,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 
 static int jmicron_config_drive_for_dma (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       if (ide_use_dma(drive)) {
-               if (config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-       }
        config_jmicron_chipset_for_pio(drive, 1);
-       return hwif->ide_dma_off_quietly(drive);
+
+       return -1;
 }
 
 /**
index 8aaea4ea5549526c12b199d9d1bbe500509e53da..b310c4f510773c6f8aa2c9961fd72a7d7261b8ce 100644 (file)
@@ -166,10 +166,10 @@ static int ns87415_ide_dma_end (ide_drive_t *drive)
        /* get dma command mode */
        dma_cmd = hwif->INB(hwif->dma_command);
        /* stop DMA */
-       hwif->OUTB(dma_cmd & ~1, hwif->dma_command);
+       outb(dma_cmd & ~1, hwif->dma_command);
        /* from ERRATA: clear the INTR & ERROR bits */
        dma_cmd = hwif->INB(hwif->dma_command);
-       hwif->OUTB(dma_cmd|6, hwif->dma_command);
+       outb(dma_cmd | 6, hwif->dma_command);
        /* and free any DMA resources */
        ide_destroy_dmatable(drive);
        /* verify good DMA status */
@@ -190,7 +190,8 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
 static int ns87415_ide_dma_check (ide_drive_t *drive)
 {
        if (drive->media != ide_disk)
-               return HWIF(drive)->ide_dma_off_quietly(drive);
+               return -1;
+
        return __ide_dma_check(drive);
 }
 
@@ -243,9 +244,9 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
                 *      to SELECT_DRIVE() properly during first probe_hwif().
                 */
                timeout = 10000;
-               hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
                udelay(10);
-               hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
                do {
                        udelay(50);
                        stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
@@ -263,7 +264,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        if (!hwif->dma_base)
                return;
 
-       hwif->OUTB(0x60, hwif->dma_status);
+       outb(0x60, hwif->dma_status);
        hwif->dma_setup = &ns87415_ide_dma_setup;
        hwif->ide_dma_check = &ns87415_ide_dma_check;
        hwif->ide_dma_end = &ns87415_ide_dma_end;
index 22bbf613f94802ef74811b7907216a487d60f843..9ca60dd2185e636c70df8baa1464bae5965e3495 100644 (file)
@@ -176,34 +176,35 @@ static int cmpt_clk(int time, int bus_speed)
        return ((time*bus_speed+999)/1000);
 }
 
-static void write_reg(ide_hwif_t *hwif, u8 value, int reg)
 /* Write value to register reg, base of register
  * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
  * This is from setupvic.exe program.
  */
+static void write_reg(u8 value, int reg)
 {
-       hwif->INW(reg_base+1);
-       hwif->INW(reg_base+1);
-       hwif->OUTB(3, reg_base+2);
-       hwif->OUTB(value, reg_base+reg);
-       hwif->OUTB(0x83, reg_base+2);
+       inw(reg_base + 1);
+       inw(reg_base + 1);
+       outb(3, reg_base + 2);
+       outb(value, reg_base + reg);
+       outb(0x83, reg_base + 2);
 }
 
-static u8 read_reg(ide_hwif_t *hwif, int reg)
 /* Read value from register reg, base of register
  * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
  * This is from setupvic.exe program.
  */
+static u8 read_reg(int reg)
 {
        u8 ret = 0;
 
-       hwif->INW(reg_base+1);
-       hwif->INW(reg_base+1);
-       hwif->OUTB(3, reg_base+2);
-       ret = hwif->INB(reg_base+reg);
-       hwif->OUTB(0x83, reg_base+2);
+       inw(reg_base + 1);
+       inw(reg_base + 1);
+       outb(3, reg_base + 2);
+       ret = inb(reg_base + reg);
+       outb(0x83, reg_base + 2);
+
        return ret;
 }
 
@@ -286,39 +287,39 @@ static void opti621_tune_drive (ide_drive_t *drive, u8 pio)
        reg_base = hwif->io_ports[IDE_DATA_OFFSET];
 
        /* allow Register-B */
-       hwif->OUTB(0xc0, reg_base+CNTRL_REG);
+       outb(0xc0, reg_base + CNTRL_REG);
        /* hmm, setupvic.exe does this ;-) */
-       hwif->OUTB(0xff, reg_base+5);
+       outb(0xff, reg_base + 5);
        /* if reads 0xff, adapter not exist? */
-       (void) hwif->INB(reg_base+CNTRL_REG);
+       (void)inb(reg_base + CNTRL_REG);
        /* if reads 0xc0, no interface exist? */
-       read_reg(hwif, CNTRL_REG);
+       read_reg(CNTRL_REG);
        /* read version, probably 0 */
-       read_reg(hwif, STRAP_REG);
+       read_reg(STRAP_REG);
 
        /* program primary drive */
-               /* select Index-0 for Register-A */
-       write_reg(hwif, 0,      MISC_REG);
-               /* set read cycle timings */
-       write_reg(hwif, cycle1, READ_REG);
-               /* set write cycle timings */
-       write_reg(hwif, cycle1, WRITE_REG);
+       /* select Index-0 for Register-A */
+       write_reg(0, MISC_REG);
+       /* set read cycle timings */
+       write_reg(cycle1, READ_REG);
+       /* set write cycle timings */
+       write_reg(cycle1, WRITE_REG);
 
        /* program secondary drive */
-               /* select Index-1 for Register-B */
-       write_reg(hwif, 1,      MISC_REG);
-               /* set read cycle timings */
-       write_reg(hwif, cycle2, READ_REG);
-               /* set write cycle timings */
-       write_reg(hwif, cycle2, WRITE_REG);
+       /* select Index-1 for Register-B */
+       write_reg(1, MISC_REG);
+       /* set read cycle timings */
+       write_reg(cycle2, READ_REG);
+       /* set write cycle timings */
+       write_reg(cycle2, WRITE_REG);
 
        /* use Register-A for drive 0 */
        /* use Register-B for drive 1 */
-       write_reg(hwif, 0x85, CNTRL_REG);
+       write_reg(0x85, CNTRL_REG);
 
        /* set address setup, DRDY timings,   */
        /*  and read prefetch for both drives */
-       write_reg(hwif, misc, MISC_REG);
+       write_reg(misc, MISC_REG);
 
        spin_unlock_irqrestore(&ide_lock, flags);
 }
index 236a03144a2796c04e35e23ae137755e6a495abd..6ceb25bc5a7bb1109e22ff804a997dde62d66cc9 100644 (file)
@@ -101,8 +101,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
 {
        u8 value;
 
-       hwif->OUTB(index, hwif->dma_vendor1);
-       value = hwif->INB(hwif->dma_vendor3);
+       outb(index, hwif->dma_vendor1);
+       value = inb(hwif->dma_vendor3);
 
        DBG("index[%02X] value[%02X]\n", index, value);
        return value;
@@ -115,8 +115,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
  */
 static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
 {
-       hwif->OUTB(index, hwif->dma_vendor1);
-       hwif->OUTB(value, hwif->dma_vendor3);
+       outb(index, hwif->dma_vendor1);
+       outb(value, hwif->dma_vendor3);
        DBG("index[%02X] value[%02X]\n", index, value);
 }
 
@@ -281,25 +281,15 @@ static int config_chipset_for_dma(ide_drive_t *drive)
 
 static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-               goto fast_ata_pio;
+       if (ide_use_fast_pio(drive))
+               pdcnew_tune_drive(drive, 255);
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-               hwif->tuneproc(drive, 255);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+       return -1;
 }
 
 static int pdcnew_quirkproc(ide_drive_t *drive)
index 730e8d1ec2f56327db16a1d204d3340b19b4e9e1..a7a639fe1eaff2b4540f52160afc8163f1eef35f 100644 (file)
@@ -2,6 +2,7 @@
  *  linux/drivers/ide/pci/pdc202xx_old.c       Version 0.36    Sept 11, 2002
  *
  *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2006-2007            MontaVista Software, Inc.
  *
  *  Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
  *  compiled into the kernel if you have more than one card installed.
@@ -216,21 +217,10 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 }
 
 
-/*   0    1    2    3    4    5    6   7   8
- * 960, 480, 390, 300, 240, 180, 120, 90, 60
- *           180, 150, 120,  90,  60
- * DMA_Speed
- * 180, 120,  90,  90,  90,  60,  30
- *  11,   5,   4,   3,   2,   1,   0
- */
-static void config_chipset_for_pio (ide_drive_t *drive, u8 pio)
+static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
-       u8 speed = 0;
-
-       if (pio == 5) pio = 4;
-       speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
-        
-       pdc202xx_tune_chipset(drive, speed);
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       pdc202xx_tune_chipset(drive, XFER_PIO_0 + pio);
 }
 
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
@@ -250,17 +240,17 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
 static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
 {
        unsigned long clock_reg = hwif->dma_master + 0x11;
-       u8 clock = hwif->INB(clock_reg);
+       u8 clock = inb(clock_reg);
 
-       hwif->OUTB(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
+       outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
 static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
 {
        unsigned long clock_reg = hwif->dma_master + 0x11;
-       u8 clock = hwif->INB(clock_reg);
+       u8 clock = inb(clock_reg);
 
-       hwif->OUTB(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
+       outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
 static int config_chipset_for_dma (ide_drive_t *drive)
@@ -332,27 +322,15 @@ chipset_is_set:
 
 static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if (id && (id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-               goto fast_ata_pio;
+       if (ide_use_fast_pio(drive))
+               pdc202xx_tune_drive(drive, 255);
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-               hwif->tuneproc(drive, 5);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+       return -1;
 }
 
 static int pdc202xx_quirkproc (ide_drive_t *drive)
@@ -375,14 +353,14 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
                unsigned long high_16   = hwif->dma_master;
                unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
                u32 word_count  = 0;
-               u8 clock = hwif->INB(high_16 + 0x11);
+               u8 clock = inb(high_16 + 0x11);
 
-               hwif->OUTB(clock|(hwif->channel ? 0x08 : 0x02), high_16+0x11);
+               outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
                word_count = (rq->nr_sectors << 8);
                word_count = (rq_data_dir(rq) == READ) ?
                                        word_count | 0x05000000 :
                                        word_count | 0x06000000;
-               hwif->OUTL(word_count, atapi_reg);
+               outl(word_count, atapi_reg);
        }
        ide_dma_start(drive);
 }
@@ -395,9 +373,9 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
                unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
                u8 clock                = 0;
 
-               hwif->OUTL(0, atapi_reg); /* zero out extra */
-               clock = hwif->INB(high_16 + 0x11);
-               hwif->OUTB(clock & ~(hwif->channel ? 0x08:0x02), high_16+0x11);
+               outl(0, atapi_reg); /* zero out extra */
+               clock = inb(high_16 + 0x11);
+               outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
        }
        if (drive->current_speed > XFER_UDMA_2)
                pdc_old_disable_66MHz_clock(drive->hwif);
@@ -408,8 +386,8 @@ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long high_16   = hwif->dma_master;
-       u8 dma_stat             = hwif->INB(hwif->dma_status);
-       u8 sc1d                 = hwif->INB((high_16 + 0x001d));
+       u8 dma_stat             = inb(hwif->dma_status);
+       u8 sc1d                 = inb(high_16 + 0x001d);
 
        if (hwif->channel) {
                /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
@@ -445,11 +423,11 @@ static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
 {
        unsigned long high_16   = hwif->dma_master;
-       u8 udma_speed_flag      = hwif->INB(high_16|0x001f);
+       u8 udma_speed_flag      = inb(high_16 | 0x001f);
 
-       hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
+       outb(udma_speed_flag | 0x10, high_16 | 0x001f);
        mdelay(100);
-       hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f));
+       outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
        mdelay(2000);   /* 2 seconds ?! */
 
        printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
@@ -463,7 +441,7 @@ static void pdc202xx_reset (ide_drive_t *drive)
        
        pdc202xx_reset_host(hwif);
        pdc202xx_reset_host(mate);
-       hwif->tuneproc(drive, 5);
+       pdc202xx_tune_drive(drive, 255);
 }
 
 static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
@@ -490,7 +468,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
                hwif->rqsize = 256;
 
        hwif->autodma = 0;
-       hwif->tuneproc  = &config_chipset_for_pio;
+       hwif->tuneproc  = &pdc202xx_tune_drive;
        hwif->quirkproc = &pdc202xx_quirkproc;
 
        if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
@@ -537,9 +515,9 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
                return;
        }
 
-       udma_speed_flag = hwif->INB((dmabase|0x1f));
-       primary_mode    = hwif->INB((dmabase|0x1a));
-       secondary_mode  = hwif->INB((dmabase|0x1b));
+       udma_speed_flag = inb(dmabase | 0x1f);
+       primary_mode    = inb(dmabase | 0x1a);
+       secondary_mode  = inb(dmabase | 0x1b);
        printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
                "Primary %s Mode " \
                "Secondary %s Mode.\n", hwif->cds->name,
@@ -552,30 +530,10 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
                printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
                        hwif->cds->name, udma_speed_flag,
                        (udma_speed_flag|1));
-               hwif->OUTB(udma_speed_flag|1,(dmabase|0x1f));
-               printk("%sACTIVE\n",
-                       (hwif->INB(dmabase|0x1f)&1) ? "":"IN");
+               outb(udma_speed_flag | 1, dmabase | 0x1f);
+               printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
        }
 #endif /* CONFIG_PDC202XX_BURST */
-#ifdef CONFIG_PDC202XX_MASTER
-       if (!(primary_mode & 1)) {
-               printk(KERN_INFO "%s: FORCING PRIMARY MODE BIT "
-                       "0x%02x -> 0x%02x ", hwif->cds->name,
-                       primary_mode, (primary_mode|1));
-               hwif->OUTB(primary_mode|1, (dmabase|0x1a));
-               printk("%s\n",
-                       (hwif->INB((dmabase|0x1a)) & 1) ? "MASTER" : "PCI");
-       }
-
-       if (!(secondary_mode & 1)) {
-               printk(KERN_INFO "%s: FORCING SECONDARY MODE BIT "
-                       "0x%02x -> 0x%02x ", hwif->cds->name,
-                       secondary_mode, (secondary_mode|1));
-               hwif->OUTB(secondary_mode|1, (dmabase|0x1b));
-               printk("%s\n",
-                       (hwif->INB((dmabase|0x1b)) & 1) ? "MASTER" : "PCI");
-       }
-#endif /* CONFIG_PDC202XX_MASTER */
 
        ide_setup_dma(hwif, dmabase, 8);
 }
index 52cfc2ac22c124bc2030025ff937de9ebb2924ce..569822f4cf55d8ba28c79f9c385db511657b8d80 100644 (file)
@@ -369,7 +369,7 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
         * If no DMA speed was available or the chipset has DMA bugs
         * then disable DMA and use PIO
         */
-       if (!speed || no_piix_dma)
+       if (!speed)
                return 0;
 
        (void) piix_tune_chipset(drive, speed);
@@ -386,41 +386,28 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
  
 static int piix_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                /* Find best PIO mode. */
-               (void) hwif->speedproc(drive, XFER_PIO_0 +
-                                      ide_get_best_pio_mode(drive, 255, 4, NULL));
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+               piix_tune_chipset(drive, XFER_PIO_0 +
+                                 ide_get_best_pio_mode(drive, 255, 4, NULL));
+
+       return -1;
 }
 
 /**
- *     init_chipset_piix       -       set up the PIIX chipset
- *     @dev: PCI device to set up
- *     @name: Name of the device
+ *     piix_is_ichx    -       check if ICHx
+ *     @dev: PCI device to check
  *
- *     Initialize the PCI device as required. For the PIIX this turns
- *     out to be nice and simple
+ *     returns 1 if ICHx, 0 otherwise.
  */
-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+static int piix_is_ichx(struct pci_dev *dev)
 {
-        switch(dev->device) {
+        switch (dev->device) {
                case PCI_DEVICE_ID_INTEL_82801EB_1:
                case PCI_DEVICE_ID_INTEL_82801AA_1:
                case PCI_DEVICE_ID_INTEL_82801AB_1:
@@ -438,18 +425,60 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
                case PCI_DEVICE_ID_INTEL_ICH7_21:
                case PCI_DEVICE_ID_INTEL_ESB2_18:
                case PCI_DEVICE_ID_INTEL_ICH8_6:
-               {
-                       unsigned int extra = 0;
-                       pci_read_config_dword(dev, 0x54, &extra);
-                       pci_write_config_dword(dev, 0x54, extra|0x400);
-               }
-               default:
-                       break;
+                       return 1;
        }
 
        return 0;
 }
 
+/**
+ *     init_chipset_piix       -       set up the PIIX chipset
+ *     @dev: PCI device to set up
+ *     @name: Name of the device
+ *
+ *     Initialize the PCI device as required. For the PIIX this turns
+ *     out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+{
+       if (piix_is_ichx(dev)) {
+               unsigned int extra = 0;
+               pci_read_config_dword(dev, 0x54, &extra);
+               pci_write_config_dword(dev, 0x54, extra|0x400);
+       }
+
+       return 0;
+}
+
+/**
+ *     piix_dma_clear_irq      -       clear BMDMA status
+ *     @drive: IDE drive to clear
+ *
+ *     Called from ide_intr() for PIO interrupts
+ *     to clear BMDMA status as needed by ICHx
+ */
+static void piix_dma_clear_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u8 dma_stat;
+
+       /* clear the INTR & ERROR bits */
+       dma_stat = hwif->INB(hwif->dma_status);
+       /* Should we force the bit as well ? */
+       hwif->OUTB(dma_stat, hwif->dma_status);
+}
+
+static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = hwif->pci_dev;
+       u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+
+       pci_read_config_byte(dev, 0x54, &reg54h);
+
+       return (reg54h & mask) ? 1 : 0;
+}
+
 /**
  *     init_hwif_piix          -       fill in the hwif for the PIIX
  *     @hwif: IDE interface
@@ -460,9 +489,6 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
 
 static void __devinit init_hwif_piix(ide_hwif_t *hwif)
 {
-       u8 reg54h = 0, reg55h = 0, ata66 = 0;
-       u8 mask = hwif->channel ? 0xc0 : 0x30;
-
 #ifndef CONFIG_IA64
        if (!hwif->irq)
                hwif->irq = hwif->channel ? 15 : 14;
@@ -472,10 +498,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
                /* This is a painful system best to let it self tune for now */
                return;
        }
-       /* ESB2 appears to generate spurious DMA interrupts in PIO mode
-          when in native mode */
-       if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
-               hwif->atapi_irq_bogon = 1;
 
        hwif->autodma = 0;
        hwif->tuneproc = &piix_tune_drive;
@@ -486,15 +508,16 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
        if (!hwif->dma_base)
                return;
 
+       /* ICHx need to clear the bmdma status for all interrupts */
+       if (piix_is_ichx(hwif->pci_dev))
+               hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
+
        hwif->atapi_dma = 1;
        hwif->ultra_mask = 0x3f;
        hwif->mwdma_mask = 0x06;
        hwif->swdma_mask = 0x04;
 
        switch(hwif->pci_dev->device) {
-               case PCI_DEVICE_ID_INTEL_82371MX:
-                       hwif->mwdma_mask = 0x80;
-                       hwif->swdma_mask = 0x80;
                case PCI_DEVICE_ID_INTEL_82371FB_0:
                case PCI_DEVICE_ID_INTEL_82371FB_1:
                case PCI_DEVICE_ID_INTEL_82371SB_1:
@@ -507,14 +530,14 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
                        hwif->ultra_mask = 0x07;
                        break;
                default:
-                       pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
-                       pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
-                       ata66 = (reg54h & mask) ? 1 : 0;
+                       if (!hwif->udma_four)
+                               hwif->udma_four = piix_cable_detect(hwif);
                        break;
        }
 
-       if (!(hwif->udma_four))
-               hwif->udma_four = ata66;
+       if (no_piix_dma)
+               hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+
        hwif->ide_dma_check = &piix_config_drive_xfer_rate;
        if (!noautodma)
                hwif->autodma = 1;
index 8d762d323f8b654504a7fe85ffe499a2a14efc38..b5ae0c50e216423670508dd014bc18c68d4e9229 100644 (file)
@@ -161,7 +161,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
        /*
         * Default to DMA-off in case we run into trouble here.
         */
-       hwif->ide_dma_off_quietly(drive);                       /* turn off DMA while we fiddle */
+       hwif->dma_off_quietly(drive);   /* turn off DMA while we fiddle */
        outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
 
        /*
@@ -241,10 +241,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
 
        outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */
 
-       /*
-        * Finally, turn DMA on in software, and exit.
-        */
-       return hwif->ide_dma_on(drive); /* success */
+       return 0;       /* success */
 }
 
 /*
@@ -442,10 +439,10 @@ static int sc1200_resume (struct pci_dev *dev)
                        ide_drive_t *drive = &(hwif->drives[d]);
                        if (drive->present && !__ide_dma_bad_drive(drive)) {
                                int was_using_dma = drive->using_dma;
-                               hwif->ide_dma_off_quietly(drive);
+                               hwif->dma_off_quietly(drive);
                                sc1200_config_dma(drive);
                                if (!was_using_dma && drive->using_dma) {
-                                       hwif->ide_dma_off_quietly(drive);
+                                       hwif->dma_off_quietly(drive);
                                }
                        }
                }
index ea9a28a45853348d21cc59e3d2f2b764556ae0e8..dbcd37a0c65217138100ad6beac91fab1cb8b306 100644 (file)
@@ -160,7 +160,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
            (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
                if (!drive->init_speed) {
-                       u8 dma_stat = hwif->INB(hwif->dma_status);
+                       u8 dma_stat = inb(hwif->dma_status);
 
 dma_pio:
                        if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
@@ -315,35 +315,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 
 static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                config_chipset_for_pio(drive);
-               //      hwif->tuneproc(drive, 5);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
-}
-
-/* This can go soon */
 
-static int svwks_ide_dma_end (ide_drive_t *drive)
-{
-       return __ide_dma_end(drive);
+       return -1;
 }
 
 static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
@@ -537,35 +517,20 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
        }
 
        hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
-       if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
-               hwif->ide_dma_end = &svwks_ide_dma_end;
-       else if (!(hwif->udma_four))
-               hwif->udma_four = ata66_svwks(hwif);
+       if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+               if (!hwif->udma_four)
+                       hwif->udma_four = ata66_svwks(hwif);
+       }
        if (!noautodma)
                hwif->autodma = 1;
 
-       dma_stat = hwif->INB(hwif->dma_status);
+       dma_stat = inb(hwif->dma_status);
        hwif->drives[0].autodma = (dma_stat & 0x20);
        hwif->drives[1].autodma = (dma_stat & 0x40);
        hwif->drives[0].autotune = (!(dma_stat & 0x20));
        hwif->drives[1].autotune = (!(dma_stat & 0x40));
 }
 
-/*
- * We allow the BM-DMA driver to only work on enabled interfaces.
- */
-static void __devinit init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase)
-{
-       struct pci_dev *dev = hwif->pci_dev;
-
-       if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-            (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
-           (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel))
-               return;
-
-       ide_setup_dma(hwif, dmabase, 8);
-}
-
 static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
 {
        return ide_setup_pci_device(dev, d);
@@ -600,7 +565,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
                .init_setup     = init_setup_svwks,
                .init_chipset   = init_chipset_svwks,
                .init_hwif      = init_hwif_svwks,
-               .init_dma       = init_dma_svwks,
                .channels       = 2,
                .autodma        = AUTODMA,
                .bootable       = ON_BOARD,
@@ -609,7 +573,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
                .init_setup     = init_setup_csb6,
                .init_chipset   = init_chipset_svwks,
                .init_hwif      = init_hwif_svwks,
-               .init_dma       = init_dma_svwks,
                .channels       = 2,
                .autodma        = AUTODMA,
                .bootable       = ON_BOARD,
@@ -618,7 +581,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
                .init_setup     = init_setup_csb6,
                .init_chipset   = init_chipset_svwks,
                .init_hwif      = init_hwif_svwks,
-               .init_dma       = init_dma_svwks,
                .channels       = 1,    /* 2 */
                .autodma        = AUTODMA,
                .bootable       = ON_BOARD,
@@ -627,7 +589,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
                .init_setup     = init_setup_svwks,
                .init_chipset   = init_chipset_svwks,
                .init_hwif      = init_hwif_svwks,
-               .init_dma       = init_dma_svwks,
                .channels       = 1,    /* 2 */
                .autodma        = AUTODMA,
                .bootable       = ON_BOARD,
index b0bf01809279d976484e15a32b2f918ba303e347..fd09b295a69dd0b86c004ada223d03b289b18a14 100644 (file)
@@ -110,24 +110,24 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
 static void
 sgiioc4_maskproc(ide_drive_t * drive, int mask)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
-                  IDE_CONTROL_REG);
+       writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+              (void __iomem *)IDE_CONTROL_REG);
 }
 
 
 static int
 sgiioc4_checkirq(ide_hwif_t * hwif)
 {
-       u8 intr_reg =
-           hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4);
+       unsigned long intr_addr =
+               hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4;
 
-       if (intr_reg & 0x03)
+       if ((u8)readl((void __iomem *)intr_addr) & 0x03)
                return 1;
 
        return 0;
 }
 
+static u8 sgiioc4_INB(unsigned long);
 
 static int
 sgiioc4_clearirq(ide_drive_t * drive)
@@ -138,21 +138,21 @@ sgiioc4_clearirq(ide_drive_t * drive)
            hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
 
        /* Code to check for PCI error conditions */
-       intr_reg = hwif->INL(other_ir);
+       intr_reg = readl((void __iomem *)other_ir);
        if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
                /*
-                * Using hwif->INB to read the IDE_STATUS_REG has a side effect
+                * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect
                 * of clearing the interrupt.  The first read should clear it
                 * if it is set.  The second read should return a "clear" status
                 * if it got cleared.  If not, then spin for a bit trying to
                 * clear it.
                 */
-               u8 stat = hwif->INB(IDE_STATUS_REG);
+               u8 stat = sgiioc4_INB(IDE_STATUS_REG);
                int count = 0;
-               stat = hwif->INB(IDE_STATUS_REG);
+               stat = sgiioc4_INB(IDE_STATUS_REG);
                while ((stat & 0x80) && (count++ < 100)) {
                        udelay(1);
-                       stat = hwif->INB(IDE_STATUS_REG);
+                       stat = sgiioc4_INB(IDE_STATUS_REG);
                }
 
                if (intr_reg & 0x02) {
@@ -161,9 +161,9 @@ sgiioc4_clearirq(ide_drive_t * drive)
                            pci_stat_cmd_reg;
 
                        pci_err_addr_low =
-                               hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]);
+                               readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
                        pci_err_addr_high =
-                               hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4);
+                               readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
                        pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
                                              &pci_stat_cmd_reg);
                        printk(KERN_ERR
@@ -180,9 +180,9 @@ sgiioc4_clearirq(ide_drive_t * drive)
                }
 
                /* Clear the Interrupt, Error bits on the IOC4 */
-               hwif->OUTL(0x03, other_ir);
+               writel(0x03, (void __iomem *)other_ir);
 
-               intr_reg = hwif->INL(other_ir);
+               intr_reg = readl((void __iomem *)other_ir);
        }
 
        return intr_reg & 3;
@@ -191,23 +191,25 @@ sgiioc4_clearirq(ide_drive_t * drive)
 static void sgiioc4_ide_dma_start(ide_drive_t * drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
-       unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
+       unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
+       unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
        unsigned int temp_reg = reg | IOC4_S_DMA_START;
 
-       hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
+       writel(temp_reg, (void __iomem *)ioc4_dma_addr);
 }
 
 static u32
 sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
 {
+       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
        u32     ioc4_dma;
        int     count;
 
        count = 0;
-       ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
        while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
                udelay(1);
-               ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+               ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
        }
        return ioc4_dma;
 }
@@ -218,11 +220,11 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
 {
        u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
        ide_hwif_t *hwif = HWIF(drive);
-       u64 dma_base = hwif->dma_base;
+       unsigned long dma_base = hwif->dma_base;
        int dma_stat = 0;
        unsigned long *ending_dma = ide_get_hwifdata(hwif);
 
-       hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+       writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
 
        ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
@@ -254,8 +256,8 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
                dma_stat = 1;
        }
 
-       bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4);
-       bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4);
+       bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
+       bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
 
        if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
                if (bc_dev > bc_mem + 8) {
@@ -273,34 +275,29 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
 }
 
 static int
-sgiioc4_ide_dma_check(ide_drive_t * drive)
+sgiioc4_ide_dma_on(ide_drive_t * drive)
 {
-       if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
-               printk(KERN_INFO
-                      "Couldnot set %s in Multimode-2 DMA mode | "
-                          "Drive %s using PIO instead\n",
-                      drive->name, drive->name);
-               drive->using_dma = 0;
-       } else
-               drive->using_dma = 1;
+       drive->using_dma = 1;
 
        return 0;
 }
 
-static int
-sgiioc4_ide_dma_on(ide_drive_t * drive)
+static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
 {
-       drive->using_dma = 1;
+       drive->using_dma = 0;
 
-       return HWIF(drive)->ide_dma_host_on(drive);
+       drive->hwif->dma_host_off(drive);
 }
 
-static int
-sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
+static int sgiioc4_ide_dma_check(ide_drive_t *drive)
 {
-       drive->using_dma = 0;
-
-       return HWIF(drive)->ide_dma_host_off(drive);
+       /* FIXME: check for available DMA modes */
+       if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
+               printk(KERN_WARNING "%s: couldn't set MWDMA2 mode, "
+                                   "using PIO instead\n", drive->name);
+               return -1;
+       } else
+               return 0;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
@@ -310,21 +307,13 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
        return sgiioc4_checkirq(HWIF(drive));
 }
 
-static int
-sgiioc4_ide_dma_host_on(ide_drive_t * drive)
+static void sgiioc4_dma_host_on(ide_drive_t * drive)
 {
-       if (drive->using_dma)
-               return 0;
-
-       return 1;
 }
 
-static int
-sgiioc4_ide_dma_host_off(ide_drive_t * drive)
+static void sgiioc4_dma_host_off(ide_drive_t * drive)
 {
        sgiioc4_clearirq(drive);
-
-       return 0;
 }
 
 static int
@@ -436,16 +425,17 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
 {
        u32 ioc4_dma;
        ide_hwif_t *hwif = HWIF(drive);
-       u64 dma_base = hwif->dma_base;
+       unsigned long dma_base = hwif->dma_base;
+       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
        u32 dma_addr, ending_dma_addr;
 
-       ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 
        if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
                printk(KERN_WARNING
                        "%s(%s):Warning!! DMA from previous transfer was still active\n",
                       __FUNCTION__, drive->name);
-               hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
                ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
                if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -454,13 +444,13 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
                               __FUNCTION__, drive->name);
        }
 
-       ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
        if (ioc4_dma & IOC4_S_DMA_ERROR) {
                printk(KERN_WARNING
                       "%s(%s) : Warning!! - DMA Error during Previous"
                       " transfer | status 0x%x\n",
                       __FUNCTION__, drive->name, ioc4_dma);
-               hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
                ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
                if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -471,14 +461,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
 
        /* Address of the Scatter Gather List */
        dma_addr = cpu_to_le32(hwif->dmatable_dma);
-       hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4);
+       writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
 
        /* Address of the Ending DMA */
        memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
        ending_dma_addr = cpu_to_le32(hwif->dma_status);
-       hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4);
+       writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
 
-       hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4);
+       writel(dma_direction, (void __iomem *)ioc4_dma_addr);
        drive->waiting_for_dma = 1;
 }
 
@@ -590,7 +580,7 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
 static void __devinit
 ide_init_sgiioc4(ide_hwif_t * hwif)
 {
-       hwif->mmio = 2;
+       hwif->mmio = 1;
        hwif->autodma = 1;
        hwif->atapi_dma = 1;
        hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
@@ -613,10 +603,10 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
        hwif->ide_dma_end = &sgiioc4_ide_dma_end;
        hwif->ide_dma_check = &sgiioc4_ide_dma_check;
        hwif->ide_dma_on = &sgiioc4_ide_dma_on;
-       hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
+       hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
        hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
-       hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
-       hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
+       hwif->dma_host_on = &sgiioc4_dma_host_on;
+       hwif->dma_host_off = &sgiioc4_dma_host_off;
        hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
        hwif->ide_dma_timeout = &__ide_dma_timeout;
 
@@ -688,7 +678,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
        default_hwif_mmiops(hwif);
 
        /* Initializing chipset IRQ Registers */
-       hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
+       writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
        ide_init_sgiioc4(hwif);
 
@@ -729,8 +719,7 @@ out:
        return ret;
 }
 
-static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
-       {
+static ide_pci_device_t sgiioc4_chipset __devinitdata = {
         /* Channel 0 */
         .name = "SGIIOC4",
         .init_hwif = ide_init_sgiioc4,
@@ -739,7 +728,6 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
         .autodma = AUTODMA,
         /* SGI IOC4 doesn't have enablebits. */
         .bootable = ON_BOARD,
-       }
 };
 
 int
@@ -751,8 +739,7 @@ ioc4_ide_attach_one(struct ioc4_driver_data *idd)
        if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
                return 0;
 
-       return pci_init_sgiioc4(idd->idd_pdev,
-                               &sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
+       return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipset);
 }
 
 static struct ioc4_submodule ioc4_ide_submodule = {
index 4ff89c7d990a026c9475b6fa16a6c1eadbd6d0cd..7b4c189a9d99c81384a8500ca7c339995b495f07 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * linux/drivers/ide/pci/siimage.c             Version 1.07    Nov 30, 2003
+ * linux/drivers/ide/pci/siimage.c             Version 1.11    Jan 27, 2007
  *
  * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003          Red Hat <alan@redhat.com>
+ * Copyright (C) 2007          MontaVista Software, Inc.
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
@@ -205,41 +206,39 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted)
        unsigned long tfaddr    = siimage_selreg(hwif, 0x02);
        
        /* cheat for now and use the docs */
-       switch(mode_wanted) {
-               case 4: 
-                       speedp = 0x10c1; 
-                       speedt = 0x10c1;
-                       break;
-               case 3: 
-                       speedp = 0x10C3; 
-                       speedt = 0x10C3;
-                       break;
-               case 2: 
-                       speedp = 0x1104; 
-                       speedt = 0x1281;
-                       break;
-               case 1:         
-                       speedp = 0x2283; 
-                       speedt = 0x1281;
-                       break;
-               case 0:
-               default:
-                       speedp = 0x328A; 
-                       speedt = 0x328A;
-                       break;
+       switch (mode_wanted) {
+       case 4:
+               speedp = 0x10c1;
+               speedt = 0x10c1;
+               break;
+       case 3:
+               speedp = 0x10c3;
+               speedt = 0x10c3;
+               break;
+       case 2:
+               speedp = 0x1104;
+               speedt = 0x1281;
+               break;
+       case 1:
+               speedp = 0x2283;
+               speedt = 0x2283;
+               break;
+       case 0:
+       default:
+               speedp = 0x328a;
+               speedt = 0x328a;
+               break;
        }
-       if (hwif->mmio)
-       {
-               hwif->OUTW(speedt, addr);
-               hwif->OUTW(speedp, tfaddr);
+
+       if (hwif->mmio) {
+               hwif->OUTW(speedp, addr);
+               hwif->OUTW(speedt, tfaddr);
                /* Now set up IORDY */
                if(mode_wanted == 3 || mode_wanted == 4)
                        hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
                else
                        hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
-       }
-       else
-       {
+       } else {
                pci_write_config_word(hwif->pci_dev, addr, speedp);
                pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
                pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
@@ -397,12 +396,9 @@ static int config_chipset_for_dma (ide_drive_t *drive)
        if (!speed)
                return 0;
 
-       if (ide_set_xfer_rate(drive, speed))
+       if (siimage_tune_chipset(drive, speed))
                return 0;
 
-       if (!drive->init_speed)
-               drive->init_speed = speed;
-
        return ide_dma_enable(drive);
 }
 
@@ -418,25 +414,13 @@ static int config_chipset_for_dma (ide_drive_t *drive)
  
 static int siimage_config_drive_for_dma (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((id->capability & 1) != 0 && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                config_chipset_for_pio(drive, 1);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
@@ -472,11 +456,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
        unsigned long addr      = siimage_selreg(hwif, 0x1);
 
        if (SATA_ERROR_REG) {
-               u32 ext_stat = hwif->INL(base + 0x10);
+               u32 ext_stat = readl((void __iomem *)(base + 0x10));
                u8 watchdog = 0;
                if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
-                       u32 sata_error = hwif->INL(SATA_ERROR_REG);
-                       hwif->OUTL(sata_error, SATA_ERROR_REG);
+                       u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
+                       writel(sata_error, (void __iomem *)SATA_ERROR_REG);
                        watchdog = (sata_error & 0x00680000) ? 1 : 0;
                        printk(KERN_WARNING "%s: sata_error = 0x%08x, "
                                "watchdog = %d, %s\n",
@@ -493,11 +477,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
        }
 
        /* return 1 if INTR asserted */
-       if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04)
+       if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04)
                return 1;
 
        /* return 1 if Device INTR asserted */
-       if ((hwif->INB(addr) & 8) == 8)
+       if ((readb((void __iomem *)addr) & 8) == 8)
                return 0;       //return 1;
 
        return 0;
@@ -519,9 +503,9 @@ static int siimage_busproc (ide_drive_t * drive, int state)
        u32 stat_config         = 0;
        unsigned long addr      = siimage_selreg(hwif, 0);
 
-       if (hwif->mmio) {
-               stat_config = hwif->INL(addr);
-       else
+       if (hwif->mmio)
+               stat_config = readl((void __iomem *)addr);
+       else
                pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
 
        switch (state) {
@@ -557,9 +541,10 @@ static int siimage_reset_poll (ide_drive_t *drive)
        if (SATA_STATUS_REG) {
                ide_hwif_t *hwif        = HWIF(drive);
 
-               if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) {
+               /* SATA_STATUS_REG is valid only when in MMIO mode */
+               if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
                        printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
-                               hwif->name, hwif->INL(SATA_STATUS_REG));
+                               hwif->name, readl((void __iomem *)SATA_STATUS_REG));
                        HWGROUP(drive)->polling = 0;
                        return ide_started;
                }
@@ -619,7 +604,8 @@ static void siimage_reset (ide_drive_t *drive)
        }
 
        if (SATA_STATUS_REG) {
-               u32 sata_stat = hwif->INL(SATA_STATUS_REG);
+               /* SATA_STATUS_REG is valid only when in MMIO mode */
+               u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG);
                printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",
                        hwif->name, sata_stat, __FUNCTION__);
                if (!(sata_stat)) {
@@ -898,7 +884,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
                base = (unsigned long) addr;
 
        hwif->dma_base                  = base + (ch ? 0x08 : 0x00);
-       hwif->mmio                      = 2;
+
+       hwif->mmio = 1;
 }
 
 static int is_dev_seagate_sata(ide_drive_t *drive)
index 1afff659ab5544e8c87918d91d595093ed1d09a2..2ba0669f36a17bd066546a56f7e49324162c91d8 100644 (file)
@@ -667,67 +667,20 @@ static int config_chipset_for_dma (ide_drive_t *drive)
        return ide_dma_enable(drive);
 }
 
-static int sis5513_config_drive_xfer_rate (ide_drive_t *drive)
+static int sis5513_config_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
+       config_art_rwp_pio(drive, 5);
 
        drive->init_speed = 0;
 
-       if (id && (id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                sis5513_tune_drive(drive, 5);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
-}
-
-/* initiates/aborts (U)DMA read/write operations on a drive. */
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
-       config_drive_art_rwp(drive);
-       config_art_rwp_pio(drive, 5);
-       return sis5513_config_drive_xfer_rate(drive);
-}
-
-/*
-  Future simpler config_xfer_rate :
-   When ide_find_best_mode is made bad-drive aware
-   - remove config_drive_xfer_rate and config_chipset_for_dma,
-   - replace config_xfer_rate with the following
-
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
-       u16 w80 = HWIF(drive)->udma_four;
-       u16 speed;
-
-       config_drive_art_rwp(drive);
-       config_art_rwp_pio(drive, 5);
-
-       speed = ide_find_best_mode(drive,
-               XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
-               (chipset_family >= ATA_33 ? XFER_UDMA : 0) |
-               (w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) |
-               (w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) |
-               (w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0));
-
-       sis5513_tune_chipset(drive, speed);
 
-       if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-               return HWIF(drive)->ide_dma_on(drive);
-       return HWIF(drive)->ide_dma_off_quietly(drive);
+       return -1;
 }
-*/
 
 /* Chip detection and general config */
 static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
index 170a261990506b5e4ed2661982d76295ca0a311e..3a8a76fc78c78b0c9e201039277d34f5252650aa 100644 (file)
@@ -161,14 +161,14 @@ static int sl82c105_check_drive (ide_drive_t *drive)
                if (id->field_valid & 2) {
                        if ((id->dma_mword & hwif->mwdma_mask) ||
                            (id->dma_1word & hwif->swdma_mask))
-                               return hwif->ide_dma_on(drive);
+                               return 0;
                }
 
-               if (__ide_dma_good_drive(drive))
-                       return hwif->ide_dma_on(drive);
+               if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
+                       return 0;
        } while (0);
 
-       return hwif->ide_dma_off_quietly(drive);
+       return -1;
 }
 
 /*
@@ -215,7 +215,7 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
         * Was DMA enabled?  If so, disable it - we're resetting the
         * host.  The IDE layer will be handling the drive for us.
         */
-       val = hwif->INB(dma_base);
+       val = inb(dma_base);
        if (val & 1) {
                outb(val & ~1, dma_base);
                printk("sl82c105: DMA was enabled\n");
@@ -259,28 +259,22 @@ static int sl82c105_ide_dma_on (ide_drive_t *drive)
 {
        DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
 
-       if (config_for_dma(drive)) {
-               config_for_pio(drive, 4, 0, 0);
-               return HWIF(drive)->ide_dma_off_quietly(drive);
-       }
+       if (config_for_dma(drive))
+               return 1;
        printk(KERN_INFO "%s: DMA enabled\n", drive->name);
        return __ide_dma_on(drive);
 }
 
-static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive)
+static void sl82c105_dma_off_quietly(ide_drive_t *drive)
 {
        u8 speed = XFER_PIO_0;
-       int rc;
-       
-       DBG(("sl82c105_ide_dma_off_quietly(drive:%s)\n", drive->name));
 
-       rc = __ide_dma_off_quietly(drive);
+       DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
+
+       ide_dma_off_quietly(drive);
        if (drive->pio_speed)
                speed = drive->pio_speed - XFER_PIO_0;
        config_for_pio(drive, speed, 0, 1);
-       drive->current_speed = drive->pio_speed;
-
-       return rc;
 }
 
 /*
@@ -401,11 +395,9 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
 /*
  * Initialise the chip
  */
-
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
        unsigned int rev;
-       u8 dma_state;
 
        DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
@@ -431,7 +423,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
        if (!hwif->dma_base)
                return;
 
-       dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60;
        rev = sl82c105_bridge_revision(hwif->pci_dev);
        if (rev <= 5) {
                /*
@@ -441,15 +432,12 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
                printk("    %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
                       hwif->name, rev);
        } else {
-               dma_state |= 0x60;
-
                hwif->atapi_dma = 1;
-               hwif->mwdma_mask = 0x07;
-               hwif->swdma_mask = 0x07;
+               hwif->mwdma_mask = 0x04;
 
                hwif->ide_dma_check = &sl82c105_check_drive;
                hwif->ide_dma_on = &sl82c105_ide_dma_on;
-               hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly;
+               hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
                hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
                hwif->dma_start = &sl82c105_ide_dma_start;
                hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
@@ -462,7 +450,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
                if (hwif->mate)
                        hwif->serialized = hwif->mate->serialized = 1;
        }
-       hwif->OUTB(dma_state, hwif->dma_base + 2);
 }
 
 static ide_pci_device_t sl82c105_chipset __devinitdata = {
index 2663ddbd9b67408bbdb68db54eece1c2beec552b..ae7eb58d961c6f46a27c153aec56dee407befe84 100644 (file)
@@ -179,26 +179,16 @@ static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
 
 static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
+       if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
+               return 0;
 
-               goto fast_ata_pio;
+       if (ide_use_fast_pio(drive))
+               (void)slc90e66_tune_chipset(drive, XFER_PIO_0 +
+                               ide_get_best_pio_mode(drive, 255, 4, NULL));
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-               (void) hwif->speedproc(drive, XFER_PIO_0 +
-                                      ide_get_best_pio_mode(drive, 255, 4, NULL));
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+       return -1;
 }
 
 static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
index 2ad72bbda34217bb3b351bda50065ee5d5385b4f..0b6d81d6ce488926dd01bcc87996559423d94bfd 100644 (file)
@@ -45,7 +45,7 @@ static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed)
 
        scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
        scr |= mode;
-       hwif->OUTW(scr, scr_port);
+       outw(scr, scr_port);
 
        return ide_config_drive_speed(drive, speed);
 }
@@ -89,15 +89,15 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
                       "attempting recovery...\n", drive->name);
 
                /* Stop DMA */
-               hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command);
+               outb(dma_cmd & ~0x01, hwif->dma_command);
 
                /* Setup the dummy DMA transfer */
-               hwif->OUTW(0, sc_base + 0x0a);  /* Sector Count */
-               hwif->OUTW(0, twcr_port);       /* Transfer Word Count 1 or 2 */
+               outw(0, sc_base + 0x0a);        /* Sector Count */
+               outw(0, twcr_port);     /* Transfer Word Count 1 or 2 */
 
                /* Start the dummy DMA transfer */
-               hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
-               hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */
+               outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
+               outb(0x01, hwif->dma_command); /* set START_STOPBM */
 
                /*
                 * If an interrupt was pending, it should come thru shortly.
@@ -128,8 +128,8 @@ static void tc86c001_dma_start(ide_drive_t *drive)
         * the appropriate system control registers for DMA to work
         * with LBA48 and ATAPI devices...
         */
-       hwif->OUTW(nsectors, sc_base + 0x0a);   /* Sector Count */
-       hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
+       outw(nsectors, sc_base + 0x0a); /* Sector Count */
+       outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
 
        /* Install our timeout expiry hook, saving the current handler... */
        ide_set_hwifdata(hwif, hwgroup->expiry);
@@ -168,7 +168,7 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
        }
 
        /* System Control 1 Register bit 11 (ATA Hard Reset) write */
-       hwif->OUTW(scr1, sc_base + 0x00);
+       outw(scr1, sc_base + 0x00);
        return 0;
 }
 
@@ -185,23 +185,13 @@ static int config_chipset_for_dma(ide_drive_t *drive)
 
 static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-                       return hwif->ide_dma_on(drive);
-
-               goto fast_ata_pio;
+       if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+               return 0;
 
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+       if (ide_use_fast_pio(drive))
                tc86c001_tune_drive(drive, 255);
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       /* IORDY not supported */
-       return 0;
+
+       return -1;
 }
 
 static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
@@ -210,13 +200,13 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
        u16 scr1                = hwif->INW(sc_base + 0x00);;
 
        /* System Control 1 Register bit 15 (Soft Reset) set */
-       hwif->OUTW(scr1 |  0x8000, sc_base + 0x00);
+       outw(scr1 |  0x8000, sc_base + 0x00);
 
        /* System Control 1 Register bit 14 (FIFO Reset) set */
-       hwif->OUTW(scr1 |  0x4000, sc_base + 0x00);
+       outw(scr1 |  0x4000, sc_base + 0x00);
 
        /* System Control 1 Register: reset clear */
-       hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00);
+       outw(scr1 & ~0xc000, sc_base + 0x00);
 
        /* Store the system control register base for convenience... */
        hwif->config_data = sc_base;
@@ -234,7 +224,7 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
         * Sector Count Control Register bits 0 and 1 set:
         * software sets Sector Count Register for master and slave device
         */
-       hwif->OUTW(0x0003, sc_base + 0x0c);
+       outw(0x0003, sc_base + 0x0c);
 
        /* Sector Count Register limit */
        hwif->rqsize     = 0xffff;
index b13cce1fd1a6aa7e973b5e7d621d2af33a6984c1..5e06179c3469ed4a1fc7956d60fd95e389a630a2 100644 (file)
@@ -104,29 +104,21 @@ static int triflex_config_drive_for_dma(ide_drive_t *drive)
 {
        int speed = ide_dma_speed(drive, 0); /* No ultra speeds */
 
-       if (!speed) { 
-               u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL);
-               speed = XFER_PIO_0 + pspeed;
-       }
-       
+       if (!speed)
+               return 0;
+
        (void) triflex_tune_chipset(drive, speed);
         return ide_dma_enable(drive);
 }
 
 static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((id->capability & 1) && drive->autodma) {
-               if (ide_use_dma(drive)) {
-                       if (triflex_config_drive_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
-       }
+       if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive))
+               return 0;
+
+       triflex_tune_drive(drive, 255);
 
-       hwif->tuneproc(drive, 255);
-       return hwif->ide_dma_off_quietly(drive);
+       return -1;
 }
 
 static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
index 174b88c4780ef276c363f1498efdce576915dd44..cbb1b11119a520b9b0c8db24d796fb7c931832f3 100644 (file)
@@ -157,16 +157,16 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
        if (reg != hwif->select_data) {
                hwif->select_data = reg;
                /* set PIO/DMA */
-               hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
-               hwif->OUTW(reg & 0xff, hwif->config_data);
+               outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+               outw(reg & 0xff, hwif->config_data);
        }
 
        /* enable IRQ if not probing */
        if (drive->present) {
-               reg = hwif->INW(hwif->config_data + 3);
+               reg = inw(hwif->config_data + 3);
                reg &= 0x13;
                reg &= ~(1 << hwif->channel);
-               hwif->OUTW(reg, hwif->config_data+3);
+               outw(reg, hwif->config_data + 3);
        }
 
        local_irq_restore(flags);
@@ -177,15 +177,12 @@ static void trm290_selectproc (ide_drive_t *drive)
        trm290_prepare_drive(drive, drive->using_dma);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-
        BUG_ON(HWGROUP(drive)->handler != NULL);        /* paranoia check */
        ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
        /* issue cmd to drive */
-       hwif->OUTB(command, IDE_COMMAND_REG);
+       outb(command, IDE_COMMAND_REG);
 }
 
 static int trm290_ide_dma_setup(ide_drive_t *drive)
@@ -211,10 +208,10 @@ static int trm290_ide_dma_setup(ide_drive_t *drive)
        }
        /* select DMA xfer */
        trm290_prepare_drive(drive, 1);
-       hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command);
+       outl(hwif->dmatable_dma | rw, hwif->dma_command);
        drive->waiting_for_dma = 1;
        /* start DMA */
-       hwif->OUTW((count * 2) - 1, hwif->dma_status);
+       outw((count * 2) - 1, hwif->dma_status);
        return 0;
 }
 
@@ -230,7 +227,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive)
        drive->waiting_for_dma = 0;
        /* purge DMA mappings */
        ide_destroy_dmatable(drive);
-       status = hwif->INW(hwif->dma_status);
+       status = inw(hwif->dma_status);
        return (status != 0x00ff);
 }
 
@@ -239,10 +236,9 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive)
        ide_hwif_t *hwif = HWIF(drive);
        u16 status = 0;
 
-       status = hwif->INW(hwif->dma_status);
+       status = inw(hwif->dma_status);
        return (status == 0x00ff);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * Invoked from ide-dma.c at boot time.
@@ -269,15 +265,15 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
 
        local_irq_save(flags);
        /* put config reg into first byte of hwif->select_data */
-       hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
+       outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
        /* select PIO as default */
        hwif->select_data = 0x21;
-       hwif->OUTB(hwif->select_data, hwif->config_data);
+       outb(hwif->select_data, hwif->config_data);
        /* get IRQ info */
-       reg = hwif->INB(hwif->config_data+3);
+       reg = inb(hwif->config_data + 3);
        /* mask IRQs for both ports */
        reg = (reg & 0x10) | 0x03;
-       hwif->OUTB(reg, hwif->config_data+3);
+       outb(reg, hwif->config_data + 3);
        local_irq_restore(flags);
 
        if ((reg & 0x10))
@@ -289,13 +285,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
 
        ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
        hwif->dma_setup = &trm290_ide_dma_setup;
        hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd;
        hwif->dma_start = &trm290_ide_dma_start;
        hwif->ide_dma_end = &trm290_ide_dma_end;
        hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
        hwif->selectproc = &trm290_selectproc;
        hwif->autodma = 0;              /* play it safe for now */
@@ -312,16 +306,16 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
                static u16 next_offset = 0;
                u8 old_mask;
 
-               hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1);
-               old = hwif->INW(hwif->config_data);
+               outb(0x54 | (hwif->channel << 3), hwif->config_data + 1);
+               old = inw(hwif->config_data);
                old &= ~1;
-               old_mask = hwif->INB(old+2);
+               old_mask = inb(old + 2);
                if (old != compat && old_mask == 0xff) {
                        /* leave lower 10 bits untouched */
                        compat += (next_offset += 0x400);
                        hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
-                       hwif->OUTW(compat|1, hwif->config_data);
-                       new = hwif->INW(hwif->config_data);
+                       outw(compat | 1, hwif->config_data);
+                       new = inw(hwif->config_data);
                        printk(KERN_INFO "%s: control basereg workaround: "
                                "old=0x%04x, new=0x%04x\n",
                                hwif->name, old, new & ~1);
index 6fb6e50b82312131b1b3ac45f29f927c0f6a7e07..a508550c4095cecb0a43ffb474ca4d94b531d30b 100644 (file)
@@ -240,8 +240,9 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
        via_set_drive(drive, speed);
 
        if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-               return hwif->ide_dma_on(drive);
-       return hwif->ide_dma_off_quietly(drive);
+               return 0;
+
+       return -1;
 }
 
 static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
index 0ac9da3a7378b327c21e66c96d2d29765a993d9d..82de2d781f2ea24da3b1c8e0c49d907d03b1d4bb 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
index 91c5344a945d5375e14103743990d19ca86c6792..395d35253d5d0084bb9cd823eb2cb1658abb10b4 100644 (file)
@@ -24,7 +24,6 @@
  */
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
@@ -1238,7 +1237,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
                hwif->OUTBSYNC = pmac_outbsync;
 
        /* Tell common code _not_ to mess with resources */
-       hwif->mmio = 2;
+       hwif->mmio = 1;
        hwif->hwif_data = pmif;
        pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq);
        memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
@@ -1980,16 +1979,12 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
        return 1;
 }
 
-static int
-pmac_ide_dma_host_off (ide_drive_t *drive)
+static void pmac_ide_dma_host_off(ide_drive_t *drive)
 {
-       return 0;
 }
 
-static int
-pmac_ide_dma_host_on (ide_drive_t *drive)
+static int pmac_ide_dma_host_on(ide_drive_t *drive)
 {
-       return 0;
 }
 
 static int
@@ -2035,7 +2030,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
                return;
        }
 
-       hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
+       hwif->dma_off_quietly = &ide_dma_off_quietly;
        hwif->ide_dma_on = &__ide_dma_on;
        hwif->ide_dma_check = &pmac_ide_dma_check;
        hwif->dma_setup = &pmac_ide_dma_setup;
@@ -2043,8 +2038,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
        hwif->dma_start = &pmac_ide_dma_start;
        hwif->ide_dma_end = &pmac_ide_dma_end;
        hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
-       hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
-       hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
+       hwif->dma_host_off = &pmac_ide_dma_host_off;
+       hwif->dma_host_on = &pmac_ide_dma_host_on;
        hwif->ide_dma_timeout = &__ide_dma_timeout;
        hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
 
diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/ppc/scc_pata.c
new file mode 100644 (file)
index 0000000..de64b02
--- /dev/null
@@ -0,0 +1,831 @@
+/*
+ * Support for IDE interfaces on Celleb platform
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on drivers/ide/pci/siimage.c:
+ * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003          Red Hat <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA            0x01b4
+
+#define SCC_PATA_NAME           "scc IDE"
+
+#define TDVHSEL_MASTER          0x00000001
+#define TDVHSEL_SLAVE           0x00000004
+
+#define MODE_JCUSFEN            0x00000080
+
+#define CCKCTRL_ATARESET        0x00040000
+#define CCKCTRL_BUFCNT          0x00020000
+#define CCKCTRL_CRST            0x00010000
+#define CCKCTRL_OCLKEN          0x00000100
+#define CCKCTRL_ATACLKOEN       0x00000002
+#define CCKCTRL_LCLKEN          0x00000001
+
+#define QCHCD_IOS_SS           0x00000001
+
+#define QCHSD_STPDIAG          0x00020000
+
+#define INTMASK_MSK             0xD1000012
+#define INTSTS_SERROR          0x80000000
+#define INTSTS_PRERR           0x40000000
+#define INTSTS_RERR            0x10000000
+#define INTSTS_ICERR           0x01000000
+#define INTSTS_BMSINT          0x00000010
+#define INTSTS_BMHE            0x00000008
+#define INTSTS_IOIRQS           0x00000004
+#define INTSTS_INTRQ            0x00000002
+#define INTSTS_ACTEINT          0x00000001
+
+#define ECMODE_VALUE 0x01
+
+static struct scc_ports {
+       unsigned long ctl, dma;
+       unsigned char hwif_id;  /* for removing hwif from system */
+} scc_ports[MAX_HWIFS];
+
+/* PIO transfer mode  table */
+/* JCHST */
+static unsigned long JCHSTtbl[2][7] = {
+       {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00},   /* 100MHz */
+       {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHHT */
+static unsigned long JCHHTtbl[2][7] = {
+       {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00},   /* 100MHz */
+       {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHCT */
+static unsigned long JCHCTtbl[2][7] = {
+       {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00},   /* 100MHz */
+       {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00}    /* 133MHz */
+};
+
+
+/* DMA transfer mode  table */
+/* JCHDCTM/JCHDCTS */
+static unsigned long JCHDCTxtbl[2][7] = {
+       {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00},   /* 100MHz */
+       {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00}    /* 133MHz */
+};
+
+/* JCSTWTM/JCSTWTS  */
+static unsigned long JCSTWTxtbl[2][7] = {
+       {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00},   /* 100MHz */
+       {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCTSS */
+static unsigned long JCTSStbl[2][7] = {
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00},   /* 100MHz */
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}    /* 133MHz */
+};
+
+/* JCENVT */
+static unsigned long JCENVTtbl[2][7] = {
+       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00},   /* 100MHz */
+       {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCACTSELS/JCACTSELM */
+static unsigned long JCACTSELtbl[2][7] = {
+       {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00},   /* 100MHz */
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}    /* 133MHz */
+};
+
+
+static u8 scc_ide_inb(unsigned long port)
+{
+       u32 data = in_be32((void*)port);
+       return (u8)data;
+}
+
+static u16 scc_ide_inw(unsigned long port)
+{
+       u32 data = in_be32((void*)port);
+       return (u16)data;
+}
+
+static void scc_ide_insw(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+       }
+}
+
+static void scc_ide_insl(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+       }
+}
+
+static void scc_ide_outb(u8 addr, unsigned long port)
+{
+       out_be32((void*)port, addr);
+}
+
+static void scc_ide_outw(u16 addr, unsigned long port)
+{
+       out_be32((void*)port, addr);
+}
+
+static void
+scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+
+       out_be32((void*)port, addr);
+       __asm__ __volatile__("eieio":::"memory");
+       in_be32((void*)(hwif->dma_base + 0x01c));
+       __asm__ __volatile__("eieio":::"memory");
+}
+
+static void
+scc_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+       }
+}
+
+static void
+scc_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+       }
+}
+
+/**
+ *     scc_ratemask    -       Compute available modes
+ *     @drive: IDE drive
+ *
+ *     Compute the available speeds for the devices on the interface.
+ *     Enforce UDMA33 as a limit if there is no 80pin cable present.
+ */
+
+static u8 scc_ratemask(ide_drive_t *drive)
+{
+       u8 mode = 4;
+
+       if (!eighty_ninty_three(drive))
+               mode = min(mode, (u8)1);
+       return mode;
+}
+
+/**
+ *     scc_tuneproc    -       tune a drive PIO mode
+ *     @drive: drive to tune
+ *     @mode_wanted: the target operating mode
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller.
+ */
+
+static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct scc_ports *ports = ide_get_hwifdata(hwif);
+       unsigned long ctl_base = ports->ctl;
+       unsigned long cckctrl_port = ctl_base + 0xff0;
+       unsigned long piosht_port = ctl_base + 0x000;
+       unsigned long pioct_port = ctl_base + 0x004;
+       unsigned long reg;
+       unsigned char speed = XFER_PIO_0;
+       int offset;
+
+       mode_wanted = ide_get_best_pio_mode(drive, mode_wanted, 4, NULL);
+       switch (mode_wanted) {
+       case 4:
+               speed = XFER_PIO_4;
+               break;
+       case 3:
+               speed = XFER_PIO_3;
+               break;
+       case 2:
+               speed = XFER_PIO_2;
+               break;
+       case 1:
+               speed = XFER_PIO_1;
+               break;
+       case 0:
+       default:
+               speed = XFER_PIO_0;
+               break;
+       }
+
+       reg = in_be32((void __iomem *)cckctrl_port);
+       if (reg & CCKCTRL_ATACLKOEN) {
+               offset = 1; /* 133MHz */
+       } else {
+               offset = 0; /* 100MHz */
+       }
+       reg = JCHSTtbl[offset][mode_wanted] << 16 | JCHHTtbl[offset][mode_wanted];
+       out_be32((void __iomem *)piosht_port, reg);
+       reg = JCHCTtbl[offset][mode_wanted];
+       out_be32((void __iomem *)pioct_port, reg);
+
+       ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *     scc_tune_chipset        -       tune a drive DMA mode
+ *     @drive: Drive to set up
+ *     @xferspeed: speed we want to achieve
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller.
+ */
+
+static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed);
+       struct scc_ports *ports = ide_get_hwifdata(hwif);
+       unsigned long ctl_base = ports->ctl;
+       unsigned long cckctrl_port = ctl_base + 0xff0;
+       unsigned long mdmact_port = ctl_base + 0x008;
+       unsigned long mcrcst_port = ctl_base + 0x00c;
+       unsigned long sdmact_port = ctl_base + 0x010;
+       unsigned long scrcst_port = ctl_base + 0x014;
+       unsigned long udenvt_port = ctl_base + 0x018;
+       unsigned long tdvhsel_port   = ctl_base + 0x020;
+       int is_slave = (&hwif->drives[1] == drive);
+       int offset, idx;
+       unsigned long reg;
+       unsigned long jcactsel;
+
+       reg = in_be32((void __iomem *)cckctrl_port);
+       if (reg & CCKCTRL_ATACLKOEN) {
+               offset = 1; /* 133MHz */
+       } else {
+               offset = 0; /* 100MHz */
+       }
+
+       switch (speed) {
+       case XFER_UDMA_6:
+               idx = 6;
+               break;
+       case XFER_UDMA_5:
+               idx = 5;
+               break;
+       case XFER_UDMA_4:
+               idx = 4;
+               break;
+       case XFER_UDMA_3:
+               idx = 3;
+               break;
+       case XFER_UDMA_2:
+               idx = 2;
+               break;
+       case XFER_UDMA_1:
+               idx = 1;
+               break;
+       case XFER_UDMA_0:
+               idx = 0;
+               break;
+       default:
+               return 1;
+       }
+
+       jcactsel = JCACTSELtbl[offset][idx];
+       if (is_slave) {
+               out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
+               jcactsel = jcactsel << 2;
+               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
+       } else {
+               out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
+               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
+       }
+       reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
+       out_be32((void __iomem *)udenvt_port, reg);
+
+       return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *     scc_config_chipset_for_dma      -       configure for DMA
+ *     @drive: drive to configure
+ *
+ *     Called by scc_config_drive_for_dma().
+ */
+
+static int scc_config_chipset_for_dma(ide_drive_t *drive)
+{
+       u8 speed = ide_dma_speed(drive, scc_ratemask(drive));
+
+       if (!speed)
+               return 0;
+
+       if (scc_tune_chipset(drive, speed))
+               return 0;
+
+       return ide_dma_enable(drive);
+}
+
+/**
+ *     scc_configure_drive_for_dma     -       set up for DMA transfers
+ *     @drive: drive we are going to set up
+ *
+ *     Set up the drive for DMA, tune the controller and drive as
+ *     required.
+ *      If the drive isn't suitable for DMA or we hit other problems
+ *      then we will drop down to PIO and set up PIO appropriately.
+ *      (return 1)
+ */
+
+static int scc_config_drive_for_dma(ide_drive_t *drive)
+{
+       if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive))
+               return 0;
+
+       if (ide_use_fast_pio(drive))
+               scc_tuneproc(drive, 4);
+
+       return -1;
+}
+
+/**
+ *     scc_ide_dma_setup       -       begin a DMA phase
+ *     @drive: target device
+ *
+ *     Build an IDE DMA PRD (IDE speak for scatter gather table)
+ *     and then set up the DMA transfer registers.
+ *
+ *     Returns 0 on success. If a PIO fallback is required then 1
+ *     is returned.
+ */
+
+static int scc_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq = HWGROUP(drive)->rq;
+       unsigned int reading;
+       u8 dma_stat;
+
+       if (rq_data_dir(rq))
+               reading = 0;
+       else
+               reading = 1 << 3;
+
+       /* fall back to pio! */
+       if (!ide_build_dmatable(drive, rq)) {
+               ide_map_sg(drive, rq);
+               return 1;
+       }
+
+       /* PRD table */
+       out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma);
+
+       /* specify r/w */
+       out_be32((void __iomem *)hwif->dma_command, reading);
+
+       /* read dma_status for INTR & ERROR flags */
+       dma_stat = in_be32((void __iomem *)hwif->dma_status);
+
+       /* clear INTR & ERROR flags */
+       out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+       drive->waiting_for_dma = 1;
+       return 0;
+}
+
+
+/**
+ *     scc_ide_dma_end -       Stop DMA
+ *     @drive: IDE drive
+ *
+ *     Check and clear INT Status register.
+ *      Then call __ide_dma_end().
+ */
+
+static int scc_ide_dma_end(ide_drive_t * drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned long intsts_port = hwif->dma_base + 0x014;
+       u32 reg;
+
+       while (1) {
+               reg = in_be32((void __iomem *)intsts_port);
+
+               if (reg & INTSTS_SERROR) {
+                       printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
+
+                       out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_PRERR) {
+                       u32 maea0, maec0;
+                       unsigned long ctl_base = hwif->config_data;
+
+                       maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
+                       maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
+
+                       printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
+
+                       out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
+
+                       out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_RERR) {
+                       printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
+
+                       out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_ICERR) {
+                       out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+
+                       printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMSINT) {
+                       printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
+
+                       ide_do_reset(drive);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMHE) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
+                       continue;
+               }
+
+               if (reg & INTSTS_ACTEINT) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_IOIRQS) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
+                       continue;
+               }
+               break;
+       }
+
+       return __ide_dma_end(drive);
+}
+
+/**
+ *     setup_mmio_scc  -       map CTRL/BMID region
+ *     @dev: PCI device we are configuring
+ *     @name: device name
+ *
+ */
+
+static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+{
+       unsigned long ctl_base = pci_resource_start(dev, 0);
+       unsigned long dma_base = pci_resource_start(dev, 1);
+       unsigned long ctl_size = pci_resource_len(dev, 0);
+       unsigned long dma_size = pci_resource_len(dev, 1);
+       void *ctl_addr;
+       void *dma_addr;
+       int i;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               if (scc_ports[i].ctl == 0)
+                       break;
+       }
+       if (i >= MAX_HWIFS)
+               return -ENOMEM;
+
+       if (!request_mem_region(ctl_base, ctl_size, name)) {
+               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+               goto fail_0;
+       }
+
+       if (!request_mem_region(dma_base, dma_size, name)) {
+               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+               goto fail_1;
+       }
+
+       if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+               goto fail_2;
+
+       if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+               goto fail_3;
+
+       pci_set_master(dev);
+       scc_ports[i].ctl = (unsigned long)ctl_addr;
+       scc_ports[i].dma = (unsigned long)dma_addr;
+       pci_set_drvdata(dev, (void *) &scc_ports[i]);
+
+       return 1;
+
+ fail_3:
+       iounmap(ctl_addr);
+ fail_2:
+       release_mem_region(dma_base, dma_size);
+ fail_1:
+       release_mem_region(ctl_base, ctl_size);
+ fail_0:
+       return -ENOMEM;
+}
+
+/**
+ *     init_setup_scc  -       set up an SCC PATA Controller
+ *     @dev: PCI device
+ *     @d: IDE PCI device
+ *
+ *     Perform the initial set up for this device.
+ */
+
+static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *d)
+{
+       unsigned long ctl_base;
+       unsigned long dma_base;
+       unsigned long cckctrl_port;
+       unsigned long intmask_port;
+       unsigned long mode_port;
+       unsigned long ecmode_port;
+       unsigned long dma_status_port;
+       u32 reg = 0;
+       struct scc_ports *ports;
+       int rc;
+
+       rc = setup_mmio_scc(dev, d->name);
+       if (rc < 0) {
+               return rc;
+       }
+
+       ports = pci_get_drvdata(dev);
+       ctl_base = ports->ctl;
+       dma_base = ports->dma;
+       cckctrl_port = ctl_base + 0xff0;
+       intmask_port = dma_base + 0x010;
+       mode_port = ctl_base + 0x024;
+       ecmode_port = ctl_base + 0xf00;
+       dma_status_port = dma_base + 0x004;
+
+       /* controller initialization */
+       reg = 0;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_ATACLKOEN;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_CRST;
+       out_be32((void*)cckctrl_port, reg);
+
+       for (;;) {
+               reg = in_be32((void*)cckctrl_port);
+               if (reg & CCKCTRL_CRST)
+                       break;
+               udelay(5000);
+       }
+
+       reg |= CCKCTRL_ATARESET;
+       out_be32((void*)cckctrl_port, reg);
+
+       out_be32((void*)ecmode_port, ECMODE_VALUE);
+       out_be32((void*)mode_port, MODE_JCUSFEN);
+       out_be32((void*)intmask_port, INTMASK_MSK);
+
+       return ide_setup_pci_device(dev, d);
+}
+
+/**
+ *     init_mmio_iops_scc      -       set up the iops for MMIO
+ *     @hwif: interface to set up
+ *
+ */
+
+static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = hwif->pci_dev;
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       unsigned long dma_base = ports->dma;
+
+       ide_set_hwifdata(hwif, ports);
+
+       hwif->INB = scc_ide_inb;
+       hwif->INW = scc_ide_inw;
+       hwif->INSW = scc_ide_insw;
+       hwif->INSL = scc_ide_insl;
+       hwif->OUTB = scc_ide_outb;
+       hwif->OUTBSYNC = scc_ide_outbsync;
+       hwif->OUTW = scc_ide_outw;
+       hwif->OUTSW = scc_ide_outsw;
+       hwif->OUTSL = scc_ide_outsl;
+
+       hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
+       hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
+       hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
+       hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
+       hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
+       hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
+       hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
+       hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+       hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
+
+       hwif->irq = hwif->pci_dev->irq;
+       hwif->dma_base = dma_base;
+       hwif->config_data = ports->ctl;
+       hwif->mmio = 1;
+}
+
+/**
+ *     init_iops_scc   -       set up iops
+ *     @hwif: interface to set up
+ *
+ *     Do the basic setup for the SCC hardware interface
+ *     and then do the MMIO setup.
+ */
+
+static void __devinit init_iops_scc(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev =  hwif->pci_dev;
+       hwif->hwif_data = NULL;
+       if (pci_get_drvdata(dev) == NULL)
+               return;
+       init_mmio_iops_scc(hwif);
+}
+
+/**
+ *     init_hwif_scc   -       set up hwif
+ *     @hwif: interface to set up
+ *
+ *     We do the basic set up of the interface structure. The SCC
+ *     requires several custom handlers so we override the default
+ *     ide DMA handlers appropriately.
+ */
+
+static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+{
+       struct scc_ports *ports = ide_get_hwifdata(hwif);
+
+       ports->hwif_id = hwif->index;
+
+       hwif->dma_command = hwif->dma_base;
+       hwif->dma_status = hwif->dma_base + 0x04;
+       hwif->dma_prdtable = hwif->dma_base + 0x08;
+
+       /* PTERADD */
+       out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
+
+       hwif->dma_setup = scc_dma_setup;
+       hwif->ide_dma_end = scc_ide_dma_end;
+       hwif->speedproc = scc_tune_chipset;
+       hwif->tuneproc = scc_tuneproc;
+       hwif->ide_dma_check = scc_config_drive_for_dma;
+
+       hwif->drives[0].autotune = IDE_TUNE_AUTO;
+       hwif->drives[1].autotune = IDE_TUNE_AUTO;
+
+       if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) {
+               hwif->ultra_mask = 0x7f; /* 133MHz */
+       } else {
+               hwif->ultra_mask = 0x3f; /* 100MHz */
+       }
+       hwif->mwdma_mask = 0x00;
+       hwif->swdma_mask = 0x00;
+       hwif->atapi_dma = 1;
+
+       /* we support 80c cable only. */
+       hwif->udma_four = 1;
+
+       hwif->autodma = 0;
+       if (!noautodma)
+               hwif->autodma = 1;
+       hwif->drives[0].autodma = hwif->autodma;
+       hwif->drives[1].autodma = hwif->autodma;
+}
+
+#define DECLARE_SCC_DEV(name_str)                      \
+  {                                                    \
+      .name            = name_str,                     \
+      .init_setup      = init_setup_scc,               \
+      .init_iops       = init_iops_scc,                \
+      .init_hwif       = init_hwif_scc,                \
+      .channels        = 1,                                    \
+      .autodma = AUTODMA,                              \
+      .bootable        = ON_BOARD,                             \
+  }
+
+static ide_pci_device_t scc_chipsets[] __devinitdata = {
+       /* 0 */ DECLARE_SCC_DEV("sccIDE"),
+};
+
+/**
+ *     scc_init_one    -       pci layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds an SCC PATA controller.
+ *     We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       ide_pci_device_t *d = &scc_chipsets[id->driver_data];
+       return d->init_setup(dev, d);
+}
+
+/**
+ *     scc_remove      -       pci layer remove entry
+ *     @dev: PCI device
+ *
+ *     Called by the PCI code when it removes an SCC PATA controller.
+ */
+
+static void __devexit scc_remove(struct pci_dev *dev)
+{
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
+       unsigned long ctl_base = pci_resource_start(dev, 0);
+       unsigned long dma_base = pci_resource_start(dev, 1);
+       unsigned long ctl_size = pci_resource_len(dev, 0);
+       unsigned long dma_size = pci_resource_len(dev, 1);
+
+       if (hwif->dmatable_cpu) {
+               pci_free_consistent(hwif->pci_dev,
+                                   PRD_ENTRIES * PRD_BYTES,
+                                   hwif->dmatable_cpu,
+                                   hwif->dmatable_dma);
+               hwif->dmatable_cpu = NULL;
+       }
+
+       ide_unregister(hwif->index);
+
+       hwif->chipset = ide_unknown;
+       iounmap((void*)ports->dma);
+       iounmap((void*)ports->ctl);
+       release_mem_region(dma_base, dma_size);
+       release_mem_region(ctl_base, ctl_size);
+       memset(ports, 0, sizeof(*ports));
+}
+
+static struct pci_device_id scc_pci_tbl[] = {
+       { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
+
+static struct pci_driver driver = {
+       .name = "SCC IDE",
+       .id_table = scc_pci_tbl,
+       .probe = scc_init_one,
+       .remove = scc_remove,
+};
+
+static int scc_ide_init(void)
+{
+       return ide_pci_register_driver(&driver);
+}
+
+module_init(scc_ide_init);
+/* -- No exit code?
+static void scc_ide_exit(void)
+{
+       ide_pci_unregister_driver(&driver);
+}
+module_exit(scc_ide_exit);
+ */
+
+
+MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
+MODULE_LICENSE("GPL");
index 97e5c3dd044d05aacae220ab5b67d02c5fe2bce6..a953135219851292b3803f3b3799ac00be810ac0 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
index 8f207508ed1dae62dc4ba417df8a5cb14089d62a..46878fef136c24d091fa05146c54cd8e7b873c10 100644 (file)
        _IO  ('#', 0x28)
 #define RAW1394_IOC_ISO_RECV_FLUSH             \
        _IO  ('#', 0x29)
+#define RAW1394_IOC_GET_CYCLE_TIMER            \
+       _IOR ('#', 0x30, struct raw1394_cycle_timer)
 
 #endif /* __IEEE1394_IOCTL_H */
index 1521e57e124bb63119b705804f8ff81d41ed77ed..d791d08c743ce22d100ad34e440f3cdb932ca30f 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
+#include <linux/preempt.h>
+#include <linux/time.h>
 
+#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "ieee1394_types.h"
@@ -186,6 +189,45 @@ int hpsb_reset_bus(struct hpsb_host *host, int type)
        }
 }
 
+/**
+ * hpsb_read_cycle_timer - read cycle timer register and system time
+ * @host: host whose isochronous cycle timer register is read
+ * @cycle_timer: address of bitfield to return the register contents
+ * @local_time: address to return the system time
+ *
+ * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
+ * format is also read from non-OHCI controllers. * @local_time contains the
+ * system time in microseconds since the Epoch, read at the moment when the
+ * cycle timer was read.
+ *
+ * Return value: 0 for success or error number otherwise.
+ */
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+                         u64 *local_time)
+{
+       int ctr;
+       struct timeval tv;
+       unsigned long flags;
+
+       if (!host || !cycle_timer || !local_time)
+               return -EINVAL;
+
+       preempt_disable();
+       local_irq_save(flags);
+
+       ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
+       if (ctr)
+               do_gettimeofday(&tv);
+
+       local_irq_restore(flags);
+       preempt_enable();
+
+       if (!ctr)
+               return -EIO;
+       *cycle_timer = ctr;
+       *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+       return 0;
+}
 
 int hpsb_bus_reset(struct hpsb_host *host)
 {
@@ -1190,6 +1232,7 @@ EXPORT_SYMBOL(hpsb_alloc_packet);
 EXPORT_SYMBOL(hpsb_free_packet);
 EXPORT_SYMBOL(hpsb_send_packet);
 EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_read_cycle_timer);
 EXPORT_SYMBOL(hpsb_bus_reset);
 EXPORT_SYMBOL(hpsb_selfid_received);
 EXPORT_SYMBOL(hpsb_selfid_complete);
index 536ba3f580fd49995fc812353167d8cc65307570..bd29d8ef5bbd9c58c7a698901c86558421367e2f 100644 (file)
@@ -127,6 +127,9 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
  * progress, 0 otherwise. */
 int hpsb_reset_bus(struct hpsb_host *host, int type);
 
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+                         u64 *local_time);
+
 /*
  * The following functions are exported for host driver module usage.  All of
  * them are safe to use in interrupt contexts, although some are quite
index 08bd15d2a7b6cea63a675664ea333e9e0837b376..c6227e51136dbecc5ea7656702bcdda7fb34c9f1 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include "hosts.h"
index ba9faeff4793a0a5891493380ff6fb3b5e3278fb..c5ace190bfe6719d78b290276ea92997a76b6563 100644 (file)
@@ -1681,7 +1681,8 @@ static int nodemgr_host_thread(void *__hi)
        for (;;) {
                /* Sleep until next bus reset */
                set_current_state(TASK_INTERRUPTIBLE);
-               if (get_hpsb_generation(host) == generation)
+               if (get_hpsb_generation(host) == generation &&
+                   !kthread_should_stop())
                        schedule();
                __set_current_state(TASK_RUNNING);
 
index 5729e412cc4aaeeb76621a0eb1848e5280eef4ab..06fac0d21264a2b022ad1c554b52351e426b7261 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
@@ -181,7 +180,7 @@ static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
 static void ohci1394_pci_remove(struct pci_dev *pdev);
 
 #ifndef __LITTLE_ENDIAN
-const static size_t hdr_sizes[] = {
+static const size_t hdr_sizes[] = {
        3,      /* TCODE_WRITEQ */
        4,      /* TCODE_WRITEB */
        3,      /* TCODE_WRITE_RESPONSE */
index aa9ca8385ec769304e0bc928c51d52be92641aa6..bb897a37d9f778cf2f64661c06069461d5d63fc5 100644 (file)
@@ -2669,6 +2669,18 @@ static void raw1394_iso_shutdown(struct file_info *fi)
        fi->iso_state = RAW1394_ISO_INACTIVE;
 }
 
+static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
+{
+       struct raw1394_cycle_timer ct;
+       int err;
+
+       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+       if (!err)
+               if (copy_to_user(uaddr, &ct, sizeof(ct)))
+                       err = -EFAULT;
+       return err;
+}
+
 /* mmap the rawiso xmit/recv buffer */
 static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
@@ -2777,6 +2789,14 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       /* state-independent commands */
+       switch(cmd) {
+       case RAW1394_IOC_GET_CYCLE_TIMER:
+               return raw1394_read_cycle_timer(fi, argp);
+       default:
+               break;
+       }
+
        return -EINVAL;
 }
 
index 35bfc38f013c25f681dda5f3a70c2fbfed6c1819..7bd22ee1afbb1d56a2a71e9c86cd86b3ad5bfc43 100644 (file)
@@ -178,4 +178,14 @@ struct raw1394_iso_status {
        __s16 xmit_cycle;
 };
 
+/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
+struct raw1394_cycle_timer {
+       /* contents of Isochronous Cycle Timer register,
+          as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
+       __u32 cycle_timer;
+
+       /* local time in microseconds since Epoch,
+          simultaneously read with cycle timer */
+       __u64 local_time;
+};
 #endif /* IEEE1394_RAW1394_H */
index 50fb1cd447b76d80de09d6f565e737cd37101af5..189e5d4b9b17ed271027e2c015b252f929fbd32d 100644 (file)
@@ -12,7 +12,7 @@ ib_core-y :=                  packer.o ud_header.o verbs.o sysfs.o \
 
 ib_mad-y :=                    mad.o smi.o agent.o mad_rmpp.o
 
-ib_sa-y :=                     sa_query.o
+ib_sa-y :=                     sa_query.o multicast.o
 
 ib_cm-y :=                     cm.o
 
index 98272fbbfb31e3d1ff4e8a010d6a7f1489a58bf8..558c9a0fc8b968fad2ee02ea199a4d8b640a4638 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/sched.h>       /* INIT_WORK, schedule_work(), flush_scheduled_work() */
 
 #include <rdma/ib_cache.h>
 
index db88e609bf429f6a1fb9f37527f0c21651d14320..f8d69b3fa30796f8c4258a858a3664c0f5bff647 100644 (file)
@@ -71,6 +71,7 @@ static struct workqueue_struct *cma_wq;
 static DEFINE_IDR(sdp_ps);
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
+static DEFINE_IDR(ipoib_ps);
 static int next_port;
 
 struct cma_device {
@@ -116,6 +117,7 @@ struct rdma_id_private {
        struct list_head        list;
        struct list_head        listen_list;
        struct cma_device       *cma_dev;
+       struct list_head        mc_list;
 
        enum cma_state          state;
        spinlock_t              lock;
@@ -134,10 +136,23 @@ struct rdma_id_private {
        } cm_id;
 
        u32                     seq_num;
+       u32                     qkey;
        u32                     qp_num;
        u8                      srq;
 };
 
+struct cma_multicast {
+       struct rdma_id_private *id_priv;
+       union {
+               struct ib_sa_multicast *ib;
+       } multicast;
+       struct list_head        list;
+       void                    *context;
+       struct sockaddr         addr;
+       u8                      pad[sizeof(struct sockaddr_in6) -
+                                   sizeof(struct sockaddr)];
+};
+
 struct cma_work {
        struct work_struct      work;
        struct rdma_id_private  *id;
@@ -243,6 +258,11 @@ static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
        hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
 }
 
+static inline int cma_is_ud_ps(enum rdma_port_space ps)
+{
+       return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB);
+}
+
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
                              struct cma_device *cma_dev)
 {
@@ -265,19 +285,41 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv)
        id_priv->cma_dev = NULL;
 }
 
+static int cma_set_qkey(struct ib_device *device, u8 port_num,
+                       enum rdma_port_space ps,
+                       struct rdma_dev_addr *dev_addr, u32 *qkey)
+{
+       struct ib_sa_mcmember_rec rec;
+       int ret = 0;
+
+       switch (ps) {
+       case RDMA_PS_UDP:
+               *qkey = RDMA_UDP_QKEY;
+               break;
+       case RDMA_PS_IPOIB:
+               ib_addr_get_mgid(dev_addr, &rec.mgid);
+               ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec);
+               *qkey = be32_to_cpu(rec.qkey);
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
 static int cma_acquire_dev(struct rdma_id_private *id_priv)
 {
-       enum rdma_node_type dev_type = id_priv->id.route.addr.dev_addr.dev_type;
+       struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
        struct cma_device *cma_dev;
        union ib_gid gid;
        int ret = -ENODEV;
 
-       switch (rdma_node_get_transport(dev_type)) {
+       switch (rdma_node_get_transport(dev_addr->dev_type)) {
        case RDMA_TRANSPORT_IB:
-               ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+               ib_addr_get_sgid(dev_addr, &gid);
                break;
        case RDMA_TRANSPORT_IWARP:
-               iw_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+               iw_addr_get_sgid(dev_addr, &gid);
                break;
        default:
                return -ENODEV;
@@ -287,7 +329,12 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
                ret = ib_find_cached_gid(cma_dev->device, &gid,
                                         &id_priv->id.port_num, NULL);
                if (!ret) {
-                       cma_attach_to_dev(id_priv, cma_dev);
+                       ret = cma_set_qkey(cma_dev->device,
+                                          id_priv->id.port_num,
+                                          id_priv->id.ps, dev_addr,
+                                          &id_priv->qkey);
+                       if (!ret)
+                               cma_attach_to_dev(id_priv, cma_dev);
                        break;
                }
        }
@@ -325,40 +372,50 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
        init_waitqueue_head(&id_priv->wait_remove);
        atomic_set(&id_priv->dev_remove, 0);
        INIT_LIST_HEAD(&id_priv->listen_list);
+       INIT_LIST_HEAD(&id_priv->mc_list);
        get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
 
        return &id_priv->id;
 }
 EXPORT_SYMBOL(rdma_create_id);
 
-static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_ud_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
 {
        struct ib_qp_attr qp_attr;
-       struct rdma_dev_addr *dev_addr;
-       int ret;
+       int qp_attr_mask, ret;
 
-       dev_addr = &id_priv->id.route.addr.dev_addr;
-       ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
-                                 ib_addr_get_pkey(dev_addr),
-                                 &qp_attr.pkey_index);
+       qp_attr.qp_state = IB_QPS_INIT;
+       ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
        if (ret)
                return ret;
 
-       qp_attr.qp_state = IB_QPS_INIT;
-       qp_attr.qp_access_flags = 0;
-       qp_attr.port_num = id_priv->id.port_num;
-       return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
-                                         IB_QP_PKEY_INDEX | IB_QP_PORT);
+       ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_RTR;
+       ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_RTS;
+       qp_attr.sq_psn = 0;
+       ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
+
+       return ret;
 }
 
-static int cma_init_iw_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_conn_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
 {
        struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
 
        qp_attr.qp_state = IB_QPS_INIT;
-       qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+       ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
 
-       return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS);
+       return ib_modify_qp(qp, &qp_attr, qp_attr_mask);
 }
 
 int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
@@ -376,18 +433,10 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
        if (IS_ERR(qp))
                return PTR_ERR(qp);
 
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
-               ret = cma_init_ib_qp(id_priv, qp);
-               break;
-       case RDMA_TRANSPORT_IWARP:
-               ret = cma_init_iw_qp(id_priv, qp);
-               break;
-       default:
-               ret = -ENOSYS;
-               break;
-       }
-
+       if (cma_is_ud_ps(id_priv->id.ps))
+               ret = cma_init_ud_qp(id_priv, qp);
+       else
+               ret = cma_init_conn_qp(id_priv, qp);
        if (ret)
                goto err;
 
@@ -460,23 +509,55 @@ static int cma_modify_qp_err(struct rdma_cm_id *id)
        return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
 }
 
+static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
+                              struct ib_qp_attr *qp_attr, int *qp_attr_mask)
+{
+       struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+       int ret;
+
+       ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+                                 ib_addr_get_pkey(dev_addr),
+                                 &qp_attr->pkey_index);
+       if (ret)
+               return ret;
+
+       qp_attr->port_num = id_priv->id.port_num;
+       *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
+
+       if (cma_is_ud_ps(id_priv->id.ps)) {
+               qp_attr->qkey = id_priv->qkey;
+               *qp_attr_mask |= IB_QP_QKEY;
+       } else {
+               qp_attr->qp_access_flags = 0;
+               *qp_attr_mask |= IB_QP_ACCESS_FLAGS;
+       }
+       return 0;
+}
+
 int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
                       int *qp_attr_mask)
 {
        struct rdma_id_private *id_priv;
-       int ret;
+       int ret = 0;
 
        id_priv = container_of(id, struct rdma_id_private, id);
        switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
-                                        qp_attr_mask);
+               if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))
+                       ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
+               else
+                       ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+                                                qp_attr_mask);
                if (qp_attr->qp_state == IB_QPS_RTR)
                        qp_attr->rq_psn = id_priv->seq_num;
                break;
        case RDMA_TRANSPORT_IWARP:
-               ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
-                                       qp_attr_mask);
+               if (!id_priv->cm_id.iw) {
+                       qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+                       *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
+               } else
+                       ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
+                                                qp_attr_mask);
                break;
        default:
                ret = -ENOSYS;
@@ -698,6 +779,19 @@ static void cma_release_port(struct rdma_id_private *id_priv)
        mutex_unlock(&lock);
 }
 
+static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
+{
+       struct cma_multicast *mc;
+
+       while (!list_empty(&id_priv->mc_list)) {
+               mc = container_of(id_priv->mc_list.next,
+                                 struct cma_multicast, list);
+               list_del(&mc->list);
+               ib_sa_free_multicast(mc->multicast.ib);
+               kfree(mc);
+       }
+}
+
 void rdma_destroy_id(struct rdma_cm_id *id)
 {
        struct rdma_id_private *id_priv;
@@ -722,6 +816,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
                default:
                        break;
                }
+               cma_leave_mc_groups(id_priv);
                mutex_lock(&lock);
                cma_detach_from_dev(id_priv);
        }
@@ -972,7 +1067,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
        memset(&event, 0, sizeof event);
        offset = cma_user_data_offset(listen_id->id.ps);
        event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-       if (listen_id->id.ps == RDMA_PS_UDP) {
+       if (cma_is_ud_ps(listen_id->id.ps)) {
                conn_id = cma_new_udp_id(&listen_id->id, ib_event);
                event.param.ud.private_data = ib_event->private_data + offset;
                event.param.ud.private_data_len =
@@ -1725,7 +1820,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
        struct rdma_bind_list *bind_list;
        int port, ret;
 
-       bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+       bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL);
        if (!bind_list)
                return -ENOMEM;
 
@@ -1847,6 +1942,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
        case RDMA_PS_UDP:
                ps = &udp_ps;
                break;
+       case RDMA_PS_IPOIB:
+               ps = &ipoib_ps;
+               break;
        default:
                return -EPROTONOSUPPORT;
        }
@@ -1961,7 +2059,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
                        event.status = ib_event->param.sidr_rep_rcvd.status;
                        break;
                }
-               if (rep->qkey != RDMA_UD_QKEY) {
+               if (id_priv->qkey != rep->qkey) {
                        event.event = RDMA_CM_EVENT_UNREACHABLE;
                        event.status = -EINVAL;
                        break;
@@ -2160,7 +2258,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
 
        switch (rdma_node_get_transport(id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               if (id->ps == RDMA_PS_UDP)
+               if (cma_is_ud_ps(id->ps))
                        ret = cma_resolve_ib_udp(id_priv, conn_param);
                else
                        ret = cma_connect_ib(id_priv, conn_param);
@@ -2256,7 +2354,7 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
        rep.status = status;
        if (status == IB_SIDR_SUCCESS) {
                rep.qp_num = id_priv->qp_num;
-               rep.qkey = RDMA_UD_QKEY;
+               rep.qkey = id_priv->qkey;
        }
        rep.private_data = private_data;
        rep.private_data_len = private_data_len;
@@ -2280,7 +2378,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
 
        switch (rdma_node_get_transport(id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               if (id->ps == RDMA_PS_UDP)
+               if (cma_is_ud_ps(id->ps))
                        ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
                                                conn_param->private_data,
                                                conn_param->private_data_len);
@@ -2341,7 +2439,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
 
        switch (rdma_node_get_transport(id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               if (id->ps == RDMA_PS_UDP)
+               if (cma_is_ud_ps(id->ps))
                        ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
                                                private_data, private_data_len);
                else
@@ -2392,6 +2490,178 @@ out:
 }
 EXPORT_SYMBOL(rdma_disconnect);
 
+static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
+{
+       struct rdma_id_private *id_priv;
+       struct cma_multicast *mc = multicast->context;
+       struct rdma_cm_event event;
+       int ret;
+
+       id_priv = mc->id_priv;
+       atomic_inc(&id_priv->dev_remove);
+       if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+           !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+               goto out;
+
+       if (!status && id_priv->id.qp)
+               status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
+                                        multicast->rec.mlid);
+
+       memset(&event, 0, sizeof event);
+       event.status = status;
+       event.param.ud.private_data = mc->context;
+       if (!status) {
+               event.event = RDMA_CM_EVENT_MULTICAST_JOIN;
+               ib_init_ah_from_mcmember(id_priv->id.device,
+                                        id_priv->id.port_num, &multicast->rec,
+                                        &event.param.ud.ah_attr);
+               event.param.ud.qp_num = 0xFFFFFF;
+               event.param.ud.qkey = be32_to_cpu(multicast->rec.qkey);
+       } else
+               event.event = RDMA_CM_EVENT_MULTICAST_ERROR;
+
+       ret = id_priv->id.event_handler(&id_priv->id, &event);
+       if (ret) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return 0;
+       }
+out:
+       cma_release_remove(id_priv);
+       return 0;
+}
+
+static void cma_set_mgid(struct rdma_id_private *id_priv,
+                        struct sockaddr *addr, union ib_gid *mgid)
+{
+       unsigned char mc_map[MAX_ADDR_LEN];
+       struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+       struct sockaddr_in *sin = (struct sockaddr_in *) addr;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
+
+       if (cma_any_addr(addr)) {
+               memset(mgid, 0, sizeof *mgid);
+       } else if ((addr->sa_family == AF_INET6) &&
+                  ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
+                                                                0xFF10A01B)) {
+               /* IPv6 address is an SA assigned MGID. */
+               memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+       } else {
+               ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
+               if (id_priv->id.ps == RDMA_PS_UDP)
+                       mc_map[7] = 0x01;       /* Use RDMA CM signature */
+               mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
+               mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
+               *mgid = *(union ib_gid *) (mc_map + 4);
+       }
+}
+
+static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
+                                struct cma_multicast *mc)
+{
+       struct ib_sa_mcmember_rec rec;
+       struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+       ib_sa_comp_mask comp_mask;
+       int ret;
+
+       ib_addr_get_mgid(dev_addr, &rec.mgid);
+       ret = ib_sa_get_mcmember_rec(id_priv->id.device, id_priv->id.port_num,
+                                    &rec.mgid, &rec);
+       if (ret)
+               return ret;
+
+       cma_set_mgid(id_priv, &mc->addr, &rec.mgid);
+       if (id_priv->id.ps == RDMA_PS_UDP)
+               rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
+       ib_addr_get_sgid(dev_addr, &rec.port_gid);
+       rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
+       rec.join_state = 1;
+
+       comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
+                   IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
+                   IB_SA_MCMEMBER_REC_QKEY | IB_SA_MCMEMBER_REC_SL |
+                   IB_SA_MCMEMBER_REC_FLOW_LABEL |
+                   IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
+
+       mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
+                                               id_priv->id.port_num, &rec,
+                                               comp_mask, GFP_KERNEL,
+                                               cma_ib_mc_handler, mc);
+       if (IS_ERR(mc->multicast.ib))
+               return PTR_ERR(mc->multicast.ib);
+
+       return 0;
+}
+
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+                       void *context)
+{
+       struct rdma_id_private *id_priv;
+       struct cma_multicast *mc;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+           !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+               return -EINVAL;
+
+       mc = kmalloc(sizeof *mc, GFP_KERNEL);
+       if (!mc)
+               return -ENOMEM;
+
+       memcpy(&mc->addr, addr, ip_addr_size(addr));
+       mc->context = context;
+       mc->id_priv = id_priv;
+
+       spin_lock(&id_priv->lock);
+       list_add(&mc->list, &id_priv->mc_list);
+       spin_unlock(&id_priv->lock);
+
+       switch (rdma_node_get_transport(id->device->node_type)) {
+       case RDMA_TRANSPORT_IB:
+               ret = cma_join_ib_multicast(id_priv, mc);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       if (ret) {
+               spin_lock_irq(&id_priv->lock);
+               list_del(&mc->list);
+               spin_unlock_irq(&id_priv->lock);
+               kfree(mc);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_join_multicast);
+
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+       struct rdma_id_private *id_priv;
+       struct cma_multicast *mc;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       spin_lock_irq(&id_priv->lock);
+       list_for_each_entry(mc, &id_priv->mc_list, list) {
+               if (!memcmp(&mc->addr, addr, ip_addr_size(addr))) {
+                       list_del(&mc->list);
+                       spin_unlock_irq(&id_priv->lock);
+
+                       if (id->qp)
+                               ib_detach_mcast(id->qp,
+                                               &mc->multicast.ib->rec.mgid,
+                                               mc->multicast.ib->rec.mlid);
+                       ib_sa_free_multicast(mc->multicast.ib);
+                       kfree(mc);
+                       return;
+               }
+       }
+       spin_unlock_irq(&id_priv->lock);
+}
+EXPORT_SYMBOL(rdma_leave_multicast);
+
 static void cma_add_one(struct ib_device *device)
 {
        struct cma_device *cma_dev;
@@ -2522,6 +2792,7 @@ static void cma_cleanup(void)
        idr_destroy(&sdp_ps);
        idr_destroy(&tcp_ps);
        idr_destroy(&udp_ps);
+       idr_destroy(&ipoib_ps);
 }
 
 module_init(cma_init);
index 8926a2bd4a8707d7b765432253a400c3719e9860..1d796e7c81991e6845c16ff3e6d1f323286afd92 100644 (file)
@@ -301,7 +301,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
 
        {
                struct ib_pool_fmr *fmr;
-               struct ib_fmr_attr attr = {
+               struct ib_fmr_attr fmr_attr = {
                        .max_pages  = params->max_pages_per_fmr,
                        .max_maps   = pool->max_remaps,
                        .page_shift = params->page_shift
@@ -321,7 +321,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                        fmr->ref_count        = 0;
                        INIT_HLIST_NODE(&fmr->cache_node);
 
-                       fmr->fmr = ib_alloc_fmr(pd, params->access, &attr);
+                       fmr->fmr = ib_alloc_fmr(pd, params->access, &fmr_attr);
                        if (IS_ERR(fmr->fmr)) {
                                printk(KERN_WARNING "fmr_create failed for FMR %d", i);
                                kfree(fmr);
index 1039ad57d53b4b0f3ef2d252c51fb9a47bfd68f0..891d1fa7b2eb44a3fc4edbd5dc93dcb22b02c473 100644 (file)
@@ -146,6 +146,12 @@ static int copy_private_data(struct iw_cm_event *event)
        return 0;
 }
 
+static void free_cm_id(struct iwcm_id_private *cm_id_priv)
+{
+       dealloc_work_entries(cm_id_priv);
+       kfree(cm_id_priv);
+}
+
 /*
  * Release a reference on cm_id. If the last reference is being
  * released, enable the waiting thread (in iw_destroy_cm_id) to
@@ -153,21 +159,14 @@ static int copy_private_data(struct iw_cm_event *event)
  */
 static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
 {
-       int ret = 0;
-
        BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
        if (atomic_dec_and_test(&cm_id_priv->refcount)) {
                BUG_ON(!list_empty(&cm_id_priv->work_list));
-               if (waitqueue_active(&cm_id_priv->destroy_comp.wait)) {
-                       BUG_ON(cm_id_priv->state != IW_CM_STATE_DESTROYING);
-                       BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY,
-                                       &cm_id_priv->flags));
-                       ret = 1;
-               }
                complete(&cm_id_priv->destroy_comp);
+               return 1;
        }
 
-       return ret;
+       return 0;
 }
 
 static void add_ref(struct iw_cm_id *cm_id)
@@ -181,7 +180,11 @@ static void rem_ref(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-       iwcm_deref_id(cm_id_priv);
+       if (iwcm_deref_id(cm_id_priv) &&
+           test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+               BUG_ON(!list_empty(&cm_id_priv->work_list));
+               free_cm_id(cm_id_priv);
+       }
 }
 
 static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
@@ -355,7 +358,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
        case IW_CM_STATE_CONN_RECV:
                /*
                 * App called destroy before/without calling accept after
-                * receiving connection request event notification.
+                * receiving connection request event notification or
+                * returned non zero from the event callback function.
+                * In either case, must tell the provider to reject.
                 */
                cm_id_priv->state = IW_CM_STATE_DESTROYING;
                break;
@@ -391,9 +396,7 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
 
        wait_for_completion(&cm_id_priv->destroy_comp);
 
-       dealloc_work_entries(cm_id_priv);
-
-       kfree(cm_id_priv);
+       free_cm_id(cm_id_priv);
 }
 EXPORT_SYMBOL(iw_destroy_cm_id);
 
@@ -647,10 +650,11 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
        /* Call the client CM handler */
        ret = cm_id->cm_handler(cm_id, iw_event);
        if (ret) {
+               iw_cm_reject(cm_id, NULL, 0);
                set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
                destroy_cm_id(cm_id);
                if (atomic_read(&cm_id_priv->refcount)==0)
-                       kfree(cm_id);
+                       free_cm_id(cm_id_priv);
        }
 
 out:
@@ -854,13 +858,12 @@ static void cm_work_handler(struct work_struct *_work)
                        destroy_cm_id(&cm_id_priv->id);
                }
                BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
-               if (iwcm_deref_id(cm_id_priv))
-                       return;
-
-               if (atomic_read(&cm_id_priv->refcount)==0 &&
-                   test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
-                       dealloc_work_entries(cm_id_priv);
-                       kfree(cm_id_priv);
+               if (iwcm_deref_id(cm_id_priv)) {
+                       if (test_bit(IWCM_F_CALLBACK_DESTROY,
+                                    &cm_id_priv->flags)) {
+                               BUG_ON(!list_empty(&cm_id_priv->work_list));
+                               free_cm_id(cm_id_priv);
+                       }
                        return;
                }
                spin_lock_irqsave(&cm_id_priv->lock, flags);
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
new file mode 100644 (file)
index 0000000..4a579b3
--- /dev/null
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  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
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/random.h>
+
+#include <rdma/ib_cache.h>
+#include "sa.h"
+
+static void mcast_add_one(struct ib_device *device);
+static void mcast_remove_one(struct ib_device *device);
+
+static struct ib_client mcast_client = {
+       .name   = "ib_multicast",
+       .add    = mcast_add_one,
+       .remove = mcast_remove_one
+};
+
+static struct ib_sa_client     sa_client;
+static struct workqueue_struct *mcast_wq;
+static union ib_gid mgid0;
+
+struct mcast_device;
+
+struct mcast_port {
+       struct mcast_device     *dev;
+       spinlock_t              lock;
+       struct rb_root          table;
+       atomic_t                refcount;
+       struct completion       comp;
+       u8                      port_num;
+};
+
+struct mcast_device {
+       struct ib_device        *device;
+       struct ib_event_handler event_handler;
+       int                     start_port;
+       int                     end_port;
+       struct mcast_port       port[0];
+};
+
+enum mcast_state {
+       MCAST_IDLE,
+       MCAST_JOINING,
+       MCAST_MEMBER,
+       MCAST_BUSY,
+       MCAST_ERROR
+};
+
+struct mcast_member;
+
+struct mcast_group {
+       struct ib_sa_mcmember_rec rec;
+       struct rb_node          node;
+       struct mcast_port       *port;
+       spinlock_t              lock;
+       struct work_struct      work;
+       struct list_head        pending_list;
+       struct list_head        active_list;
+       struct mcast_member     *last_join;
+       int                     members[3];
+       atomic_t                refcount;
+       enum mcast_state        state;
+       struct ib_sa_query      *query;
+       int                     query_id;
+};
+
+struct mcast_member {
+       struct ib_sa_multicast  multicast;
+       struct ib_sa_client     *client;
+       struct mcast_group      *group;
+       struct list_head        list;
+       enum mcast_state        state;
+       atomic_t                refcount;
+       struct completion       comp;
+};
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+                        void *context);
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+                         void *context);
+
+static struct mcast_group *mcast_find(struct mcast_port *port,
+                                     union ib_gid *mgid)
+{
+       struct rb_node *node = port->table.rb_node;
+       struct mcast_group *group;
+       int ret;
+
+       while (node) {
+               group = rb_entry(node, struct mcast_group, node);
+               ret = memcmp(mgid->raw, group->rec.mgid.raw, sizeof *mgid);
+               if (!ret)
+                       return group;
+
+               if (ret < 0)
+                       node = node->rb_left;
+               else
+                       node = node->rb_right;
+       }
+       return NULL;
+}
+
+static struct mcast_group *mcast_insert(struct mcast_port *port,
+                                       struct mcast_group *group,
+                                       int allow_duplicates)
+{
+       struct rb_node **link = &port->table.rb_node;
+       struct rb_node *parent = NULL;
+       struct mcast_group *cur_group;
+       int ret;
+
+       while (*link) {
+               parent = *link;
+               cur_group = rb_entry(parent, struct mcast_group, node);
+
+               ret = memcmp(group->rec.mgid.raw, cur_group->rec.mgid.raw,
+                            sizeof group->rec.mgid);
+               if (ret < 0)
+                       link = &(*link)->rb_left;
+               else if (ret > 0)
+                       link = &(*link)->rb_right;
+               else if (allow_duplicates)
+                       link = &(*link)->rb_left;
+               else
+                       return cur_group;
+       }
+       rb_link_node(&group->node, parent, link);
+       rb_insert_color(&group->node, &port->table);
+       return NULL;
+}
+
+static void deref_port(struct mcast_port *port)
+{
+       if (atomic_dec_and_test(&port->refcount))
+               complete(&port->comp);
+}
+
+static void release_group(struct mcast_group *group)
+{
+       struct mcast_port *port = group->port;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       if (atomic_dec_and_test(&group->refcount)) {
+               rb_erase(&group->node, &port->table);
+               spin_unlock_irqrestore(&port->lock, flags);
+               kfree(group);
+               deref_port(port);
+       } else
+               spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void deref_member(struct mcast_member *member)
+{
+       if (atomic_dec_and_test(&member->refcount))
+               complete(&member->comp);
+}
+
+static void queue_join(struct mcast_member *member)
+{
+       struct mcast_group *group = member->group;
+       unsigned long flags;
+
+       spin_lock_irqsave(&group->lock, flags);
+       list_add(&member->list, &group->pending_list);
+       if (group->state == MCAST_IDLE) {
+               group->state = MCAST_BUSY;
+               atomic_inc(&group->refcount);
+               queue_work(mcast_wq, &group->work);
+       }
+       spin_unlock_irqrestore(&group->lock, flags);
+}
+
+/*
+ * A multicast group has three types of members: full member, non member, and
+ * send only member.  We need to keep track of the number of members of each
+ * type based on their join state.  Adjust the number of members the belong to
+ * the specified join states.
+ */
+static void adjust_membership(struct mcast_group *group, u8 join_state, int inc)
+{
+       int i;
+
+       for (i = 0; i < 3; i++, join_state >>= 1)
+               if (join_state & 0x1)
+                       group->members[i] += inc;
+}
+
+/*
+ * If a multicast group has zero members left for a particular join state, but
+ * the group is still a member with the SA, we need to leave that join state.
+ * Determine which join states we still belong to, but that do not have any
+ * active members.
+ */
+static u8 get_leave_state(struct mcast_group *group)
+{
+       u8 leave_state = 0;
+       int i;
+
+       for (i = 0; i < 3; i++)
+               if (!group->members[i])
+                       leave_state |= (0x1 << i);
+
+       return leave_state & group->rec.join_state;
+}
+
+static int check_selector(ib_sa_comp_mask comp_mask,
+                         ib_sa_comp_mask selector_mask,
+                         ib_sa_comp_mask value_mask,
+                         u8 selector, u8 src_value, u8 dst_value)
+{
+       int err;
+
+       if (!(comp_mask & selector_mask) || !(comp_mask & value_mask))
+               return 0;
+
+       switch (selector) {
+       case IB_SA_GT:
+               err = (src_value <= dst_value);
+               break;
+       case IB_SA_LT:
+               err = (src_value >= dst_value);
+               break;
+       case IB_SA_EQ:
+               err = (src_value != dst_value);
+               break;
+       default:
+               err = 0;
+               break;
+       }
+
+       return err;
+}
+
+static int cmp_rec(struct ib_sa_mcmember_rec *src,
+                  struct ib_sa_mcmember_rec *dst, ib_sa_comp_mask comp_mask)
+{
+       /* MGID must already match */
+
+       if (comp_mask & IB_SA_MCMEMBER_REC_PORT_GID &&
+           memcmp(&src->port_gid, &dst->port_gid, sizeof src->port_gid))
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_QKEY && src->qkey != dst->qkey)
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_MLID && src->mlid != dst->mlid)
+               return -EINVAL;
+       if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_MTU_SELECTOR,
+                          IB_SA_MCMEMBER_REC_MTU, dst->mtu_selector,
+                          src->mtu, dst->mtu))
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_TRAFFIC_CLASS &&
+           src->traffic_class != dst->traffic_class)
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_PKEY && src->pkey != dst->pkey)
+               return -EINVAL;
+       if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_RATE_SELECTOR,
+                          IB_SA_MCMEMBER_REC_RATE, dst->rate_selector,
+                          src->rate, dst->rate))
+               return -EINVAL;
+       if (check_selector(comp_mask,
+                          IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR,
+                          IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME,
+                          dst->packet_life_time_selector,
+                          src->packet_life_time, dst->packet_life_time))
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_SL && src->sl != dst->sl)
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_FLOW_LABEL &&
+           src->flow_label != dst->flow_label)
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_HOP_LIMIT &&
+           src->hop_limit != dst->hop_limit)
+               return -EINVAL;
+       if (comp_mask & IB_SA_MCMEMBER_REC_SCOPE && src->scope != dst->scope)
+               return -EINVAL;
+
+       /* join_state checked separately, proxy_join ignored */
+
+       return 0;
+}
+
+static int send_join(struct mcast_group *group, struct mcast_member *member)
+{
+       struct mcast_port *port = group->port;
+       int ret;
+
+       group->last_join = member;
+       ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+                                      port->port_num, IB_MGMT_METHOD_SET,
+                                      &member->multicast.rec,
+                                      member->multicast.comp_mask,
+                                      3000, GFP_KERNEL, join_handler, group,
+                                      &group->query);
+       if (ret >= 0) {
+               group->query_id = ret;
+               ret = 0;
+       }
+       return ret;
+}
+
+static int send_leave(struct mcast_group *group, u8 leave_state)
+{
+       struct mcast_port *port = group->port;
+       struct ib_sa_mcmember_rec rec;
+       int ret;
+
+       rec = group->rec;
+       rec.join_state = leave_state;
+
+       ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+                                      port->port_num, IB_SA_METHOD_DELETE, &rec,
+                                      IB_SA_MCMEMBER_REC_MGID     |
+                                      IB_SA_MCMEMBER_REC_PORT_GID |
+                                      IB_SA_MCMEMBER_REC_JOIN_STATE,
+                                      3000, GFP_KERNEL, leave_handler,
+                                      group, &group->query);
+       if (ret >= 0) {
+               group->query_id = ret;
+               ret = 0;
+       }
+       return ret;
+}
+
+static void join_group(struct mcast_group *group, struct mcast_member *member,
+                      u8 join_state)
+{
+       member->state = MCAST_MEMBER;
+       adjust_membership(group, join_state, 1);
+       group->rec.join_state |= join_state;
+       member->multicast.rec = group->rec;
+       member->multicast.rec.join_state = join_state;
+       list_move(&member->list, &group->active_list);
+}
+
+static int fail_join(struct mcast_group *group, struct mcast_member *member,
+                    int status)
+{
+       spin_lock_irq(&group->lock);
+       list_del_init(&member->list);
+       spin_unlock_irq(&group->lock);
+       return member->multicast.callback(status, &member->multicast);
+}
+
+static void process_group_error(struct mcast_group *group)
+{
+       struct mcast_member *member;
+       int ret;
+
+       spin_lock_irq(&group->lock);
+       while (!list_empty(&group->active_list)) {
+               member = list_entry(group->active_list.next,
+                                   struct mcast_member, list);
+               atomic_inc(&member->refcount);
+               list_del_init(&member->list);
+               adjust_membership(group, member->multicast.rec.join_state, -1);
+               member->state = MCAST_ERROR;
+               spin_unlock_irq(&group->lock);
+
+               ret = member->multicast.callback(-ENETRESET,
+                                                &member->multicast);
+               deref_member(member);
+               if (ret)
+                       ib_sa_free_multicast(&member->multicast);
+               spin_lock_irq(&group->lock);
+       }
+
+       group->rec.join_state = 0;
+       group->state = MCAST_BUSY;
+       spin_unlock_irq(&group->lock);
+}
+
+static void mcast_work_handler(struct work_struct *work)
+{
+       struct mcast_group *group;
+       struct mcast_member *member;
+       struct ib_sa_multicast *multicast;
+       int status, ret;
+       u8 join_state;
+
+       group = container_of(work, typeof(*group), work);
+retest:
+       spin_lock_irq(&group->lock);
+       while (!list_empty(&group->pending_list) ||
+              (group->state == MCAST_ERROR)) {
+
+               if (group->state == MCAST_ERROR) {
+                       spin_unlock_irq(&group->lock);
+                       process_group_error(group);
+                       goto retest;
+               }
+
+               member = list_entry(group->pending_list.next,
+                                   struct mcast_member, list);
+               multicast = &member->multicast;
+               join_state = multicast->rec.join_state;
+               atomic_inc(&member->refcount);
+
+               if (join_state == (group->rec.join_state & join_state)) {
+                       status = cmp_rec(&group->rec, &multicast->rec,
+                                        multicast->comp_mask);
+                       if (!status)
+                               join_group(group, member, join_state);
+                       else
+                               list_del_init(&member->list);
+                       spin_unlock_irq(&group->lock);
+                       ret = multicast->callback(status, multicast);
+               } else {
+                       spin_unlock_irq(&group->lock);
+                       status = send_join(group, member);
+                       if (!status) {
+                               deref_member(member);
+                               return;
+                       }
+                       ret = fail_join(group, member, status);
+               }
+
+               deref_member(member);
+               if (ret)
+                       ib_sa_free_multicast(&member->multicast);
+               spin_lock_irq(&group->lock);
+       }
+
+       join_state = get_leave_state(group);
+       if (join_state) {
+               group->rec.join_state &= ~join_state;
+               spin_unlock_irq(&group->lock);
+               if (send_leave(group, join_state))
+                       goto retest;
+       } else {
+               group->state = MCAST_IDLE;
+               spin_unlock_irq(&group->lock);
+               release_group(group);
+       }
+}
+
+/*
+ * Fail a join request if it is still active - at the head of the pending queue.
+ */
+static void process_join_error(struct mcast_group *group, int status)
+{
+       struct mcast_member *member;
+       int ret;
+
+       spin_lock_irq(&group->lock);
+       member = list_entry(group->pending_list.next,
+                           struct mcast_member, list);
+       if (group->last_join == member) {
+               atomic_inc(&member->refcount);
+               list_del_init(&member->list);
+               spin_unlock_irq(&group->lock);
+               ret = member->multicast.callback(status, &member->multicast);
+               deref_member(member);
+               if (ret)
+                       ib_sa_free_multicast(&member->multicast);
+       } else
+               spin_unlock_irq(&group->lock);
+}
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+                        void *context)
+{
+       struct mcast_group *group = context;
+
+       if (status)
+               process_join_error(group, status);
+       else {
+               spin_lock_irq(&group->port->lock);
+               group->rec = *rec;
+               if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+                       rb_erase(&group->node, &group->port->table);
+                       mcast_insert(group->port, group, 1);
+               }
+               spin_unlock_irq(&group->port->lock);
+       }
+       mcast_work_handler(&group->work);
+}
+
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+                         void *context)
+{
+       struct mcast_group *group = context;
+
+       mcast_work_handler(&group->work);
+}
+
+static struct mcast_group *acquire_group(struct mcast_port *port,
+                                        union ib_gid *mgid, gfp_t gfp_mask)
+{
+       struct mcast_group *group, *cur_group;
+       unsigned long flags;
+       int is_mgid0;
+
+       is_mgid0 = !memcmp(&mgid0, mgid, sizeof mgid0);
+       if (!is_mgid0) {
+               spin_lock_irqsave(&port->lock, flags);
+               group = mcast_find(port, mgid);
+               if (group)
+                       goto found;
+               spin_unlock_irqrestore(&port->lock, flags);
+       }
+
+       group = kzalloc(sizeof *group, gfp_mask);
+       if (!group)
+               return NULL;
+
+       group->port = port;
+       group->rec.mgid = *mgid;
+       INIT_LIST_HEAD(&group->pending_list);
+       INIT_LIST_HEAD(&group->active_list);
+       INIT_WORK(&group->work, mcast_work_handler);
+       spin_lock_init(&group->lock);
+
+       spin_lock_irqsave(&port->lock, flags);
+       cur_group = mcast_insert(port, group, is_mgid0);
+       if (cur_group) {
+               kfree(group);
+               group = cur_group;
+       } else
+               atomic_inc(&port->refcount);
+found:
+       atomic_inc(&group->refcount);
+       spin_unlock_irqrestore(&port->lock, flags);
+       return group;
+}
+
+/*
+ * We serialize all join requests to a single group to make our lives much
+ * easier.  Otherwise, two users could try to join the same group
+ * simultaneously, with different configurations, one could leave while the
+ * join is in progress, etc., which makes locking around error recovery
+ * difficult.
+ */
+struct ib_sa_multicast *
+ib_sa_join_multicast(struct ib_sa_client *client,
+                    struct ib_device *device, u8 port_num,
+                    struct ib_sa_mcmember_rec *rec,
+                    ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+                    int (*callback)(int status,
+                                    struct ib_sa_multicast *multicast),
+                    void *context)
+{
+       struct mcast_device *dev;
+       struct mcast_member *member;
+       struct ib_sa_multicast *multicast;
+       int ret;
+
+       dev = ib_get_client_data(device, &mcast_client);
+       if (!dev)
+               return ERR_PTR(-ENODEV);
+
+       member = kmalloc(sizeof *member, gfp_mask);
+       if (!member)
+               return ERR_PTR(-ENOMEM);
+
+       ib_sa_client_get(client);
+       member->client = client;
+       member->multicast.rec = *rec;
+       member->multicast.comp_mask = comp_mask;
+       member->multicast.callback = callback;
+       member->multicast.context = context;
+       init_completion(&member->comp);
+       atomic_set(&member->refcount, 1);
+       member->state = MCAST_JOINING;
+
+       member->group = acquire_group(&dev->port[port_num - dev->start_port],
+                                     &rec->mgid, gfp_mask);
+       if (!member->group) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       /*
+        * The user will get the multicast structure in their callback.  They
+        * could then free the multicast structure before we can return from
+        * this routine.  So we save the pointer to return before queuing
+        * any callback.
+        */
+       multicast = &member->multicast;
+       queue_join(member);
+       return multicast;
+
+err:
+       ib_sa_client_put(client);
+       kfree(member);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(ib_sa_join_multicast);
+
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast)
+{
+       struct mcast_member *member;
+       struct mcast_group *group;
+
+       member = container_of(multicast, struct mcast_member, multicast);
+       group = member->group;
+
+       spin_lock_irq(&group->lock);
+       if (member->state == MCAST_MEMBER)
+               adjust_membership(group, multicast->rec.join_state, -1);
+
+       list_del_init(&member->list);
+
+       if (group->state == MCAST_IDLE) {
+               group->state = MCAST_BUSY;
+               spin_unlock_irq(&group->lock);
+               /* Continue to hold reference on group until callback */
+               queue_work(mcast_wq, &group->work);
+       } else {
+               spin_unlock_irq(&group->lock);
+               release_group(group);
+       }
+
+       deref_member(member);
+       wait_for_completion(&member->comp);
+       ib_sa_client_put(member->client);
+       kfree(member);
+}
+EXPORT_SYMBOL(ib_sa_free_multicast);
+
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+                          union ib_gid *mgid, struct ib_sa_mcmember_rec *rec)
+{
+       struct mcast_device *dev;
+       struct mcast_port *port;
+       struct mcast_group *group;
+       unsigned long flags;
+       int ret = 0;
+
+       dev = ib_get_client_data(device, &mcast_client);
+       if (!dev)
+               return -ENODEV;
+
+       port = &dev->port[port_num - dev->start_port];
+       spin_lock_irqsave(&port->lock, flags);
+       group = mcast_find(port, mgid);
+       if (group)
+               *rec = group->rec;
+       else
+               ret = -EADDRNOTAVAIL;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(ib_sa_get_mcmember_rec);
+
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+                            struct ib_sa_mcmember_rec *rec,
+                            struct ib_ah_attr *ah_attr)
+{
+       int ret;
+       u16 gid_index;
+       u8 p;
+
+       ret = ib_find_cached_gid(device, &rec->port_gid, &p, &gid_index);
+       if (ret)
+               return ret;
+
+       memset(ah_attr, 0, sizeof *ah_attr);
+       ah_attr->dlid = be16_to_cpu(rec->mlid);
+       ah_attr->sl = rec->sl;
+       ah_attr->port_num = port_num;
+       ah_attr->static_rate = rec->rate;
+
+       ah_attr->ah_flags = IB_AH_GRH;
+       ah_attr->grh.dgid = rec->mgid;
+
+       ah_attr->grh.sgid_index = (u8) gid_index;
+       ah_attr->grh.flow_label = be32_to_cpu(rec->flow_label);
+       ah_attr->grh.hop_limit = rec->hop_limit;
+       ah_attr->grh.traffic_class = rec->traffic_class;
+
+       return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_mcmember);
+
+static void mcast_groups_lost(struct mcast_port *port)
+{
+       struct mcast_group *group;
+       struct rb_node *node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       for (node = rb_first(&port->table); node; node = rb_next(node)) {
+               group = rb_entry(node, struct mcast_group, node);
+               spin_lock(&group->lock);
+               if (group->state == MCAST_IDLE) {
+                       atomic_inc(&group->refcount);
+                       queue_work(mcast_wq, &group->work);
+               }
+               group->state = MCAST_ERROR;
+               spin_unlock(&group->lock);
+       }
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void mcast_event_handler(struct ib_event_handler *handler,
+                               struct ib_event *event)
+{
+       struct mcast_device *dev;
+
+       dev = container_of(handler, struct mcast_device, event_handler);
+
+       switch (event->event) {
+       case IB_EVENT_PORT_ERR:
+       case IB_EVENT_LID_CHANGE:
+       case IB_EVENT_SM_CHANGE:
+       case IB_EVENT_CLIENT_REREGISTER:
+               mcast_groups_lost(&dev->port[event->element.port_num -
+                                            dev->start_port]);
+               break;
+       default:
+               break;
+       }
+}
+
+static void mcast_add_one(struct ib_device *device)
+{
+       struct mcast_device *dev;
+       struct mcast_port *port;
+       int i;
+
+       if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+               return;
+
+       dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
+                     GFP_KERNEL);
+       if (!dev)
+               return;
+
+       if (device->node_type == RDMA_NODE_IB_SWITCH)
+               dev->start_port = dev->end_port = 0;
+       else {
+               dev->start_port = 1;
+               dev->end_port = device->phys_port_cnt;
+       }
+
+       for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+               port = &dev->port[i];
+               port->dev = dev;
+               port->port_num = dev->start_port + i;
+               spin_lock_init(&port->lock);
+               port->table = RB_ROOT;
+               init_completion(&port->comp);
+               atomic_set(&port->refcount, 1);
+       }
+
+       dev->device = device;
+       ib_set_client_data(device, &mcast_client, dev);
+
+       INIT_IB_EVENT_HANDLER(&dev->event_handler, device, mcast_event_handler);
+       ib_register_event_handler(&dev->event_handler);
+}
+
+static void mcast_remove_one(struct ib_device *device)
+{
+       struct mcast_device *dev;
+       struct mcast_port *port;
+       int i;
+
+       dev = ib_get_client_data(device, &mcast_client);
+       if (!dev)
+               return;
+
+       ib_unregister_event_handler(&dev->event_handler);
+       flush_workqueue(mcast_wq);
+
+       for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+               port = &dev->port[i];
+               deref_port(port);
+               wait_for_completion(&port->comp);
+       }
+
+       kfree(dev);
+}
+
+int mcast_init(void)
+{
+       int ret;
+
+       mcast_wq = create_singlethread_workqueue("ib_mcast");
+       if (!mcast_wq)
+               return -ENOMEM;
+
+       ib_sa_register_client(&sa_client);
+
+       ret = ib_register_client(&mcast_client);
+       if (ret)
+               goto err;
+       return 0;
+
+err:
+       ib_sa_unregister_client(&sa_client);
+       destroy_workqueue(mcast_wq);
+       return ret;
+}
+
+void mcast_cleanup(void)
+{
+       ib_unregister_client(&mcast_client);
+       ib_sa_unregister_client(&sa_client);
+       destroy_workqueue(mcast_wq);
+}
diff --git a/drivers/infiniband/core/sa.h b/drivers/infiniband/core/sa.h
new file mode 100644 (file)
index 0000000..24c93fd
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation.  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
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SA_H
+#define SA_H
+
+#include <rdma/ib_sa.h>
+
+static inline void ib_sa_client_get(struct ib_sa_client *client)
+{
+       atomic_inc(&client->users);
+}
+
+static inline void ib_sa_client_put(struct ib_sa_client *client)
+{
+       if (atomic_dec_and_test(&client->users))
+               complete(&client->comp);
+}
+
+int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
+                            struct ib_device *device, u8 port_num,
+                            u8 method,
+                            struct ib_sa_mcmember_rec *rec,
+                            ib_sa_comp_mask comp_mask,
+                            int timeout_ms, gfp_t gfp_mask,
+                            void (*callback)(int status,
+                                             struct ib_sa_mcmember_rec *resp,
+                                             void *context),
+                            void *context,
+                            struct ib_sa_query **sa_query);
+
+int mcast_init(void);
+void mcast_cleanup(void);
+
+#endif /* SA_H */
index e45afba75341ee86d80464406564c3492366edbd..68db633711c5dfd58711c9018ea11d599a9cc3c0 100644 (file)
@@ -47,8 +47,8 @@
 #include <linux/workqueue.h>
 
 #include <rdma/ib_pack.h>
-#include <rdma/ib_sa.h>
 #include <rdma/ib_cache.h>
+#include "sa.h"
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -425,17 +425,6 @@ void ib_sa_register_client(struct ib_sa_client *client)
 }
 EXPORT_SYMBOL(ib_sa_register_client);
 
-static inline void ib_sa_client_get(struct ib_sa_client *client)
-{
-       atomic_inc(&client->users);
-}
-
-static inline void ib_sa_client_put(struct ib_sa_client *client)
-{
-       if (atomic_dec_and_test(&client->users))
-               complete(&client->comp);
-}
-
 void ib_sa_unregister_client(struct ib_sa_client *client)
 {
        ib_sa_client_put(client);
@@ -482,6 +471,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
        ah_attr->sl = rec->sl;
        ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
        ah_attr->port_num = port_num;
+       ah_attr->static_rate = rec->rate;
 
        if (rec->hop_limit > 1) {
                ah_attr->ah_flags = IB_AH_GRH;
@@ -901,7 +891,6 @@ err1:
        kfree(query);
        return ret;
 }
-EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
 
 static void send_handler(struct ib_mad_agent *agent,
                         struct ib_mad_send_wc *mad_send_wc)
@@ -1053,14 +1042,27 @@ static int __init ib_sa_init(void)
        get_random_bytes(&tid, sizeof tid);
 
        ret = ib_register_client(&sa_client);
-       if (ret)
+       if (ret) {
                printk(KERN_ERR "Couldn't register ib_sa client\n");
+               goto err1;
+       }
+
+       ret = mcast_init();
+       if (ret) {
+               printk(KERN_ERR "Couldn't initialize multicast handling\n");
+               goto err2;
+       }
 
+       return 0;
+err2:
+       ib_unregister_client(&sa_client);
+err1:
        return ret;
 }
 
 static void __exit ib_sa_cleanup(void)
 {
+       mcast_cleanup();
        ib_unregister_client(&sa_client);
        idr_destroy(&query_idr);
 }
index 709323c14c5d3fff1fba12f50c6290e0a17d6a4a..000c086bf2e9bf9d6ec0e8d90e7d9c5cec7fc4ec 100644 (file)
@@ -714,8 +714,6 @@ int ib_device_register_sysfs(struct ib_device *device)
                if (ret)
                        goto err_put;
        } else {
-               int i;
-
                for (i = 1; i <= device->phys_port_cnt; ++i) {
                        ret = add_port(device, i);
                        if (ret)
index 6b81b98961c7b8014120cfd79cf939f478778e12..b516b93b85505b5a243a88ad00a670defab4c452 100644 (file)
@@ -70,10 +70,24 @@ struct ucma_context {
        u64                     uid;
 
        struct list_head        list;
+       struct list_head        mc_list;
+};
+
+struct ucma_multicast {
+       struct ucma_context     *ctx;
+       int                     id;
+       int                     events_reported;
+
+       u64                     uid;
+       struct list_head        list;
+       struct sockaddr         addr;
+       u8                      pad[sizeof(struct sockaddr_in6) -
+                                   sizeof(struct sockaddr)];
 };
 
 struct ucma_event {
        struct ucma_context     *ctx;
+       struct ucma_multicast   *mc;
        struct list_head        list;
        struct rdma_cm_id       *cm_id;
        struct rdma_ucm_event_resp resp;
@@ -81,6 +95,7 @@ struct ucma_event {
 
 static DEFINE_MUTEX(mut);
 static DEFINE_IDR(ctx_idr);
+static DEFINE_IDR(multicast_idr);
 
 static inline struct ucma_context *_ucma_find_context(int id,
                                                      struct ucma_file *file)
@@ -124,6 +139,7 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
 
        atomic_set(&ctx->ref, 1);
        init_completion(&ctx->comp);
+       INIT_LIST_HEAD(&ctx->mc_list);
        ctx->file = file;
 
        do {
@@ -147,6 +163,37 @@ error:
        return NULL;
 }
 
+static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx)
+{
+       struct ucma_multicast *mc;
+       int ret;
+
+       mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+       if (!mc)
+               return NULL;
+
+       do {
+               ret = idr_pre_get(&multicast_idr, GFP_KERNEL);
+               if (!ret)
+                       goto error;
+
+               mutex_lock(&mut);
+               ret = idr_get_new(&multicast_idr, mc, &mc->id);
+               mutex_unlock(&mut);
+       } while (ret == -EAGAIN);
+
+       if (ret)
+               goto error;
+
+       mc->ctx = ctx;
+       list_add_tail(&mc->list, &ctx->mc_list);
+       return mc;
+
+error:
+       kfree(mc);
+       return NULL;
+}
+
 static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
                                 struct rdma_conn_param *src)
 {
@@ -180,8 +227,19 @@ static void ucma_set_event_context(struct ucma_context *ctx,
                                   struct ucma_event *uevent)
 {
        uevent->ctx = ctx;
-       uevent->resp.uid = ctx->uid;
-       uevent->resp.id = ctx->id;
+       switch (event->event) {
+       case RDMA_CM_EVENT_MULTICAST_JOIN:
+       case RDMA_CM_EVENT_MULTICAST_ERROR:
+               uevent->mc = (struct ucma_multicast *)
+                            event->param.ud.private_data;
+               uevent->resp.uid = uevent->mc->uid;
+               uevent->resp.id = uevent->mc->id;
+               break;
+       default:
+               uevent->resp.uid = ctx->uid;
+               uevent->resp.id = ctx->id;
+               break;
+       }
 }
 
 static int ucma_event_handler(struct rdma_cm_id *cm_id,
@@ -199,7 +257,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
        ucma_set_event_context(ctx, event, uevent);
        uevent->resp.event = event->event;
        uevent->resp.status = event->status;
-       if (cm_id->ps == RDMA_PS_UDP)
+       if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
                ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
        else
                ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -290,6 +348,8 @@ static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
 
        list_del(&uevent->list);
        uevent->ctx->events_reported++;
+       if (uevent->mc)
+               uevent->mc->events_reported++;
        kfree(uevent);
 done:
        mutex_unlock(&file->mut);
@@ -342,6 +402,19 @@ err1:
        return ret;
 }
 
+static void ucma_cleanup_multicast(struct ucma_context *ctx)
+{
+       struct ucma_multicast *mc, *tmp;
+
+       mutex_lock(&mut);
+       list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) {
+               list_del(&mc->list);
+               idr_remove(&multicast_idr, mc->id);
+               kfree(mc);
+       }
+       mutex_unlock(&mut);
+}
+
 static void ucma_cleanup_events(struct ucma_context *ctx)
 {
        struct ucma_event *uevent, *tmp;
@@ -360,6 +433,19 @@ static void ucma_cleanup_events(struct ucma_context *ctx)
        }
 }
 
+static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
+{
+       struct ucma_event *uevent, *tmp;
+
+       list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
+               if (uevent->mc != mc)
+                       continue;
+
+               list_del(&uevent->list);
+               kfree(uevent);
+       }
+}
+
 static int ucma_free_ctx(struct ucma_context *ctx)
 {
        int events_reported;
@@ -367,6 +453,8 @@ static int ucma_free_ctx(struct ucma_context *ctx)
        /* No new events will be generated after destroying the id. */
        rdma_destroy_id(ctx->cm_id);
 
+       ucma_cleanup_multicast(ctx);
+
        /* Cleanup events not yet reported to the user. */
        mutex_lock(&ctx->file->mut);
        ucma_cleanup_events(ctx);
@@ -731,6 +819,114 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
        return ret;
 }
 
+static ssize_t ucma_join_multicast(struct ucma_file *file,
+                                  const char __user *inbuf,
+                                  int in_len, int out_len)
+{
+       struct rdma_ucm_join_mcast cmd;
+       struct rdma_ucm_create_id_resp resp;
+       struct ucma_context *ctx;
+       struct ucma_multicast *mc;
+       int ret;
+
+       if (out_len < sizeof(resp))
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+               return -EFAULT;
+
+       ctx = ucma_get_ctx(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
+       mutex_lock(&file->mut);
+       mc = ucma_alloc_multicast(ctx);
+       if (IS_ERR(mc)) {
+               ret = PTR_ERR(mc);
+               goto err1;
+       }
+
+       mc->uid = cmd.uid;
+       memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
+       ret = rdma_join_multicast(ctx->cm_id, &mc->addr, mc);
+       if (ret)
+               goto err2;
+
+       resp.id = mc->id;
+       if (copy_to_user((void __user *)(unsigned long)cmd.response,
+                        &resp, sizeof(resp))) {
+               ret = -EFAULT;
+               goto err3;
+       }
+
+       mutex_unlock(&file->mut);
+       ucma_put_ctx(ctx);
+       return 0;
+
+err3:
+       rdma_leave_multicast(ctx->cm_id, &mc->addr);
+       ucma_cleanup_mc_events(mc);
+err2:
+       mutex_lock(&mut);
+       idr_remove(&multicast_idr, mc->id);
+       mutex_unlock(&mut);
+       list_del(&mc->list);
+       kfree(mc);
+err1:
+       mutex_unlock(&file->mut);
+       ucma_put_ctx(ctx);
+       return ret;
+}
+
+static ssize_t ucma_leave_multicast(struct ucma_file *file,
+                                   const char __user *inbuf,
+                                   int in_len, int out_len)
+{
+       struct rdma_ucm_destroy_id cmd;
+       struct rdma_ucm_destroy_id_resp resp;
+       struct ucma_multicast *mc;
+       int ret = 0;
+
+       if (out_len < sizeof(resp))
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+               return -EFAULT;
+
+       mutex_lock(&mut);
+       mc = idr_find(&multicast_idr, cmd.id);
+       if (!mc)
+               mc = ERR_PTR(-ENOENT);
+       else if (mc->ctx->file != file)
+               mc = ERR_PTR(-EINVAL);
+       else {
+               idr_remove(&multicast_idr, mc->id);
+               atomic_inc(&mc->ctx->ref);
+       }
+       mutex_unlock(&mut);
+
+       if (IS_ERR(mc)) {
+               ret = PTR_ERR(mc);
+               goto out;
+       }
+
+       rdma_leave_multicast(mc->ctx->cm_id, &mc->addr);
+       mutex_lock(&mc->ctx->file->mut);
+       ucma_cleanup_mc_events(mc);
+       list_del(&mc->list);
+       mutex_unlock(&mc->ctx->file->mut);
+
+       ucma_put_ctx(mc->ctx);
+       resp.events_reported = mc->events_reported;
+       kfree(mc);
+
+       if (copy_to_user((void __user *)(unsigned long)cmd.response,
+                        &resp, sizeof(resp)))
+               ret = -EFAULT;
+out:
+       return ret;
+}
+
 static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
                                   const char __user *inbuf,
                                   int in_len, int out_len) = {
@@ -750,6 +946,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
        [RDMA_USER_CM_CMD_GET_OPTION]   = NULL,
        [RDMA_USER_CM_CMD_SET_OPTION]   = NULL,
        [RDMA_USER_CM_CMD_NOTIFY]       = ucma_notify,
+       [RDMA_USER_CM_CMD_JOIN_MCAST]   = ucma_join_multicast,
+       [RDMA_USER_CM_CMD_LEAVE_MCAST]  = ucma_leave_multicast,
 };
 
 static ssize_t ucma_write(struct file *filp, const char __user *buf,
index 27fe242ed4353bc33fdb76410c9dcc4fd6cb6b30..59243d9aedd6e93ee07d88a189d2a5878a959b84 100644 (file)
@@ -1073,7 +1073,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
             0xffffc000) / sizeof(struct c2_rxp_desc);
 
        /* Request an interrupt line for the driver */
-       ret = request_irq(pcidev->irq, c2_interrupt, SA_SHIRQ, DRV_NAME, c2dev);
+       ret = request_irq(pcidev->irq, c2_interrupt, IRQF_SHARED, DRV_NAME, c2dev);
        if (ret) {
                printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n",
                        pci_name(pcidev), pcidev->irq);
index 5a7306f5efae8433b2769cc59853ddc49f04b9c4..75f7b16a271d6652a9aac3326c6a56ffc18f5ffe 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 82fa72041989e54695a7bfc2b13279b4ea4fe1f2..114ac3b775dc2fb527222a0c575d782af5d7e736 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 1b97e80b87805d98f7b519f744334d1258c02337..8ab04a7c6f6eec1558546a57c8e2397e920e643c 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 997aa32cbf0794102677b448d3b03599d71e3869..65bf577311aa628af1e980f073e4c4c9268e1383 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index a6bbe8370d818c8328fbf48ff1e6c34bd93922c0..a2703a3d882d0c2279a215f0d90a6aa63ddb357f 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 103fc42d6976471a1d4b87ed51321b327d6d3c4c..90d7b8972cb46d21a554393abf88cd5d69730eff 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 4611afa5222003d9f121658116c364175920d4ef..0315c9d9fce931c680f99107c7cfc322f7d86533 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 6517ef85026feaa7b73a8b2c6ec52514b6d0b159..caf4e6007a44cc4aef2e47c08f2ebb5c0db4e875 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index a522b1baa3b40854fcdbca1b166e4052385b6024..e5442e34b788566f4adba514fa4bc332db8f8698 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 7c810d9042796c7fc87ec38cb1657bb4d94274b7..0c6f281bd4a03726c4875ccb03c75771bde28f7b 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 98b3bdb5de9e99872d8762eeed2a1b4131d42415..d7624c170ee73e16a13ef7c35c0366d37faa473a 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index a6efa8fe15d8cd000dece3cfaac93c2a86fb8469..54362afbf72f6f410b5224e8c297afb92559a6e3 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 2b6cd53bb3fc741344577cd461700c9174637627..a6c2c4ba29e69244b896849b376698a5c2ab7cd2 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 6861087d776cfecca15ab8e276f84284ede49eb4..2aef122f9955b63cce07d008aee911282cc14a40 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 61e3278fd7a88dd0cb5dc18f86399c0bbe9d7163..2af3e93b607f2a380f13b21148432e95bbd03557 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index e066727504b6db81ce4f9bfe406e43251c5b2f10..4dda2f6da2dec84869e0838e5ced54e5f86d3ff2 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
@@ -846,6 +845,8 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
                        break;
                case IWCH_QP_STATE_TERMINATE:
                        qhp->attr.state = IWCH_QP_STATE_TERMINATE;
+                       if (t3b_device(qhp->rhp))
+                               cxio_set_wq_in_error(&qhp->wq);
                        if (!internal)
                                terminate = 1;
                        break;
index c4e7fbea8bbdb83d1839905c9d46b8c1772f06e4..cb7086f558c1e769ad66eee48fee14d1bbe97081 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. 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
index 727b10d896868516e1776938ef5fdbafedd0cba7..1a854598e0e68d01ca4a4ede2bb765cc13e2dac5 100644 (file)
@@ -7,11 +7,3 @@ config INFINIBAND_EHCA
        To compile the driver as a module, choose M here. The module
        will be called ib_ehca.
 
-config INFINIBAND_EHCA_SCALING
-       bool "Scaling support (EXPERIMENTAL)"
-       depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL
-       default y
-       ---help---
-       eHCA scaling support schedules the CQ callbacks to different CPUs.
-
-       To enable this feature choose Y here.
index cf95ee474b0f6a1105551ce69f342168d5c2034e..40404c9e28179558d45feccc83880feb8b4132b5 100644 (file)
@@ -42,8 +42,6 @@
 #ifndef __EHCA_CLASSES_H__
 #define __EHCA_CLASSES_H__
 
-#include "ehca_classes.h"
-#include "ipz_pt_fn.h"
 
 struct ehca_module;
 struct ehca_qp;
@@ -54,14 +52,22 @@ struct ehca_mw;
 struct ehca_pd;
 struct ehca_av;
 
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
 #ifdef CONFIG_PPC64
 #include "ehca_classes_pSeries.h"
 #endif
+#include "ipz_pt_fn.h"
+#include "ehca_qes.h"
+#include "ehca_irq.h"
 
-#include <rdma/ib_verbs.h>
-#include <rdma/ib_user_verbs.h>
+#define EHCA_EQE_CACHE_SIZE 20
 
-#include "ehca_irq.h"
+struct ehca_eqe_cache_entry {
+       struct ehca_eqe *eqe;
+       struct ehca_cq *cq;
+};
 
 struct ehca_eq {
        u32 length;
@@ -74,6 +80,8 @@ struct ehca_eq {
        spinlock_t spinlock;
        struct tasklet_struct interrupt_task;
        u32 ist;
+       spinlock_t irq_spinlock;
+       struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
 };
 
 struct ehca_sport {
@@ -269,6 +277,7 @@ extern struct idr ehca_cq_idr;
 extern int ehca_static_rate;
 extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
+extern int ehca_scaling_code;
 
 struct ipzu_queue_resp {
        u32 qe_size;      /* queue entry size */
index 5281dec66f127c5667c3ac44aab490d3f644a417..4961eb88827cd85bb6438a5777c1458297f349e0 100644 (file)
@@ -61,6 +61,7 @@ int ehca_create_eq(struct ehca_shca *shca,
        struct ib_device *ib_dev = &shca->ib_device;
 
        spin_lock_init(&eq->spinlock);
+       spin_lock_init(&eq->irq_spinlock);
        eq->is_initialized = 0;
 
        if (type != EHCA_EQ && type != EHCA_NEQ) {
@@ -122,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca,
        /* register interrupt handlers and initialize work queues */
        if (type == EHCA_EQ) {
                ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
-                                         SA_INTERRUPT, "ehca_eq",
+                                         IRQF_DISABLED, "ehca_eq",
                                          (void *)shca);
                if (ret < 0)
                        ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -130,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca,
                tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
        } else if (type == EHCA_NEQ) {
                ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
-                                         SA_INTERRUPT, "ehca_neq",
+                                         IRQF_DISABLED, "ehca_neq",
                                          (void *)shca);
                if (ret < 0)
                        ehca_err(ib_dev, "Can't map interrupt handler.");
index b7be950ab47c3a700737feae370d8bd09a2d2b69..30eb45df9f0b8d8207173c0023b481af89e6a95f 100644 (file)
@@ -162,6 +162,9 @@ int ehca_query_port(struct ib_device *ibdev,
        props->active_width    = IB_WIDTH_12X;
        props->active_speed    = 0x1;
 
+       /* at the moment (logical) link state is always LINK_UP */
+       props->phys_state      = 0x5;
+
 query_port1:
        ehca_free_fw_ctrlblock(rblock);
 
index 6c4f9f91b15df3e10f9e417f3deac51abcfd4077..3ec53c687d0823c2eb0e7d34409f8684d7bdbe5e 100644 (file)
 #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
 #define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
 
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
-
 static void queue_comp_task(struct ehca_cq *__cq);
 
 static struct ehca_comp_pool* pool;
 static struct notifier_block comp_pool_callback_nb;
 
-#endif
-
 static inline void comp_event_callback(struct ehca_cq *cq)
 {
        if (!cq->ib_cq.comp_handler)
@@ -206,7 +202,7 @@ static void qp_event_callback(struct ehca_shca *shca,
 }
 
 static void cq_event_callback(struct ehca_shca *shca,
-                                         u64 eqe)
+                             u64 eqe)
 {
        struct ehca_cq *cq;
        unsigned long flags;
@@ -318,7 +314,7 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
                          "disruptive port %x configuration change", port);
 
                ehca_info(&shca->ib_device,
-                        "port %x is inactive.", port);
+                         "port %x is inactive.", port);
                event.device = &shca->ib_device;
                event.event = IB_EVENT_PORT_ERR;
                event.element.port_num = port;
@@ -326,7 +322,7 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
                ib_dispatch_event(&event);
 
                ehca_info(&shca->ib_device,
-                        "port %x is active.", port);
+                         "port %x is active.", port);
                event.device = &shca->ib_device;
                event.event = IB_EVENT_PORT_ACTIVE;
                event.element.port_num = port;
@@ -401,115 +397,170 @@ irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-void ehca_tasklet_eq(unsigned long data)
-{
-       struct ehca_shca *shca = (struct ehca_shca*)data;
-       struct ehca_eqe *eqe;
-       int int_state;
-       int query_cnt = 0;
 
-       do {
-               eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
+{
+       u64 eqe_value;
+       u32 token;
+       unsigned long flags;
+       struct ehca_cq *cq;
+       eqe_value = eqe->entry;
+       ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
+       if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+               ehca_dbg(&shca->ib_device, "... completion event");
+               token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               cq = idr_find(&ehca_cq_idr, token);
+               if (cq == NULL) {
+                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+                       ehca_err(&shca->ib_device,
+                                "Invalid eqe for non-existing cq token=%x",
+                                token);
+                       return;
+               }
+               reset_eq_pending(cq);
+               if (ehca_scaling_code) {
+                       queue_comp_task(cq);
+                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+               } else {
+                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+                       comp_event_callback(cq);
+               }
+       } else {
+               ehca_dbg(&shca->ib_device,
+                        "Got non completion event");
+               parse_identifier(shca, eqe_value);
+       }
+}
 
-               if ((shca->hw_level >= 2) && eqe)
-                       int_state = 1;
-               else
-                       int_state = 0;
-
-               while ((int_state == 1) || eqe) {
-                       while (eqe) {
-                               u64 eqe_value = eqe->entry;
-
-                               ehca_dbg(&shca->ib_device,
-                                        "eqe_value=%lx", eqe_value);
-
-                               /* TODO: better structure */
-                               if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT,
-                                                  eqe_value)) {
-                                       unsigned long flags;
-                                       u32 token;
-                                       struct ehca_cq *cq;
-
-                                       ehca_dbg(&shca->ib_device,
-                                                "... completion event");
-                                       token =
-                                               EHCA_BMASK_GET(EQE_CQ_TOKEN,
-                                                              eqe_value);
-                                       spin_lock_irqsave(&ehca_cq_idr_lock,
-                                                         flags);
-                                       cq = idr_find(&ehca_cq_idr, token);
-
-                                       if (cq == NULL) {
-                                               spin_unlock_irqrestore(&ehca_cq_idr_lock,
-                                                                      flags);
-                                               break;
-                                       }
-
-                                       reset_eq_pending(cq);
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
-                                       queue_comp_task(cq);
-                                       spin_unlock_irqrestore(&ehca_cq_idr_lock,
-                                                              flags);
-#else
-                                       spin_unlock_irqrestore(&ehca_cq_idr_lock,
-                                                              flags);
-                                       comp_event_callback(cq);
-#endif
-                               } else {
-                                       ehca_dbg(&shca->ib_device,
-                                                "... non completion event");
-                                       parse_identifier(shca, eqe_value);
-                               }
-                               eqe =
-                                       (struct ehca_eqe *)ehca_poll_eq(shca,
-                                                                   &shca->eq);
-                       }
+void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+{
+       struct ehca_eq *eq = &shca->eq;
+       struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
+       u64 eqe_value;
+       unsigned long flags;
+       int eqe_cnt, i;
+       int eq_empty = 0;
+
+       spin_lock_irqsave(&eq->irq_spinlock, flags);
+       if (is_irq) {
+               const int max_query_cnt = 100;
+               int query_cnt = 0;
+               int int_state = 1;
+               do {
+                       int_state = hipz_h_query_int_state(
+                               shca->ipz_hca_handle, eq->ist);
+                       query_cnt++;
+                       iosync();
+               } while (int_state && query_cnt < max_query_cnt);
+               if (unlikely((query_cnt == max_query_cnt)))
+                       ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x",
+                                int_state, query_cnt);
+       }
 
-                       if (shca->hw_level >= 2) {
-                               int_state =
-                                   hipz_h_query_int_state(shca->ipz_hca_handle,
-                                                          shca->eq.ist);
-                               query_cnt++;
-                               iosync();
-                               if (query_cnt >= 100) {
-                                       query_cnt = 0;
-                                       int_state = 0;
-                               }
+       /* read out all eqes */
+       eqe_cnt = 0;
+       do {
+               u32 token;
+               eqe_cache[eqe_cnt].eqe =
+                       (struct ehca_eqe *)ehca_poll_eq(shca, eq);
+               if (!eqe_cache[eqe_cnt].eqe)
+                       break;
+               eqe_value = eqe_cache[eqe_cnt].eqe->entry;
+               if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+                       token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+                       spin_lock(&ehca_cq_idr_lock);
+                       eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+                       if (!eqe_cache[eqe_cnt].cq) {
+                               spin_unlock(&ehca_cq_idr_lock);
+                               ehca_err(&shca->ib_device,
+                                        "Invalid eqe for non-existing cq "
+                                        "token=%x", token);
+                               continue;
                        }
-                       eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
-
+                       spin_unlock(&ehca_cq_idr_lock);
+               } else
+                       eqe_cache[eqe_cnt].cq = NULL;
+               eqe_cnt++;
+       } while (eqe_cnt < EHCA_EQE_CACHE_SIZE);
+       if (!eqe_cnt) {
+               if (is_irq)
+                       ehca_dbg(&shca->ib_device,
+                                "No eqe found for irq event");
+               goto unlock_irq_spinlock;
+       } else if (!is_irq)
+               ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
+       if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
+               ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
+       /* enable irq for new packets */
+       for (i = 0; i < eqe_cnt; i++) {
+               if (eq->eqe_cache[i].cq)
+                       reset_eq_pending(eq->eqe_cache[i].cq);
+       }
+       /* check eq */
+       spin_lock(&eq->spinlock);
+       eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+       spin_unlock(&eq->spinlock);
+       /* call completion handler for cached eqes */
+       for (i = 0; i < eqe_cnt; i++)
+               if (eq->eqe_cache[i].cq) {
+                       if (ehca_scaling_code) {
+                               spin_lock(&ehca_cq_idr_lock);
+                               queue_comp_task(eq->eqe_cache[i].cq);
+                               spin_unlock(&ehca_cq_idr_lock);
+                       } else
+                               comp_event_callback(eq->eqe_cache[i].cq);
+               } else {
+                       ehca_dbg(&shca->ib_device, "Got non completion event");
+                       parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
                }
-       } while (int_state != 0);
-
-       return;
+       /* poll eq if not empty */
+       if (eq_empty)
+               goto unlock_irq_spinlock;
+       do {
+               struct ehca_eqe *eqe;
+               eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+               if (!eqe)
+                       break;
+               process_eqe(shca, eqe);
+               eqe_cnt++;
+       } while (1);
+
+unlock_irq_spinlock:
+       spin_unlock_irqrestore(&eq->irq_spinlock, flags);
 }
 
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
+void ehca_tasklet_eq(unsigned long data)
+{
+       ehca_process_eq((struct ehca_shca*)data, 1);
+}
 
 static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
 {
-       unsigned long flags_last_cpu;
+       int cpu;
+       unsigned long flags;
 
+       WARN_ON_ONCE(!in_interrupt());
        if (ehca_debug_level)
                ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
 
-       spin_lock_irqsave(&pool->last_cpu_lock, flags_last_cpu);
-       pool->last_cpu = next_cpu(pool->last_cpu, cpu_online_map);
-       if (pool->last_cpu == NR_CPUS)
-               pool->last_cpu = first_cpu(cpu_online_map);
-       spin_unlock_irqrestore(&pool->last_cpu_lock, flags_last_cpu);
+       spin_lock_irqsave(&pool->last_cpu_lock, flags);
+       cpu = next_cpu(pool->last_cpu, cpu_online_map);
+       if (cpu == NR_CPUS)
+               cpu = first_cpu(cpu_online_map);
+       pool->last_cpu = cpu;
+       spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
 
-       return pool->last_cpu;
+       return cpu;
 }
 
 static void __queue_comp_task(struct ehca_cq *__cq,
                              struct ehca_cpu_comp_task *cct)
 {
-       unsigned long flags_cct;
-       unsigned long flags_cq;
+       unsigned long flags;
 
-       spin_lock_irqsave(&cct->task_lock, flags_cct);
-       spin_lock_irqsave(&__cq->task_lock, flags_cq);
+       spin_lock_irqsave(&cct->task_lock, flags);
+       spin_lock(&__cq->task_lock);
 
        if (__cq->nr_callbacks == 0) {
                __cq->nr_callbacks++;
@@ -520,8 +571,8 @@ static void __queue_comp_task(struct ehca_cq *__cq,
        else
                __cq->nr_callbacks++;
 
-       spin_unlock_irqrestore(&__cq->task_lock, flags_cq);
-       spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+       spin_unlock(&__cq->task_lock);
+       spin_unlock_irqrestore(&cct->task_lock, flags);
 }
 
 static void queue_comp_task(struct ehca_cq *__cq)
@@ -532,69 +583,69 @@ static void queue_comp_task(struct ehca_cq *__cq)
 
        cpu = get_cpu();
        cpu_id = find_next_online_cpu(pool);
-
        BUG_ON(!cpu_online(cpu_id));
 
        cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+       BUG_ON(!cct);
 
        if (cct->cq_jobs > 0) {
                cpu_id = find_next_online_cpu(pool);
                cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+               BUG_ON(!cct);
        }
 
        __queue_comp_task(__cq, cct);
-
-       put_cpu();
-
-       return;
 }
 
 static void run_comp_task(struct ehca_cpu_comp_task* cct)
 {
        struct ehca_cq *cq;
-       unsigned long flags_cct;
-       unsigned long flags_cq;
+       unsigned long flags;
 
-       spin_lock_irqsave(&cct->task_lock, flags_cct);
+       spin_lock_irqsave(&cct->task_lock, flags);
 
        while (!list_empty(&cct->cq_list)) {
                cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
-               spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+               spin_unlock_irqrestore(&cct->task_lock, flags);
                comp_event_callback(cq);
-               spin_lock_irqsave(&cct->task_lock, flags_cct);
+               spin_lock_irqsave(&cct->task_lock, flags);
 
-               spin_lock_irqsave(&cq->task_lock, flags_cq);
+               spin_lock(&cq->task_lock);
                cq->nr_callbacks--;
                if (cq->nr_callbacks == 0) {
                        list_del_init(cct->cq_list.next);
                        cct->cq_jobs--;
                }
-               spin_unlock_irqrestore(&cq->task_lock, flags_cq);
-
+               spin_unlock(&cq->task_lock);
        }
 
-       spin_unlock_irqrestore(&cct->task_lock, flags_cct);
-
-       return;
+       spin_unlock_irqrestore(&cct->task_lock, flags);
 }
 
 static int comp_task(void *__cct)
 {
        struct ehca_cpu_comp_task* cct = __cct;
+       int cql_empty;
        DECLARE_WAITQUEUE(wait, current);
 
        set_current_state(TASK_INTERRUPTIBLE);
        while(!kthread_should_stop()) {
                add_wait_queue(&cct->wait_queue, &wait);
 
-               if (list_empty(&cct->cq_list))
+               spin_lock_irq(&cct->task_lock);
+               cql_empty = list_empty(&cct->cq_list);
+               spin_unlock_irq(&cct->task_lock);
+               if (cql_empty)
                        schedule();
                else
                        __set_current_state(TASK_RUNNING);
 
                remove_wait_queue(&cct->wait_queue, &wait);
 
-               if (!list_empty(&cct->cq_list))
+               spin_lock_irq(&cct->task_lock);
+               cql_empty = list_empty(&cct->cq_list);
+               spin_unlock_irq(&cct->task_lock);
+               if (!cql_empty)
                        run_comp_task(__cct);
 
                set_current_state(TASK_INTERRUPTIBLE);
@@ -637,8 +688,6 @@ static void destroy_comp_task(struct ehca_comp_pool *pool,
 
        if (task)
                kthread_stop(task);
-
-       return;
 }
 
 static void take_over_work(struct ehca_comp_pool *pool,
@@ -654,11 +703,11 @@ static void take_over_work(struct ehca_comp_pool *pool,
        list_splice_init(&cct->cq_list, &list);
 
        while(!list_empty(&list)) {
-              cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
+               cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 
-              list_del(&cq->entry);
-              __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
-                                                smp_processor_id()));
+               list_del(&cq->entry);
+               __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
+                                                 smp_processor_id()));
        }
 
        spin_unlock_irqrestore(&cct->task_lock, flags_cct);
@@ -708,14 +757,14 @@ static int comp_pool_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-#endif
-
 int ehca_create_comp_pool(void)
 {
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
        int cpu;
        struct task_struct *task;
 
+       if (!ehca_scaling_code)
+               return 0;
+
        pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL);
        if (pool == NULL)
                return -ENOMEM;
@@ -740,16 +789,19 @@ int ehca_create_comp_pool(void)
        comp_pool_callback_nb.notifier_call = comp_pool_callback;
        comp_pool_callback_nb.priority =0;
        register_cpu_notifier(&comp_pool_callback_nb);
-#endif
+
+       printk(KERN_INFO "eHCA scaling code enabled\n");
 
        return 0;
 }
 
 void ehca_destroy_comp_pool(void)
 {
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
        int i;
 
+       if (!ehca_scaling_code)
+               return;
+
        unregister_cpu_notifier(&comp_pool_callback_nb);
 
        for (i = 0; i < NR_CPUS; i++) {
@@ -758,7 +810,4 @@ void ehca_destroy_comp_pool(void)
        }
        free_percpu(pool->cpu_comp_tasks);
        kfree(pool);
-#endif
-
-       return;
 }
index be579cc0adf632f23283aedf74668a5714a0a2c9..6ed06ee033ed2f326a6674d21701eed3479fa2df 100644 (file)
@@ -56,6 +56,7 @@ void ehca_tasklet_neq(unsigned long data);
 
 irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
 void ehca_tasklet_eq(unsigned long data);
+void ehca_process_eq(struct ehca_shca *shca, int is_irq);
 
 struct ehca_cpu_comp_task {
        wait_queue_head_t wait_queue;
index 1155bcf48212ef33da22d188a4530d7545e92661..c1835121a82223612195fce09369ba0b58173e4a 100644 (file)
@@ -52,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0020");
+MODULE_VERSION("SVNEHCA_0021");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -62,6 +62,7 @@ int ehca_use_hp_mr     = 0;
 int ehca_port_act_time = 30;
 int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
+int ehca_scaling_code  = 1;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     int, 0);
 module_param_named(debug_level,   ehca_debug_level,   int, 0);
@@ -71,6 +72,7 @@ module_param_named(use_hp_mr,     ehca_use_hp_mr,     int, 0);
 module_param_named(port_act_time, ehca_port_act_time, int, 0);
 module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 0);
 module_param_named(static_rate,   ehca_static_rate,   int, 0);
+module_param_named(scaling_code,   ehca_scaling_code,   int, 0);
 
 MODULE_PARM_DESC(open_aqp1,
                 "AQP1 on startup (0: no (default), 1: yes)");
@@ -91,6 +93,8 @@ MODULE_PARM_DESC(poll_all_eqs,
                 " (0: no, 1: yes (default))");
 MODULE_PARM_DESC(static_rate,
                 "set permanent static rate (default: disabled)");
+MODULE_PARM_DESC(scaling_code,
+                "set scaling code (0: disabled, 1: enabled/default)");
 
 spinlock_t ehca_qp_idr_lock;
 spinlock_t ehca_cq_idr_lock;
@@ -432,8 +436,8 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
 
 static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
 {
-       return  snprintf(buf, PAGE_SIZE, "%d\n",
-                        ehca_debug_level);
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       ehca_debug_level);
 }
 
 static ssize_t ehca_store_debug_level(struct device_driver *ddp,
@@ -778,8 +782,24 @@ void ehca_poll_eqs(unsigned long data)
 
        spin_lock(&shca_list_lock);
        list_for_each_entry(shca, &shca_list, shca_list) {
-               if (shca->eq.is_initialized)
-                       ehca_tasklet_eq((unsigned long)(void*)shca);
+               if (shca->eq.is_initialized) {
+                       /* call deadman proc only if eq ptr does not change */
+                       struct ehca_eq *eq = &shca->eq;
+                       int max = 3;
+                       volatile u64 q_ofs, q_ofs2;
+                       u64 flags;
+                       spin_lock_irqsave(&eq->spinlock, flags);
+                       q_ofs = eq->ipz_queue.current_q_offset;
+                       spin_unlock_irqrestore(&eq->spinlock, flags);
+                       do {
+                               spin_lock_irqsave(&eq->spinlock, flags);
+                               q_ofs2 = eq->ipz_queue.current_q_offset;
+                               spin_unlock_irqrestore(&eq->spinlock, flags);
+                               max--;
+                       } while (q_ofs == q_ofs2 && max > 0);
+                       if (q_ofs == q_ofs2)
+                               ehca_process_eq(shca, 0);
+               }
        }
        mod_timer(&poll_eqs_timer, jiffies + HZ);
        spin_unlock(&shca_list_lock);
@@ -790,7 +810,7 @@ int __init ehca_module_init(void)
        int ret;
 
        printk(KERN_INFO "eHCA Infiniband Device Driver "
-                        "(Rel.: SVNEHCA_0020)\n");
+              "(Rel.: SVNEHCA_0021)\n");
        idr_init(&ehca_qp_idr);
        idr_init(&ehca_cq_idr);
        spin_lock_init(&ehca_qp_idr_lock);
index dc3bda2634b7dfcbd5fd3db3e791249c1d0cbe22..8199c45768a321a9c89d54f18d0d03c759a5a7e0 100644 (file)
@@ -79,7 +79,7 @@ static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
        if (q_offset >= queue->queue_length)
                return NULL;
        current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
-       return  &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
+       return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
 }
 
 /*
@@ -247,6 +247,15 @@ static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
        return ret;
 }
 
+static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       u32 qe = *(u8 *) ret;
+       if ((qe >> 7) != (queue->toggle_state & 1))
+               return NULL;
+       return ret;
+}
+
 /* returns address (GX) of first queue entry */
 static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
 {
index 6e0f2b8918ce893ce746fba86726e9140185df32..f6f9490408258da1c8e49b09a54a362e48930ff0 100644 (file)
@@ -96,8 +96,8 @@ static void ipath_dma_unmap_page(struct ib_device *dev,
        BUG_ON(!valid_dma_direction(direction));
 }
 
-int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
-                enum dma_data_direction direction)
+static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
+                       enum dma_data_direction direction)
 {
        u64 addr;
        int i;
index 7468477ba837886f4c96f2e5e1e52ae0fcf57760..993482545021e67d2ff5c1a0901cba49de062983 100644 (file)
@@ -1534,7 +1534,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
  * @kbase: ipath_base_info pointer
  *
  * We set the PCIE flag because the lower bandwidth on PCIe vs
- * HyperTransport can affect some user packet algorithims.
+ * HyperTransport can affect some user packet algorithms.
  */
 static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase)
 {
index ae8bf9950c6d43bad85bcda0863af08468cfb681..05918e1e7c363ac8b824cd006333ed515af0541b 100644 (file)
@@ -1293,7 +1293,7 @@ int __attribute__((weak)) ipath_unordered_wc(void)
  * @kbase: ipath_base_info pointer
  *
  * We set the PCIE flag because the lower bandwidth on PCIe vs
- * HyperTransport can affect some user packet algorithims.
+ * HyperTransport can affect some user packet algorithms.
  */
 static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
 {
index 0b9d053a599d2c3a328913aceccafb5721ed5698..48f7c65e9aedb372336ec0db1e299276f94e01e8 100644 (file)
@@ -175,7 +175,9 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
                if (!ret) {
                        ++chunk->npages;
 
-                       if (!coherent && chunk->npages == MTHCA_ICM_CHUNK_LEN) {
+                       if (coherent)
+                               ++chunk->nsg;
+                       else if (chunk->npages == MTHCA_ICM_CHUNK_LEN) {
                                chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
                                                        chunk->npages,
                                                        PCI_DMA_BIDIRECTIONAL);
index 224c93dd29eb7ecd9c56e8df0044aaa5c6609277..71dc84bd425498cd968a33cfa6e005804861474f 100644 (file)
@@ -573,6 +573,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
                goto out;
        }
 
+       if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+               err = 0;
+               goto out;
+       }
+
        if ((attr_mask & IB_QP_PKEY_INDEX) &&
             attr->pkey_index >= dev->limits.pkey_table_len) {
                mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
index 2d483874a58909ca77d359c1d201067dea7cb450..4d59682f7d4a39084e61361925c6b7dc0041047c 100644 (file)
@@ -145,7 +145,7 @@ partial_error:
        for (; i >= 0; --i)
                ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return -ENOMEM;
 }
 
@@ -1138,7 +1138,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
        return -EINVAL;
 }
 
-static DEVICE_ATTR(mode, S_IWUGO | S_IRUGO, show_mode, set_mode);
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
 
 int ipoib_cm_add_mode_attr(struct net_device *dev)
 {
index fea737f520fdfeae5a8a7b85765799552406b379..b303ce6bc21ee6664d1471a3a99d2455e11aef2e 100644 (file)
@@ -60,14 +60,11 @@ static DEFINE_MUTEX(mcast_mutex);
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
 struct ipoib_mcast {
        struct ib_sa_mcmember_rec mcmember;
+       struct ib_sa_multicast   *mc;
        struct ipoib_ah          *ah;
 
        struct rb_node    rb_node;
        struct list_head  list;
-       struct completion done;
-
-       int                 query_id;
-       struct ib_sa_query *query;
 
        unsigned long created;
        unsigned long backoff;
@@ -299,18 +296,22 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
        return 0;
 }
 
-static void
+static int
 ipoib_mcast_sendonly_join_complete(int status,
-                                  struct ib_sa_mcmember_rec *mcmember,
-                                  void *mcast_ptr)
+                                  struct ib_sa_multicast *multicast)
 {
-       struct ipoib_mcast *mcast = mcast_ptr;
+       struct ipoib_mcast *mcast = multicast->context;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+       /* We trap for port events ourselves. */
+       if (status == -ENETRESET)
+               return 0;
+
        if (!status)
-               ipoib_mcast_join_finish(mcast, mcmember);
-       else {
+               status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+       if (status) {
                if (mcast->logcount++ < 20)
                        ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for "
                                        IPOIB_GID_FMT ", status %d\n",
@@ -325,11 +326,10 @@ ipoib_mcast_sendonly_join_complete(int status,
                spin_unlock_irq(&priv->tx_lock);
 
                /* Clear the busy flag so we try again */
-               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-               mcast->query = NULL;
+               status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
+                                           &mcast->flags);
        }
-
-       complete(&mcast->done);
+       return status;
 }
 
 static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
@@ -359,35 +359,33 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
        rec.port_gid = priv->local_gid;
        rec.pkey     = cpu_to_be16(priv->pkey);
 
-       init_completion(&mcast->done);
-
-       ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port, &rec,
-                                    IB_SA_MCMEMBER_REC_MGID            |
-                                    IB_SA_MCMEMBER_REC_PORT_GID        |
-                                    IB_SA_MCMEMBER_REC_PKEY            |
-                                    IB_SA_MCMEMBER_REC_JOIN_STATE,
-                                    1000, GFP_ATOMIC,
-                                    ipoib_mcast_sendonly_join_complete,
-                                    mcast, &mcast->query);
-       if (ret < 0) {
-               ipoib_warn(priv, "ib_sa_mcmember_rec_set failed (ret = %d)\n",
+       mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,
+                                        priv->port, &rec,
+                                        IB_SA_MCMEMBER_REC_MGID        |
+                                        IB_SA_MCMEMBER_REC_PORT_GID    |
+                                        IB_SA_MCMEMBER_REC_PKEY        |
+                                        IB_SA_MCMEMBER_REC_JOIN_STATE,
+                                        GFP_ATOMIC,
+                                        ipoib_mcast_sendonly_join_complete,
+                                        mcast);
+       if (IS_ERR(mcast->mc)) {
+               ret = PTR_ERR(mcast->mc);
+               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
                           ret);
        } else {
                ipoib_dbg_mcast(priv, "no multicast record for " IPOIB_GID_FMT
                                ", starting join\n",
                                IPOIB_GID_ARG(mcast->mcmember.mgid));
-
-               mcast->query_id = ret;
        }
 
        return ret;
 }
 
-static void ipoib_mcast_join_complete(int status,
-                                     struct ib_sa_mcmember_rec *mcmember,
-                                     void *mcast_ptr)
+static int ipoib_mcast_join_complete(int status,
+                                    struct ib_sa_multicast *multicast)
 {
-       struct ipoib_mcast *mcast = mcast_ptr;
+       struct ipoib_mcast *mcast = multicast->context;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -395,24 +393,25 @@ static void ipoib_mcast_join_complete(int status,
                        " (status %d)\n",
                        IPOIB_GID_ARG(mcast->mcmember.mgid), status);
 
-       if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
+       /* We trap for port events ourselves. */
+       if (status == -ENETRESET)
+               return 0;
+
+       if (!status)
+               status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+       if (!status) {
                mcast->backoff = 1;
                mutex_lock(&mcast_mutex);
                if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
                        queue_delayed_work(ipoib_workqueue,
                                           &priv->mcast_task, 0);
                mutex_unlock(&mcast_mutex);
-               complete(&mcast->done);
-               return;
-       }
-
-       if (status == -EINTR) {
-               complete(&mcast->done);
-               return;
+               return 0;
        }
 
-       if (status && mcast->logcount++ < 20) {
-               if (status == -ETIMEDOUT || status == -EINTR) {
+       if (mcast->logcount++ < 20) {
+               if (status == -ETIMEDOUT) {
                        ipoib_dbg_mcast(priv, "multicast join failed for " IPOIB_GID_FMT
                                        ", status %d\n",
                                        IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -429,24 +428,18 @@ static void ipoib_mcast_join_complete(int status,
        if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
                mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
 
-       mutex_lock(&mcast_mutex);
+       /* Clear the busy flag so we try again */
+       status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
 
+       mutex_lock(&mcast_mutex);
        spin_lock_irq(&priv->lock);
-       mcast->query = NULL;
-
-       if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
-               if (status == -ETIMEDOUT)
-                       queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-                                          0);
-               else
-                       queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-                                          mcast->backoff * HZ);
-       } else
-               complete(&mcast->done);
+       if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
+               queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+                                  mcast->backoff * HZ);
        spin_unlock_irq(&priv->lock);
        mutex_unlock(&mcast_mutex);
 
-       return;
+       return status;
 }
 
 static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
@@ -495,15 +488,14 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                rec.hop_limit     = priv->broadcast->mcmember.hop_limit;
        }
 
-       init_completion(&mcast->done);
-
-       ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port,
-                                    &rec, comp_mask, mcast->backoff * 1000,
-                                    GFP_ATOMIC, ipoib_mcast_join_complete,
-                                    mcast, &mcast->query);
-
-       if (ret < 0) {
-               ipoib_warn(priv, "ib_sa_mcmember_rec_set failed, status %d\n", ret);
+       set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+       mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
+                                        &rec, comp_mask, GFP_KERNEL,
+                                        ipoib_mcast_join_complete, mcast);
+       if (IS_ERR(mcast->mc)) {
+               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               ret = PTR_ERR(mcast->mc);
+               ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
 
                mcast->backoff *= 2;
                if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
@@ -515,8 +507,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                                           &priv->mcast_task,
                                           mcast->backoff * HZ);
                mutex_unlock(&mcast_mutex);
-       } else
-               mcast->query_id = ret;
+       }
 }
 
 void ipoib_mcast_join_task(struct work_struct *work)
@@ -541,7 +532,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
                        priv->local_rate = attr.active_speed *
                                ib_width_enum_to_int(attr.active_width);
                } else
-               ipoib_warn(priv, "ib_query_port failed\n");
+                       ipoib_warn(priv, "ib_query_port failed\n");
        }
 
        if (!priv->broadcast) {
@@ -568,7 +559,8 @@ void ipoib_mcast_join_task(struct work_struct *work)
        }
 
        if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
-               ipoib_mcast_join(dev, priv->broadcast, 0);
+               if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
+                       ipoib_mcast_join(dev, priv->broadcast, 0);
                return;
        }
 
@@ -625,26 +617,9 @@ int ipoib_mcast_start_thread(struct net_device *dev)
        return 0;
 }
 
-static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
-                               struct ipoib_mcast *mcast)
-{
-       spin_lock_irq(&priv->lock);
-       if (mcast && mcast->query) {
-               ib_sa_cancel_query(mcast->query_id, mcast->query);
-               mcast->query = NULL;
-               spin_unlock_irq(&priv->lock);
-               ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
-                               IPOIB_GID_ARG(mcast->mcmember.mgid));
-               wait_for_completion(&mcast->done);
-       }
-       else
-               spin_unlock_irq(&priv->lock);
-}
-
 int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ipoib_mcast *mcast;
 
        ipoib_dbg_mcast(priv, "stopping multicast thread\n");
 
@@ -660,52 +635,27 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
        if (flush)
                flush_workqueue(ipoib_workqueue);
 
-       wait_for_mcast_join(priv, priv->broadcast);
-
-       list_for_each_entry(mcast, &priv->multicast_list, list)
-               wait_for_mcast_join(priv, mcast);
-
        return 0;
 }
 
 static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ib_sa_mcmember_rec rec = {
-               .join_state = 1
-       };
        int ret = 0;
 
-       if (!test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags))
-               return 0;
-
-       ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
-                       IPOIB_GID_ARG(mcast->mcmember.mgid));
-
-       rec.mgid     = mcast->mcmember.mgid;
-       rec.port_gid = priv->local_gid;
-       rec.pkey     = cpu_to_be16(priv->pkey);
+       if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
+               ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
+                               IPOIB_GID_ARG(mcast->mcmember.mgid));
 
-       /* Remove ourselves from the multicast group */
-       ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
-                                &mcast->mcmember.mgid);
-       if (ret)
-               ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+               /* Remove ourselves from the multicast group */
+               ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
+                                        &mcast->mcmember.mgid);
+               if (ret)
+                       ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+       }
 
-       /*
-        * Just make one shot at leaving and don't wait for a reply;
-        * if we fail, too bad.
-        */
-       ret = ib_sa_mcmember_rec_delete(&ipoib_sa_client, priv->ca, priv->port, &rec,
-                                       IB_SA_MCMEMBER_REC_MGID         |
-                                       IB_SA_MCMEMBER_REC_PORT_GID     |
-                                       IB_SA_MCMEMBER_REC_PKEY         |
-                                       IB_SA_MCMEMBER_REC_JOIN_STATE,
-                                       0, GFP_ATOMIC, NULL,
-                                       mcast, &mcast->query);
-       if (ret < 0)
-               ipoib_warn(priv, "ib_sa_mcmember_rec_delete failed "
-                          "for leave (result = %d)\n", ret);
+       if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+               ib_sa_free_multicast(mcast->mc);
 
        return 0;
 }
@@ -758,7 +708,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
                        dev_kfree_skb_any(skb);
                }
 
-               if (mcast->query)
+               if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
                        ipoib_dbg_mcast(priv, "no address vector, "
                                        "but multicast join already started\n");
                else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
@@ -916,7 +866,6 @@ void ipoib_mcast_restart_task(struct work_struct *work)
 
        /* We have to cancel outside of the spinlock */
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
-               wait_for_mcast_join(priv, mcast);
                ipoib_mcast_leave(mcast->dev, mcast);
                ipoib_mcast_free(mcast);
        }
index eba18b6ac5e4dc3afe012436f62441f04675eaf9..d226d935b0dcd57afc9c0e3fb921c47f3005bf92 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 
 #include "fixp-arith.h"
 
index 14d4c0493c36c7da7ec4a0b0c3e55162a2b3b72a..a9a706f8fff90ef1f0faf0149e8d3b4c1b5dabad 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/module.h>
@@ -589,18 +588,9 @@ static inline void input_proc_exit(void) { }
 static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)      \
 {                                                                              \
        struct input_dev *input_dev = to_input_dev(dev);                        \
-       int retval;                                                             \
                                                                                \
-       retval = mutex_lock_interruptible(&input_dev->mutex);                   \
-       if (retval)                                                             \
-               return retval;                                                  \
-                                                                               \
-       retval = scnprintf(buf, PAGE_SIZE,                                      \
-                          "%s\n", input_dev->name ? input_dev->name : "");     \
-                                                                               \
-       mutex_unlock(&input_dev->mutex);                                        \
-                                                                               \
-       return retval;                                                          \
+       return scnprintf(buf, PAGE_SIZE, "%s\n",                                \
+                        input_dev->name ? input_dev->name : "");               \
 }                                                                              \
 static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
 
@@ -1050,10 +1040,6 @@ void input_unregister_device(struct input_dev *dev)
        sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
        sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
 
-       mutex_lock(&dev->mutex);
-       dev->name = dev->phys = dev->uniq = NULL;
-       mutex_unlock(&dev->mutex);
-
        class_device_unregister(&dev->cdev);
 
        input_wakeup_procfs_readers();
index e608691b5a61963b1928f9185e6c8f317af2a612..b0f5541ec3e6849725955c655cbb4c5ea1f6559c 100644 (file)
@@ -50,8 +50,6 @@ static int amijoy[2] = { 0, 1 };
 module_param_array_named(map, amijoy, uint, NULL, 0);
 MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
 
-__obsolete_setup("amijoy=");
-
 static int amijoy_used;
 static DEFINE_MUTEX(amijoy_mutex);
 static struct input_dev *amijoy_dev[2];
index 7ef68456d7d65c3cddc339a9018c828de48b3dcd..51f1e4bfff3ee0c5f4112eae34b7d7d1e38ea498 100644 (file)
@@ -58,8 +58,6 @@ static int analog_options[ANALOG_PORTS];
 module_param_array_named(map, js, charp, &js_nargs, 0);
 MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
 
-__obsolete_setup("js=");
-
 /*
  * Times, feature definitions.
  */
index 5080e15c6d30c6dca5a1f40fc28c419843cbdf3b..b41bd2eb37dd35363d442bdd8670d4036e567c3a 100644 (file)
@@ -59,10 +59,6 @@ MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
 module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
 MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
 
-__obsolete_setup("db9=");
-__obsolete_setup("db9_2=");
-__obsolete_setup("db9_3=");
-
 #define DB9_ARG_PARPORT                0
 #define DB9_ARG_MODE           1
 
index fe12aa37393d9560c080f823182cd21b93339f8b..711e4b3e9e6130c4bf1fa71a234260576bd6cdca 100644 (file)
@@ -60,10 +60,6 @@ MODULE_PARM_DESC(map2, "Describes second set of devices");
 module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
-__obsolete_setup("gc=");
-__obsolete_setup("gc_2=");
-__obsolete_setup("gc_3=");
-
 /* see also gs_psx_delay parameter in PSX support section */
 
 #define GC_SNES                1
@@ -403,8 +399,6 @@ static int gc_psx_delay = GC_PSX_DELAY;
 module_param_named(psx_delay, gc_psx_delay, uint, 0);
 MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");
 
-__obsolete_setup("gc_psx_delay=");
-
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
                                BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
index 5570fd5487c730bc973b29736033942c00c1c560..037d3487fcc76ee48c04bd053d0f04995a5bb13f 100644 (file)
@@ -60,10 +60,6 @@ MODULE_PARM_DESC(map2, "Describes second set of devices");
 module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
-__obsolete_setup("tgfx=");
-__obsolete_setup("tgfx_2=");
-__obsolete_setup("tgfx_3=");
-
 #define TGFX_REFRESH_TIME      HZ/100  /* 10 ms */
 
 #define TGFX_TRIGGER           0x08
index 1b81a72e19d92c7fc7bdfa41a215cbda7039d9a7..64509689fa6514827bccff60e62f24abe8df873f 100644 (file)
@@ -215,11 +215,11 @@ config KEYBOARD_AAED2000
          module will be called aaed2000_kbd.
 
 config KEYBOARD_GPIO
-        tristate "Buttons on CPU GPIOs (PXA)"
-        depends on ARCH_PXA
+       tristate "Buttons on CPU GPIOs (PXA)"
+       depends on (ARCH_SA1100 || ARCH_PXA || ARCH_S3C2410)
        help
          This driver implements support for buttons connected
-         directly to GPIO pins of PXA CPUs.
+         directly to GPIO pins of SA1100, PXA or S3C24xx CPUs.
 
          Say Y here if your device has buttons connected
          directly to GPIO pins of the CPU.
index c621a9177a565353c424b610d2901a4c4ff87834..663877076bc7d9ef047a836815fe31eabbe920c4 100644 (file)
@@ -63,10 +63,6 @@ static int atkbd_extra;
 module_param_named(extra, atkbd_extra, bool, 0);
 MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
 
-__obsolete_setup("atkbd_set=");
-__obsolete_setup("atkbd_reset");
-__obsolete_setup("atkbd_softrepeat=");
-
 /*
  * Scancode to keycode tables. These are just the default setting, and
  * are loadable via an userland utility.
index 3a8f1b427a7fdc7547b7d7d91a4d45495829102e..fa03a00b4c6df8948e8d6eba0033cf58bf360ba8 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/input.h>
 #include <linux/irq.h>
 
-#include <asm/arch/pxa-regs.h>
+#include <asm/gpio.h>
 #include <asm/arch/hardware.h>
 
 #include <asm/hardware/gpio_keys.h>
@@ -38,8 +38,8 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 
        for (i = 0; i < pdata->nbuttons; i++) {
                int gpio = pdata->buttons[i].gpio;
-               if (irq == IRQ_GPIO(gpio)) {
-                       int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) ^ (pdata->buttons[i].active_low);
+               if (irq == gpio_to_irq(gpio)) {
+                       int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[i].active_low);
 
                        input_report_key(input, pdata->buttons[i].keycode, state);
                        input_sync(input);
@@ -75,14 +75,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 
        for (i = 0; i < pdata->nbuttons; i++) {
                int code = pdata->buttons[i].keycode;
-               int irq = IRQ_GPIO(pdata->buttons[i].gpio);
+               int irq = gpio_to_irq(pdata->buttons[i].gpio);
 
                set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
-               error = request_irq(irq, gpio_keys_isr, SA_SAMPLE_RANDOM,
+               error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
                                     pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
                                     pdev);
                if (error) {
-                       printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, ret);
+                       printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
+                               irq, error);
                        goto fail;
                }
                set_bit(code, input->keybit);
@@ -98,7 +99,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 
  fail:
        for (i = i - 1; i >= 0; i--)
-               free_irq(IRQ_GPIO(pdata->buttons[i].gpio), pdev);
+               free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
 
        input_free_device(input);
 
@@ -112,7 +113,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
        int i;
 
        for (i = 0; i < pdata->nbuttons; i++) {
-               int irq = IRQ_GPIO(pdata->buttons[i].gpio);
+               int irq = gpio_to_irq(pdata->buttons[i].gpio);
                free_irq(irq, pdev);
        }
 
index 255a6ec75a4826a66db9d630a0dbd51aa5fdfe69..4de4dc297d506b7b2d6f3d8ed9a1137324879e64 100644 (file)
@@ -294,8 +294,10 @@ err3:
        disable_irq(HIL_IRQ);
        free_irq(HIL_IRQ, hil_dev.dev_id);
 err2:
+#if defined(CONFIG_HP300)
        release_region(HILBASE + HIL_DATA, 2);
 err1:
+#endif
        input_free_device(hil_dev.dev);
        hil_dev.dev = NULL;
        return err;
index 701ebd5473cfe8745ca8ef4e82e2f6a7647d352c..79b624fe8994ff2d513b91a984840df869704e80 100644 (file)
@@ -84,8 +84,6 @@ static int inport_irq = INPORT_IRQ;
 module_param_named(irq, inport_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
-__obsolete_setup("inport_irq=");
-
 static struct input_dev *inport_dev;
 
 static irqreturn_t inport_interrupt(int irq, void *dev_id)
index db205995bffd08baf589ab5457c71ee8f640efe8..26c3b2e2ca94a3eff06a3ef800f59f78a19f5c58 100644 (file)
@@ -75,8 +75,6 @@ static int logibm_irq = LOGIBM_IRQ;
 module_param_named(irq, logibm_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
-__obsolete_setup("logibm_irq=");
-
 static struct input_dev *logibm_dev;
 
 static irqreturn_t logibm_interrupt(int irq, void *dev_id)
index a0e4a033e2db553346e646044a8bf25c298735fb..0fe5869d7d4c586bf782a794f48884b1564e0eec 100644 (file)
@@ -93,12 +93,6 @@ static struct attribute_group psmouse_attribute_group = {
        .attrs  = psmouse_attributes,
 };
 
-__obsolete_setup("psmouse_noext");
-__obsolete_setup("psmouse_resolution=");
-__obsolete_setup("psmouse_smartscroll=");
-__obsolete_setup("psmouse_resetafter=");
-__obsolete_setup("psmouse_rate=");
-
 /*
  * psmouse_mutex protects all operations changing state of mouse
  * (connecting, disconnecting, changing rate or resolution via
@@ -987,8 +981,36 @@ static void psmouse_resync(struct work_struct *work)
 static void psmouse_cleanup(struct serio *serio)
 {
        struct psmouse *psmouse = serio_get_drvdata(serio);
+       struct psmouse *parent = NULL;
+
+       mutex_lock(&psmouse_mutex);
+
+       if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+               parent = serio_get_drvdata(serio->parent);
+               psmouse_deactivate(parent);
+       }
+
+       psmouse_deactivate(psmouse);
+
+       if (psmouse->cleanup)
+               psmouse->cleanup(psmouse);
 
        psmouse_reset(psmouse);
+
+/*
+ * Some boxes, such as HP nx7400, get terribly confused if mouse
+ * is not fully enabled before suspending/shutting down.
+ */
+       ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+       if (parent) {
+               if (parent->pt_deactivate)
+                       parent->pt_deactivate(parent);
+
+               psmouse_activate(parent);
+       }
+
+       mutex_unlock(&psmouse_mutex);
 }
 
 /*
index 1b74cae8a556d5ed1287c9881ddbfc50aebd254f..cf1de95b6f27a536a8cf8699d8215105dca5f1ac 100644 (file)
@@ -68,6 +68,7 @@ struct psmouse {
 
        int (*reconnect)(struct psmouse *psmouse);
        void (*disconnect)(struct psmouse *psmouse);
+       void (*cleanup)(struct psmouse *psmouse);
        int (*poll)(struct psmouse *psmouse);
 
        void (*pt_activate)(struct psmouse *psmouse);
index fbdcfd8eb4e9d9860a2f190d98dcbfb32e175c3d..355efd0423e7df49cd5cbbf35b26eb3da774adf5 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 49ac696d6cff5c8f234e1536cafee778a3ccfecd..f0f9413d762c9a36b5e9c6f4db3afbb4d8a82eeb 100644 (file)
@@ -652,6 +652,7 @@ int synaptics_init(struct psmouse *psmouse)
        psmouse->set_rate = synaptics_set_rate;
        psmouse->disconnect = synaptics_disconnect;
        psmouse->reconnect = synaptics_reconnect;
+       psmouse->cleanup = synaptics_reset;
        psmouse->pktsize = 6;
        /* Synaptics can usually stay in sync without extra help */
        psmouse->resync_time = 0;
index 49e11e2c1d5dd24e08c8c0caab91d270e805c19e..4fa93ff309199e1f041657341eb379aca744aff7 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
index 9907ad3bea23252547a6a26c6cfd4d4dafae1269..b57370dc4e3d55956cbb3e03f2721553069e75dc 100644 (file)
@@ -62,7 +62,6 @@
  */
 
 #include <linux/hp_sdc.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/module.h>
index c3fdfc1f342a2fdd38b35e1294adc77ca0d44d9e..ec195a36e8f66ea9f170698d5b6dbb34f6140649 100644 (file)
@@ -76,13 +76,6 @@ module_param_named(debug, i8042_debug, bool, 0600);
 MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
 #endif
 
-__obsolete_setup("i8042_noaux");
-__obsolete_setup("i8042_nomux");
-__obsolete_setup("i8042_unlock");
-__obsolete_setup("i8042_reset");
-__obsolete_setup("i8042_direct");
-__obsolete_setup("i8042_dumbkbd");
-
 #include "i8042.h"
 
 static DEFINE_SPINLOCK(i8042_lock);
@@ -724,7 +717,7 @@ static int i8042_controller_init(void)
        if (~i8042_read_status() & I8042_STR_KEYLOCK) {
                if (i8042_unlock)
                        i8042_ctr |= I8042_CTR_IGNKEYLOCK;
-                else
+               else
                        printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
        }
        spin_unlock_irqrestore(&i8042_lock, flags);
@@ -790,27 +783,6 @@ static void i8042_controller_reset(void)
 }
 
 
-/*
- * Here we try to reset everything back to a state in which the BIOS will be
- * able to talk to the hardware when rebooting.
- */
-
-static void i8042_controller_cleanup(void)
-{
-       int i;
-
-/*
- * Reset anything that is connected to the ports.
- */
-
-       for (i = 0; i < I8042_NUM_PORTS; i++)
-               if (i8042_ports[i].serio)
-                       serio_cleanup(i8042_ports[i].serio);
-
-       i8042_controller_reset();
-}
-
-
 /*
  * i8042_panic_blink() will flash the keyboard LEDs and is called when
  * kernel panics. Flashing LEDs is useful for users running X who may
@@ -857,13 +829,22 @@ static long i8042_panic_blink(long count)
 
 #undef DELAY
 
+#ifdef CONFIG_PM
 /*
- * Here we try to restore the original BIOS settings
+ * Here we try to restore the original BIOS settings. We only want to
+ * do that once, when we really suspend, not when we taking memory
+ * snapshot for swsusp (in this case we'll perform required cleanup
+ * as part of shutdown process).
  */
 
 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
 {
-       i8042_controller_cleanup();
+       if (dev->dev.power.power_state.event != state.event) {
+               if (state.event == PM_EVENT_SUSPEND)
+                       i8042_controller_reset();
+
+               dev->dev.power.power_state = state;
+       }
 
        return 0;
 }
@@ -877,6 +858,12 @@ static int i8042_resume(struct platform_device *dev)
 {
        int error;
 
+/*
+ * Do not bother with restoring state if we haven't suspened yet
+ */
+       if (dev->dev.power.power_state.event == PM_EVENT_ON)
+               return 0;
+
        error = i8042_controller_check();
        if (error)
                return error;
@@ -886,9 +873,12 @@ static int i8042_resume(struct platform_device *dev)
                return error;
 
 /*
- * Restore pre-resume CTR value and disable all ports
+ * Restore original CTR value and disable all ports
  */
 
+       i8042_ctr = i8042_initial_ctr;
+       if (i8042_direct)
+               i8042_ctr &= ~I8042_CTR_XLATE;
        i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS;
        i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT);
        if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
@@ -909,8 +899,11 @@ static int i8042_resume(struct platform_device *dev)
 
        i8042_interrupt(0, NULL);
 
+       dev->dev.power.power_state = PMSG_ON;
+
        return 0;
 }
+#endif /* CONFIG_PM */
 
 /*
  * We need to reset the 8042 back to original mode on system shutdown,
@@ -919,7 +912,7 @@ static int i8042_resume(struct platform_device *dev)
 
 static void i8042_shutdown(struct platform_device *dev)
 {
-       i8042_controller_cleanup();
+       i8042_controller_reset();
 }
 
 static int __devinit i8042_create_kbd_port(void)
@@ -1154,9 +1147,11 @@ static struct platform_driver i8042_driver = {
        },
        .probe          = i8042_probe,
        .remove         = __devexit_p(i8042_remove),
+       .shutdown       = i8042_shutdown,
+#ifdef CONFIG_PM
        .suspend        = i8042_suspend,
        .resume         = i8042_resume,
-       .shutdown       = i8042_shutdown,
+#endif
 };
 
 static int __init i8042_init(void)
index b3e84d3bb7f7cc22f38883d6ee65966c2a345b36..10d9d74ae43aa0ceecbd88e9932ace7e045a1b0a 100644 (file)
@@ -97,7 +97,7 @@ EXPORT_SYMBOL(ps2_drain);
 
 int ps2_is_keyboard_id(char id_byte)
 {
-       const static char keyboard_ids[] = {
+       static const char keyboard_ids[] = {
                0xab,   /* Regular keyboards            */
                0xac,   /* NCD Sun keyboard             */
                0x2b,   /* Trust keyboard, translated   */
index 17c8c63cbe1a1306d31abba7f58db5bea9ed9bed..a15e531ec755fae2d8befa7615530676914a703b 100644 (file)
@@ -778,6 +778,19 @@ static int serio_driver_remove(struct device *dev)
        return 0;
 }
 
+static void serio_cleanup(struct serio *serio)
+{
+       if (serio->drv && serio->drv->cleanup)
+               serio->drv->cleanup(serio);
+}
+
+static void serio_shutdown(struct device *dev)
+{
+       struct serio *serio = to_serio_port(dev);
+
+       serio_cleanup(serio);
+}
+
 static void serio_attach_driver(struct serio_driver *drv)
 {
        int error;
@@ -910,11 +923,25 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
 
 #endif /* CONFIG_HOTPLUG */
 
+#ifdef CONFIG_PM
+static int serio_suspend(struct device *dev, pm_message_t state)
+{
+       if (dev->power.power_state.event != state.event) {
+               if (state.event == PM_EVENT_SUSPEND)
+                       serio_cleanup(to_serio_port(dev));
+
+               dev->power.power_state = state;
+       }
+
+       return 0;
+}
+
 static int serio_resume(struct device *dev)
 {
        struct serio *serio = to_serio_port(dev);
 
-       if (serio_reconnect_driver(serio)) {
+       if (dev->power.power_state.event != PM_EVENT_ON &&
+           serio_reconnect_driver(serio)) {
                /*
                 * Driver re-probing can take a while, so better let kseriod
                 * deal with it.
@@ -922,8 +949,11 @@ static int serio_resume(struct device *dev)
                serio_rescan(serio);
        }
 
+       dev->power.power_state = PMSG_ON;
+
        return 0;
 }
+#endif /* CONFIG_PM */
 
 /* called from serio_driver->connect/disconnect methods under serio_mutex */
 int serio_open(struct serio *serio, struct serio_driver *drv)
@@ -974,7 +1004,11 @@ static struct bus_type serio_bus = {
        .uevent         = serio_uevent,
        .probe          = serio_driver_probe,
        .remove         = serio_driver_remove,
+       .shutdown       = serio_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = serio_suspend,
        .resume         = serio_resume,
+#endif
 };
 
 static int __init serio_init(void)
index cd251efda41062cb6705f0cc6e5ba06af9ceafaf..0a26e0663542bf968b517ac6b0e087ff8cf64237 100644 (file)
@@ -546,7 +546,7 @@ static void ads7846_rx(void *ads)
                        ts->spi->dev.bus_id, ts->tc.ignore, Rt);
 #endif
                hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-                             HRTIMER_REL);
+                             HRTIMER_MODE_REL);
                return;
        }
 
@@ -578,7 +578,8 @@ static void ads7846_rx(void *ads)
 #endif
        }
 
-       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL);
+       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
+                       HRTIMER_MODE_REL);
 }
 
 static int ads7846_debounce(void *ads, int data_idx, int *val)
@@ -667,7 +668,7 @@ static void ads7846_rx_val(void *ads)
                                status);
 }
 
-static int ads7846_timer(struct hrtimer *handle)
+static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
 {
        struct ads7846  *ts = container_of(handle, struct ads7846, timer);
        int             status = 0;
@@ -724,7 +725,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
                        disable_irq(ts->spi->irq);
                        ts->pending = 1;
                        hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
-                                       HRTIMER_REL);
+                                       HRTIMER_MODE_REL);
                }
        }
        spin_unlock_irqrestore(&ts->lock, flags);
@@ -862,7 +863,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        ts->spi = spi;
        ts->input = input_dev;
 
-       hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_REL);
+       hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        ts->timer.function = ads7846_timer;
 
        spin_lock_init(&ts->lock);
index 8cec9c3898ec809c0d5e56dd6ad97a5b5e8d131d..2a49cea0a223e19e41cdeee3e4f900886521949f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
index 835b806a9de71bcf679c6550c7f0c18a3c0f9cda..077e297d8c7239b9d6cbd5ee7307cd94f22ace16 100644 (file)
@@ -5,4 +5,4 @@ ser_gigaset-y := ser-gigaset.o asyncdata.o
 
 obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o
 obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o
-obj-$(CONFIG_GIGASET_M105) += ser_gigaset.o gigaset.o
+obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o
index eba10466ccc61fd58eddd1b230629c7d84058781..a5b941c327f71477eecda3edb0f9b4c02acd4dda 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 6b2940ed077692c66f030c761997d060403918c2..4aba5c502d8e18759fb274f522244700b4abf752 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <asm/uaccess.h>
index b365e44072c020970c00eb1572814b4b5b67e5cb..5e862e2441171e029954a76a01713bd5aa8adf72 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
index 9e70c206779e4619a0af7c811a354d526480eb91..fc6cc2c065b807ac72c44992bb885a1d92e6ec0d 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 79ab9dda7d08984650dd6c980ed2d1ec12acdb08..db7e64424afe02fca1896c1b1edefdced2e2ac72 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 42bbae2a646c49622af83b6e6cda2db04a188c03..9f44d3e69fb0e78ef86362031999f0911e15c337 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/usb.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
 #include "hisax.h"
 #include "hisax_if.h"
 #include "hfc_usb.h"
index 45debde05fbd111ab2db7cad15e5fefd63cde6d7..439cb530def8833a7c1e17f9e363d3d8341b3518 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 3e3e18239ec77fa0bbb30e96ae744d6451d1bc2c..ab4bd455450eef1a7b6f5c39968b9416ac4bc459 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index a1206498a1cf17bb1e39149103aeda8545b79a87..84dccd526ac07dc0488db9f6c60b21031f3c8299 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
index 18758772b744e21822e22ad557cdb38d19064484..b7b5aa4748a0984ee46471e9cf707143c8c32593 100644 (file)
@@ -11,7 +11,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
index a20f33b4a220f4399dd635dd3af6344f62bb8304..90a23795db7e3a64ea24154c03d53b5a57de375f 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 4e3f127e4003612106c3b1fa10aab971bd88e69b..1b2df80c3bce818598e724bebd25385b4e487276 100644 (file)
@@ -1680,7 +1680,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
         * - we hit a gap in the sequence, so no reassembly/processing is 
         *   possible ('start' would be set to NULL)
         *
-        * algorightm for this code is derived from code in the book
+        * algorithm for this code is derived from code in the book
         * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
         */
        while (start != NULL || newfrag != NULL) {
index f151f36c8255d4995efccdf53cd2097ddda406e9..43ecd0f5423567c0dc2026106512383126bf813a 100644 (file)
@@ -15,7 +15,6 @@
  * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
index bef321d0e51d5a2775ef47fd6ddbcd6b6507bffc..47c59e95898d8be074a30bdc9535100073bfd96d 100644 (file)
@@ -27,7 +27,6 @@
  *              encode our number in CallerPN and ConnectedPN
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
index 386c5ce648444138965a21ba991446d5021f806e..8c66bcb953a1e97051b1fc23e7f7e43eb78f957b 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 
 #include <linux/kernel.h>
 
index 1ad8b07efd8ba3ab773d501d20eaa5a9e066f0cc..37e9626cebf6ccdd3d5013aee3a4f8d8be10c385 100644 (file)
@@ -15,7 +15,6 @@
  *              move state/event descriptions to a user space logger
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
index 58eee50c8e263debb3a2848e71f778bb09f8ef86..5ba2a879df1447e42bcead890600ba9c51ed9800 100644 (file)
@@ -24,7 +24,6 @@
  *              re-write/remove debug printks
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index 7b7b1777f09b88f29d2422ffc5517352f7fa32a0..04ea241ff176fad600990888fe822ab31e09026a 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
index 1e640b899175df4f178d5828e1d2025ed9551e57..fd4e91734388204a08e52d05fe0900920a48e866 100644 (file)
@@ -1879,12 +1879,6 @@ again:
 
        asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 
-       /*
-        * Profile KVM exit RIPs:
-        */
-       if (unlikely(prof_on == KVM_PROFILING))
-               profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
-
        kvm_run->exit_type = 0;
        if (fail) {
                kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
@@ -1907,6 +1901,12 @@ again:
 
                        reload_tss();
                }
+               /*
+                * Profile KVM exit RIPs:
+                */
+               if (unlikely(prof_on == KVM_PROFILING))
+                       profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
+
                vcpu->launched = 1;
                kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
                r = kvm_handle_exit(kvm_run, vcpu);
index f632cec9ce45eab7ac136408c683b6f7f1d97d60..c1fd816e9f09d282b9ec8cd5678dcb2c84ef3f1f 100644 (file)
@@ -138,7 +138,7 @@ int __init mac_hid_init(void)
                return err;
 
 #if defined(CONFIG_SYSCTL)
-       mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
+       mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir);
 #endif /* CONFIG_SYSCTL */
 
        return 0;
index 797cef72258f317a06340a08107e0f357326d73c..026b67f4f659f59fb55e9953dd87ba05952207e5 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/prom.h>
index 3797f503cd6cfdf9ad006af706d3472d42743586..d58fcf6cca0aec41f68344f9cf99e880193ba9da 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/spinlock.h>
index 175b3e56e37541f1131acba6cf5912871bd0894f..1b3bad62a1be6c623ffcc32f4d8fbb9ac97163d5 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 10051db48d2323a8b828f6271f4f8d1732a6c35f..2dc788042707fb6dd6abc78abafc84d678c977cd 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/delay.h>
index 54baee57d2f8bec36cbc9977d301896dbb558d30..356c7216a1795e7b4eb183cda6a349e3efdff133 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/blkdev.h>
 #include <linux/pci.h>
index e85fa75a7912e5c17879e819e21b835b22bce942..05febfd9f0712d0875b52dcb4f2c07cd15ff7c8f 100644 (file)
@@ -5581,7 +5581,7 @@ static int __init md_init(void)
                            md_probe, NULL, NULL);
 
        register_reboot_notifier(&md_notifier);
-       raid_table_header = register_sysctl_table(raid_root_table, 1);
+       raid_table_header = register_sysctl_table(raid_root_table);
 
        md_geninit();
        return (0);
index 988499dfddf8d8d17bcffbb6522231f9d1485fd0..fc77de45ca4dc415fdaa77634eda086a2e78945e 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
index e85972222ab42d1f01593941517d810f5cf13c37..7c42d53a1cc7df9ecc55ba8859f50d75ccc14a82 100644 (file)
@@ -915,7 +915,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        fetunesettings.parameters.inversion = INVERSION_AUTO;
                }
                if (fe->ops.info.type == FE_OFDM) {
-                       /* without hierachical coding code_rate_LP is irrelevant,
+                       /* without hierarchical coding code_rate_LP is irrelevant,
                         * so we tolerate the otherwise invalid FEC_NONE setting */
                        if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
                            fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
index 40774feb8953d241566ef2cc79d3e5a11d3fdeb2..826b47f155a02cfae38471272360024da72d37f7 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
index adbabfdb04a95c0fe50f23251af39e2140139d2a..b6adea5ffeb89b04851c0d55ccd952b6077ade91 100644 (file)
@@ -239,7 +239,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
                default:
                        return -EINVAL;
        }
-       deb_setf("hierachy: ");
+       deb_setf("hierarchy: ");
        switch (ofdm->hierarchy_information) {
                case HIERARCHY_NONE:
                        deb_setf("none ");
index 8c577cf30fb379359dc52841642bf2dd24d844ae..795e6e95915c6d5e5a9d25d2033d30f8f6f1903a 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
index dd9aee314e0a389b72f2347c347c5e45ad8df3ee..4251a97d420e81ee128edf9ec0bab913ddd300f4 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
index 37de2e88a273b9616a8af19129f7cf880682d766..4d7150e15d1e1378c244df17f95569bd15f44843 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
index 10cfe3131e72aad0ecdeec292d926b5fcab126eb..dbfd5e7b4be0c3ef40b79ec3a4b48a6c6a2855af 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
index c93490ec96bb7b2f5a4145047e5730fefbf29c9b..aed11477378bd5bf018a9d7a4eec1e9c960ca86e 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
-#include <linux/sched.h>       /* current, TASK_*, schedule_timeout() */
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
index 9bba6eb1092537cc45fbcb3087c2e01af07a57b6..e67b7f2580297b9cad40a80244625197d775500d 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
index 00a2f31d2af32b07c080a041e704f8e013c282d9..6beeb74004b1349a90f17f97e3f784b77dfc2663 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
index 48709582a18612400040d91a53e4368cb0cf2081..2aa9ce9206074a449919ea8c9897e5805d41896f 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index 68e7d7aff5e6423b4bf51386473fe6c6d2c62663..a3246a283aa4f1661c6f06b2726eeab1a2992343 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index e7b38fdd5e3c9389e2032ca1c8c5103a19a120a1..68673863d5c9347ca3e326e9b429bdc74a6a9be4 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index af3b61d4fa7ddacd95f0ac356cf3170818f75a2c..42e2299dcb223774f8faeb067b847ff4a4804c8a 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index 63676e7bd635f6b403a69be86e0e24d602c56337..6fc6b026005617815ad4d22533531798d2da2e4b 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
 #include <asm/io.h>
index 2bd84d351a18eb3bf7e9f2301583ed04a004ed16..063df03dcf2ee54c3f6232b42ca23fc93ce25dd1 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/pci.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
index 3ffb5684f127ecaa3e9bc68584df8450370edaf0..55d45b0032cff0cda5a84844aaceeff096547d0f 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/usb.h>
index 7420b79e987abe775d81a5135d9d8e2657a227f2..5c2c4029ff86bd76a3872152b198b58259e73936 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include <linux/videodev.h>
index 59edf58204de311935cc3d807b7d2bd3745c148d..210582d420f861c457977ba18ecab8c36e6ef627 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index 9528e10c2828a7fc78aaae5cfafac7de8213f1df..98681da5e3b91fbbd72d9c665c277eaf22e48cea 100644 (file)
@@ -28,7 +28,6 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
index d38d3dc4a0120c0c242daa87150b4ae930856a32..b5a67f0dd19f95b6cb3ef88f87525056bc91139f 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <linux/mutex.h>
index 9846c464ec801d02be993f2955edbfb0cd405894..122496f368458f71161743a537c3c1924853660f 100644 (file)
@@ -158,7 +158,7 @@ static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
 }
 
 
-const static struct pvr2_i2c_handler_functions msp3400_funcs = {
+static const struct pvr2_i2c_handler_functions msp3400_funcs = {
        .detach = (void (*)(void *))pvr2_msp3400_detach,
        .check = (int (*)(void *))msp3400_check,
        .update = (void (*)(void *))msp3400_update,
index 848fb233d80861efe8cb88d07787d61aaeb587b2..8df969c4874c7a7dcddd8b5232ccf87f0a84115e 100644 (file)
@@ -226,7 +226,7 @@ static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
        .detach = (void (*)(void *))decoder_detach,
        .check = (int (*)(void *))decoder_check,
        .update = (void (*)(void *))decoder_update,
index f95c598ff627a263fa019e472e92d5ea7d743d44..c08925557ed45755232f9e83c8b49f8534a4f076 100644 (file)
@@ -78,14 +78,14 @@ struct std_name {
 #define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
 
 /* Mapping of standard bits to color system */
-const static struct std_name std_groups[] = {
+static const struct std_name std_groups[] = {
        {"PAL",CSTD_PAL},
        {"NTSC",CSTD_NTSC},
        {"SECAM",CSTD_SECAM},
 };
 
 /* Mapping of standard bits to modulation system */
-const static struct std_name std_items[] = {
+static const struct std_name std_items[] = {
        {"B",TSTD_B},
        {"B1",TSTD_B1},
        {"D",TSTD_D},
index af9f246f8d3f08dc6bd29d0330218fa3309e495e..bb17db3f6434a6e50f1bfea5bffe2095145bf26d 100644 (file)
@@ -80,7 +80,7 @@ static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *bu
 }
 
 
-const static struct pvr2_i2c_handler_functions tuner_funcs = {
+static const struct pvr2_i2c_handler_functions tuner_funcs = {
        .detach = (void (*)(void *))pvr2_tuner_detach,
        .check = (int (*)(void *))tuner_check,
        .update = (void (*)(void *))tuner_update,
index 05f2cddeb47bbe86e594a26215a74d850fabbc60..2a826464911a7e6d0f553c029970b19f60d8c0f3 100644 (file)
@@ -201,7 +201,7 @@ static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,uns
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
        .detach = (void (*)(void *))decoder_detach,
        .check = (int (*)(void *))decoder_check,
        .update = (void (*)(void *))decoder_update,
index 2413e5198e1676f1d8d2b99a8da9724a83440941..7794c34c355e18e248970a11de55a5e4c8c9c986 100644 (file)
@@ -126,7 +126,7 @@ static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
        .detach = (void (*)(void *))wm8775_detach,
        .check = (int (*)(void *))wm8775_check,
        .update = (void (*)(void *))wm8775_update,
index 0b5d159895bf974724736de08847f981621d13db..76f5f5d49dae8ed162abdf3066e9962af2426aa6 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
index 686fd4746205385c23c8b6b53731e37df5de7287..44dc7479119c3f0fbb2254ec8359b4cb3f03b9dd 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index 90398ab8252e62053a6fcf54e41af77a31500d9a..2ce3321ab995032d7ae1c932fcacc458c7856670 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index 708fae51e8ee61555c18ab4f1bae967a9ec8470a..269d7114a93abc8ebf4995a5cbed7ef58af5ccc1 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
index afc8f352b8e713ea66c9a15a50f0fcb05f24ba31..57f1f5d409e0e0f3f11b1b046c4672f57edd16c8 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index 60b38defd9bccf3d86a1428c7a87dc1544100321..e4252683a597018741ca63b57b5c1730b46891f2 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 
index 9c308410856d9ad211d89fd2907e96ffd1dfa2ab..e0fdb1ab7580e02c1e9a64c32d387b6bb3b9bbc2 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
index 746cadb8f1c45d9b1af42ad892b98cc4a695df4b..8615a6081a5d2eeae75143c4b6b1a93444807854 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include <linux/videodev.h>
index 78e043ac9ea0e39fa2195d0b9ddba060db56361b..d1ccc064206f89c4b865e64e8da7722312d5bab8 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index 827633b3bb4325239ed282e96c44aac306bbbc5d..00f0e8b6e03b96621d5c8d0ad3309611c1650404 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index ee4a493032d6406815ebf0d1fd1304ebae3ad158..7be73e3763de4d14439a02a8c651a8aeb947bf0d 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index e2747bd373fddd94e1779a7604b18284ef820b67..7ea9132a1965f86b28b85ef7a504db74bc2b83cd 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
index 76f771b6a32ff458896c12f4bdb17fd643e8d710..14db95e10cfee6d8828b9d607b94369ffbf0f449 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
index 10c58b4a2e5b159195fc64f4e6293626603a0421..95453c108d40e650de7c1ddfb14bb8e59916f59b 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
index a807d971e27357accfb2e26128e9db6c7563b54f..901f664dc6db4eae563b9dbb35a6ab7971dcfa9d 100644 (file)
@@ -24,7 +24,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
index a242b76aea894c8b0b7e16282c063b5733f0fe0d..609e1fd9c784f7304442f1b856ff01fcb9bde7ea 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include "usbvision.h"
index 4eb7330b96f83107dbdaf63df76dcbaf6163b496..af33653f0db8a18b22097785b50ed7f06cdc75a8 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
index b87d571e046337122bcfd0759a885ac006089482..b8ee37ded3c98c1cedf4cd5b4ee79a3f1e58dec1 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
index 30c3822692fb02d2d1fb0a8242147809ca31c6a1..a786c1f5b9601a98474f70073cb107df1ff9e0bc 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
index b7d4c7265ec66ec226b04e5b6120b6b1c48e316c..0caaf64039936eb7690e5fbba93291b8c34058c8 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/delay.h>       /* for mdelay */
 #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
 #include <linux/reboot.h>      /* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/sort.h>
 
index 84b8b485e95bd8b57b6a11685a2cf64cd317d704..404c014db1bdaa30538a4f2fff0c25b2151f7e47 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>       /* for mdelay */
 
index c417ae0b5fe61c017da74fd45d4cd593cc49cd45..2a3e9e66d4ef7ed49c535597da34a8073417c219 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/delay.h>       /* for mdelay */
 #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
 #include <linux/reboot.h>      /* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 
 #include <scsi/scsi.h>
index c31a9e3c8a26c91bb6ca48e0db622212bc173eff..85f21b54cb7de6702e89d4fb6728fa25e37e0e3c 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/delay.h>       /* for mdelay */
 #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
 #include <linux/reboot.h>      /* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/raid_class.h>
 
index bedae4ad3f74f1d916a0e2a7b555e39474244b31..80b199fa0aa9b7173fc684b1866de7c1c2e46b2f 100644 (file)
@@ -107,4 +107,19 @@ config MSI_LAPTOP
 
          If you have an MSI S270 laptop, say Y or M here.
 
+config SONY_LAPTOP
+       tristate "Sony Laptop Extras"
+       depends on X86 && ACPI
+       select BACKLIGHT_CLASS_DEVICE
+         ---help---
+         This mini-driver drives the SNC device present in the ACPI BIOS of
+         the Sony Vaio laptops.
+
+         It gives access to some extra laptop functionalities. In its current
+         form, this driver let the user set or query the screen brightness
+         through the backlight subsystem and remove/apply power to some
+         devices.
+
+         Read <file:Documentation/sony-laptop.txt> for more information.
+
 endmenu
index 35da53c409c02c8f43b0bf81539e7988c2387c08..7793ccd7904962c699340c53e8ef1cfa6389e9b1 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_LKDTM)           += lkdtm.o
 obj-$(CONFIG_TIFM_CORE)        += tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)        += tifm_7xx1.o
 obj-$(CONFIG_SGI_IOC4)         += ioc4.o
+obj-$(CONFIG_SONY_LAPTOP)      += sony-laptop.o
index 861c39935f99f7127e48a6d15527e412343f6e28..e4e2b707a3531f0ae8371ac7f730ce27917f65ee 100644 (file)
@@ -1088,11 +1088,6 @@ static int __init asus_laptop_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-       if (!acpi_specific_hotkey_enabled) {
-               printk(ASUS_ERR "Using generic hotkey driver\n");
-               return -ENODEV;
-       }
-
        result = acpi_bus_register_driver(&asus_hotk_driver);
        if (result < 0)
                return result;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
new file mode 100644 (file)
index 0000000..cabbed0
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * ACPI Sony Notebook Control Driver (SNC)
+ *
+ * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+ *
+ * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
+ * which are copyrighted by their respective authors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
+
+#define ACPI_SNC_CLASS         "sony"
+#define ACPI_SNC_HID           "SNY5001"
+#define ACPI_SNC_DRIVER_NAME   "ACPI Sony Notebook Control Driver v0.4"
+
+/* the device uses 1-based values, while the backlight subsystem uses
+   0-based values */
+#define SONY_MAX_BRIGHTNESS    8
+
+#define LOG_PFX                        KERN_WARNING "sony-laptop: "
+
+MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
+MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
+                "the development of this driver");
+
+static ssize_t sony_acpi_show(struct device *, struct device_attribute *,
+                             char *);
+static ssize_t sony_acpi_store(struct device *, struct device_attribute *,
+                              const char *, size_t);
+static int boolean_validate(const int, const int);
+static int brightness_default_validate(const int, const int);
+
+#define SNC_VALIDATE_IN                0
+#define SNC_VALIDATE_OUT       1
+
+struct sony_acpi_value {
+       char *name;             /* name of the entry */
+       char **acpiget;         /* names of the ACPI get function */
+       char **acpiset;         /* names of the ACPI set function */
+       int (*validate)(const int, const int);  /* input/output validation */
+       int value;              /* current setting */
+       int valid;              /* Has ever been set */
+       int debug;              /* active only in debug mode ? */
+       struct device_attribute devattr;        /* sysfs atribute */
+};
+
+#define HANDLE_NAMES(_name, _values...) \
+       static char *snc_##_name[] = { _values, NULL }
+
+#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \
+       { \
+               .name           = __stringify(_name), \
+               .acpiget        = _getters, \
+               .acpiset        = _setters, \
+               .validate       = _validate, \
+               .debug          = _debug, \
+               .devattr        = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \
+       }
+
+#define SONY_ACPI_VALUE_NULL   { .name = NULL }
+
+HANDLE_NAMES(fnkey_get, "GHKE");
+
+HANDLE_NAMES(brightness_def_get, "GPBR");
+HANDLE_NAMES(brightness_def_set, "SPBR");
+
+HANDLE_NAMES(cdpower_get, "GCDP");
+HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
+
+HANDLE_NAMES(audiopower_get, "GAZP");
+HANDLE_NAMES(audiopower_set, "AZPW");
+
+HANDLE_NAMES(lanpower_get, "GLNP");
+HANDLE_NAMES(lanpower_set, "LNPW");
+
+HANDLE_NAMES(PID_get, "GPID");
+
+HANDLE_NAMES(CTR_get, "GCTR");
+HANDLE_NAMES(CTR_set, "SCTR");
+
+HANDLE_NAMES(PCR_get, "GPCR");
+HANDLE_NAMES(PCR_set, "SPCR");
+
+HANDLE_NAMES(CMI_get, "GCMI");
+HANDLE_NAMES(CMI_set, "SCMI");
+
+static struct sony_acpi_value sony_acpi_values[] = {
+       SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get,
+                       snc_brightness_def_set, brightness_default_validate, 0),
+       SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0),
+       SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
+       SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set,
+                       boolean_validate, 0),
+       SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set,
+                       boolean_validate, 1),
+       /* unknown methods */
+       SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1),
+       SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
+       SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
+       SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
+       SONY_ACPI_VALUE_NULL
+};
+
+static acpi_handle sony_acpi_handle;
+static struct acpi_device *sony_acpi_acpi_device = NULL;
+
+/*
+ * acpi_evaluate_object wrappers
+ */
+static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
+{
+       struct acpi_buffer output;
+       union acpi_object out_obj;
+       acpi_status status;
+
+       output.length = sizeof(out_obj);
+       output.pointer = &out_obj;
+
+       status = acpi_evaluate_object(handle, name, NULL, &output);
+       if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) {
+               *result = out_obj.integer.value;
+               return 0;
+       }
+
+       printk(LOG_PFX "acpi_callreadfunc failed\n");
+
+       return -1;
+}
+
+static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
+                           int *result)
+{
+       struct acpi_object_list params;
+       union acpi_object in_obj;
+       struct acpi_buffer output;
+       union acpi_object out_obj;
+       acpi_status status;
+
+       params.count = 1;
+       params.pointer = &in_obj;
+       in_obj.type = ACPI_TYPE_INTEGER;
+       in_obj.integer.value = value;
+
+       output.length = sizeof(out_obj);
+       output.pointer = &out_obj;
+
+       status = acpi_evaluate_object(handle, name, &params, &output);
+       if (status == AE_OK) {
+               if (result != NULL) {
+                       if (out_obj.type != ACPI_TYPE_INTEGER) {
+                               printk(LOG_PFX "acpi_evaluate_object bad "
+                                      "return type\n");
+                               return -1;
+                       }
+                       *result = out_obj.integer.value;
+               }
+               return 0;
+       }
+
+       printk(LOG_PFX "acpi_evaluate_object failed\n");
+
+       return -1;
+}
+
+/*
+ * sony_acpi_values input/output validate functions
+ */
+
+/* brightness_default_validate:
+ *
+ * manipulate input output values to keep consistency with the
+ * backlight framework for which brightness values are 0-based.
+ */
+static int brightness_default_validate(const int direction, const int value)
+{
+       switch (direction) {
+               case SNC_VALIDATE_OUT:
+                       return value - 1;
+               case SNC_VALIDATE_IN:
+                       if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
+                               return value + 1;
+       }
+       return -EINVAL;
+}
+
+/* boolean_validate:
+ *
+ * on input validate boolean values 0/1, on output just pass the
+ * received value.
+ */
+static int boolean_validate(const int direction, const int value)
+{
+       if (direction == SNC_VALIDATE_IN) {
+               if (value != 0 && value != 1)
+                       return -EINVAL;
+       }
+       return value;
+}
+
+/*
+ * Sysfs show/store common to all sony_acpi_values
+ */
+static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
+                             char *buffer)
+{
+       int value;
+       struct sony_acpi_value *item =
+           container_of(attr, struct sony_acpi_value, devattr);
+
+       if (!*item->acpiget)
+               return -EIO;
+
+       if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0)
+               return -EIO;
+
+       if (item->validate)
+               value = item->validate(SNC_VALIDATE_OUT, value);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t sony_acpi_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buffer, size_t count)
+{
+       int value;
+       struct sony_acpi_value *item =
+           container_of(attr, struct sony_acpi_value, devattr);
+
+       if (!item->acpiset)
+               return -EIO;
+
+       if (count > 31)
+               return -EINVAL;
+
+       value = simple_strtoul(buffer, NULL, 10);
+
+       if (item->validate)
+               value = item->validate(SNC_VALIDATE_IN, value);
+
+       if (value < 0)
+               return value;
+
+       if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0)
+               return -EIO;
+       item->value = value;
+       item->valid = 1;
+       return count;
+}
+
+/*
+ * Platform device
+ */
+static struct platform_driver sncpf_driver = {
+       .driver = {
+                  .name = "sony-laptop",
+                  .owner = THIS_MODULE,
+                  }
+};
+static struct platform_device *sncpf_device;
+
+static int sony_snc_pf_add(void)
+{
+       acpi_handle handle;
+       struct sony_acpi_value *item;
+       int ret = 0;
+
+       ret = platform_driver_register(&sncpf_driver);
+       if (ret)
+               goto out;
+
+       sncpf_device = platform_device_alloc("sony-laptop", -1);
+       if (!sncpf_device) {
+               ret = -ENOMEM;
+               goto out_platform_registered;
+       }
+
+       ret = platform_device_add(sncpf_device);
+       if (ret)
+               goto out_platform_alloced;
+
+       for (item = sony_acpi_values; item->name; ++item) {
+
+               if (!debug && item->debug)
+                       continue;
+
+               /* find the available acpiget as described in the DSDT */
+               for (; item->acpiget && *item->acpiget; ++item->acpiget) {
+                       if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+                                                        *item->acpiget,
+                                                        &handle))) {
+                               if (debug)
+                                       printk(LOG_PFX "Found %s getter: %s\n",
+                                              item->name, *item->acpiget);
+                               item->devattr.attr.mode |= S_IRUGO;
+                               break;
+                       }
+               }
+
+               /* find the available acpiset as described in the DSDT */
+               for (; item->acpiset && *item->acpiset; ++item->acpiset) {
+                       if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+                                                        *item->acpiset,
+                                                        &handle))) {
+                               if (debug)
+                                       printk(LOG_PFX "Found %s setter: %s\n",
+                                              item->name, *item->acpiset);
+                               item->devattr.attr.mode |= S_IWUSR;
+                               break;
+                       }
+               }
+
+               if (item->devattr.attr.mode != 0) {
+                       ret =
+                           device_create_file(&sncpf_device->dev,
+                                              &item->devattr);
+                       if (ret)
+                               goto out_sysfs;
+               }
+       }
+
+       return 0;
+
+      out_sysfs:
+       for (item = sony_acpi_values; item->name; ++item) {
+               device_remove_file(&sncpf_device->dev, &item->devattr);
+       }
+       platform_device_del(sncpf_device);
+      out_platform_alloced:
+       platform_device_put(sncpf_device);
+      out_platform_registered:
+       platform_driver_unregister(&sncpf_driver);
+      out:
+       return ret;
+}
+
+static void sony_snc_pf_remove(void)
+{
+       struct sony_acpi_value *item;
+
+       for (item = sony_acpi_values; item->name; ++item) {
+               device_remove_file(&sncpf_device->dev, &item->devattr);
+       }
+
+       platform_device_del(sncpf_device);
+       platform_device_put(sncpf_device);
+       platform_driver_unregister(&sncpf_driver);
+}
+
+/*
+ * Backlight device
+ */
+static int sony_backlight_update_status(struct backlight_device *bd)
+{
+       return acpi_callsetfunc(sony_acpi_handle, "SBRT",
+                               bd->props->brightness + 1, NULL);
+}
+
+static int sony_backlight_get_brightness(struct backlight_device *bd)
+{
+       int value;
+
+       if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value))
+               return 0;
+       /* brightness levels are 1-based, while backlight ones are 0-based */
+       return value - 1;
+}
+
+static struct backlight_device *sony_backlight_device;
+static struct backlight_properties sony_backlight_properties = {
+       .owner = THIS_MODULE,
+       .update_status = sony_backlight_update_status,
+       .get_brightness = sony_backlight_get_brightness,
+       .max_brightness = SONY_MAX_BRIGHTNESS - 1,
+};
+
+/*
+ * ACPI callbacks
+ */
+static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+       if (debug)
+               printk(LOG_PFX "sony_acpi_notify, event: %d\n", event);
+       acpi_bus_generate_event(sony_acpi_acpi_device, 1, event);
+}
+
+static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
+                                     void *context, void **return_value)
+{
+       struct acpi_namespace_node *node;
+       union acpi_operand_object *operand;
+
+       node = (struct acpi_namespace_node *)handle;
+       operand = (union acpi_operand_object *)node->object;
+
+       printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
+              (u32) operand->method.param_count);
+
+       return AE_OK;
+}
+
+/*
+ * ACPI device
+ */
+static int sony_acpi_resume(struct acpi_device *device)
+{
+       struct sony_acpi_value *item;
+
+       for (item = sony_acpi_values; item->name; item++) {
+               int ret;
+
+               if (!item->valid)
+                       continue;
+               ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset,
+                                      item->value, NULL);
+               if (ret < 0) {
+                       printk("%s: %d\n", __FUNCTION__, ret);
+                       break;
+               }
+       }
+       return 0;
+}
+
+static int sony_acpi_add(struct acpi_device *device)
+{
+       acpi_status status;
+       int result;
+       acpi_handle handle;
+
+       sony_acpi_acpi_device = device;
+
+       sony_acpi_handle = device->handle;
+
+       if (debug) {
+               status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle,
+                                            1, sony_walk_callback, NULL, NULL);
+               if (ACPI_FAILURE(status)) {
+                       printk(LOG_PFX "unable to walk acpi resources\n");
+                       result = -ENODEV;
+                       goto outwalk;
+               }
+       }
+
+       status = acpi_install_notify_handler(sony_acpi_handle,
+                                            ACPI_DEVICE_NOTIFY,
+                                            sony_acpi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(LOG_PFX "unable to install notify handler\n");
+               result = -ENODEV;
+               goto outwalk;
+       }
+
+       if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
+               sony_backlight_device = backlight_device_register("sony", NULL,
+                                                                 NULL,
+                                                                 &sony_backlight_properties);
+
+               if (IS_ERR(sony_backlight_device)) {
+                       printk(LOG_PFX "unable to register backlight device\n");
+                       sony_backlight_device = NULL;
+               } else
+                       sony_backlight_properties.brightness =
+                           sony_backlight_get_brightness
+                           (sony_backlight_device);
+       }
+
+       if (sony_snc_pf_add())
+               goto outbacklight;
+
+       printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n");
+
+       return 0;
+
+      outbacklight:
+       if (sony_backlight_device)
+               backlight_device_unregister(sony_backlight_device);
+
+       status = acpi_remove_notify_handler(sony_acpi_handle,
+                                           ACPI_DEVICE_NOTIFY,
+                                           sony_acpi_notify);
+       if (ACPI_FAILURE(status))
+               printk(LOG_PFX "unable to remove notify handler\n");
+      outwalk:
+       return result;
+}
+
+static int sony_acpi_remove(struct acpi_device *device, int type)
+{
+       acpi_status status;
+
+       if (sony_backlight_device)
+               backlight_device_unregister(sony_backlight_device);
+
+       sony_acpi_acpi_device = NULL;
+
+       status = acpi_remove_notify_handler(sony_acpi_handle,
+                                           ACPI_DEVICE_NOTIFY,
+                                           sony_acpi_notify);
+       if (ACPI_FAILURE(status))
+               printk(LOG_PFX "unable to remove notify handler\n");
+
+       sony_snc_pf_remove();
+
+       printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n");
+
+       return 0;
+}
+
+static struct acpi_driver sony_acpi_driver = {
+       .name = ACPI_SNC_DRIVER_NAME,
+       .class = ACPI_SNC_CLASS,
+       .ids = ACPI_SNC_HID,
+       .ops = {
+               .add = sony_acpi_add,
+               .remove = sony_acpi_remove,
+               .resume = sony_acpi_resume,
+               },
+};
+
+static int __init sony_acpi_init(void)
+{
+       return acpi_bus_register_driver(&sony_acpi_driver);
+}
+
+static void __exit sony_acpi_exit(void)
+{
+       acpi_bus_unregister_driver(&sony_acpi_driver);
+}
+
+module_init(sony_acpi_init);
+module_exit(sony_acpi_exit);
index e21e490fedb04dc40b215a8715e93a9ffdb1cc7c..bc60e2fc3c2cc8e6342a74403cdd2b5687b7c8a0 100644 (file)
@@ -367,7 +367,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        if (!fm->addr)
                goto err_out_free;
 
-       rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
+       rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
        if (rc)
                goto err_out_unmap;
 
index 2ce50f38e3c7d21c54d22b2be788bd6f4fc0acbd..459f4b4feded9f9302c493083c116bcaa85cc00c 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/err.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/atmel_pdc.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
@@ -75,7 +76,6 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
-#include <asm/arch/at91_pdc.h>
 
 #define DRIVER_NAME "at91_mci"
 
@@ -211,13 +211,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
 
                /* Check to see if this needs filling */
                if (i == 0) {
-                       if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
+                       if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
                                pr_debug("Transfer active in current\n");
                                continue;
                        }
                }
                else {
-                       if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
+                       if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
                                pr_debug("Transfer active in next\n");
                                continue;
                        }
@@ -234,12 +234,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
                pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
 
                if (i == 0) {
-                       at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
-                       at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
+                       at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
+                       at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4);
                }
                else {
-                       at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
-                       at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
+                       at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
+                       at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4);
                }
        }
 
@@ -303,7 +303,7 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
                at91mci_pre_dma_read(host);
        else {
                at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-               at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
        }
 
        pr_debug("post dma read done\n");
@@ -320,7 +320,7 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
        pr_debug("Handling the transmit\n");
 
        /* Disable the transfer */
-       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
        /* Now wait for cmd ready */
        at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
@@ -431,15 +431,15 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
                cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
 
        if (!data) {
-               at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
-               at91_mci_write(host, AT91_PDC_RPR, 0);
-               at91_mci_write(host, AT91_PDC_RCR, 0);
-               at91_mci_write(host, AT91_PDC_RNPR, 0);
-               at91_mci_write(host, AT91_PDC_RNCR, 0);
-               at91_mci_write(host, AT91_PDC_TPR, 0);
-               at91_mci_write(host, AT91_PDC_TCR, 0);
-               at91_mci_write(host, AT91_PDC_TNPR, 0);
-               at91_mci_write(host, AT91_PDC_TNCR, 0);
+               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
+               at91_mci_write(host, ATMEL_PDC_RPR, 0);
+               at91_mci_write(host, ATMEL_PDC_RCR, 0);
+               at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+               at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+               at91_mci_write(host, ATMEL_PDC_TPR, 0);
+               at91_mci_write(host, ATMEL_PDC_TCR, 0);
+               at91_mci_write(host, ATMEL_PDC_TNPR, 0);
+               at91_mci_write(host, ATMEL_PDC_TNCR, 0);
 
                at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
                at91_mci_write(host, AT91_MCI_CMDR, cmdr);
@@ -452,7 +452,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
        /*
         * Disable the PDC controller
         */
-       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
        if (cmdr & AT91_MCI_TRCMD_START) {
                data->bytes_xfered = 0;
@@ -481,8 +481,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
 
                        pr_debug("Transmitting %d bytes\n", host->total_length);
 
-                       at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
-                       at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
+                       at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+                       at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
                        ier = AT91_MCI_TXBUFE;
                }
        }
@@ -497,9 +497,9 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
 
        if (cmdr & AT91_MCI_TRCMD_START) {
                if (cmdr & AT91_MCI_TRDIR)
-                       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
+                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
                else
-                       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
+                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
        }
        return ier;
 }
index 05ba8ace70e7801071a2a614ad4e9d74d13f1502..86439a0bb271c2e815bd940e21d19e67bcaaf572 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
index f69184a92eb2389d7370d726a346602c117d51dd..f334959a335ba0fc3bcb90f5042be352f871a14b 100644 (file)
@@ -397,9 +397,23 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
        cfi_fixup(mtd, fixup_table);
 
        for (i=0; i< cfi->numchips; i++) {
-               cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
-               cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-               cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
+               if (cfi->cfiq->WordWriteTimeoutTyp)
+                       cfi->chips[i].word_write_time =
+                               1<<cfi->cfiq->WordWriteTimeoutTyp;
+               else
+                       cfi->chips[i].word_write_time = 50000;
+
+               if (cfi->cfiq->BufWriteTimeoutTyp)
+                       cfi->chips[i].buffer_write_time =
+                               1<<cfi->cfiq->BufWriteTimeoutTyp;
+               /* No default; if it isn't specified, we won't use it */
+
+               if (cfi->cfiq->BlockEraseTimeoutTyp)
+                       cfi->chips[i].erase_time =
+                               1000<<cfi->cfiq->BlockEraseTimeoutTyp;
+               else
+                       cfi->chips[i].erase_time = 2000000;
+
                cfi->chips[i].ref_point_counter = 0;
                init_waitqueue_head(&(cfi->chips[i].wq));
        }
@@ -546,13 +560,11 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
                        struct cfi_intelext_programming_regioninfo *prinfo;
                        prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
                        mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
-                       MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
-                       MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
                        mtd->flags &= ~MTD_BIT_WRITEABLE;
                        printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
                               map->name, mtd->writesize,
-                              MTD_PROGREGION_CTRLMODE_VALID(mtd),
-                              MTD_PROGREGION_CTRLMODE_INVALID(mtd));
+                              cfi->interleave * prinfo->ControlValid,
+                              cfi->interleave * prinfo->ControlInvalid);
                }
 
                /*
index d56849f5f107bbb119569ef42c27f3cdbc5e60ab..69d49e0250a9a3a532ff95f9ac7ce261862e314d 100644 (file)
@@ -662,7 +662,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
  * a small buffer for this.
  * XXX: If the buffer size is not a multiple of 2, this will break
  */
-#define ECCBUF_SIZE (mtd->eccsize)
+#define ECCBUF_SIZE (mtd->writesize)
 #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
 #define ECCBUF_MOD(x) ((x) &  (ECCBUF_SIZE - 1))
 static int
index d8e7a026ba5ae945a83da21485f4a34dac71ef2d..2e51496c248e0b718273ec3715d5c16b2c689ff8 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
index 603a7951ac9b1e3e9b646811a840c4e8139745b8..8a0c4dec6351ff993fc5bed3f9f3df6ee1406df5 100644 (file)
@@ -569,7 +569,6 @@ void DoC2k_init(struct mtd_info *mtd)
 
        mtd->type = MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->ecctype = MTD_ECC_RS_DiskOnChip;
        mtd->size = 0;
        mtd->erasesize = 0;
        mtd->writesize = 512;
index 0e2a9326f717da9f18213b2032195e0529b7c132..6f368aec5d5d15bc21e75db9595d1c34fb9779d3 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -349,7 +348,6 @@ void DoCMil_init(struct mtd_info *mtd)
 
        mtd->type = MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->ecctype = MTD_ECC_RS_DiskOnChip;
        mtd->size = 0;
 
        /* FIXME: erase size is not always 8KiB */
index 92dbb47f2ac35597e5e4d18cc39bd079eb6dc0ed..88ba82df0fbbf624d4f2885e17fafc37ab993ad7 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -473,7 +472,6 @@ void DoCMilPlus_init(struct mtd_info *mtd)
 
        mtd->type = MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->ecctype = MTD_ECC_RS_DiskOnChip;
        mtd->size = 0;
 
        mtd->erasesize = 0;
index cd3db72bef96ae92cfd9a69ee688d20d5759bc33..52b5d638077faa69a23113640472baed2c8fa7ca 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 
index 354e1657cc26aae7e33e17439d6be18e85107548..a4873ab84e6bcc9fd73ef1cf8c17353e9b474b25 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
index 5f49248a48564398a82239c569bf860b5d431da0..d293add1857cfba358a033ff0247e7c755ef42c1 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 24235d4f1d23219255da945d14afe2493a742ef6..c815d0f38577281f3b033570d2ac1607a361e15f 100644 (file)
@@ -61,7 +61,6 @@
 /*#define PSYCHO_DEBUG */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 8f6006f1a519480c3fbba9581294b901bc2571b9..acf3ba223298e2ff06ba79a769bd1a8ffb7a7911 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
index f457315579db924c71ba6298ec91f0e6a952af9d..bbf0553bdb2e67890a83387d30a2810f6bda5c93 100644 (file)
@@ -204,7 +204,7 @@ config MTD_ESB2ROM
 
 config MTD_CK804XROM
        tristate "BIOS flash chip on Nvidia CK804"
-       depends on X86 && MTD_JEDECPROBE
+       depends on X86 && MTD_JEDECPROBE && PCI
        help
          Support for treating the BIOS flash chip on nvidia motherboards
          as an MTD device - with this you can reprogram your BIOS.
index 78b671172bb225d6978cacd5f164c13628a39066..728aed6ad722e276e1642da0a7951b3bd61363f2 100644 (file)
@@ -205,8 +205,8 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
                        (((unsigned long)(window->virt)) + offset);
                map->map.size = 0xffffffffUL - map_top + 1UL;
                /* Set the name of the map to the address I am trying */
-               sprintf(map->map_name, "%s @%08lx",
-                       MOD_NAME, map->map.phys);
+               sprintf(map->map_name, "%s @%08Lx",
+                       MOD_NAME, (unsigned long long)map->map.phys);
 
                /* There is no generic VPP support */
                for(map->map.bankwidth = 32; map->map.bankwidth;
index 238d42e88ec52eeb050276480d9dcc1e7759a003..3d4a4d8ac789758b677b796cb83048ba59a93d47 100644 (file)
@@ -207,8 +207,8 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
                        (((unsigned long)(window->virt)) + offset);
                map->map.size = 0xffffffffUL - map_top + 1UL;
                /* Set the name of the map to the address I am trying */
-               sprintf(map->map_name, "%s @%08lx",
-                       MOD_NAME, map->map.phys);
+               sprintf(map->map_name, "%s @%08Lx",
+                       MOD_NAME, (unsigned long long)map->map.phys);
 
                /* There is no generic VPP support */
                for(map->map.bankwidth = 32; map->map.bankwidth;
@@ -327,7 +327,7 @@ static int __init init_ck804xrom(void)
        pdev = NULL;
 
        for(id = ck804xrom_pci_tbl; id->vendor; id++) {
-               pdev = pci_find_device(id->vendor, id->device, NULL);
+               pdev = pci_get_device(id->vendor, id->device, NULL);
                if (pdev)
                        break;
        }
index a9d808a617c9e62fe12932910dfba3e859323348..0bc013fd66a3f08570be112bca66454bff67da9b 100644 (file)
@@ -289,8 +289,8 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
                        (((unsigned long)(window->virt)) + offset);
                map->map.size = 0xffffffffUL - map_top + 1UL;
                /* Set the name of the map to the address I am trying */
-               sprintf(map->map_name, "%s @%08lx",
-                       MOD_NAME, map->map.phys);
+               sprintf(map->map_name, "%s @%08Lx",
+                       MOD_NAME, (unsigned long long)map->map.phys);
 
                /* Firmware hubs only use vpp when being programmed
                 * in a factory setting.  So in-place programming
index 2bb3e63606e5df9e343a87a81f1fe9a9e412bd04..2c884c49e84a5cd5f0bb1a50e8fc285bb408ceb3 100644 (file)
@@ -227,8 +227,8 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
                        (((unsigned long)(window->virt)) + offset);
                map->map.size = 0xffffffffUL - map_top + 1UL;
                /* Set the name of the map to the address I am trying */
-               sprintf(map->map_name, "%s @%08lx",
-                       MOD_NAME, map->map.phys);
+               sprintf(map->map_name, "%s @%08Lx",
+                       MOD_NAME, (unsigned long long)map->map.phys);
 
                /* Firmware hubs only use vpp when being programmed
                 * in a factory setting.  So in-place programming
index ed215470158bf808cff3e7d150715a8170c22bbd..95dcab2146ad821c90fa29df1784d62076b7d3ee 100644 (file)
@@ -94,7 +94,9 @@ static struct mtd_info *mymtd;
 
 static int __init init_netsc520(void)
 {
-       printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
+       printk(KERN_NOTICE "NetSc520 flash device: 0x%Lx at 0x%Lx\n",
+                       (unsigned long long)netsc520_map.size,
+                       (unsigned long long)netsc520_map.phys);
        netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size);
 
        if (!netsc520_map.virt) {
index 9b50cfc355b113b411040b6d473a518ec5e92ccb..4045e372b90db10b53baaae4d15d045a881e90f9 100644 (file)
@@ -237,8 +237,9 @@ static int __init init_sc520cdp(void)
 #endif
 
        for (i = 0; i < NUM_FLASH_BANKS; i++) {
-               printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
-                      sc520cdp_map[i].size, sc520cdp_map[i].phys);
+               printk(KERN_NOTICE "SC520 CDP flash device: 0x%Lx at 0x%Lx\n",
+                       (unsigned long long)sc520cdp_map[i].size,
+                       (unsigned long long)sc520cdp_map[i].phys);
 
                sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
 
index 61a994ea8af1f884b078e9253039819a1a42b1d6..1592eac64e57baaefb8daecabfe700b27277247a 100644 (file)
@@ -419,8 +419,9 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                info.erasesize  = mtd->erasesize;
                info.writesize  = mtd->writesize;
                info.oobsize    = mtd->oobsize;
-               info.ecctype    = mtd->ecctype;
-               info.eccsize    = mtd->eccsize;
+               /* The below fields are obsolete */
+               info.ecctype    = -1;
+               info.eccsize    = 0;
                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
                        return -EFAULT;
                break;
index 06902683bc2a7c0a71541558b76aaad032e0c578..880580c44e0134186d9a3df3fd1b81731359aa2b 100644 (file)
@@ -727,8 +727,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        concat->mtd.erasesize = subdev[0]->erasesize;
        concat->mtd.writesize = subdev[0]->writesize;
        concat->mtd.oobsize = subdev[0]->oobsize;
-       concat->mtd.ecctype = subdev[0]->ecctype;
-       concat->mtd.eccsize = subdev[0]->eccsize;
        if (subdev[0]->writev)
                concat->mtd.writev = concat_writev;
        if (subdev[0]->read_oob)
@@ -774,8 +772,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
                if (concat->mtd.writesize   !=  subdev[i]->writesize ||
                    concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
                    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
-                   concat->mtd.ecctype    !=  subdev[i]->ecctype ||
-                   concat->mtd.eccsize    !=  subdev[i]->eccsize ||
                    !concat->mtd.read_oob  != !subdev[i]->read_oob ||
                    !concat->mtd.write_oob != !subdev[i]->write_oob) {
                        kfree(concat);
index 7070110aba2a62fb9650a6c14c2e49e38f98ea37..c153b64a830063f719e363917aacdd69fc7afff8 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index bafd2fba87bde0f2b6f82bed155e751cbe408c12..633def3fb0875daf3a38bda7dea4cfb5d8adee77 100644 (file)
@@ -338,8 +338,6 @@ int add_mtd_partitions(struct mtd_info *master,
                slave->mtd.size = parts[i].size;
                slave->mtd.writesize = master->writesize;
                slave->mtd.oobsize = master->oobsize;
-               slave->mtd.ecctype = master->ecctype;
-               slave->mtd.eccsize = master->eccsize;
                slave->mtd.subpage_sft = master->subpage_sft;
 
                slave->mtd.name = parts[i].name;
index 358f55a82dbe4ebb73b1b0ee460063a6145e3f0e..2d12dcdd740cfd42d3b06d29b9ab947e12e98651 100644 (file)
@@ -126,10 +126,6 @@ config MTD_NAND_S3C2410_HWECC
          incorrect ECC generation, and if using these, the default of
          software ECC is preferable.
 
-         If you lay down a device with the hardware ECC, then you will
-         currently not be able to switch to software, as there is no
-         implementation for ECC method used by the S3C2410
-
 config MTD_NAND_NDFC
        tristate "NDFC NanD Flash Controller"
        depends on MTD_NAND && 44x
@@ -221,9 +217,17 @@ config MTD_NAND_SHARPSL
        tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
        depends on MTD_NAND && ARCH_PXA
 
+config MTD_NAND_BASLER_EXCITE
+       tristate  "Support for NAND Flash on Basler eXcite"
+       depends on MTD_NAND && BASLER_EXCITE
+       help
+          This enables the driver for the NAND flash device found on the
+          Basler eXcite Smart Camera. If built as a module, the driver
+          will be named "excite_nandflash.ko".
+
 config MTD_NAND_CAFE
        tristate "NAND support for OLPC CAFÉ chip"
-       depends on PCI
+       depends on MTD_NAND && PCI
        help
         Use NAND flash attached to the CAFÉ chip designed for the $100
         laptop.
index f7a53f0b70177451680402a2c2cce4c98991cd6e..80f1dfc77949de321c45eb45d0902c5abc8bb41d 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_MTD_NAND_NANDSIM)                += nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
 obj-$(CONFIG_MTD_NAND_AT91)            += at91_nand.o
+obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
 
 nand-objs := nand_base.o nand_bbt.o
 cafe_nand-objs := cafe.o cafe_ecc.o
index 65f9bd3ceebfb6d707d2d7301568fe3786bacb0f..fd6bb3ed40dfb73936abf9481527915038d002a7 100644 (file)
@@ -78,8 +78,9 @@ module_param(regdebug, int, 0644);
 static int checkecc = 1;
 module_param(checkecc, int, 0644);
 
-static int slowtiming = 0;
-module_param(slowtiming, int, 0644);
+static int numtimings;
+static int timing[3];
+module_param_array(timing, int, &numtimings, 0644);
 
 /* Hrm. Why isn't this already conditional on something in the struct device? */
 #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
@@ -264,10 +265,10 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
        ndelay(100);
 
        if (1) {
-               int c = 500000;
+               int c;
                uint32_t irqs;
 
-               while (c--) {
+               for (c = 500000; c != 0; c--) {
                        irqs = cafe_readl(cafe, NAND_IRQ);
                        if (irqs & doneint)
                                break;
@@ -529,6 +530,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 {
        struct mtd_info *mtd;
        struct cafe_priv *cafe;
+       uint32_t timing1, timing2, timing3;
        uint32_t ctrl;
        int err = 0;
 
@@ -580,30 +582,45 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
                cafe->nand.block_bad = cafe_nand_block_bad;
        }
 
+       if (numtimings && numtimings != 3) {
+               dev_warn(&cafe->pdev->dev, "%d timing register values ignored; precisely three are required\n", numtimings);
+       }
+
+       if (numtimings == 3) {
+               timing1 = timing[0];
+               timing2 = timing[1];
+               timing3 = timing[2];
+               cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
+                            timing1, timing2, timing3);
+       } else {
+               timing1 = cafe_readl(cafe, NAND_TIMING1);
+               timing2 = cafe_readl(cafe, NAND_TIMING2);
+               timing3 = cafe_readl(cafe, NAND_TIMING3);
+
+               if (timing1 | timing2 | timing3) {
+                       cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3);
+               } else {
+                       dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
+                       timing1 = timing2 = timing3 = 0xffffffff;
+               }
+       }
+
        /* Start off by resetting the NAND controller completely */
        cafe_writel(cafe, 1, NAND_RESET);
        cafe_writel(cafe, 0, NAND_RESET);
 
-       cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+       cafe_writel(cafe, timing1, NAND_TIMING1);
+       cafe_writel(cafe, timing2, NAND_TIMING2);
+       cafe_writel(cafe, timing3, NAND_TIMING3);
 
-       /* Timings from Marvell's test code (not verified or calculated by us) */
-       if (!slowtiming) {
-               cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
-               cafe_writel(cafe, 0x24121212, NAND_TIMING2);
-               cafe_writel(cafe, 0x11000000, NAND_TIMING3);
-       } else {
-               cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
-               cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
-               cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
-       }
        cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
-       err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
+       err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
+                         "CAFE NAND", mtd);
        if (err) {
                dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
-
                goto out_free_dma;
        }
-#if 1
+
        /* Disable master reset, enable NAND clock */
        ctrl = cafe_readl(cafe, GLOBAL_CTRL);
        ctrl &= 0xffffeff0;
@@ -630,32 +647,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
        cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
                cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
-#endif
-#if 1
-       mtd->writesize=2048;
-       mtd->oobsize = 0x40;
-       memset(cafe->dmabuf, 0x5a, 2112);
-       cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-#endif
-#if 0
-       cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
-       //      nand_wait_ready(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-       cafe->nand.read_byte(mtd);
-#endif
-#if 0
-       writel(0x84600070, cafe->mmio);
-       udelay(10);
-       cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
-#endif
-       /* Scan to find existance of the device */
+
+       /* Scan to find existence of the device */
        if (nand_scan_ident(mtd, 1)) {
                err = -ENXIO;
                goto out_irq;
@@ -759,13 +752,4 @@ module_exit(cafe_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
-
-/* Correct ECC for 2048 bytes of 0xff:
-   41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
-
-/* dwmw2's B-test board, in case of completely screwing it:
-Bad eraseblock 2394 at 0x12b40000
-Bad eraseblock 2627 at 0x14860000
-Bad eraseblock 3349 at 0x1a2a0000
-*/
+MODULE_DESCRIPTION("NAND flash driver for OLPC CAFÉ chip");
index 1b9fa05a44747fdb7eeb9bb9049dc47e6131edf1..ea5c8491d2c57677250b012f1d9261494cead565 100644 (file)
@@ -1045,7 +1045,7 @@ static unsigned short err_pos_lut[4096] = {
 
 static unsigned short err_pos(unsigned short din)
 {
-       BUG_ON(din > 4096);
+       BUG_ON(din >= ARRAY_SIZE(err_pos_lut));
        return err_pos_lut[din];
 }
 static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
new file mode 100644 (file)
index 0000000..7e9afc4
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+*  Copyright (C) 2005 - 2007 by Basler Vision Technologies AG
+*  Author: Thomas Koeller <thomas.koeller.qbaslerweb.com>
+*  Original code by Thies Moeller <thies.moeller@baslerweb.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite_nandflash.h>
+
+#define EXCITE_NANDFLASH_VERSION "0.1"
+
+/* I/O register offsets */
+#define EXCITE_NANDFLASH_DATA_BYTE   0x00
+#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c
+#define EXCITE_NANDFLASH_ADDR_BYTE   0x10
+#define EXCITE_NANDFLASH_CMD_BYTE    0x14
+
+/* prefix for debug output */
+static const char module_id[] = "excite_nandflash";
+
+/*
+ * partition definition
+ */
+static const struct mtd_partition partition_info[] = {
+       {
+               .name = "eXcite RootFS",
+               .offset = 0,
+               .size = MTDPART_SIZ_FULL
+       }
+};
+
+static inline const struct resource *
+excite_nand_get_resource(struct platform_device *d, unsigned long flags,
+                        const char *basename)
+{
+       char buf[80];
+
+       if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf)
+               return NULL;
+       return platform_get_resource_byname(d, flags, buf);
+}
+
+static inline void __iomem *
+excite_nand_map_regs(struct platform_device *d, const char *basename)
+{
+       void *result = NULL;
+       const struct resource *const r =
+           excite_nand_get_resource(d, IORESOURCE_MEM, basename);
+
+       if (r)
+               result = ioremap_nocache(r->start, r->end + 1 - r->start);
+       return result;
+}
+
+/* controller and mtd information */
+struct excite_nand_drvdata {
+       struct mtd_info board_mtd;
+       struct nand_chip board_chip;
+       void __iomem *regs;
+       void __iomem *tgt;
+};
+
+/* Control function */
+static void excite_nand_control(struct mtd_info *mtd, int cmd,
+                                      unsigned int ctrl)
+{
+       struct excite_nand_drvdata * const d =
+           container_of(mtd, struct excite_nand_drvdata, board_mtd);
+
+       switch (ctrl) {
+       case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
+               d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE;
+               break;
+       case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
+               d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE;
+               break;
+       case NAND_CTRL_CHANGE | NAND_NCE:
+               d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE;
+               break;
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               __raw_writeb(cmd, d->tgt);
+}
+
+/* Return 0 if flash is busy, 1 if ready */
+static int excite_nand_devready(struct mtd_info *mtd)
+{
+       struct excite_nand_drvdata * const drvdata =
+           container_of(mtd, struct excite_nand_drvdata, board_mtd);
+
+       return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE);
+}
+
+/*
+ * Called by device layer to remove the driver.
+ * The binding to the mtd and all allocated
+ * resources are released.
+ */
+static int __exit excite_nand_remove(struct device *dev)
+{
+       struct excite_nand_drvdata * const this = dev_get_drvdata(dev);
+
+       dev_set_drvdata(dev, NULL);
+
+       if (unlikely(!this)) {
+               printk(KERN_ERR "%s: called %s without private data!!",
+                      module_id, __func__);
+               return -EINVAL;
+       }
+
+       /* first thing we need to do is release our mtd
+        * then go through freeing the resource used
+        */
+       nand_release(&this->board_mtd);
+
+       /* free the common resources */
+       iounmap(this->regs);
+       kfree(this);
+
+       DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id);
+       return 0;
+}
+
+/*
+ * Called by device layer when it finds a device matching
+ * one our driver can handle. This code checks to see if
+ * it can allocate all necessary resources then calls the
+ * nand layer to look for devices.
+*/
+static int __init excite_nand_probe(struct device *dev)
+{
+       struct platform_device * const pdev = to_platform_device(dev);
+       struct excite_nand_drvdata *drvdata;    /* private driver data */
+       struct nand_chip *board_chip;   /* private flash chip data */
+       struct mtd_info *board_mtd;     /* mtd info for this board */
+       int scan_res;
+
+       drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+       if (unlikely(!drvdata)) {
+               printk(KERN_ERR "%s: no memory for drvdata\n",
+                      module_id);
+               return -ENOMEM;
+       }
+
+       /* bind private data into driver */
+       dev_set_drvdata(dev, drvdata);
+
+       /* allocate and map the resource */
+       drvdata->regs =
+               excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
+
+       if (unlikely(!drvdata->regs)) {
+               printk(KERN_ERR "%s: cannot reserve register region\n",
+                      module_id);
+               kfree(drvdata);
+               return -ENXIO;
+       }
+       
+       drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
+
+       /* initialise our chip */
+       board_chip = &drvdata->board_chip;
+       board_chip->IO_ADDR_R = board_chip->IO_ADDR_W =
+               drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
+       board_chip->cmd_ctrl = excite_nand_control;
+       board_chip->dev_ready = excite_nand_devready;
+       board_chip->chip_delay = 25;
+       board_chip->ecc.mode = NAND_ECC_SOFT;
+
+       /* link chip to mtd */
+       board_mtd = &drvdata->board_mtd;
+       board_mtd->priv = board_chip;
+
+       DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id);
+       scan_res = nand_scan(&drvdata->board_mtd, 1);
+
+       if (likely(!scan_res)) {
+               DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
+               add_mtd_partitions(&drvdata->board_mtd, partition_info,
+                                  sizeof partition_info / sizeof partition_info[0]);
+       } else {
+               iounmap(drvdata->regs);
+               kfree(drvdata);
+               printk(KERN_ERR "%s: device scan failed\n", module_id);
+               return -EIO;
+       }
+       return 0;
+}
+
+static struct device_driver excite_nand_driver = {
+       .name = "excite_nand",
+       .bus = &platform_bus_type,
+       .probe = excite_nand_probe,
+       .remove = __exit_p(excite_nand_remove)
+};
+
+static int __init excite_nand_init(void)
+{
+       pr_info("Basler eXcite nand flash driver Version "
+               EXCITE_NANDFLASH_VERSION "\n");
+       return driver_register(&excite_nand_driver);
+}
+
+static void __exit excite_nand_exit(void)
+{
+       driver_unregister(&excite_nand_driver);
+}
+
+module_init(excite_nand_init);
+module_exit(excite_nand_exit);
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(EXCITE_NANDFLASH_VERSION)
index dfe56e03e48b0bf9ca9bfa89fc4b11e5e15d4dc6..acaf97bc80d18f89696987db2c0370fd8cac0b76 100644 (file)
@@ -1272,10 +1272,25 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
        DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
              (unsigned long long)from, readlen);
 
-       if (ops->mode == MTD_OOB_RAW)
-               len = mtd->oobsize;
-       else
+       if (ops->mode == MTD_OOB_AUTO)
                len = chip->ecc.layout->oobavail;
+       else
+               len = mtd->oobsize;
+
+       if (unlikely(ops->ooboffs >= len)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                       "Attempt to start read outside oob\n");
+               return -EINVAL;
+       }
+
+       /* Do not allow reads past end of device */
+       if (unlikely(from >= mtd->size ||
+                    ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
+                                       (from >> chip->page_shift)) * len)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                       "Attempt read beyond end of device\n");
+               return -EINVAL;
+       }
 
        chipnr = (int)(from >> chip->chip_shift);
        chip->select_chip(mtd, chipnr);
@@ -1742,19 +1757,40 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
 {
-       int chipnr, page, status;
+       int chipnr, page, status, len;
        struct nand_chip *chip = mtd->priv;
 
        DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
              (unsigned int)to, (int)ops->ooblen);
 
+       if (ops->mode == MTD_OOB_AUTO)
+               len = chip->ecc.layout->oobavail;
+       else
+               len = mtd->oobsize;
+
        /* Do not allow write past end of page */
-       if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
+       if ((ops->ooboffs + ops->ooblen) > len) {
                DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
                      "Attempt to write past end of page\n");
                return -EINVAL;
        }
 
+       if (unlikely(ops->ooboffs >= len)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                       "Attempt to start write outside oob\n");
+               return -EINVAL;
+       }
+
+       /* Do not allow reads past end of device */
+       if (unlikely(to >= mtd->size ||
+                    ops->ooboffs + ops->ooblen >
+                       ((mtd->size >> chip->page_shift) -
+                        (to >> chip->page_shift)) * len)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                       "Attempt write beyond end of device\n");
+               return -EINVAL;
+       }
+
        chipnr = (int)(to >> chip->chip_shift);
        chip->select_chip(mtd, chipnr);
 
@@ -2530,7 +2566,6 @@ int nand_scan_tail(struct mtd_info *mtd)
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->ecctype = MTD_ECC_SW;
        mtd->erase = nand_erase;
        mtd->point = NULL;
        mtd->unpoint = NULL;
index 8b3203571eeb3e0d7afbb36bc9c8b092ff49b840..0ddfd6de75c52e75864c6cb6ab7d7550e45089dd 100644 (file)
@@ -337,17 +337,69 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                     u_char *read_ecc, u_char *calc_ecc)
 {
-       pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
+       struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+       unsigned int diff0, diff1, diff2;
+       unsigned int bit, byte;
 
-       pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
-                read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
+       pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
 
-       if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
-               return 0;
+       diff0 = read_ecc[0] ^ calc_ecc[0];
+       diff1 = read_ecc[1] ^ calc_ecc[1];
+       diff2 = read_ecc[2] ^ calc_ecc[2];
+
+       pr_debug("%s: rd %02x%02x%02x calc %02x%02x%02x diff %02x%02x%02x\n",
+                __func__,
+                read_ecc[0], read_ecc[1], read_ecc[2],
+                calc_ecc[0], calc_ecc[1], calc_ecc[2],
+                diff0, diff1, diff2);
+
+       if (diff0 == 0 && diff1 == 0 && diff2 == 0)
+               return 0;               /* ECC is ok */
+
+       /* Can we correct this ECC (ie, one row and column change).
+        * Note, this is similar to the 256 error code on smartmedia */
+
+       if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
+           ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
+           ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
+               /* calculate the bit position of the error */
+
+               bit  = (diff2 >> 2) & 1;
+               bit |= (diff2 >> 3) & 2;
+               bit |= (diff2 >> 4) & 4;
+
+               /* calculate the byte position of the error */
+
+               byte  = (diff1 << 1) & 0x80;
+               byte |= (diff1 << 2) & 0x40;
+               byte |= (diff1 << 3) & 0x20;
+               byte |= (diff1 << 4) & 0x10;
+
+               byte |= (diff0 >> 3) & 0x08;
+               byte |= (diff0 >> 2) & 0x04;
+               byte |= (diff0 >> 1) & 0x02;
+               byte |= (diff0 >> 0) & 0x01;
 
-       /* we curently have no method for correcting the error */
+               byte |= (diff2 << 8) & 0x100;
 
-       return -1;
+               dev_dbg(info->device, "correcting error bit %d, byte %d\n",
+                       bit, byte);
+
+               dat[byte] ^= (1 << bit);
+               return 1;
+       }
+
+       /* if there is only one bit difference in the ECC, then
+        * one of only a row or column parity has changed, which
+        * means the error is most probably in the ECC itself */
+
+       diff0 |= (diff1 << 8);
+       diff0 |= (diff2 << 16);
+
+       if ((diff0 & ~(1<<fls(diff0))) == 0)
+               return 1;
+
+       return 0;
 }
 
 /* ECC functions
@@ -366,6 +418,15 @@ static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
        writel(ctrl, info->regs + S3C2410_NFCONF);
 }
 
+static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+       unsigned long ctrl;
+
+       ctrl = readl(info->regs + S3C2440_NFCONT);
+       writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC, info->regs + S3C2440_NFCONT);
+}
+
 static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
@@ -383,6 +444,21 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
        ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 
+       pr_debug("%s: returning ecc %02x%02x%02x\n", __func__,
+                ecc_code[0], ecc_code[1], ecc_code[2]);
+
+       return 0;
+}
+
+static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+       struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+       unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
+
+       ecc_code[0] = ecc;
+       ecc_code[1] = ecc >> 8;
+       ecc_code[2] = ecc >> 16;
+
        pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
        return 0;
@@ -397,7 +473,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = ecc >> 8;
        ecc_code[2] = ecc >> 16;
 
-       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
+       pr_debug("%s: returning ecc %06x\n", __func__, ecc);
 
        return 0;
 }
@@ -565,6 +641,10 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
                        break;
 
                case TYPE_S3C2412:
+                       chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+                       chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+                       break;
+
                case TYPE_S3C2440:
                        chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
                        chip->ecc.calculate = s3c2440_nand_calculate_ecc;
index 4b1ba4fcfcd3235ad231259aa1ddae23b11b8599..e6ef7d7f9f14a316c1b058ff08acbb1637dfcf2c 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
 
index 2da6bb26353e22c6966c0835cf596cb227ac1883..7f1cb6e5dccb5b8463554cbf48e5227b66b1597d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mtd/onenand/onenand_base.c
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -94,16 +94,9 @@ static void onenand_writew(unsigned short value, void __iomem *addr)
  */
 static int onenand_block_address(struct onenand_chip *this, int block)
 {
-       if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-               /* Device Flash Core select, NAND Flash Block Address */
-               int dfs = 0;
-
-               if (block & this->density_mask)
-                       dfs = 1;
-
-               return (dfs << ONENAND_DDP_SHIFT) |
-                       (block & (this->density_mask - 1));
-       }
+       /* Device Flash Core select, NAND Flash Block Address */
+       if (block & this->density_mask)
+               return ONENAND_DDP_CHIP1 | (block ^ this->density_mask);
 
        return block;
 }
@@ -118,17 +111,11 @@ static int onenand_block_address(struct onenand_chip *this, int block)
  */
 static int onenand_bufferram_address(struct onenand_chip *this, int block)
 {
-       if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-               /* Device BufferRAM Select */
-               int dbs = 0;
-
-               if (block & this->density_mask)
-                       dbs = 1;
+       /* Device BufferRAM Select */
+       if (block & this->density_mask)
+               return ONENAND_DDP_CHIP1;
 
-               return (dbs << ONENAND_DDP_SHIFT);
-       }
-
-       return 0;
+       return ONENAND_DDP_CHIP0;
 }
 
 /**
@@ -317,22 +304,25 @@ static int onenand_wait(struct mtd_info *mtd, int state)
        ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
        if (ctrl & ONENAND_CTRL_ERROR) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
+               printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
                if (ctrl & ONENAND_CTRL_LOCK)
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
+                       printk(KERN_ERR "onenand_wait: it's locked error.\n");
                return ctrl;
        }
 
        if (interrupt & ONENAND_INT_READ) {
                int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
                if (ecc) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
+                       printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
                        if (ecc & ONENAND_ECC_2BIT_ALL) {
                                mtd->ecc_stats.failed++;
                                return ecc;
                        } else if (ecc & ONENAND_ECC_1BIT_ALL)
                                mtd->ecc_stats.corrected++;
                }
+       } else if (state == FL_READING) {
+               printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+               return -EIO;
        }
 
        return 0;
@@ -587,22 +577,32 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,
 static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
 {
        struct onenand_chip *this = mtd->priv;
-       int block, page;
-       int i;
+       int blockpage, found = 0;
+       unsigned int i;
 
-       block = (int) (addr >> this->erase_shift);
-       page = (int) (addr >> this->page_shift);
-       page &= this->page_mask;
+       blockpage = (int) (addr >> this->page_shift);
 
+       /* Is there valid data? */
        i = ONENAND_CURRENT_BUFFERRAM(this);
+       if (this->bufferram[i].blockpage == blockpage)
+               found = 1;
+       else {
+               /* Check another BufferRAM */
+               i = ONENAND_NEXT_BUFFERRAM(this);
+               if (this->bufferram[i].blockpage == blockpage) {
+                       ONENAND_SET_NEXT_BUFFERRAM(this);
+                       found = 1;
+               }
+       }
 
-       /* Is there valid data? */
-       if (this->bufferram[i].block == block &&
-           this->bufferram[i].page == page &&
-           this->bufferram[i].valid)
-               return 1;
+       if (found && ONENAND_IS_DDP(this)) {
+               /* Select DataRAM for DDP */
+               int block = (int) (addr >> this->erase_shift);
+               int value = onenand_bufferram_address(this, block);
+               this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
+       }
 
-       return 0;
+       return found;
 }
 
 /**
@@ -613,31 +613,49 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
  *
  * Update BufferRAM information
  */
-static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
+static void onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
                int valid)
 {
        struct onenand_chip *this = mtd->priv;
-       int blockpage;
-       int i;
+       int blockpage;
+       unsigned int i;
 
-       block = (int) (addr >> this->erase_shift);
-       page = (int) (addr >> this->page_shift);
-       page &= this->page_mask;
+       blockpage = (int) (addr >> this->page_shift);
 
-       /* Invalidate BufferRAM */
-       for (i = 0; i < MAX_BUFFERRAM; i++) {
-               if (this->bufferram[i].block == block &&
-                   this->bufferram[i].page == page)
-                       this->bufferram[i].valid = 0;
-       }
+       /* Invalidate another BufferRAM */
+       i = ONENAND_NEXT_BUFFERRAM(this);
+       if (this->bufferram[i].blockpage == blockpage)
+               this->bufferram[i].blockpage = -1;
 
        /* Update BufferRAM */
        i = ONENAND_CURRENT_BUFFERRAM(this);
-       this->bufferram[i].block = block;
-       this->bufferram[i].page = page;
-       this->bufferram[i].valid = valid;
+       if (valid)
+               this->bufferram[i].blockpage = blockpage;
+       else
+               this->bufferram[i].blockpage = -1;
+}
 
-       return 0;
+/**
+ * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
+ * @param mtd          MTD data structure
+ * @param addr         start address to invalidate
+ * @param len          length to invalidate
+ *
+ * Invalidate BufferRAM information
+ */
+static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
+               unsigned int len)
+{
+       struct onenand_chip *this = mtd->priv;
+       int i;
+       loff_t end_addr = addr + len;
+
+       /* Invalidate BufferRAM */
+       for (i = 0; i < MAX_BUFFERRAM; i++) {
+               loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift;
+               if (buf_addr >= addr && buf_addr < end_addr)
+                       this->bufferram[i].blockpage = -1;
+       }
 }
 
 /**
@@ -716,7 +734,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        /* Do not allow reads past end of device */
        if ((from + len) > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n");
+               printk(KERN_ERR "onenand_read: Attempt read beyond end of device\n");
                *retlen = 0;
                return -EINVAL;
        }
@@ -724,8 +742,6 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_READING);
 
-       /* TODO handling oob */
-
        stats = mtd->ecc_stats;
 
        /* Read-while-load method */
@@ -754,9 +770,9 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
                         * Now we issued chip 1 read and pointed chip 1
                         * bufferam so we have to point chip 0 bufferam.
                         */
-                       if (this->device_id & ONENAND_DEVICE_IS_DDP &&
-                                       unlikely(from == (this->chipsize >> 1))) {
-                               this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);
+                       if (ONENAND_IS_DDP(this) &&
+                           unlikely(from == (this->chipsize >> 1))) {
+                               this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
                                boundary = 1;
                        } else
                                boundary = 0;
@@ -770,7 +786,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
                        break;
                /* Set up for next read from bufferRAM */
                if (unlikely(boundary))
-                       this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);
+                       this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
                ONENAND_SET_NEXT_BUFFERRAM(this);
                buf += thislen;
                thislen = min_t(int, mtd->writesize, len - read);
@@ -800,6 +816,44 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
        return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
+/**
+ * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd          MTD device structure
+ * @param buf          destination address
+ * @param column       oob offset to read from
+ * @param thislen      oob length to read
+ */
+static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int column,
+                               int thislen)
+{
+       struct onenand_chip *this = mtd->priv;
+       struct nand_oobfree *free;
+       int readcol = column;
+       int readend = column + thislen;
+       int lastgap = 0;
+       uint8_t *oob_buf = this->page_buf + mtd->writesize;
+
+       for (free = this->ecclayout->oobfree; free->length; ++free) {
+               if (readcol >= lastgap)
+                       readcol += free->offset - lastgap;
+               if (readend >= lastgap)
+                       readend += free->offset - lastgap;
+               lastgap = free->offset + free->length;
+       }
+       this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
+       for (free = this->ecclayout->oobfree; free->length; ++free) {
+               int free_end = free->offset + free->length;
+               if (free->offset < readend && free_end > readcol) {
+                       int st = max_t(int,free->offset,readcol);
+                       int ed = min_t(int,free_end,readend);
+                       int n = ed - st;
+                       memcpy(buf, oob_buf + st, n);
+                       buf += n;
+               }
+       }
+       return 0;
+}
+
 /**
  * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band
  * @param mtd          MTD device structure
@@ -807,14 +861,15 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @param len          number of bytes to read
  * @param retlen       pointer to variable to store the number of read bytes
  * @param buf          the databuffer to put data
+ * @param mode         operation mode
  *
  * OneNAND read out-of-band data from the spare area
  */
-int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
+static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, u_char *buf, mtd_oob_mode_t mode)
 {
        struct onenand_chip *this = mtd->priv;
-       int read = 0, thislen, column;
+       int read = 0, thislen, column, oobsize;
        int ret = 0;
 
        DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
@@ -822,21 +877,33 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
        /* Initialize return length value */
        *retlen = 0;
 
+       if (mode == MTD_OOB_AUTO)
+               oobsize = this->ecclayout->oobavail;
+       else
+               oobsize = mtd->oobsize;
+
+       column = from & (mtd->oobsize - 1);
+
+       if (unlikely(column >= oobsize)) {
+               printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n");
+               return -EINVAL;
+       }
+
        /* Do not allow reads past end of device */
-       if (unlikely((from + len) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n");
+       if (unlikely(from >= mtd->size ||
+                    column + len > ((mtd->size >> this->page_shift) -
+                                    (from >> this->page_shift)) * oobsize)) {
+               printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of device\n");
                return -EINVAL;
        }
 
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_READING);
 
-       column = from & (mtd->oobsize - 1);
-
        while (read < len) {
                cond_resched();
 
-               thislen = mtd->oobsize - column;
+               thislen = oobsize - column;
                thislen = min_t(int, thislen, len);
 
                this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
@@ -846,11 +913,14 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
                ret = this->wait(mtd, FL_READING);
                /* First copy data and check return value for ECC handling */
 
-               this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+               if (mode == MTD_OOB_AUTO)
+                       onenand_transfer_auto_oob(mtd, buf, column, thislen);
+               else
+                       this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
 
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
-                       goto out;
+                       printk(KERN_ERR "onenand_read_oob: read failed = 0x%x\n", ret);
+                       break;
                }
 
                read += thislen;
@@ -868,7 +938,6 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
                }
        }
 
-out:
        /* Deselect and wake up anyone waiting on the device */
        onenand_release_device(mtd);
 
@@ -885,10 +954,132 @@ out:
 static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
                            struct mtd_oob_ops *ops)
 {
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
-
+       switch (ops->mode) {
+       case MTD_OOB_PLACE:
+       case MTD_OOB_AUTO:
+               break;
+       case MTD_OOB_RAW:
+               /* Not implemented yet */
+       default:
+               return -EINVAL;
+       }
        return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen,
-                                  &ops->oobretlen, ops->oobbuf);
+                                  &ops->oobretlen, ops->oobbuf, ops->mode);
+}
+
+/**
+ * onenand_bbt_wait - [DEFAULT] wait until the command is done
+ * @param mtd          MTD device structure
+ * @param state                state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_bbt_wait(struct mtd_info *mtd, int state)
+{
+       struct onenand_chip *this = mtd->priv;
+       unsigned long timeout;
+       unsigned int interrupt;
+       unsigned int ctrl;
+
+       /* The 20 msec is enough */
+       timeout = jiffies + msecs_to_jiffies(20);
+       while (time_before(jiffies, timeout)) {
+               interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+               if (interrupt & ONENAND_INT_MASTER)
+                       break;
+       }
+       /* To get correct interrupt status in timeout case */
+       interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+       ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+       if (ctrl & ONENAND_CTRL_ERROR) {
+               printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
+               /* Initial bad block case */
+               if (ctrl & ONENAND_CTRL_LOAD)
+                       return ONENAND_BBT_READ_ERROR;
+               return ONENAND_BBT_READ_FATAL_ERROR;
+       }
+
+       if (interrupt & ONENAND_INT_READ) {
+               int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+               if (ecc & ONENAND_ECC_2BIT_ALL)
+                       return ONENAND_BBT_READ_ERROR;
+       } else {
+               printk(KERN_ERR "onenand_bbt_wait: read timeout!"
+                       "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+               return ONENAND_BBT_READ_FATAL_ERROR;
+       }
+
+       return 0;
+}
+
+/**
+ * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
+ * @param mtd          MTD device structure
+ * @param from         offset to read from
+ * @param @ops         oob operation description structure
+ *
+ * OneNAND read out-of-band data from the spare area for bbt scan
+ */
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, 
+                           struct mtd_oob_ops *ops)
+{
+       struct onenand_chip *this = mtd->priv;
+       int read = 0, thislen, column;
+       int ret = 0;
+       size_t len = ops->ooblen;
+       u_char *buf = ops->oobbuf;
+
+       DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
+
+       /* Initialize return value */
+       ops->oobretlen = 0;
+
+       /* Do not allow reads past end of device */
+       if (unlikely((from + len) > mtd->size)) {
+               printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
+               return ONENAND_BBT_READ_FATAL_ERROR;
+       }
+
+       /* Grab the lock and see if the device is available */
+       onenand_get_device(mtd, FL_READING);
+
+       column = from & (mtd->oobsize - 1);
+
+       while (read < len) {
+               cond_resched();
+
+               thislen = mtd->oobsize - column;
+               thislen = min_t(int, thislen, len);
+
+               this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+
+               onenand_update_bufferram(mtd, from, 0);
+
+               ret = onenand_bbt_wait(mtd, FL_READING);
+               if (ret)
+                       break;
+
+               this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+               read += thislen;
+               if (read == len)
+                       break;
+
+               buf += thislen;
+
+               /* Read more? */
+               if (read < len) {
+                       /* Update Page size */
+                       from += mtd->writesize;
+                       column = 0;
+               }
+       }
+
+       /* Deselect and wake up anyone waiting on the device */
+       onenand_release_device(mtd);
+
+       ops->oobretlen = read;
+       return ret;
 }
 
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
@@ -897,14 +1088,12 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
  * @param mtd          MTD device structure
  * @param buf          the databuffer to verify
  * @param to           offset to read from
- * @param len          number of bytes to read and compare
  *
  */
-static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to, int len)
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
 {
        struct onenand_chip *this = mtd->priv;
-       char *readp = this->page_buf;
-       int column = to & (mtd->oobsize - 1);
+       char *readp = this->page_buf + mtd->writesize;
        int status, i;
 
        this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
@@ -913,9 +1102,8 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
        if (status)
                return status;
 
-       this->read_bufferram(mtd, ONENAND_SPARERAM, readp, column, len);
-
-       for(i = 0; i < len; i++)
+       this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize);
+       for(i = 0; i < mtd->oobsize; i++)
                if (buf[i] != 0xFF && buf[i] != readp[i])
                        return -EBADMSG;
 
@@ -923,41 +1111,51 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
 }
 
 /**
- * onenand_verify_page - [GENERIC] verify the chip contents after a write
- * @param mtd          MTD device structure
- * @param buf          the databuffer to verify
+ * onenand_verify - [GENERIC] verify the chip contents after a write
+ * @param mtd          MTD device structure
+ * @param buf          the databuffer to verify
+ * @param addr         offset to read from
+ * @param len          number of bytes to read and compare
  *
- * Check DataRAM area directly
  */
-static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
+static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
 {
        struct onenand_chip *this = mtd->priv;
-       void __iomem *dataram0, *dataram1;
+       void __iomem *dataram;
        int ret = 0;
+       int thislen, column;
 
-       /* In partial page write, just skip it */
-       if ((addr & (mtd->writesize - 1)) != 0)
-               return 0;
+       while (len != 0) {
+               thislen = min_t(int, mtd->writesize, len);
+               column = addr & (mtd->writesize - 1);
+               if (column + thislen > mtd->writesize)
+                       thislen = mtd->writesize - column;
 
-       this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
+               this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
-       ret = this->wait(mtd, FL_READING);
-       if (ret)
-               return ret;
+               onenand_update_bufferram(mtd, addr, 0);
+
+               ret = this->wait(mtd, FL_READING);
+               if (ret)
+                       return ret;
 
-       onenand_update_bufferram(mtd, addr, 1);
+               onenand_update_bufferram(mtd, addr, 1);
 
-       /* Check, if the two dataram areas are same */
-       dataram0 = this->base + ONENAND_DATARAM;
-       dataram1 = dataram0 + mtd->writesize;
+               dataram = this->base + ONENAND_DATARAM;
+               dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM);
 
-       if (memcmp(dataram0, dataram1, mtd->writesize))
-               return -EBADMSG;
+               if (memcmp(buf, dataram + column, thislen))
+                       return -EBADMSG;
+
+               len -= thislen;
+               buf += thislen;
+               addr += thislen;
+       }
 
        return 0;
 }
 #else
-#define onenand_verify_page(...)       (0)
+#define onenand_verify(...)            (0)
 #define onenand_verify_oob(...)                (0)
 #endif
 
@@ -988,60 +1186,57 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
 
        /* Do not allow writes past end of device */
        if (unlikely((to + len) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n");
+               printk(KERN_ERR "onenand_write: Attempt write to past end of device\n");
                return -EINVAL;
        }
 
        /* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n");
+                printk(KERN_ERR "onenand_write: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
 
        column = to & (mtd->writesize - 1);
-       subpage = column || (len & (mtd->writesize - 1));
 
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_WRITING);
 
        /* Loop until all data write */
        while (written < len) {
-               int bytes = mtd->writesize;
-               int thislen = min_t(int, bytes, len - written);
+               int thislen = min_t(int, mtd->writesize - column, len - written);
                u_char *wbuf = (u_char *) buf;
 
                cond_resched();
 
-               this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);
+               this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
 
                /* Partial page write */
+               subpage = thislen < mtd->writesize;
                if (subpage) {
-                       bytes = min_t(int, bytes - column, (int) len);
                        memset(this->page_buf, 0xff, mtd->writesize);
-                       memcpy(this->page_buf + column, buf, bytes);
+                       memcpy(this->page_buf + column, buf, thislen);
                        wbuf = this->page_buf;
-                       /* Even though partial write, we need page size */
-                       thislen = mtd->writesize;
                }
 
-               this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);
+               this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
                this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
 
                this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
+               ret = this->wait(mtd, FL_WRITING);
+
                /* In partial page write we don't update bufferram */
-               onenand_update_bufferram(mtd, to, !subpage);
+               onenand_update_bufferram(mtd, to, !ret && !subpage);
 
-               ret = this->wait(mtd, FL_WRITING);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
+                       printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
                        break;
                }
 
                /* Only check verify write turn on */
-               ret = onenand_verify_page(mtd, (u_char *) wbuf, to);
+               ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
+                       printk(KERN_ERR "onenand_write: verify failed %d\n", ret);
                        break;
                }
 
@@ -1063,6 +1258,43 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
        return ret;
 }
 
+/**
+ * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd          MTD device structure
+ * @param oob_buf      oob buffer
+ * @param buf          source address
+ * @param column       oob offset to write to
+ * @param thislen      oob length to write
+ */
+static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
+                                 const u_char *buf, int column, int thislen)
+{
+       struct onenand_chip *this = mtd->priv;
+       struct nand_oobfree *free;
+       int writecol = column;
+       int writeend = column + thislen;
+       int lastgap = 0;
+
+       for (free = this->ecclayout->oobfree; free->length; ++free) {
+               if (writecol >= lastgap)
+                       writecol += free->offset - lastgap;
+               if (writeend >= lastgap)
+                       writeend += free->offset - lastgap;
+               lastgap = free->offset + free->length;
+       }
+       for (free = this->ecclayout->oobfree; free->length; ++free) {
+               int free_end = free->offset + free->length;
+               if (free->offset < writeend && free_end > writecol) {
+                       int st = max_t(int,free->offset,writecol);
+                       int ed = min_t(int,free_end,writeend);
+                       int n = ed - st;
+                       memcpy(oob_buf + st, buf, n);
+                       buf += n;
+               }
+       }
+       return 0;
+}
+
 /**
  * onenand_do_write_oob - [Internal] OneNAND write out-of-band
  * @param mtd          MTD device structure
@@ -1070,14 +1302,15 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
  * @param len          number of bytes to write
  * @param retlen       pointer to variable to store the number of written bytes
  * @param buf          the data to write
+ * @param mode         operation mode
  *
  * OneNAND write out-of-band
  */
 static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-                               size_t *retlen, const u_char *buf)
+                               size_t *retlen, const u_char *buf, mtd_oob_mode_t mode)
 {
        struct onenand_chip *this = mtd->priv;
-       int column, ret = 0;
+       int column, ret = 0, oobsize;
        int written = 0;
 
        DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -1085,9 +1318,30 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
        /* Initialize retlen, in case of early exit */
        *retlen = 0;
 
-       /* Do not allow writes past end of device */
-       if (unlikely((to + len) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n");
+       if (mode == MTD_OOB_AUTO)
+               oobsize = this->ecclayout->oobavail;
+       else
+               oobsize = mtd->oobsize;
+
+       column = to & (mtd->oobsize - 1);
+
+       if (unlikely(column >= oobsize)) {
+               printk(KERN_ERR "onenand_write_oob: Attempted to start write outside oob\n");
+               return -EINVAL;
+       }
+
+       /* For compatibility with NAND: Do not allow write past end of page */
+       if (column + len > oobsize) {
+               printk(KERN_ERR "onenand_write_oob: "
+                     "Attempt to write past end of page\n");
+               return -EINVAL;
+       }
+
+       /* Do not allow reads past end of device */
+       if (unlikely(to >= mtd->size ||
+                    column + len > ((mtd->size >> this->page_shift) -
+                                    (to >> this->page_shift)) * oobsize)) {
+               printk(KERN_ERR "onenand_write_oob: Attempted to write past end of device\n");
                return -EINVAL;
        }
 
@@ -1096,18 +1350,19 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 
        /* Loop until all data write */
        while (written < len) {
-               int thislen = min_t(int, mtd->oobsize, len - written);
+               int thislen = min_t(int, oobsize, len - written);
 
                cond_resched();
 
-               column = to & (mtd->oobsize - 1);
-
                this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
 
                /* We send data to spare ram with oobsize
                 * to prevent byte access */
                memset(this->page_buf, 0xff, mtd->oobsize);
-               memcpy(this->page_buf + column, buf, thislen);
+               if (mode == MTD_OOB_AUTO)
+                       onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen);
+               else
+                       memcpy(this->page_buf + column, buf, thislen);
                this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
 
                this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
@@ -1116,26 +1371,25 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 
                ret = this->wait(mtd, FL_WRITING);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write filaed %d\n", ret);
-                       goto out;
+                       printk(KERN_ERR "onenand_write_oob: write failed %d\n", ret);
+                       break;
                }
 
-               ret = onenand_verify_oob(mtd, buf, to, thislen);
+               ret = onenand_verify_oob(mtd, this->page_buf, to);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret);
-                       goto out;
+                       printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
+                       break;
                }
 
                written += thislen;
-
                if (written == len)
                        break;
 
-               to += thislen;
+               to += mtd->writesize;
                buf += thislen;
+               column = 0;
        }
 
-out:
        /* Deselect and wake up anyone waiting on the device */
        onenand_release_device(mtd);
 
@@ -1153,10 +1407,17 @@ out:
 static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
 {
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
-
+       switch (ops->mode) {
+       case MTD_OOB_PLACE:
+       case MTD_OOB_AUTO:
+               break;
+       case MTD_OOB_RAW:
+               /* Not implemented yet */
+       default:
+               return -EINVAL;
+       }
        return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen,
-                                   &ops->oobretlen, ops->oobbuf);
+                                   &ops->oobretlen, ops->oobbuf, ops->mode);
 }
 
 /**
@@ -1199,19 +1460,19 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        /* Start address must align on block boundary */
        if (unlikely(instr->addr & (block_size - 1))) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n");
+               printk(KERN_ERR "onenand_erase: Unaligned address\n");
                return -EINVAL;
        }
 
        /* Length must align on block boundary */
        if (unlikely(instr->len & (block_size - 1))) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n");
+               printk(KERN_ERR "onenand_erase: Length not block aligned\n");
                return -EINVAL;
        }
 
        /* Do not allow erase past end of device */
        if (unlikely((instr->len + instr->addr) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n");
+               printk(KERN_ERR "onenand_erase: Erase past end of device\n");
                return -EINVAL;
        }
 
@@ -1238,10 +1499,12 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
                this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
 
+               onenand_invalidate_bufferram(mtd, addr, block_size);
+
                ret = this->wait(mtd, FL_ERASING);
                /* Check, if it is write protected */
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+                       printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
                        instr->state = MTD_ERASE_FAILED;
                        instr->fail_addr = addr;
                        goto erase_exit;
@@ -1322,7 +1585,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
         /* We write two bytes, so we dont have to mess with 16 bit access */
         ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
-        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf);
+        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf, MTD_OOB_PLACE);
 }
 
 /**
@@ -1491,6 +1754,8 @@ static int onenand_unlock_all(struct mtd_info *mtd)
        struct onenand_chip *this = mtd->priv;
 
        if (this->options & ONENAND_HAS_UNLOCK_ALL) {
+               /* Set start block address */
+               this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
                /* Write unlock command */
                this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
 
@@ -1503,13 +1768,10 @@ static int onenand_unlock_all(struct mtd_info *mtd)
                        continue;
 
                /* Workaround for all block unlock in DDP */
-               if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-                       loff_t ofs;
-                       size_t len;
-
+               if (ONENAND_IS_DDP(this)) {
                        /* 1st block on another chip */
-                       ofs = this->chipsize >> 1;
-                       len = 1 << this->erase_shift;
+                       loff_t ofs = this->chipsize >> 1;
+                       size_t len = mtd->erasesize;
 
                        onenand_unlock(mtd, ofs, len);
                }
@@ -1617,7 +1879,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
        this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
        this->wait(mtd, FL_OTPING);
 
-       ret = onenand_do_write_oob(mtd, from, len, retlen, buf);
+       ret = onenand_do_write_oob(mtd, from, len, retlen, buf, MTD_OOB_PLACE);
 
        /* Exit OTP access mode */
        this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -1823,12 +2085,13 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
 #endif /* CONFIG_MTD_ONENAND_OTP */
 
 /**
- * onenand_lock_scheme - Check and set OneNAND lock scheme
+ * onenand_check_features - Check and set OneNAND features
  * @param mtd          MTD data structure
  *
- * Check and set OneNAND lock scheme
+ * Check and set OneNAND features
+ * - lock scheme
  */
-static void onenand_lock_scheme(struct mtd_info *mtd)
+static void onenand_check_features(struct mtd_info *mtd)
 {
        struct onenand_chip *this = mtd->priv;
        unsigned int density, process;
@@ -1961,26 +2224,28 @@ static int onenand_probe(struct mtd_info *mtd)
        density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
        this->chipsize = (16 << density) << 20;
        /* Set density mask. it is used for DDP */
-       this->density_mask = (1 << (density + 6));
+       if (ONENAND_IS_DDP(this))
+               this->density_mask = (1 << (density + 6));
+       else
+               this->density_mask = 0;
 
        /* OneNAND page size & block size */
        /* The data buffer size is equal to page size */
        mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
        mtd->oobsize = mtd->writesize >> 5;
-       /* Pagers per block is always 64 in OneNAND */
+       /* Pages per a block are always 64 in OneNAND */
        mtd->erasesize = mtd->writesize << 6;
 
        this->erase_shift = ffs(mtd->erasesize) - 1;
        this->page_shift = ffs(mtd->writesize) - 1;
-       this->ppb_shift = (this->erase_shift - this->page_shift);
-       this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
+       this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
 
        /* REVIST: Multichip handling */
 
        mtd->size = this->chipsize;
 
-       /* Check OneNAND lock scheme */
-       onenand_lock_scheme(mtd);
+       /* Check OneNAND features */
+       onenand_check_features(mtd);
 
        return 0;
 }
@@ -2021,6 +2286,7 @@ static void onenand_resume(struct mtd_info *mtd)
  */
 int onenand_scan(struct mtd_info *mtd, int maxchips)
 {
+       int i;
        struct onenand_chip *this = mtd->priv;
 
        if (!this->read_word)
@@ -2092,12 +2358,21 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        }
 
        this->subpagesize = mtd->writesize >> mtd->subpage_sft;
+
+       /*
+        * The number of bytes available for a client to place data into
+        * the out of band area
+        */
+       this->ecclayout->oobavail = 0;
+       for (i = 0; this->ecclayout->oobfree[i].length; i++)
+               this->ecclayout->oobavail +=
+                       this->ecclayout->oobfree[i].length;
+
        mtd->ecclayout = this->ecclayout;
 
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->ecctype = MTD_ECC_SW;
        mtd->erase = onenand_erase;
        mtd->point = NULL;
        mtd->unpoint = NULL;
@@ -2144,8 +2419,11 @@ void onenand_release(struct mtd_info *mtd)
        del_mtd_device (mtd);
 
        /* Free bad block table memory, if allocated */
-       if (this->bbm)
+       if (this->bbm) {
+               struct bbm_info *bbm = this->bbm;
+               kfree(bbm->bbt);
                kfree(this->bbm);
+       }
        /* Buffer allocated by onenand_scan */
        if (this->options & ONENAND_PAGEBUF_ALLOC)
                kfree(this->page_buf);
index 98f8fd1c637510706676b3d5fff7289496f305d0..aecdd50a1781354556c9948ed86b4a1f09e52c36 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
-extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-                              size_t *retlen, u_char *buf);
+extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+                               struct mtd_oob_ops *ops);
 
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
@@ -65,10 +65,11 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        int startblock;
        loff_t from;
        size_t readlen, ooblen;
+       struct mtd_oob_ops ops;
 
        printk(KERN_INFO "Scanning device for bad blocks\n");
 
-       len = 1;
+       len = 2;
 
        /* We need only read few bytes from the OOB area */
        scanlen = ooblen = 0;
@@ -82,22 +83,24 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        startblock = 0;
        from = 0;
 
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooblen = readlen;
+       ops.oobbuf = buf;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
        for (i = startblock; i < numblocks; ) {
                int ret;
 
                for (j = 0; j < len; j++) {
-                       size_t retlen;
-
                        /* No need to read pages fully,
                         * just read required OOB bytes */
-                       ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
-                                                 readlen, &retlen, &buf[0]);
+                       ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
 
                        /* If it is a initial bad block, just ignore it */
-                       if (ret && !(ret & ONENAND_CTRL_LOAD))
-                               return ret;
+                       if (ret == ONENAND_BBT_READ_FATAL_ERROR)
+                               return -EIO;
 
-                       if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+                       if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
                                bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
                                printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
                                        i >> 1, (unsigned int) from);
@@ -168,8 +171,8 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
  * marked good / bad blocks and writes the bad block table(s) to
  * the selected place.
  *
- * The bad block table memory is allocated here. It must be freed
- * by calling the onenand_free_bbt function.
+ * The bad block table memory is allocated here. It is freed
+ * by the onenand_release function.
  *
  */
 int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
index 035cd9b0cc08b327f83d8f12958eacdcab7f6c94..a61351f88ec046d894bf07bc042907e2a22bb364 100644 (file)
@@ -94,8 +94,19 @@ static int parse_redboot_partitions(struct mtd_info *master,
                         * (NOTE: this is 'size' not 'data_length'; size is
                         * the full size of the entry.)
                         */
-                       if (swab32(buf[i].size) == master->erasesize) {
+
+                       /* RedBoot can combine the FIS directory and
+                          config partitions into a single eraseblock;
+                          we assume wrong-endian if either the swapped
+                          'size' matches the eraseblock size precisely,
+                          or if the swapped size actually fits in an
+                          eraseblock while the unswapped size doesn't. */
+                       if (swab32(buf[i].size) == master->erasesize ||
+                           (buf[i].size > master->erasesize
+                            && swab32(buf[i].size) < master->erasesize)) {
                                int j;
+                               /* Update numslots based on actual FIS directory size */
+                               numslots = swab32(buf[i].size) / sizeof (struct fis_image_desc);
                                for (j = 0; j < numslots; ++j) {
 
                                        /* A single 0xff denotes a deleted entry.
@@ -120,11 +131,11 @@ static int parse_redboot_partitions(struct mtd_info *master,
                                        swab32s(&buf[j].desc_cksum);
                                        swab32s(&buf[j].file_cksum);
                                }
+                       } else if (buf[i].size < master->erasesize) {
+                               /* Update numslots based on actual FIS directory size */
+                               numslots = buf[i].size / sizeof(struct fis_image_desc);
                        }
                        break;
-               } else {
-                       /* re-calculate of real numslots */
-                       numslots = buf[i].size / sizeof(struct fis_image_desc);
                }
        }
        if (i == numslots) {
index 2d5ba076471c29d3b62a43c3765780711eb5d4af..1b3d11ed6cff5a3980d4f3fe4997feee7e628e11 100644 (file)
@@ -500,7 +500,7 @@ int lance_open (struct net_device *dev)
        int res;
 
         /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
-        if (request_irq(lp->irq, lance_interrupt, SA_SHIRQ, lp->name, dev))
+        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
                 return -EAGAIN;
 
         res = lance_reset(dev);
index 38f41a593b1269961e8ce8040751c644a46fa9f6..d9400ef87195d9ba7a114726436d21d26f9e16c7 100644 (file)
@@ -1284,8 +1284,8 @@ config PCNET32
          will be called pcnet32.
 
 config PCNET32_NAPI
-       bool "Use RX polling (NAPI) (EXPERIMENTAL)"
-       depends on PCNET32 && EXPERIMENTAL
+       bool "Use RX polling (NAPI)"
+       depends on PCNET32
        help
          NAPI is a new driver API designed to reduce CPU and interrupt load
          when the driver is receiving lots of packets from the card. It is
@@ -2125,14 +2125,16 @@ config SKY2
          will be called sky2.  This is recommended.
 
 config SK98LIN
-       tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
+       tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
        depends on PCI
        ---help---
          Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
          compliant Gigabit Ethernet Adapter.
 
-         This driver supports the original Yukon chipset. A cleaner driver is 
-         also available (skge) which seems to work better than this one.
+         This driver supports the original Yukon chipset. This driver is
+         deprecated and will be removed from the kernel in the near future,
+         it has been replaced by the skge driver. skge is cleaner and
+         seems to work better.
 
          This driver does not support the newer Yukon2 chipset. A separate
          driver, sky2, is provided to support Yukon2-based adapters.
@@ -2337,7 +2339,7 @@ config QLA3XXX
 
 config ATL1
        tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)"
-       depends on NET_PCI && PCI && EXPERIMENTAL
+       depends on PCI && EXPERIMENTAL
        select CRC32
        select MII
        help
index e7555d4e6ff1c98e44cae1de1cc1048e33d4816c..6318814a11a8a7a3294ee371e2d4017f48900afa 100644 (file)
@@ -94,7 +94,7 @@ static void rx(struct net_device *dev, int bufnum,
 
        BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
 
-       if (length >= MinTU)
+       if (length > MTU)
                ofs = 512 - length;
        else
                ofs = 256 - length;
@@ -183,7 +183,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
                       length, XMTU);
                length = XMTU;
        }
-       if (length > MinTU) {
+       if (length >= MinTU) {
                hard->offset[0] = 0;
                hard->offset[1] = ofs = 512 - length;
        } else if (length > MTU) {
index 4e91dab1f17f330ee4c5108e22c62e20f17c09d0..83004fdab0a4d29e0fc6a798e2d9501c46516e9f 100644 (file)
@@ -41,7 +41,7 @@
  *     <jojo@repas.de>
  */
 
-#define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
 
 #include <linux/module.h>
 #include <linux/types.h>
index 98d326b23c92bd3fd9b2fbea95805bfaf7b6eea2..b8c0fa6d401db146998c21c29b7928806a5fe9f3 100644 (file)
@@ -155,6 +155,7 @@ static struct pci_device_id com20020pci_id_table[] = {
        { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
        { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
        { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+       { 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
        { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
@@ -163,6 +164,8 @@ static struct pci_device_id com20020pci_id_table[] = {
        { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+       { 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+       { 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        {0,}
 };
 
index 4218075c8aa38e47b878386c9627169659cbbb54..7cf0a2511697fbe0aedc6b619c243b6b8d2269ef 100644 (file)
@@ -104,7 +104,7 @@ int com20020_check(struct net_device *dev)
        SET_SUBADR(SUB_SETUP1);
        outb(lp->setup, _XREG);
 
-       if (lp->card_flags & ARC_CAN_10MBIT)
+       if (lp->clockm != 0)
        {
                SET_SUBADR(SUB_SETUP2);
                outb(lp->setup2, _XREG);
index d6da3ce9ad7967776716827d5e8474fe7a2599f1..a2921882eba8559e5c342f24e4afeed265587012 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 4fc234785d56069b47ce25261a0c8c8a148f29de..841178343a07104f5856c32ded46cada9feb82e9 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 72c41f5907f252f517bdfdf451b02167b13b8962..61f574aa3a991eede306c19dbb5fe4972289a889 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 08b2d785469d13ae524b60d3092b676900980da5..314dbaabb642454a1e2389caeef97fcc87995eb8 100644 (file)
@@ -243,14 +243,8 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
                        i += 4;
                }
 
-/*
- * The following 2 lines are the Attansic originals.  Saving for posterity.
- *             *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
- *             *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
- */
-               *(u32 *) & eth_addr[2] = swab32(addr[0]);
-               *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
-
+               *(u32 *) &eth_addr[2] = swab32(addr[0]);
+               *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
                if (is_valid_ether_addr(eth_addr)) {
                        memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
                        return 0;
@@ -281,17 +275,28 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
                i += 4;
        }
 
-/*
- * The following 2 lines are the Attansic originals.  Saving for posterity.
- *     *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
- *     *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
- */
-       *(u32 *) & eth_addr[2] = swab32(addr[0]);
-       *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
+       *(u32 *) &eth_addr[2] = swab32(addr[0]);
+       *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
        if (is_valid_ether_addr(eth_addr)) {
                memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
                return 0;
        }
+
+       /*
+        * On some motherboards, the MAC address is written by the
+        * BIOS directly to the MAC register during POST, and is
+        * not stored in eeprom.  If all else thus far has failed
+        * to fetch the permanent MAC address, try reading it directly.
+        */
+       addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+       addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+       *(u32 *) &eth_addr[2] = swab32(addr[0]);
+       *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+       if (is_valid_ether_addr(eth_addr)) {
+               memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+               return 0;
+       }
+
        return 1;
 }
 
@@ -357,7 +362,7 @@ void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
         */
        hash_reg = (hash_value >> 31) & 0x1;
        hash_bit = (hash_value >> 26) & 0x1F;
-       mta = ioread32((hw + REG_RX_HASH_TABLE) + (hash_reg << 2));
+       mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
        mta |= (1 << hash_bit);
        iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
 }
index 6655640eb4ca130e6fe03da5dda3681cfdf6d167..65673485bb6b35c1f1e457261a14a7740d5b9389 100644 (file)
@@ -82,8 +82,7 @@
 
 #include "atl1.h"
 
-#define RUN_REALTIME 0
-#define DRIVER_VERSION "2.0.6"
+#define DRIVER_VERSION "2.0.7"
 
 char atl1_driver_name[] = "atl1";
 static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
@@ -100,7 +99,7 @@ MODULE_VERSION(DRIVER_VERSION);
  * atl1_pci_tbl - PCI Device ID Table
  */
 static const struct pci_device_id atl1_pci_tbl[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1048)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
        /* required last entry */
        {0,}
 };
index f0b6879a1c7d31463ab03da8682f8e23b68366c8..69ae229b680e25ee5226528736bcd8c111e66da5 100644 (file)
@@ -37,7 +37,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
index 5ff7882297d66910c15db46406eda5e8a4a33e50..aaada572732a87fd3c8fd2d03898861d834c2c86 100644 (file)
@@ -59,7 +59,6 @@
 #define B44_DEF_TX_RING_PENDING                (B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES      (sizeof(struct dma_desc) * \
                                 B44_TX_RING_SIZE)
-#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)        \
        (B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -665,7 +664,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        /* Hardware bug work-around, the chip is unable to do PCI DMA
           to/from anything above 1GB :-( */
        if (dma_mapping_error(mapping) ||
-               mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+               mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
                /* Sigh... */
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
@@ -677,7 +676,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                                         RX_PKT_BUF_SZ,
                                         PCI_DMA_FROMDEVICE);
                if (dma_mapping_error(mapping) ||
-                       mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+                       mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
                        if (!dma_mapping_error(mapping))
                                pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
                        dev_kfree_skb_any(skb);
@@ -988,7 +987,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
-       if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+       if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
                /* Chip can't handle DMA to/from >1GB, use bounce buffer */
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
@@ -1000,7 +999,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                mapping = pci_map_single(bp->pdev, bounce_skb->data,
                                         len, PCI_DMA_TODEVICE);
-               if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+               if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
                        if (!dma_mapping_error(mapping))
                                pci_unmap_single(bp->pdev, mapping,
                                         len, PCI_DMA_TODEVICE);
@@ -1227,7 +1226,7 @@ static int b44_alloc_consistent(struct b44 *bp)
                                             DMA_BIDIRECTIONAL);
 
                if (dma_mapping_error(rx_ring_dma) ||
-                       rx_ring_dma + size > B44_DMA_MASK) {
+                       rx_ring_dma + size > DMA_30BIT_MASK) {
                        kfree(rx_ring);
                        goto out_err;
                }
@@ -1254,7 +1253,7 @@ static int b44_alloc_consistent(struct b44 *bp)
                                             DMA_TO_DEVICE);
 
                if (dma_mapping_error(tx_ring_dma) ||
-                       tx_ring_dma + size > B44_DMA_MASK) {
+                       tx_ring_dma + size > DMA_30BIT_MASK) {
                        kfree(tx_ring);
                        goto out_err;
                }
@@ -1289,7 +1288,7 @@ static void b44_chip_reset(struct b44 *bp)
        if (ssb_is_core_up(bp)) {
                bw32(bp, B44_RCV_LAZY, 0);
                bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
-               b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
+               b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
                bw32(bp, B44_DMATX_CTRL, 0);
                bp->tx_prod = bp->tx_cons = 0;
                if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
@@ -2151,13 +2150,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
+       err = pci_set_dma_mask(pdev, (u64) DMA_30BIT_MASK);
        if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
                goto err_out_free_res;
        }
 
-       err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+       err = pci_set_consistent_dma_mask(pdev, (u64) DMA_30BIT_MASK);
        if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
                goto err_out_free_res;
index 61a6fa465d716fba007d839638cf136f9ef5a7ad..a7c8f98a890c12bae0f8e8ac1e47a9037476f01f 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
index 878f7aabeeac2b1a27324e3a2a89bef0371343c4..a122baa5c7bb937ebcc5c436d5710fe785ae3b61 100644 (file)
@@ -22,7 +22,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/fs.h>
index a03d781f6d0a459c56f6009d56ce64ed355e72fb..8eb57127600090d4d44a8fdcaaba41ca1ccb0d04 100644 (file)
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
index 16e004990c597d9da1ce1a248e417c2e66a14b74..e14862b43d174041845086e35e5b617627c69980 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. 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
index c67f7d3c2f92a8195ca2f5f2837526452b759d1e..43583ed655ab8a3171b5dc9be25c26078a10a79d 100644 (file)
@@ -757,7 +757,8 @@ static int cxgb_up(struct adapter *adap)
                                      t3_intr_handler(adap,
                                                      adap->sge.qs[0].rspq.
                                                      polling),
-                                     (adap->flags & USING_MSI) ? 0 : SA_SHIRQ,
+                                     (adap->flags & USING_MSI) ?
+                                      0 : IRQF_SHARED,
                                      adap->name, adap)))
                goto irq_err;
 
index c6b72664318571f81d5ad09b3f0c3f6600bf21f4..b2cf5f6feb4a4ada3b8ab4bacd48943efdb4d9af 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. 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
index 0e6beb69ba17bd75eba6fddf08658584a673402e..f15446a32efca176c2c1c0ddfb442a399bcd046e 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. 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
index 3c0cb8557058bfbd70009e6c7a7c289849f7f41e..d660af74606e4abbb20f9d964c0080367425662e 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. 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
index ba5d2cbd7241c716b013d9a510c96fa51b2ad6de..d79001336cfdcaf6e4c0afdb9ac32aa7223519ec 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. 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
index 9af3bcd64b3b011c11d166ac71ba2e3c9ba1d432..fa4099bc0416a0220c6d80a29b9c01a22188f4db 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2006-2007 Chelsio Communications.  All rights reserved.
- * Copyright (C) 2006-2007 Open Grid Computing, Inc.  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
index 689f158a469eb78d6146f98231e0f36b69680f5d..dd4b728ac4b58712ceb88658c1fa82807fccda39 100644 (file)
@@ -337,7 +337,6 @@ struct e1000_adapter {
        struct e1000_rx_ring test_rx_ring;
 
 
-       uint32_t *config_space;
        int msg_enable;
 #ifdef CONFIG_PCI_MSI
        boolean_t have_msi;
index 44ebc72962dc47d6e434f8153b21f4932985cac1..6777887295f538822d006aa582986cac6eeb94a7 100644 (file)
@@ -166,7 +166,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                        ecmd->transceiver = XCVR_EXTERNAL;
        }
 
-       if (netif_carrier_ok(adapter->netdev)) {
+       if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
 
                e1000_get_speed_and_duplex(hw, &adapter->link_speed,
                                                   &adapter->link_duplex);
index d67105883341ef69db334d1ddeb7c5ab3e3be961..bd000b802ee7190a325e9b573621350affe4ce36 100644 (file)
@@ -3253,7 +3253,7 @@ struct e1000_host_command_info {
 #define IFE_PMC_AUTO_MDIX                    0x0080  /* 1=enable MDI/MDI-X feature, default 0=disabled */
 #define IFE_PMC_FORCE_MDIX                   0x0040  /* 1=force MDIX-X, 0=force MDI */
 #define IFE_PMC_MDIX_STATUS                  0x0020  /* 1=MDI-X, 0=MDI */
-#define IFE_PMC_AUTO_MDIX_COMPLETE           0x0010  /* Resolution algorthm is completed */
+#define IFE_PMC_AUTO_MDIX_COMPLETE           0x0010  /* Resolution algorithm is completed */
 #define IFE_PMC_MDIX_MODE_SHIFT              6
 #define IFE_PHC_MDIX_RESET_ALL_MASK          0x0000  /* Disable auto MDI-X */
 
index 619c89218b4bcb0cd113bfdadf11206c1bf7e027..a71023741c3af8b3acb1c61ecd90bab11b3faaab 100644 (file)
@@ -1417,10 +1417,6 @@ e1000_open(struct net_device *netdev)
        if ((err = e1000_setup_all_rx_resources(adapter)))
                goto err_setup_rx;
 
-       err = e1000_request_irq(adapter);
-       if (err)
-               goto err_req_irq;
-
        e1000_power_up_phy(adapter);
 
        if ((err = e1000_up(adapter)))
@@ -1431,6 +1427,10 @@ e1000_open(struct net_device *netdev)
                e1000_update_mng_vlan(adapter);
        }
 
+       err = e1000_request_irq(adapter);
+       if (err)
+               goto err_req_irq;
+
        /* If AMT is enabled, let the firmware know that the network
         * interface is now open */
        if (adapter->hw.mac_type == e1000_82573 &&
@@ -1439,10 +1439,10 @@ e1000_open(struct net_device *netdev)
 
        return E1000_SUCCESS;
 
+err_req_irq:
+       e1000_down(adapter);
 err_up:
        e1000_power_down_phy(adapter);
-       e1000_free_irq(adapter);
-err_req_irq:
        e1000_free_all_rx_resources(adapter);
 err_setup_rx:
        e1000_free_all_tx_resources(adapter);
@@ -5071,58 +5071,6 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
        return 0;
 }
 
-#ifdef CONFIG_PM
-/* Save/restore 16 or 64 dwords of PCI config space depending on which
- * bus we're on (PCI(X) vs. PCI-E)
- */
-#define PCIE_CONFIG_SPACE_LEN 256
-#define PCI_CONFIG_SPACE_LEN 64
-static int
-e1000_pci_save_state(struct e1000_adapter *adapter)
-{
-       struct pci_dev *dev = adapter->pdev;
-       int size;
-       int i;
-
-       if (adapter->hw.mac_type >= e1000_82571)
-               size = PCIE_CONFIG_SPACE_LEN;
-       else
-               size = PCI_CONFIG_SPACE_LEN;
-
-       WARN_ON(adapter->config_space != NULL);
-
-       adapter->config_space = kmalloc(size, GFP_KERNEL);
-       if (!adapter->config_space) {
-               DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
-               return -ENOMEM;
-       }
-       for (i = 0; i < (size / 4); i++)
-               pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
-       return 0;
-}
-
-static void
-e1000_pci_restore_state(struct e1000_adapter *adapter)
-{
-       struct pci_dev *dev = adapter->pdev;
-       int size;
-       int i;
-
-       if (adapter->config_space == NULL)
-               return;
-
-       if (adapter->hw.mac_type >= e1000_82571)
-               size = PCIE_CONFIG_SPACE_LEN;
-       else
-               size = PCI_CONFIG_SPACE_LEN;
-       for (i = 0; i < (size / 4); i++)
-               pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
-       kfree(adapter->config_space);
-       adapter->config_space = NULL;
-       return;
-}
-#endif /* CONFIG_PM */
-
 static int
 e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -5142,9 +5090,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
        }
 
 #ifdef CONFIG_PM
-       /* Implement our own version of pci_save_state(pdev) because pci-
-        * express adapters have 256-byte config spaces. */
-       retval = e1000_pci_save_state(adapter);
+       retval = pci_save_state(pdev);
        if (retval)
                return retval;
 #endif
@@ -5231,7 +5177,7 @@ e1000_resume(struct pci_dev *pdev)
        uint32_t err;
 
        pci_set_power_state(pdev, PCI_D0);
-       e1000_pci_restore_state(adapter);
+       pci_restore_state(pdev);
        if ((err = pci_enable_device(pdev))) {
                printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
                return err;
index 4a50fcb5ad6b6538b62fb58530182ecc2051e17c..3868b8031266bfea0b84648f3e50acc65309f636 100644 (file)
@@ -707,13 +707,6 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
        return 0;
 }
 
-/*
- * Handle an EtherExpress interrupt
- * If we've finished initializing, start the RU and CU up.
- * If we've already started, reap tx buffers, handle any received packets,
- * check to make sure we've not become wedged.
- */
-
 /*
  * Handle an EtherExpress interrupt
  * If we've finished initializing, start the RU and CU up.
index 272e1ec51aa2b4202c5ea93980d9026039ef6a05..42295d61ecd847791f6a8c04513940c471732790 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0045"
+#define DRV_VERSION    "EHEA_0046"
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
        | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
index 9de2d38a5321f6d40194a0a2eb061685b9773331..88ad1c8bcee49d2a34f1d00aac8a0292a17deaab 100644 (file)
@@ -76,7 +76,7 @@ void ehea_dump(void *adr, int len, char *msg) {
        int x;
        unsigned char *deb = adr;
        for (x = 0; x < len; x += 16) {
-               printk(DRV_NAME "%s adr=%p ofs=%04x %016lx %016lx\n", msg,
+               printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
                          deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
                deb += 16;
        }
@@ -555,6 +555,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
 {
        struct ehea_port *port = param;
        struct ehea_eqe *eqe;
+       struct ehea_qp *qp;
        u32 qp_token;
 
        eqe = ehea_poll_eq(port->qp_eq);
@@ -563,9 +564,14 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
                qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
                ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
                           eqe->entry, qp_token);
+
+               qp = port->port_res[qp_token].qp;
+               ehea_error_data(port->adapter, qp->fw_handle);
                eqe = ehea_poll_eq(port->qp_eq);
        }
 
+       queue_work(port->adapter->ehea_wq, &port->reset_task);
+
        return IRQ_HANDLED;
 }
 
@@ -882,7 +888,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
                         , "%s-recv%d", dev->name, i);
                ret = ibmebus_request_irq(NULL, pr->recv_eq->attr.ist1,
                                          ehea_recv_irq_handler,
-                                         SA_INTERRUPT, pr->int_recv_name, pr);
+                                         IRQF_DISABLED, pr->int_recv_name, pr);
                if (ret) {
                        ehea_error("failed registering irq for ehea_recv_int:"
                                   "port_res_nr:%d, ist=%X", i,
@@ -899,7 +905,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
 
        ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
                                  ehea_qp_aff_irq_handler,
-                                 SA_INTERRUPT, port->int_aff_name, port);
+                                 IRQF_DISABLED, port->int_aff_name, port);
        if (ret) {
                ehea_error("failed registering irq for qp_aff_irq_handler:"
                           "ist=%X", port->qp_eq->attr.ist1);
@@ -916,7 +922,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
                         "%s-send%d", dev->name, i);
                ret = ibmebus_request_irq(NULL, pr->send_eq->attr.ist1,
                                          ehea_send_irq_handler,
-                                         SA_INTERRUPT, pr->int_send_name,
+                                         IRQF_DISABLED, pr->int_send_name,
                                          pr);
                if (ret) {
                        ehea_error("failed registering irq for ehea_send "
@@ -2539,7 +2545,7 @@ static int __devinit ehea_probe(struct ibmebus_dev *dev,
                     (unsigned long)adapter);
 
        ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
-                                 ehea_interrupt_neq, SA_INTERRUPT,
+                                 ehea_interrupt_neq, IRQF_DISABLED,
                                  "ehea_neq", adapter);
        if (ret) {
                dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
index 37716e05e808fe50e777da3490331bf60ea9a64e..bc3c005472642af53f72627c666911cf380c60f0 100644 (file)
@@ -612,3 +612,13 @@ u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
                                       event_mask,              /* R6 */
                                       0, 0, 0, 0);             /* R7-R12 */
 }
+
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+                     void *rblock)
+{
+       return ehea_plpar_hcall_norets(H_ERROR_DATA,
+                                      adapter_handle,          /* R4 */
+                                      ressource_handle,        /* R5 */
+                                      virt_to_abs(rblock),     /* R6 */
+                                      0, 0, 0, 0);             /* R7-R12 */
+}
index 919f94b759336e95cd25afe54b1217ae22bde9bf..90acddb068a1ab819938631675c4db83ab01bda3 100644 (file)
@@ -454,4 +454,7 @@ u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
 u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
                        const u64 event_mask);
 
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+                     void *rblock);
+
 #endif /* __EHEA_PHYP_H__ */
index f143e13b229dda570b10f84142398aad43ee8699..96ff3b6799969d50c2cd9f13e6899c1f3f1e8993 100644 (file)
@@ -486,6 +486,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
        if (!qp)
                return 0;
 
+       ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
        hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle);
        if (hret != H_SUCCESS) {
                ehea_error("destroy_qp failed");
@@ -581,4 +582,45 @@ out:
        return ret;
 }
 
+void print_error_data(u64 *data)
+{
+       int length;
+       u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
+       u64 resource = data[1];
+
+       length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]);
+
+       if (length > EHEA_PAGESIZE)
+               length = EHEA_PAGESIZE;
+
+       if (type == 0x8) /* Queue Pair */
+               ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
+                          "port=%lX", resource, data[6], data[12], data[22]);
+
+       ehea_dump(data, length, "error data");
+}
+
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
+{
+       unsigned long ret;
+       u64 *rblock;
+
+       rblock = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!rblock) {
+               ehea_error("Cannot allocate rblock memory.");
+               return;
+       }
 
+       ret = ehea_h_error_data(adapter->handle,
+                               res_handle,
+                               rblock);
+
+       if (ret == H_R_STATE)
+               ehea_error("No error data is available: %lX.", res_handle);
+       else if (ret == H_SUCCESS)
+               print_error_data(rblock);
+       else
+               ehea_error("Error data could not be fetched: %lX", res_handle);
+
+       kfree(rblock);
+}
index 7efdc96919ca606a5920ff8aca7a95b909265484..1ff60983504d07385bed88e72dc3c7c65a3dd018 100644 (file)
@@ -180,6 +180,9 @@ struct ehea_eqe {
        u64 entry;
 };
 
+#define ERROR_DATA_LENGTH  EHEA_BMASK_IBM(52,63)
+#define ERROR_DATA_TYPE    EHEA_BMASK_IBM(0,7)
+
 static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset)
 {
        struct ehea_page *current_page;
@@ -355,4 +358,6 @@ int ehea_destroy_qp(struct ehea_qp *qp);
 
 int ehea_reg_mr_adapter(struct ehea_adapter *adapter);
 
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+
 #endif /* __EHEA_QMR_H__ */
index 790d9dbe42ddf127b4e9f6794d8b26cb60cdbb6c..e492eb84f94811bd8037bd56a3730441acf87e29 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index 8e7a56fadfd2b1e29ba0eed297338a36ec609c44..77f747a5afa71aaf5d964c26a89d792339e46faa 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index d3c16b85d9a41fa405b1f2da83ff144f08b521fd..e79700abf7b651aec8c87609cf13e42cf8dcdeaa 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index 889d3a13e95e4ef36ca3efedb35cc7fb3afdac37..4a05c14bf7ec3a4fda1504757e8bd15b62df7936 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index 1ff2597b8495b7fbd54d5a8d62a3ea11e7c1a623..8545e84fc9a07a1bdf370ed7df3a177bf2822131 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index ff6839477306fa15c14bee44f350551c888872b5..cdcfb96f360f3c81f30bc8babb3668e80da12de0 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index afd7fca7c6c419290b628bdc6a7cda98784f1e4c..65925b5a224f761afdb169762e376f7d4c3890a0 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index 0b9b8b5c847cee9597c31e4e9c3dfff9c54d5322..f91447837fd49a709b5f62f4911a42db8ccd89f4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index baaae3dbf2e6c2eb0d2931f8e18a0f4bb9c8f54e..235b177fb9acb1253efa7ce98aaf8bdeebaefaed 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
index baa35144134c8a1459a7d104bc6e74db6123f4aa..1f83988a6a640c3b40f882e48fef8e11669d32e1 100644 (file)
@@ -10,6 +10,7 @@
  * Maintainer: Kumar Gala
  *
  * Copyright (c) 2002-2006 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007 MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -65,7 +66,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -1613,71 +1613,17 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id)
        /* Save ievent for future reference */
        u32 events = gfar_read(&priv->regs->ievent);
 
-       /* Clear IEVENT */
-       gfar_write(&priv->regs->ievent, events);
-
        /* Check for reception */
-       if ((events & IEVENT_RXF0) || (events & IEVENT_RXB0))
+       if (events & IEVENT_RX_MASK)
                gfar_receive(irq, dev_id);
 
        /* Check for transmit completion */
-       if ((events & IEVENT_TXF) || (events & IEVENT_TXB))
+       if (events & IEVENT_TX_MASK)
                gfar_transmit(irq, dev_id);
 
-       /* Update error statistics */
-       if (events & IEVENT_TXE) {
-               priv->stats.tx_errors++;
-
-               if (events & IEVENT_LC)
-                       priv->stats.tx_window_errors++;
-               if (events & IEVENT_CRL)
-                       priv->stats.tx_aborted_errors++;
-               if (events & IEVENT_XFUN) {
-                       if (netif_msg_tx_err(priv))
-                               printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name);
-                       priv->stats.tx_dropped++;
-                       priv->extra_stats.tx_underrun++;
-
-                       /* Reactivate the Tx Queues */
-                       gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
-               }
-       }
-       if (events & IEVENT_BSY) {
-               priv->stats.rx_errors++;
-               priv->extra_stats.rx_bsy++;
-
-               gfar_receive(irq, dev_id);
-
-#ifndef CONFIG_GFAR_NAPI
-               /* Clear the halt bit in RSTAT */
-               gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
-#endif
-
-               if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
-                                       dev->name,
-                                       gfar_read(&priv->regs->rstat));
-       }
-       if (events & IEVENT_BABR) {
-               priv->stats.rx_errors++;
-               priv->extra_stats.rx_babr++;
-
-               if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: babbling error\n", dev->name);
-       }
-       if (events & IEVENT_EBERR) {
-               priv->extra_stats.eberr++;
-               if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: EBERR\n", dev->name);
-       }
-       if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv)))
-                       printk(KERN_DEBUG "%s: control frame\n", dev->name);
-
-       if (events & IEVENT_BABT) {
-               priv->extra_stats.tx_babt++;
-               if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: babt error\n", dev->name);
-       }
+       /* Check for errors */
+       if (events & IEVENT_ERR_MASK)
+               gfar_error(irq, dev_id);
 
        return IRQ_HANDLED;
 }
@@ -1939,7 +1885,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        /* Hmm... */
        if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
                printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
-                               dev->name, events, gfar_read(&priv->regs->imask));
+                      dev->name, events, gfar_read(&priv->regs->imask));
 
        /* Update the error counters */
        if (events & IEVENT_TXE) {
@@ -1951,8 +1897,8 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
                        priv->stats.tx_aborted_errors++;
                if (events & IEVENT_XFUN) {
                        if (netif_msg_tx_err(priv))
-                               printk(KERN_DEBUG "%s: underrun.  packet dropped.\n",
-                                               dev->name);
+                               printk(KERN_DEBUG "%s: TX FIFO underrun, "
+                                      "packet dropped.\n", dev->name);
                        priv->stats.tx_dropped++;
                        priv->extra_stats.tx_underrun++;
 
@@ -1974,30 +1920,28 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
 #endif
 
                if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
-                                       dev->name,
-                                       gfar_read(&priv->regs->rstat));
+                       printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
+                              dev->name, gfar_read(&priv->regs->rstat));
        }
        if (events & IEVENT_BABR) {
                priv->stats.rx_errors++;
                priv->extra_stats.rx_babr++;
 
                if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+                       printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
        }
        if (events & IEVENT_EBERR) {
                priv->extra_stats.eberr++;
                if (netif_msg_rx_err(priv))
-                       printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+                       printk(KERN_DEBUG "%s: bus error\n", dev->name);
        }
        if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
-               if (netif_msg_rx_status(priv))
-                       printk(KERN_DEBUG "%s: control frame\n", dev->name);
+               printk(KERN_DEBUG "%s: control frame\n", dev->name);
 
        if (events & IEVENT_BABT) {
                priv->extra_stats.tx_babt++;
                if (netif_msg_tx_err(priv))
-                       printk(KERN_DEBUG "%s: babt error\n", dev->name);
+                       printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
        }
        return IRQ_HANDLED;
 }
index 0d6943d6709638764e885400be50db4b283f1b49..7b411c1514db364c1c662d7abb3e90a4c8ea6356 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
index ff684d4be96d657797474046f6fec8843c9830c9..bcc6b82f4a33b6a9385ef66197a556fdf3b82149 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 9dd387fb3d741b1190b88191bc0eae5de92d483f..aec9ab17a9a5884df180ac4e26ec59b3ec82185c 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include "gianfar.h"
 
 #define GFAR_ATTR(_name) \
-static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \
-static ssize_t gfar_set_##_name(struct class_device *cdev, \
+static ssize_t gfar_show_##_name(struct device *dev, \
+        struct device_attribute *attr, char *buf); \
+static ssize_t gfar_set_##_name(struct device *dev, \
+               struct device_attribute *attr, \
                const char *buf, size_t count); \
-static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
+static DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
 
 #define GFAR_CREATE_FILE(_dev, _name) \
-       class_device_create_file(&_dev->class_dev, &class_device_attr_##_name)
+       device_create_file(&_dev->dev, &dev_attr_##_name)
 
 GFAR_ATTR(bd_stash);
 GFAR_ATTR(rx_stash_size);
@@ -54,29 +55,28 @@ GFAR_ATTR(fifo_threshold);
 GFAR_ATTR(fifo_starve);
 GFAR_ATTR(fifo_starve_off);
 
-#define to_net_dev(cd) container_of(cd, struct net_device, class_dev)
-
-static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_bd_stash(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
-       return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off");
+       return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
 }
 
-static ssize_t gfar_set_bd_stash(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_bd_stash(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        int new_setting = 0;
        u32 temp;
        unsigned long flags;
 
        /* Find out the new setting */
-       if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1))
+       if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
                new_setting = 1;
-       else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1))
+       else if (!strncmp("off", buf, count - 1)
+                || !strncmp("0", buf, count - 1))
                new_setting = 0;
        else
                return count;
@@ -100,19 +100,19 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
        return count;
 }
 
-static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_size(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
        return sprintf(buf, "%d\n", priv->rx_stash_size);
 }
 
-static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_size(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        unsigned int length = simple_strtoul(buf, NULL, 0);
        u32 temp;
        unsigned long flags;
@@ -146,21 +146,21 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
        return count;
 }
 
-
 /* Stashing will only be enabled when rx_stash_size != 0 */
-static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_index(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
        return sprintf(buf, "%d\n", priv->rx_stash_index);
 }
 
-static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_index(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        unsigned short index = simple_strtoul(buf, NULL, 0);
        u32 temp;
        unsigned long flags;
@@ -184,19 +184,20 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
        return count;
 }
 
-static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_threshold(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
        return sprintf(buf, "%d\n", priv->fifo_threshold);
 }
 
-static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_fifo_threshold(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        unsigned int length = simple_strtoul(buf, NULL, 0);
        u32 temp;
        unsigned long flags;
@@ -218,20 +219,19 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
        return count;
 }
 
-static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
        return sprintf(buf, "%d\n", priv->fifo_starve);
 }
 
-
-static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        unsigned int num = simple_strtoul(buf, NULL, 0);
        u32 temp;
        unsigned long flags;
@@ -253,19 +253,20 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
        return count;
 }
 
-static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve_off(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
        return sprintf(buf, "%d\n", priv->fifo_starve_off);
 }
 
-static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
-               const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve_off(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
 {
-       struct net_device *dev = to_net_dev(cdev);
-       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar_private *priv = netdev_priv(to_net_dev(dev));
        unsigned int num = simple_strtoul(buf, NULL, 0);
        u32 temp;
        unsigned long flags;
index feb0ada7a0257157cc1240e08767c6bcad6f51a1..6e90619b3b41d483cef4e12a51c9e1188cf29395 100644 (file)
@@ -138,7 +138,7 @@ config BAYCOM_SER_HDX
        ---help---
          This is one of two drivers for Baycom style simple amateur radio
          modems that connect to a serial interface. The driver supports the
-         ser12 design in full-duplex mode. This is the old driver.  It is
+         ser12 design in half-duplex mode. This is the old driver.  It is
          still provided in case your serial interface chip does not work with
          the full-duplex driver. This driver is depreciated.  To configure
          the driver, use the sethdlc utility available in the standard ax25
@@ -190,3 +190,4 @@ config YAM
          To compile this driver as a module, choose M here: the module
          will be called yam.
 
index ffeafb28f782036dff1255ce92fff70efbae68fb..dd8ad87468258152417592bcc4042e0f93434bc7 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
index f0d30cf67b5f6ba8b09746d72f41256ac09e93ba..4ad780719a848de644fb503a2f2e3f8dabfcb2dd 100644 (file)
@@ -836,13 +836,17 @@ static int ioc3_mii_init(struct ioc3_private *ip)
        }
 
        ip->mii.phy_id = i;
+
+out:
+       return res;
+}
+
+static void ioc3_mii_start(struct ioc3_private *ip)
+{
        ip->ioc3_timer.expires = jiffies + (12 * HZ)/10;  /* 1.2 sec. */
        ip->ioc3_timer.data = (unsigned long) ip;
        ip->ioc3_timer.function = &ioc3_timer;
        add_timer(&ip->ioc3_timer);
-
-out:
-       return res;
 }
 
 static inline void ioc3_clean_rx_ring(struct ioc3_private *ip)
@@ -1071,6 +1075,7 @@ static int ioc3_open(struct net_device *dev)
        ip->ehar_h = 0;
        ip->ehar_l = 0;
        ioc3_init(dev);
+       ioc3_mii_start(ip);
 
        netif_start_queue(dev);
        return 0;
@@ -1274,6 +1279,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_stop;
        }
 
+       ioc3_mii_start(ip);
        ioc3_ssram_disc(ip);
        ioc3_get_eaddr(ip);
 
@@ -1314,6 +1320,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 out_stop:
        ioc3_stop(ip);
+       del_timer_sync(&ip->ioc3_timer);
        ioc3_free_rings(ip);
 out_res:
        pci_release_regions(pdev);
@@ -1335,6 +1342,8 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev)
        struct ioc3 *ioc3 = ip->regs;
 
        unregister_netdev(dev);
+       del_timer_sync(&ip->ioc3_timer);
+
        iounmap(ioc3);
        pci_release_regions(pdev);
        free_netdev(dev);
@@ -1492,6 +1501,7 @@ static void ioc3_timeout(struct net_device *dev)
        ioc3_stop(ip);
        ioc3_init(dev);
        ioc3_mii_init(ip);
+       ioc3_mii_start(ip);
 
        spin_unlock_irq(&ip->ioc3_lock);
 
index ebed168b7da674125d6b63091defa12f58e21225..809906d94762ba2d11c1e0e855768cab1a515901 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <net/irda/irda.h>
 
index e67361e2bf5dc9f29ca7bbbd182c416cbc33bc85..2e9571bf0736391a6cf425039793c5443f6da52e 100644 (file)
@@ -881,27 +881,15 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct macb *bp = netdev_priv(dev);
-       int ret;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bp->lock, flags);
-       ret = mii_ethtool_gset(&bp->mii, cmd);
-       spin_unlock_irqrestore(&bp->lock, flags);
 
-       return ret;
+       return mii_ethtool_gset(&bp->mii, cmd);
 }
 
 static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct macb *bp = netdev_priv(dev);
-       int ret;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bp->lock, flags);
-       ret = mii_ethtool_sset(&bp->mii, cmd);
-       spin_unlock_irqrestore(&bp->lock, flags);
 
-       return ret;
+       return mii_ethtool_sset(&bp->mii, cmd);
 }
 
 static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -930,17 +918,11 @@ static struct ethtool_ops macb_ethtool_ops = {
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct macb *bp = netdev_priv(dev);
-       int ret;
-       unsigned long flags;
 
        if (!netif_running(dev))
                return -EINVAL;
 
-       spin_lock_irqsave(&bp->lock, flags);
-       ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
-       spin_unlock_irqrestore(&bp->lock, flags);
-
-       return ret;
+       return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
 }
 
 static ssize_t macb_mii_show(const struct device *_dev, char *buf,
@@ -1077,7 +1059,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
        }
 
        dev->irq = platform_get_irq(pdev, 0);
-       err = request_irq(dev->irq, macb_interrupt, SA_SAMPLE_RANDOM,
+       err = request_irq(dev->irq, macb_interrupt, IRQF_SAMPLE_RANDOM,
                          dev->name, dev);
        if (err) {
                printk(KERN_ERR
index e1d97cdf649eeb6a8d9ac4167dfb0bd4f7dda0da..7e69ca6edd91a0a443c4f9f1349d9381ed0f4eb1 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h> /* printk() */
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -171,7 +170,7 @@ static int mdio_probe(struct meth_private *priv)
 
 static void meth_check_link(struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long mii_advertising = mdio_read(priv, 4);
        unsigned long mii_partner = mdio_read(priv, 5);
        unsigned long negotiated = mii_advertising & mii_partner;
@@ -269,7 +268,7 @@ static void meth_free_rx_ring(struct meth_private *priv)
 
 int meth_reset(struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
 
        /* Reset card */
        mace->eth.mac_ctrl = SGI_MAC_RESET;
@@ -311,7 +310,7 @@ int meth_reset(struct net_device *dev)
  */
 static int meth_open(struct net_device *dev)
 {
-       struct meth_private *priv = dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        int ret;
 
        priv->phy_addr = -1;    /* No PHY is known yet... */
@@ -355,7 +354,7 @@ out_free_tx_ring:
 
 static int meth_release(struct net_device *dev)
 {
-       struct meth_private *priv = dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
 
        DPRINTK("Stopping queue\n");
        netif_stop_queue(dev); /* can't transmit any more */
@@ -377,7 +376,7 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
 {
        struct sk_buff *skb;
        unsigned long status;
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long fifo_rptr = (int_status & METH_INT_RX_RPTR_MASK) >> 8;
 
        spin_lock(&priv->meth_lock);
@@ -467,14 +466,14 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
 
 static int meth_tx_full(struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
 
        return (priv->tx_count >= TX_RING_ENTRIES - 1);
 }
 
 static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
 {
-       struct meth_private *priv = dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long status;
        struct sk_buff *skb;
        unsigned long rptr = (int_status&TX_INFO_RPTR) >> 16;
@@ -537,7 +536,7 @@ static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
 
 static void meth_error(struct net_device* dev, unsigned status)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
 
        printk(KERN_WARNING "meth: error status: 0x%08x\n",status);
        /* check for errors too... */
@@ -571,7 +570,7 @@ static void meth_error(struct net_device* dev, unsigned status)
 static irqreturn_t meth_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *)dev_id;
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long status;
 
        status = mace->eth.int_stat;
@@ -696,7 +695,7 @@ static void meth_add_to_tx_ring(struct meth_private *priv, struct sk_buff *skb)
  */
 static int meth_tx(struct sk_buff *skb, struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long flags;
 
        spin_lock_irqsave(&priv->meth_lock, flags);
@@ -727,7 +726,7 @@ static int meth_tx(struct sk_buff *skb, struct net_device *dev)
  */
 static void meth_tx_timeout(struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        unsigned long flags;
 
        printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
@@ -779,7 +778,7 @@ static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  */
 static struct net_device_stats *meth_stats(struct net_device *dev)
 {
-       struct meth_private *priv = (struct meth_private *) dev->priv;
+       struct meth_private *priv = netdev_priv(dev);
        return &priv->stats;
 }
 
@@ -808,7 +807,7 @@ static struct net_device *meth_init(void)
        dev->irq             = MACE_ETHERNET_IRQ;
        dev->base_addr       = (unsigned long)&mace->eth;
 
-       priv = (struct meth_private *) dev->priv;
+       priv = netdev_priv(dev);
        spin_lock_init(&priv->meth_lock);
 
        ret = register_netdev(dev);
index c9469985bd713b61e4fc6d987aed10ec3bf51d34..f42b9e201937928d156159419d2fd06320083954 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
 #include <linux/platform_device.h>
index 3f3896e988790ab9a5484c6f267902bc56f03612..2807ef400fb583ecdb5c248e8cc05b2330ec3fff 100644 (file)
@@ -252,7 +252,7 @@ typedef u32 netxen_ctx_msg;
 #define netxen_set_msg_ctxid(config_word, val) \
        ((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
 #define netxen_set_msg_opcode(config_word, val)        \
-       ((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
+       ((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
 
 struct netxen_rcv_context {
        __le64 rcv_ring_addr;
@@ -303,14 +303,14 @@ struct netxen_ring_ctx {
        (cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
 #define netxen_set_cmd_desc_opcode(cmd_desc, val)      \
        ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
-       (cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
+       (cmd_desc)->flags_opcode |= cpu_to_le16(((val & 0x3f)<<7)))
 
 #define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
        ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
        (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
 #define netxen_set_cmd_desc_totallength(cmd_desc, val) \
-       ((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
-       (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
+       ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xffffff00), \
+       (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 8))
 
 #define netxen_get_cmd_desc_opcode(cmd_desc)   \
        ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
@@ -1040,6 +1040,7 @@ int netxen_flash_unlock(struct netxen_adapter *adapter);
 int netxen_backup_crbinit(struct netxen_adapter *adapter);
 int netxen_flash_erase_secondary(struct netxen_adapter *adapter);
 int netxen_flash_erase_primary(struct netxen_adapter *adapter);
+void netxen_halt_pegs(struct netxen_adapter *adapter);
 
 int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data);
 int netxen_rom_se(struct netxen_adapter *adapter, int addr);
index cc0efe213e01f84b95af13e4bbf81dceb3c02a47..6252e9a8727854719cf2323fe5f5f61a867ea54f 100644 (file)
@@ -402,7 +402,7 @@ netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        wol->wolopts = 0;
 }
 
-static u32 netxen_nic_get_link(struct net_device *dev)
+static u32 netxen_nic_test_link(struct net_device *dev)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
@@ -459,6 +459,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        int ret;
 
        if (flash_start == 0) {
+               netxen_halt_pegs(adapter);
                ret = netxen_flash_unlock(adapter);
                if (ret < 0) {
                        printk(KERN_ERR "%s: Flash unlock failed.\n",
@@ -712,7 +713,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 {
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {   /* offline tests */
                /* link test */
-               if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+               if (!(data[4] = (u64) netxen_nic_test_link(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
                if (netif_running(dev))
@@ -727,7 +728,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
                        dev->open(dev);
        } else {                /* online tests */
                /* link test */
-               if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+               if (!(data[4] = (u64) netxen_nic_test_link(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
                /* other tests pass by default */
@@ -783,7 +784,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
        .get_regs_len = netxen_nic_get_regs_len,
        .get_regs = netxen_nic_get_regs,
        .get_wol = netxen_nic_get_wol,
-       .get_link = netxen_nic_get_link,
+       .get_link = ethtool_op_get_link,
        .get_eeprom_len = netxen_nic_get_eeprom_len,
        .get_eeprom = netxen_nic_get_eeprom,
        .set_eeprom = netxen_nic_set_eeprom,
index f263232f499fdc56fc7cc0837bc4783d12d62c0f..7195af3e8f3ddb1182d5b81d1debe33adc44be1c 100644 (file)
@@ -420,6 +420,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
        for (i = 0; i < size / sizeof(u32); i++) {
                if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
                        return -1;
+               *ptr32 = cpu_to_le32(*ptr32);
                ptr32++;
                addr += sizeof(u32);
        }
@@ -428,6 +429,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
 
                if (netxen_rom_fast_read(adapter, addr, &local) == -1)
                        return -1;
+               local = cpu_to_le32(local);
                memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
        }
 
index f7bb8c90537cd9880603b0abd41ae24907fb2c1c..2f324366784d9e9a3509dddb56bb1864d423e6ba 100644 (file)
@@ -717,6 +717,14 @@ netxen_flash_erase_primary(struct netxen_adapter *adapter)
        return ret;
 }
 
+void netxen_halt_pegs(struct netxen_adapter *adapter)
+{
+        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1);
+        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1);
+        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1);
+        netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1);
+}
+
 int netxen_flash_unlock(struct netxen_adapter *adapter)
 {
        int ret = 0;
@@ -1246,7 +1254,7 @@ int netxen_process_cmd_ring(unsigned long data)
         * the netdev which is associated with that device.
         */
 
-       consumer = *(adapter->cmd_consumer);
+       consumer = le32_to_cpu(*(adapter->cmd_consumer));
        if (last_consumer == consumer) {        /* Ring is empty    */
                DPRINTK(INFO, "last_consumer %d == consumer %d\n",
                        last_consumer, consumer);
@@ -1340,7 +1348,7 @@ int netxen_process_cmd_ring(unsigned long data)
        if (adapter->last_cmd_consumer == consumer &&
            (((adapter->cmd_producer + 1) %
              adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
-               consumer = *(adapter->cmd_consumer);
+               consumer = le32_to_cpu(*(adapter->cmd_consumer));
        }
        done = (adapter->last_cmd_consumer == consumer);
 
index 69c1b9d23a1aecaa99d2b6d752f9d5c1cf9e749c..225ff55527c447f1e0955eac185cec895e951548 100644 (file)
@@ -434,12 +434,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->port_count++;
                adapter->port[i] = port;
        }
-
+#ifndef CONFIG_PPC64
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
        netxen_pinit_from_rom(adapter, 0);
        udelay(500);
        netxen_load_firmware(adapter);
        netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+#endif
        /*
         * delay a while to ensure that the Pegs are up & running.
         * Otherwise, we might see some flaky behaviour.
@@ -619,8 +620,8 @@ static int netxen_nic_open(struct net_device *netdev)
                }
                adapter->irq = adapter->ahw.pdev->irq;
                err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
-                                 adapter);
+                                 IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+                                 netdev->name, adapter);
                if (err) {
                        printk(KERN_ERR "request_irq failed with: %d\n", err);
                        netxen_free_hw_resources(adapter);
index 40d7003a371caf4d06dd9d0cd91aa84ce1845bc7..d5d95074e56942a93a171671de337e36b6e9ce5c 100644 (file)
@@ -458,7 +458,7 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
-       long reg = 0, ret = 0;
+       u32 reg = 0, ret = 0;
 
        if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
                netxen_crb_writelit_adapter(adapter,
index 448bf4a780163751bc154d543b7289e1d50dcf67..c7bd9c1c7f31a0aeed77ff659ee2c6d81151e736 100644 (file)
@@ -915,7 +915,7 @@ static void media_check(unsigned long arg)
        if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
                if (!lp->fast_poll)
                        printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-               el3_interrupt(dev->irq, lp);
+               el3_interrupt(dev->irq, dev);
                lp->fast_poll = HZ;
        }
        if (lp->fast_poll) {
index 530df8883fe5a207a7d6465604ad11ce7327e1b5..2561f76033eab60ec944dd04f06a8d22f2d3b7d7 100644 (file)
@@ -1927,7 +1927,7 @@ static void media_check(u_long arg)
     if (smc->watchdog++ && ((i>>8) & i)) {
        if (!smc->fast_poll)
            printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-       smc_interrupt(dev->irq, smc);
+       smc_interrupt(dev->irq, dev);
        smc->fast_poll = HZ;
     }
     if (smc->fast_poll) {
index ae60e6e4107c09b502c3c111617add99c2f90d32..a1bd599c8a5b5014c1465cd4e7f56be3701567a5 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index aa7983f55838b5c844cebccb6f4a8bb5bfe4257f..519baa38be8dcf767eac87b6f19843ef4ae21e52 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 86135397f430b089b1abb0a1dd696fa4bc64e2a3..66da91bb1388945bac1d2c0c259bf3616a6b1e4d 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 69d2325f848c7ee55690f3dc7074cd7bd9142726..4cf3324ba166405ef45a86f4161cc97ac16802fb 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 0ad253282d0d0c8388503efcf7d7e6e9304fbb60..22aec5cce68310ab6e4128b2ec30435fcff5c375 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #define MII_M1011_IMASK_INIT           0x6400
 #define MII_M1011_IMASK_CLEAR          0x0000
 
+#define MII_M1011_PHY_SCR              0x10
+#define MII_M1011_PHY_SCR_AUTO_CROSS   0x0060
+
+#define MII_M1145_PHY_EXT_CR           0x14
+#define MII_M1145_RGMII_RX_DELAY       0x0080
+#define MII_M1145_RGMII_TX_DELAY       0x0002
+
+#define M1145_DEV_FLAGS_RESISTANCE     0x00000001
+
+#define MII_M1111_PHY_LED_CONTROL      0x18
+#define MII_M1111_PHY_LED_DIRECT       0x4100
+#define MII_M1111_PHY_LED_COMBINE      0x411c
+
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
 MODULE_LICENSE("GPL");
@@ -64,7 +76,7 @@ static int marvell_config_intr(struct phy_device *phydev)
 {
        int err;
 
-       if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
        else
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
@@ -104,34 +116,153 @@ static int marvell_config_aneg(struct phy_device *phydev)
        if (err < 0)
                return err;
 
+       err = phy_write(phydev, MII_M1011_PHY_SCR,
+                       MII_M1011_PHY_SCR_AUTO_CROSS);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
+                       MII_M1111_PHY_LED_DIRECT);
+       if (err < 0)
+               return err;
 
        err = genphy_config_aneg(phydev);
 
        return err;
 }
 
+static int m88e1145_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       /* Take care of errata E0 & E1 */
+       err = phy_write(phydev, 0x1d, 0x001b);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0x418f);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1d, 0x0016);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0xa2da);
+       if (err < 0)
+               return err;
+
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+               int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
+               if (temp < 0)
+                       return temp;
+
+               temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
+
+               err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
+               if (err < 0)
+                       return err;
+
+               if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
+                       err = phy_write(phydev, 0x1d, 0x0012);
+                       if (err < 0)
+                               return err;
+
+                       temp = phy_read(phydev, 0x1e);
+                       if (temp < 0)
+                               return temp;
+
+                       temp &= 0xf03f;
+                       temp |= 2 << 9; /* 36 ohm */
+                       temp |= 2 << 6; /* 39 ohm */
+
+                       err = phy_write(phydev, 0x1e, temp);
+                       if (err < 0)
+                               return err;
+
+                       err = phy_write(phydev, 0x1d, 0x3);
+                       if (err < 0)
+                               return err;
+
+                       err = phy_write(phydev, 0x1e, 0x8000);
+                       if (err < 0)
+                               return err;
+               }
+       }
+
+       return 0;
+}
 
 static struct phy_driver m88e1101_driver = {
-       .phy_id         = 0x01410c00,
-       .phy_id_mask    = 0xffffff00,
-       .name           = "Marvell 88E1101",
-       .features       = PHY_GBIT_FEATURES,
-       .flags          = PHY_HAS_INTERRUPT,
-       .config_aneg    = &marvell_config_aneg,
-       .read_status    = &genphy_read_status,
-       .ack_interrupt  = &marvell_ack_interrupt,
-       .config_intr    = &marvell_config_intr,
-       .driver         = { .owner = THIS_MODULE,},
+       .phy_id = 0x01410c60,
+       .phy_id_mask = 0xfffffff0,
+       .name = "Marvell 88E1101",
+       .features = PHY_GBIT_FEATURES,
+       .flags = PHY_HAS_INTERRUPT,
+       .config_aneg = &marvell_config_aneg,
+       .read_status = &genphy_read_status,
+       .ack_interrupt = &marvell_ack_interrupt,
+       .config_intr = &marvell_config_intr,
+       .driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1111s_driver = {
+       .phy_id = 0x01410cc0,
+       .phy_id_mask = 0xfffffff0,
+       .name = "Marvell 88E1111",
+       .features = PHY_GBIT_FEATURES,
+       .flags = PHY_HAS_INTERRUPT,
+       .config_aneg = &marvell_config_aneg,
+       .read_status = &genphy_read_status,
+       .ack_interrupt = &marvell_ack_interrupt,
+       .config_intr = &marvell_config_intr,
+       .driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1145_driver = {
+       .phy_id = 0x01410cd0,
+       .phy_id_mask = 0xfffffff0,
+       .name = "Marvell 88E1145",
+       .features = PHY_GBIT_FEATURES,
+       .flags = PHY_HAS_INTERRUPT,
+       .config_init = &m88e1145_config_init,
+       .config_aneg = &marvell_config_aneg,
+       .read_status = &genphy_read_status,
+       .ack_interrupt = &marvell_ack_interrupt,
+       .config_intr = &marvell_config_intr,
+       .driver = {.owner = THIS_MODULE,},
 };
 
 static int __init marvell_init(void)
 {
-       return phy_driver_register(&m88e1101_driver);
+       int ret;
+
+       ret = phy_driver_register(&m88e1101_driver);
+       if (ret)
+               return ret;
+
+       ret = phy_driver_register(&m88e1111s_driver);
+       if (ret)
+               goto err1111s;
+
+       ret = phy_driver_register(&m88e1145_driver);
+       if (ret)
+               goto err1145;
+
+       return 0;
+
+      err1145:
+       phy_driver_unregister(&m88e1111s_driver);
+      err1111s:
+       phy_driver_unregister(&m88e1101_driver);
+       return ret;
 }
 
 static void __exit marvell_exit(void)
 {
        phy_driver_unregister(&m88e1101_driver);
+       phy_driver_unregister(&m88e1111s_driver);
+       phy_driver_unregister(&m88e1145_driver);
 }
 
 module_init(marvell_init);
index cf6660c93ffa57aeca305f53abe0a500ca38a0f4..b31ce278bf35be071e6aa5cbbfe528c36086c00f 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 9765fa6614676d1d62009cf38342e0969136b755..c94a1fb3a4bee56bcb9bf9d8235b3453cfce7195 100644 (file)
@@ -16,7 +16,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index a4d7529ef41515d464282c883fe6c191b8b4366d..7d5b6d1838c8ddc56563ec0aba05aed388778e0e 100644 (file)
@@ -15,7 +15,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -139,7 +138,7 @@ void phy_prepare_link(struct phy_device *phydev,
  */
 struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
                void (*handler)(struct net_device *), u32 flags,
-               u32 interface)
+               phy_interface_t interface)
 {
        struct phy_device *phydev;
 
@@ -188,7 +187,7 @@ static int phy_compare_id(struct device *dev, void *data)
 }
 
 struct phy_device *phy_attach(struct net_device *dev,
-               const char *phy_id, u32 flags, u32 interface)
+               const char *phy_id, u32 flags, phy_interface_t interface)
 {
        struct bus_type *bus = &mdio_bus_type;
        struct phy_device *phydev;
index 2b50e1739aa54deaa3ebae7105d3ea866769b377..23062d0672314a3e5a9fb8d130cab45e43acc824 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 2429b274f0b0dd5ae6d4355bac15d777741be051..a142cdfd947b961f0420ce74a0339de272c5b8b0 100755 (executable)
@@ -3228,7 +3228,7 @@ static int ql_adapter_up(struct ql3_adapter *qdev)
 {
        struct net_device *ndev = qdev->ndev;
        int err;
-       unsigned long irq_flags = SA_SAMPLE_RANDOM | SA_SHIRQ;
+       unsigned long irq_flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
        unsigned long hw_flags;
 
        if (ql_alloc_mem_resources(qdev)) {
@@ -3247,7 +3247,7 @@ static int ql_adapter_up(struct ql3_adapter *qdev)
                } else {
                        printk(KERN_INFO PFX "%s: MSI Enabled...\n", qdev->ndev->name);
                        set_bit(QL_MSI_ENABLED,&qdev->flags);
-                       irq_flags &= ~SA_SHIRQ;
+                       irq_flags &= ~IRQF_SHARED;
                }
        }
 
index 8646b64994abadee6b2e38bcf0b7fe4209d1d6da..e8e0d94e9bddfa9c1935b7752f8daa303e5387d7 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/stddef.h>
 #include <linux/ioctl.h>
 #include <linux/timex.h>
-#include <linux/sched.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
index 7f800feaa9a2efb9ec81fd447dcbc443ed85aa9c..4a926f20b6ea9e8603e1f5d5967a937f402da406 100644 (file)
@@ -1035,7 +1035,7 @@ static int sc92031_open(struct net_device *dev)
        priv->tx_head = priv->tx_tail = 0;
 
        err = request_irq(pdev->irq, sc92031_interrupt,
-                       SA_SHIRQ, dev->name, dev);
+                       IRQF_SHARED, dev->name, dev);
        if (unlikely(err < 0))
                goto out_request_irq;
 
index 92d11b961db88bd81133ce89eb7fec03365f1f40..e94ab256b5406afc5b4a80559e880c5680b54bc6 100644 (file)
@@ -5188,6 +5188,9 @@ static struct pci_driver skge_driver = {
 
 static int __init skge_init(void)
 {
+       printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
+              " and is scheduled for removal\n");
+
        return pci_register_driver(&skge_driver);
 }
 
index f2ab3d56e5653663040190dd91dcdfbc3e38ed70..52edbd7ac17e6a134e2af1ca4fe3abd9e42c46ac 100644 (file)
@@ -49,7 +49,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.12"
+#define DRV_VERSION            "1.13"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -1742,13 +1742,6 @@ static void sky2_link_down(struct sky2_port *sky2)
        reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
        gma_write16(hw, port, GM_GP_CTRL, reg);
 
-       if (sky2->flow_status == FC_RX) {
-               /* restore Asymmetric Pause bit */
-               gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
-                            gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
-                            | PHY_M_AN_ASP);
-       }
-
        netif_carrier_off(sky2->netdev);
        netif_stop_queue(sky2->netdev);
 
@@ -1773,10 +1766,10 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
 {
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u16 lpa;
+       u16 advert, lpa;
 
+       advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
        lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
-
        if (lpa & PHY_M_AN_RF) {
                printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
                return -1;
@@ -1791,20 +1784,40 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
        sky2->speed = sky2_phy_speed(hw, aux);
        sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
 
-       /* Pause bits are offset (9..8) */
-       if (hw->chip_id == CHIP_ID_YUKON_XL
-           || hw->chip_id == CHIP_ID_YUKON_EC_U
-           || hw->chip_id == CHIP_ID_YUKON_EX)
-               aux >>= 6;
-
-       sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
-                                     aux & PHY_M_PS_TX_P_EN);
+       /* Since the pause result bits seem to in different positions on
+        * different chips. look at registers.
+        */
+       if (!sky2_is_copper(hw)) {
+               /* Shift for bits in fiber PHY */
+               advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
+               lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
+
+               if (advert & ADVERTISE_1000XPAUSE)
+                       advert |= ADVERTISE_PAUSE_CAP;
+               if (advert & ADVERTISE_1000XPSE_ASYM)
+                       advert |= ADVERTISE_PAUSE_ASYM;
+               if (lpa & LPA_1000XPAUSE)
+                       lpa |= LPA_PAUSE_CAP;
+               if (lpa & LPA_1000XPAUSE_ASYM)
+                       lpa |= LPA_PAUSE_ASYM;
+       }
+
+       sky2->flow_status = FC_NONE;
+       if (advert & ADVERTISE_PAUSE_CAP) {
+               if (lpa & LPA_PAUSE_CAP)
+                       sky2->flow_status = FC_BOTH;
+               else if (advert & ADVERTISE_PAUSE_ASYM)
+                       sky2->flow_status = FC_RX;
+       } else if (advert & ADVERTISE_PAUSE_ASYM) {
+               if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
+                       sky2->flow_status = FC_TX;
+       }
 
        if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
            && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
                sky2->flow_status = FC_NONE;
 
-       if (aux & PHY_M_PS_RX_P_EN)
+       if (sky2->flow_status & FC_TX)
                sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
        else
                sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1853,16 +1866,13 @@ out:
        spin_unlock(&sky2->phy_lock);
 }
 
-
 /* Transmit timeout is only called if we are running, carrier is up
  * and tx queue is full (stopped).
- * Called with netif_tx_lock held.
  */
 static void sky2_tx_timeout(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
-       u32 imask;
 
        if (netif_msg_timer(sky2))
                printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
@@ -1872,19 +1882,8 @@ static void sky2_tx_timeout(struct net_device *dev)
               sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
               sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
 
-       imask = sky2_read32(hw, B0_IMSK);       /* block IRQ in hw */
-       sky2_write32(hw, B0_IMSK, 0);
-       sky2_read32(hw, B0_IMSK);
-
-       netif_poll_disable(hw->dev[0]);         /* stop NAPI poll */
-       synchronize_irq(hw->pdev->irq);
-
-       netif_start_queue(dev);                 /* don't wakeup during flush */
-       sky2_tx_complete(sky2, sky2->tx_prod);  /* Flush transmit queue */
-
-       sky2_write32(hw, B0_IMSK, imask);
-
-       sky2_phy_reinit(sky2);                  /* this clears flow control etc */
+       /* can't restart safely under softirq */
+       schedule_work(&hw->restart_work);
 }
 
 static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2057,9 +2056,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        if (!(status & GMR_FS_RX_OK))
                goto resubmit;
 
-       if (length > dev->mtu + ETH_HLEN)
-               goto oversize;
-
        if (length < copybreak)
                skb = receive_copy(sky2, re, length);
        else
@@ -2069,14 +2065,10 @@ resubmit:
 
        return skb;
 
-oversize:
-       ++sky2->net_stats.rx_over_errors;
-       goto resubmit;
-
 error:
        ++sky2->net_stats.rx_errors;
        if (status & GMR_FS_RX_FF_OV) {
-               sky2->net_stats.rx_fifo_errors++;
+               sky2->net_stats.rx_over_errors++;
                goto resubmit;
        }
 
@@ -2638,6 +2630,49 @@ static void sky2_reset(struct sky2_hw *hw)
        sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
 }
 
+static void sky2_restart(struct work_struct *work)
+{
+       struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
+       struct net_device *dev;
+       int i, err;
+
+       dev_dbg(&hw->pdev->dev, "restarting\n");
+
+       del_timer_sync(&hw->idle_timer);
+
+       rtnl_lock();
+       sky2_write32(hw, B0_IMSK, 0);
+       sky2_read32(hw, B0_IMSK);
+
+       netif_poll_disable(hw->dev[0]);
+
+       for (i = 0; i < hw->ports; i++) {
+               dev = hw->dev[i];
+               if (netif_running(dev))
+                       sky2_down(dev);
+       }
+
+       sky2_reset(hw);
+       sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+       netif_poll_enable(hw->dev[0]);
+
+       for (i = 0; i < hw->ports; i++) {
+               dev = hw->dev[i];
+               if (netif_running(dev)) {
+                       err = sky2_up(dev);
+                       if (err) {
+                               printk(KERN_INFO PFX "%s: could not restart %d\n",
+                                      dev->name, err);
+                               dev_close(dev);
+                       }
+               }
+       }
+
+       sky2_idle_start(hw);
+
+       rtnl_unlock();
+}
+
 static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
 {
        return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
@@ -3600,6 +3635,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        }
 
        setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+       INIT_WORK(&hw->restart_work, sky2_restart);
+
        sky2_idle_start(hw);
 
        pci_set_drvdata(pdev, hw);
@@ -3636,6 +3673,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
 
        del_timer_sync(&hw->idle_timer);
 
+       flush_scheduled_work();
+
        sky2_write32(hw, B0_IMSK, 0);
        synchronize_irq(hw->pdev->irq);
 
index 3b0189569d525dce17eeac1d2cfdc826113713fc..ac24bdc429761da6f584259b5ef4f4f6337c571f 100644 (file)
@@ -1589,7 +1589,7 @@ enum {
 
        GMR_FS_ANY_ERR  = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
                          GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
-                         GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC |
+                         GMR_FS_MII_ERR | GMR_FS_BAD_FC |
                          GMR_FS_UN_SIZE | GMR_FS_JABBER,
 };
 
@@ -1933,6 +1933,7 @@ struct sky2_hw {
        dma_addr_t           st_dma;
 
        struct timer_list    idle_timer;
+       struct work_struct   restart_work;
        int                  msi;
        wait_queue_head_t    msi_wait;
 };
index d21991ee88c492fc5899ff449e038a8dc68f9d1d..701ba4f3b69d865a87a51ae9eebf8698d6c91edc 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 893808ab3742ed86ac818b6336399d256d2a75c5..d92c5c597e16261d6acc97bbe9d87872552ef135 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
index 31c97a6591a44cdc3b10b3f5f5ac0fb7f3f500e9..a2fc2bbcf97f71c623baab814250d61463d7a95a 100644 (file)
@@ -3939,8 +3939,8 @@ static void ugeth_phy_startup_timer(unsigned long data)
        /* Grab the PHY interrupt, if necessary/possible */
        if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
                if (request_irq(ugeth->ug_info->phy_interrupt,
-                               phy_interrupt,
-                               SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) {
+                               phy_interrupt, IRQF_SHARED,
+                               "phy_interrupt", mii_info->dev) < 0) {
                        ugeth_err("%s: Can't get IRQ %d (PHY)",
                                  mii_info->dev->name,
                                  ugeth->ug_info->phy_interrupt);
index 6fda6d88be499d1ce0e79ccc98eb0818f8f713dd..9373d895b9ec5926d67b4d7c180eec34432cb95b 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
index 61708cf4c85df29fe27829d27483f69cd24ccfe5..8897f538a7c788f6c2b7a7a65f7f7414e12ab6be 100644 (file)
@@ -26,7 +26,7 @@ config WAN
 # There is no way to detect a comtrol sv11 - force it modular for now.
 config HOSTESS_SV11
        tristate "Comtrol Hostess SV-11 support"
-       depends on WAN && ISA && m && ISA_DMA_API
+       depends on WAN && ISA && m && ISA_DMA_API && INET
        help
          Driver for Comtrol Hostess SV-11 network card which
          operates on low speed synchronous serial links at up to
index e6d005726aadea2875fca2e747cee73aaa9225db..d347d59db656057cffdc3c27260d8866188374be 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
-#include <linux/sched.h>       /* for jiffies, HZ, etc. */
 #include <linux/cycx_drv.h>    /* API definitions */
 #include <linux/cycx_cfm.h>    /* CYCX firmware module definitions */
 #include <linux/delay.h>       /* udelay, msleep_interruptible */
index bc156b51678ac18bf3225d3b817ac773793f689d..aff05dba720ab023983212dba42172ca65b9d53f 100644 (file)
@@ -542,7 +542,7 @@ static int __init pc300_init_module(void)
 
        CLOCK_BASE = use_crystal_clock ? 24576000 : pci_clock_freq;
 
-       return pci_module_init(&pc300_pci_driver);
+       return pci_register_driver(&pc300_pci_driver);
 }
 
 
index a6b9c33b68e45b91bb502ad043fbe220467adf84..ca06a00d9d864967c604c1582a346d80d512b367 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
index 5fa985435ffa2f9f56d1aed7019fab856e49c841..015abd928ab0b156ad49562b6107810e32f774b8 100644 (file)
@@ -1216,7 +1216,7 @@ static ctl_table arlan_table[MAX_ARLANS + 1] =
 static ctl_table arlan_root_table[] =
 {
        {
-               .ctl_name       = 254,
+               .ctl_name       = CTL_ARLAN,
                .procname       = "arlan",
                .maxlen         = 0,
                .mode           = 0555,
@@ -1244,7 +1244,7 @@ int __init init_arlan_proc(void)
                return 0;
        for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++)
                arlan_table[i].ctl_name = i + 1;
-       arlan_device_sysctl_header = register_sysctl_table(arlan_root_table, 0);
+       arlan_device_sysctl_header = register_sysctl_table(arlan_root_table);
        if (!arlan_device_sysctl_header)
                return -1;
 
index 10bcb48e80d0e8635c3e90493a66934966e525ae..23eba698aec545fb45408aab1b49586fd1c776a8 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/init.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 3a064def162e70d7e37547b1e3c97a9b6bc74b33..0e790efae683cfdbe2e17e204ad7667af56871ed 100644 (file)
@@ -771,6 +771,7 @@ struct bcm43xx_private {
         * This is currently always BCM43xx_BUSTYPE_PCI
         */
        u8 bustype;
+       u64 dma_mask;
 
        u16 board_vendor;
        u16 board_type;
index 978ed099e2852e45fa20c08a3bebf2011b927a0e..6e0dc76400e5e309a331d62e7620ed63afac49dd 100644 (file)
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
                          int tx)
 {
        dma_addr_t dmaaddr;
+       int direction = PCI_DMA_FROMDEVICE;
 
-       if (tx) {
-               dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-                                        buf, len,
-                                        DMA_TO_DEVICE);
-       } else {
-               dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+       if (tx)
+               direction = PCI_DMA_TODEVICE;
+
+       dmaaddr = pci_map_single(ring->bcm->pci_dev,
                                         buf, len,
-                                        DMA_FROM_DEVICE);
-       }
+                                        direction);
 
        return dmaaddr;
 }
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dmaring *ring,
                      int tx)
 {
        if (tx) {
-               dma_unmap_single(&ring->bcm->pci_dev->dev,
+               pci_unmap_single(ring->bcm->pci_dev,
                                 addr, len,
-                                DMA_TO_DEVICE);
+                                PCI_DMA_TODEVICE);
        } else {
-               dma_unmap_single(&ring->bcm->pci_dev->dev,
+               pci_unmap_single(ring->bcm->pci_dev,
                                 addr, len,
-                                DMA_FROM_DEVICE);
+                                PCI_DMA_FROMDEVICE);
        }
 }
 
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
 {
        assert(!ring->tx);
 
-       dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-                               addr, len, DMA_FROM_DEVICE);
+       pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+                                   addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
 {
        assert(!ring->tx);
 
-       dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-                                  addr, len, DMA_FROM_DEVICE);
+       pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+                                   addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-       struct device *dev = &(ring->bcm->pci_dev->dev);
-
-       ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-                                           &(ring->dmabase), GFP_KERNEL);
+       ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+                                           &(ring->dmabase));
        if (!ring->descbase) {
-               printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-               return -ENOMEM;
+               /* Allocation may have failed due to pci_alloc_consistent
+                  insisting on use of GFP_DMA, which is more restrictive
+                  than necessary...  */
+               struct dma_desc *rx_ring;
+               dma_addr_t rx_ring_dma;
+
+               rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+               if (!rx_ring)
+                       goto out_err;
+
+               rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+                                            BCM43xx_DMA_RINGMEMSIZE,
+                                            PCI_DMA_BIDIRECTIONAL);
+
+               if (pci_dma_mapping_error(rx_ring_dma) ||
+                   rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+                       /* Sigh... */
+                       if (!pci_dma_mapping_error(rx_ring_dma))
+                               pci_unmap_single(ring->bcm->pci_dev,
+                                                rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+                                                PCI_DMA_BIDIRECTIONAL);
+                       rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+                                                rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+                                                PCI_DMA_BIDIRECTIONAL);
+                       if (pci_dma_mapping_error(rx_ring_dma) ||
+                           rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+                               assert(0);
+                               if (!pci_dma_mapping_error(rx_ring_dma))
+                                       pci_unmap_single(ring->bcm->pci_dev,
+                                                        rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+                                                        PCI_DMA_BIDIRECTIONAL);
+                               goto out_err;
+                       }
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
        }
        memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
        return 0;
+out_err:
+       printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+       return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
        if (unlikely(!skb))
                return -ENOMEM;
        dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+       /* This hardware bug work-around adapted from the b44 driver.
+          The chip may be unable to do PCI DMA to/from anything above 1GB */
+       if (pci_dma_mapping_error(dmaaddr) ||
+           dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+               /* This one has 30-bit addressing... */
+               if (!pci_dma_mapping_error(dmaaddr))
+                       pci_unmap_single(ring->bcm->pci_dev,
+                                        dmaaddr, ring->rx_buffersize,
+                                        PCI_DMA_FROMDEVICE);
+               dev_kfree_skb_any(skb);
+               skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+               if (skb == NULL)
+                       return -ENOMEM;
+               dmaaddr = pci_map_single(ring->bcm->pci_dev,
+                                        skb->data, ring->rx_buffersize,
+                                        PCI_DMA_FROMDEVICE);
+               if (pci_dma_mapping_error(dmaaddr) ||
+                   dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+                       assert(0);
+                       dev_kfree_skb_any(skb);
+                       return -ENOMEM;
+               }
+       }
        meta->skb = skb;
        meta->dmaaddr = dmaaddr;
        skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
        err = dmacontroller_setup(ring);
        if (err)
                goto err_free_ringmemory;
+       return ring;
 
 out:
+       printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
        return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
        struct bcm43xx_dmaring *ring;
        int err = -ENOMEM;
        int dma64 = 0;
-       u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-       int nobits;
 
-       if (mask == DMA_64BIT_MASK) {
+       bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+       if (bcm->dma_mask == DMA_64BIT_MASK)
                dma64 = 1;
-               nobits = 64;
-       } else if (mask == DMA_32BIT_MASK)
-               nobits = 32;
-       else
-               nobits = 30;
-       err = pci_set_dma_mask(bcm->pci_dev, mask);
-       err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-       if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-               printk(KERN_WARNING PFX "DMA not supported on this device."
-                                       " Falling back to PIO.\n");
-               bcm->__using_pio = 1;
-               return -ENOSYS;
-#else
-               printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-                                   "Please recompile the driver with PIO support.\n");
-               return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-       }
+       err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+       if (err)
+               goto no_dma;
+       err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+       if (err)
+               goto no_dma;
 
        /* setup TX DMA channels. */
        ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
                dma->rx_ring3 = ring;
        }
 
-       dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+       dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+               (bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+               (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
        err = 0;
 out:
        return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
 err_destroy_tx0:
        bcm43xx_destroy_dmaring(dma->tx_ring0);
        dma->tx_ring0 = NULL;
-       goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+       printk(KERN_WARNING PFX "DMA not supported on this device."
+                               " Falling back to PIO.\n");
+       bcm->__using_pio = 1;
+       return -ENOSYS;
+#else
+       printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+                           "Please recompile the driver with PIO support.\n");
+       return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
        struct bcm43xx_dmadesc_generic *desc;
        struct bcm43xx_dmadesc_meta *meta;
        dma_addr_t dmaaddr;
+       struct sk_buff *bounce_skb;
 
        assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
                               skb->len - sizeof(struct bcm43xx_txhdr),
                               (cur_frag == 0),
                               generate_cookie(ring, slot));
+       dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+       if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+               /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+               if (!dma_mapping_error(dmaaddr))
+                       unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+               bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+               if (!bounce_skb)
+                       return;
+               dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+               if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+                       if (!dma_mapping_error(dmaaddr))
+                               unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+                       dev_kfree_skb_any(bounce_skb);
+                       assert(0);
+                       return;
+               }
+               memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+               dev_kfree_skb_any(skb);
+               skb = bounce_skb;
+       }
 
        meta->skb = skb;
-       dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
        meta->dmaaddr = dmaaddr;
 
        fill_descriptor(ring, desc, dmaaddr,
index 23aaf1ed8541d925bf1d453a43536b7766fc843d..2e400aacc436e2a72d10ab2f18a7875a15e0bfa5 100644 (file)
@@ -95,13 +95,9 @@ static int modparam_noleds;
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
@@ -2983,8 +2979,10 @@ static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
        err = bcm43xx_pctl_set_crystal(bcm, 1);
        if (err)
                goto out;
-       bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
-       bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+       err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+       if (err)
+               goto out;
+       err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
 
 out:
        return err;
@@ -3796,12 +3794,18 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
        }
        net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
-       bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+       err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
                                  &bcm->board_vendor);
-       bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+       if (err)
+               goto err_iounmap;
+       err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
                                  &bcm->board_type);
-       bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+       if (err)
+               goto err_iounmap;
+       err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
                                  &bcm->board_revision);
+       if (err)
+               goto err_iounmap;
 
        err = bcm43xx_chipset_attach(bcm);
        if (err)
@@ -3892,6 +3896,7 @@ err_pci_release:
        pci_release_regions(pci_dev);
 err_pci_disable:
        pci_disable_device(pci_dev);
+       printk(KERN_ERR PFX "Unable to attach board\n");
        goto out;
 }
 
index a659442b9c15e09e978f1c2c0264536df51cc884..7b665e2386a8caaa888b355e80e58510d7e3a201 100644 (file)
@@ -33,7 +33,6 @@
 #include <net/ieee80211softmac.h>
 #include <net/ieee80211softmac_wx.h>
 #include <linux/capability.h>
-#include <linux/sched.h> /* for capable() */
 #include <linux/delay.h>
 
 #include "bcm43xx.h"
@@ -261,22 +260,22 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
        if (phy->type == BCM43xx_PHYTYPE_A ||
            phy->type == BCM43xx_PHYTYPE_G) {
                range->num_bitrates = 8;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-               range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+               range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
        }
        if (phy->type == BCM43xx_PHYTYPE_B ||
            phy->type == BCM43xx_PHYTYPE_G) {
                range->num_bitrates += 4;
-               range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-               range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-               range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-               range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+               range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+               range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+               range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+               range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
        }
 
        geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +285,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
                if (j == IW_MAX_FREQUENCIES)
                        break;
                range->freq[j].i = j + 1;
-               range->freq[j].m = geo->a[i].freq;//FIXME?
+               range->freq[j].m = geo->a[i].freq * 100000;
                range->freq[j].e = 1;
                j++;
        }
@@ -294,7 +293,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
                if (j == IW_MAX_FREQUENCIES)
                        break;
                range->freq[j].i = j + 1;
-               range->freq[j].m = geo->bg[i].freq;//FIXME?
+               range->freq[j].m = geo->bg[i].freq * 100000;
                range->freq[j].e = 1;
                j++;
        }
index b85857a848706fcde3c25d251fac7d280aea9201..d0639a45cd2c4fbc083695b2ed4a6bf657e4f9f4 100644 (file)
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG        /* Reception debugging */
+#define IPW2100_RX_DEBUG       /* Reception debugging */
 #endif
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
        priv->snapshot[0] = NULL;
 }
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
        int i;
@@ -2314,13 +2314,13 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
  * The size of the constructed ethernet
  *
  */
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 #endif
 
 static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
        struct ipw2100_status *status = &priv->status_queue.drv[i];
        u32 match, reg;
        int j;
@@ -2342,7 +2342,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
        }
 #endif
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
        /* Halt the fimrware so we can get a good image */
        write_register(priv->net_dev, IPW_REG_RESET_REG,
                       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 
        skb_put(packet->skb, status->frame_size);
 
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
        /* Make a copy of the frame so we can dump it to the logs if
         * ieee80211_rx fails */
        memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 #endif
 
        if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
                IPW_DEBUG_DROP("%s: Non consumed packet:\n",
                               priv->net_dev->name);
                printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -4912,7 +4912,7 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level)
        else
                priv->power_mode = IPW_POWER_ENABLED | power_level;
 
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
        if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
                /* Set beacon interval */
                cmd.host_command = TX_POWER_INDEX;
index 5eb81638e8467a1ff7b516a33aa9888941839f31..b04239792f63ba2b71c9f6444f78a2d71cc783bd 100644 (file)
@@ -1168,7 +1168,7 @@ wv_mmc_show(struct net_device *   dev)
         m.mmr_unused0[6],
         m.mmr_unused0[7]);
 #endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "Encryption algorythm: %02X - Status: %02X\n",
+  printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
         m.mmr_des_avail, m.mmr_des_status);
 #ifdef DEBUG_SHOW_UNUSED
   printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
@@ -3590,9 +3590,9 @@ wv_82593_config(struct net_device *       dev)
   cfblk.acloc = TRUE;           /* Disable source addr insertion by i82593 */
   cfblk.preamb_len = 0;         /* 2 bytes preamble (SFD) */
   cfblk.loopback = FALSE;
-  cfblk.lin_prio = 0;          /* conform to 802.3 backoff algoritm */
-  cfblk.exp_prio = 5;          /* conform to 802.3 backoff algoritm */
-  cfblk.bof_met = 1;           /* conform to 802.3 backoff algoritm */
+  cfblk.lin_prio = 0;          /* conform to 802.3 backoff algorithm */
+  cfblk.exp_prio = 5;          /* conform to 802.3 backoff algorithm */
+  cfblk.bof_met = 1;           /* conform to 802.3 backoff algorithm */
   cfblk.ifrm_spc = 0x20 >> 4;  /* 32 bit times interframe spacing */
   cfblk.slottim_low = 0x20 >> 5;       /* 32 bit times slot time */
   cfblk.slottim_hi = 0x0;
index a08524191b5d837d0f24c92e8a37374f5a2e5d24..4c5f78eac349a4f77d5d897a9936618c0dc562a3 100644 (file)
@@ -156,7 +156,7 @@ void zd_mac_clear(struct zd_mac *mac)
 static int reset_mode(struct zd_mac *mac)
 {
        struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-       struct zd_ioreq32 ioreqs[3] = {
+       struct zd_ioreq32 ioreqs[] = {
                { CR_RX_FILTER, STA_RX_FILTER },
                { CR_SNIFFER_ON, 0U },
        };
@@ -164,10 +164,9 @@ static int reset_mode(struct zd_mac *mac)
        if (ieee->iw_mode == IW_MODE_MONITOR) {
                ioreqs[0].value = 0xffffffff;
                ioreqs[1].value = 0x1;
-               ioreqs[2].value = ENC_SNIFFER;
        }
 
-       return zd_iowrite32a(&mac->chip, ioreqs, 3);
+       return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@ static int fill_ctrlset(struct zd_mac *mac,
 static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
 {
        int i, r;
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
        for (i = 0; i < txb->nr_frags; i++) {
                struct sk_buff *skb = txb->fragments[i];
 
                r = fill_ctrlset(mac, txb, i);
-               if (r)
+               if (r) {
+                       ieee->stats.tx_dropped++;
                        return r;
+               }
                r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
-               if (r)
+               if (r) {
+                       ieee->stats.tx_dropped++;
                        return r;
+               }
        }
 
        /* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
 
        *pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
        if (status->frame_status & ZD_RX_ERROR) {
-               /* FIXME: update? */
+               struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+               ieee->stats.rx_errors++;
+               if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+                       ieee->stats.rx_missed_errors++;
+               else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+                       ieee->stats.rx_fifo_errors++;
+               else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+                       ieee->ieee_stats.rx_discards_undecryptable++;
+               else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+                       ieee->stats.rx_crc_errors++;
+                       ieee->ieee_stats.rx_fcs_errors++;
+               }
+               else if (status->frame_status & ZD_RX_CRC16_ERROR)
+                       ieee->stats.rx_crc_errors++;
                return -EINVAL;
        }
+
        memset(stats, 0, sizeof(struct ieee80211_rx_stats));
        stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
                               + sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
        if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
                       IEEE80211_FCS_LEN + sizeof(struct rx_status))
        {
-               dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
-                        skb->len);
+               ieee->stats.rx_errors++;
+               ieee->stats.rx_length_errors++;
                goto free_skb;
        }
 
        r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
        if (r) {
-               /* Only packets with rx errors are included here. */
+               /* Only packets with rx errors are included here.
+                * The error stats have already been set in fill_rx_stats.
+                */
                goto free_skb;
        }
 
@@ -1114,8 +1134,10 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 
        r = filter_rx(ieee, skb->data, skb->len, &stats);
        if (r <= 0) {
-               if (r < 0)
+               if (r < 0) {
+                       ieee->stats.rx_errors++;
                        dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+               }
                goto free_skb;
        }
 
@@ -1146,7 +1168,9 @@ int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
 
        skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
        if (!skb) {
+               struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
                dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+               ieee->stats.rx_dropped++;
                return -ENOMEM;
        }
        skb_reserve(skb, sizeof(struct zd_rt_hdr));
index 75ef55624d7fd2cf15820e79127beff3e6e393dd..aac8a1c5ba08fb94e7919fc4e6b930e4b55ea595 100644 (file)
@@ -313,6 +313,12 @@ out:
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+       struct zd_usb *usb = urb->context;
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+       ieee->stats.tx_errors++;
+       ieee->ieee_stats.tx_retry_limit_exceeded++;
        dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -487,6 +493,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
        if (length < sizeof(struct rx_length_info)) {
                /* It's not a complete packet anyhow. */
+               struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+               ieee->stats.rx_errors++;
+               ieee->stats.rx_length_errors++;
                return;
        }
        length_info = (struct rx_length_info *)
@@ -923,6 +932,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
        }
 
+       usb_reset_device(interface_to_usbdev(intf));
+
        netdev = zd_netdev_alloc(intf);
        if (netdev == NULL) {
                r = -ENOMEM;
@@ -1024,6 +1035,7 @@ static int __init usb_init(void)
 
        r = usb_register(&driver);
        if (r) {
+               destroy_workqueue(zd_workqueue);
                printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
                       driver.name, r);
                return r;
index e97cecbc4d183e6b0772e824747e2de8d4341e69..309076b39853be3a0f51a565dec251f9156c82ba 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/eisa.h>
 
index e60b4bf6bae8f754e48daa268846407b0404096d..316c06f4423c381ba05792840750b683d4ba4add 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index a7c5ead9a3d38ab146811f4077a5499c5e0f8e74..17bf9937d276d66e792adaf17763c5550e65a716 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
index 2e744a274517c517b31889e0553451427e28a209..bdbdab9285cacfbb6839c24cbbf9f11239e5796f 100644 (file)
@@ -233,12 +233,12 @@ static int do_hardware_modes (ctl_table *table, int write,
        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 }
 
-#define PARPORT_PORT_DIR(child) { 0, NULL, NULL, 0, 0555, child }
-#define PARPORT_PARPORT_DIR(child) { DEV_PARPORT, "parport", \
-                                     NULL, 0, 0555, child }
-#define PARPORT_DEV_DIR(child) { CTL_DEV, "dev", NULL, 0, 0555, child }
-#define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
-                                    NULL, 0, 0555, NULL }
+#define PARPORT_PORT_DIR(CHILD) { .ctl_name = 0, .procname = NULL, .mode = 0555, .child = CHILD }
+#define PARPORT_PARPORT_DIR(CHILD) { .ctl_name = DEV_PARPORT, .procname = "parport", \
+                                     .mode = 0555, .child = CHILD }
+#define PARPORT_DEV_DIR(CHILD) { .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = CHILD }
+#define PARPORT_DEVICES_ROOT_DIR  { .ctl_name = DEV_PARPORT_DEVICES, .procname = "devices", \
+                                    .mode = 0555, .child = NULL }
 
 static const unsigned long parport_min_timeslice_value =
 PARPORT_MIN_TIMESLICE_VALUE;
@@ -263,50 +263,118 @@ struct parport_sysctl_table {
 };
 
 static const struct parport_sysctl_table parport_sysctl_template = {
-       NULL,
+       .sysctl_header = NULL,
         {
-               { DEV_PARPORT_SPINTIME, "spintime",
-                 NULL, sizeof(int), 0644, NULL,
-                 &proc_dointvec_minmax, NULL, NULL,
-                 (void*) &parport_min_spintime_value,
-                 (void*) &parport_max_spintime_value },
-               { DEV_PARPORT_BASE_ADDR, "base-addr",
-                 NULL, 0, 0444, NULL,
-                 &do_hardware_base_addr },
-               { DEV_PARPORT_IRQ, "irq",
-                 NULL, 0, 0444, NULL,
-                 &do_hardware_irq },
-               { DEV_PARPORT_DMA, "dma",
-                 NULL, 0, 0444, NULL,
-                 &do_hardware_dma },
-               { DEV_PARPORT_MODES, "modes",
-                 NULL, 0, 0444, NULL,
-                 &do_hardware_modes },
+               {
+                       .ctl_name       = DEV_PARPORT_SPINTIME,
+                       .procname       = "spintime",
+                       .data           = NULL,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = &proc_dointvec_minmax,
+                       .extra1         = (void*) &parport_min_spintime_value,
+                       .extra2         = (void*) &parport_max_spintime_value
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_BASE_ADDR,
+                       .procname       = "base-addr",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_hardware_base_addr
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_IRQ,
+                       .procname       = "irq",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_hardware_irq
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_DMA,
+                       .procname       = "dma",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_hardware_dma
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_MODES,
+                       .procname       = "modes",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_hardware_modes
+               },
                PARPORT_DEVICES_ROOT_DIR,
 #ifdef CONFIG_PARPORT_1284
-               { DEV_PARPORT_AUTOPROBE, "autoprobe",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 1, "autoprobe0",
-                NULL, 0, 0444, NULL,
-                &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 2, "autoprobe1",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 3, "autoprobe2",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 4, "autoprobe3",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
+               {
+                       .ctl_name       = DEV_PARPORT_AUTOPROBE,
+                       .procname       = "autoprobe",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_autoprobe
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_AUTOPROBE + 1,
+                       .procname       = "autoprobe0",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   =  &do_autoprobe
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_AUTOPROBE + 2,
+                       .procname       = "autoprobe1",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_autoprobe
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_AUTOPROBE + 3,
+                       .procname       = "autoprobe2",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_autoprobe
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_AUTOPROBE + 4,
+                       .procname       = "autoprobe3",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_autoprobe
+               },
 #endif /* IEEE 1284 support */
-               {0}
+               {}
        },
-       { {DEV_PARPORT_DEVICES_ACTIVE, "active", NULL, 0, 0444, NULL,
-         &do_active_device }, {0}},
-       { PARPORT_PORT_DIR(NULL), {0}},
-       { PARPORT_PARPORT_DIR(NULL), {0}},
-       { PARPORT_DEV_DIR(NULL), {0}}
+       {
+               {
+                       .ctl_name       = DEV_PARPORT_DEVICES_ACTIVE,
+                       .procname       = "active",
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0444,
+                       .proc_handler   = &do_active_device
+               },
+               {}
+       },
+       {
+               PARPORT_PORT_DIR(NULL),
+               {}
+       },
+       {
+               PARPORT_PARPORT_DIR(NULL),
+               {}
+       },
+       {
+               PARPORT_DEV_DIR(NULL),
+               {}
+       }
 };
 
 struct parport_device_sysctl_table
@@ -322,19 +390,46 @@ struct parport_device_sysctl_table
 
 static const struct parport_device_sysctl_table
 parport_device_sysctl_template = {
-       NULL,
+       .sysctl_header = NULL,
+       {
+               {
+                       .ctl_name       = DEV_PARPORT_DEVICE_TIMESLICE,
+                       .procname       = "timeslice",
+                       .data           = NULL,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = &proc_doulongvec_ms_jiffies_minmax,
+                       .extra1         = (void*) &parport_min_timeslice_value,
+                       .extra2         = (void*) &parport_max_timeslice_value
+               },
+       },
+       {
+               {
+                       .ctl_name       = 0,
+                       .procname       = NULL,
+                       .data           = NULL,
+                       .maxlen         = 0,
+                       .mode           = 0555,
+                       .child          = NULL
+               },
+               {}
+       },
        {
-               { DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
-                 NULL, sizeof(int), 0644, NULL,
-                 &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
-                 (void*) &parport_min_timeslice_value,
-                 (void*) &parport_max_timeslice_value },
+               PARPORT_DEVICES_ROOT_DIR,
+               {}
+       },
+       {
+               PARPORT_PORT_DIR(NULL),
+               {}
        },
-       { {0, NULL, NULL, 0, 0555, NULL}, {0}},
-       { PARPORT_DEVICES_ROOT_DIR, {0}},
-       { PARPORT_PORT_DIR(NULL), {0}},
-       { PARPORT_PARPORT_DIR(NULL), {0}},
-       { PARPORT_DEV_DIR(NULL), {0}}
+       {
+               PARPORT_PARPORT_DIR(NULL),
+               {}
+       },
+       {
+               PARPORT_DEV_DIR(NULL),
+               {}
+       }
 };
 
 struct parport_default_sysctl_table
@@ -351,28 +446,47 @@ extern int parport_default_spintime;
 
 static struct parport_default_sysctl_table
 parport_default_sysctl_table = {
-       NULL,
+       .sysctl_header  = NULL,
+       {
+               {
+                       .ctl_name       = DEV_PARPORT_DEFAULT_TIMESLICE,
+                       .procname       = "timeslice",
+                       .data           = &parport_default_timeslice,
+                       .maxlen         = sizeof(parport_default_timeslice),
+                       .mode           = 0644,
+                       .proc_handler   = &proc_doulongvec_ms_jiffies_minmax,
+                       .extra1         = (void*) &parport_min_timeslice_value,
+                       .extra2         = (void*) &parport_max_timeslice_value
+               },
+               {
+                       .ctl_name       = DEV_PARPORT_DEFAULT_SPINTIME,
+                       .procname       = "spintime",
+                       .data           = &parport_default_spintime,
+                       .maxlen         = sizeof(parport_default_spintime),
+                       .mode           = 0644,
+                       .proc_handler   = &proc_dointvec_minmax,
+                       .extra1         = (void*) &parport_min_spintime_value,
+                       .extra2         = (void*) &parport_max_spintime_value
+               },
+               {}
+       },
        {
-               { DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
-                 &parport_default_timeslice,
-                 sizeof(parport_default_timeslice), 0644, NULL,
-                 &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
-                 (void*) &parport_min_timeslice_value,
-                 (void*) &parport_max_timeslice_value },
-               { DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
-                 &parport_default_spintime,
-                 sizeof(parport_default_spintime), 0644, NULL,
-                 &proc_dointvec_minmax, NULL, NULL,
-                 (void*) &parport_min_spintime_value,
-                 (void*) &parport_max_spintime_value },
-               {0}
+               {
+                       .ctl_name       = DEV_PARPORT_DEFAULT,
+                       .procname       = "default",
+                       .mode           = 0555,
+                       .child          = parport_default_sysctl_table.vars
+               },
+               {}
        },
-       { { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
-           parport_default_sysctl_table.vars },{0}},
        {
-       PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 
-       {0}},
-       { PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), {0}}
+               PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
+               {}
+       },
+       {
+               PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
+               {}
+       }
 };
 
 
@@ -404,7 +518,7 @@ int parport_proc_register(struct parport *port)
        t->parport_dir[0].child = t->port_dir;
        t->dev_dir[0].child = t->parport_dir;
 
-       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->dev_dir);
        if (t->sysctl_header == NULL) {
                kfree(t);
                t = NULL;
@@ -460,7 +574,7 @@ int parport_device_proc_register(struct pardevice *device)
        t->device_dir[0].child = t->vars;
        t->vars[0].data = &device->timeslice;
 
-       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->dev_dir);
        if (t->sysctl_header == NULL) {
                kfree(t);
                t = NULL;
@@ -483,7 +597,7 @@ int parport_device_proc_unregister(struct pardevice *device)
 static int __init parport_default_proc_register(void)
 {
        parport_default_sysctl_table.sysctl_header =
-               register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
+               register_sysctl_table(parport_default_sysctl_table.dev_dir);
        return 0;
 }
 
index 05e4f5a1927ac38fa16e629151dcd676705c417d..600ed7b67ae7fab1f748d2d99cfee8a3dc516de4 100644 (file)
@@ -28,7 +28,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
index 4438ae1ede4fa5034ad8085c51819fec4252e7b9..a3c1755b2f28329313eaf6c088190470b918d7b0 100644 (file)
@@ -415,6 +415,7 @@ static struct kobj_type pci_driver_kobj_type = {
  * __pci_register_driver - register a new pci driver
  * @drv: the driver structure to register
  * @owner: owner module of drv
+ * @mod_name: module name string
  * 
  * Adds the driver structure to the list of registered drivers.
  * Returns a negative value on error, otherwise 0. 
index 7a94076752d047125d4b72b876afeb28c034a344..cd913a2a416f08e6cd705d030a36c718fbe9df39 100644 (file)
@@ -143,6 +143,14 @@ static ssize_t is_enabled_show(struct device *dev,
        return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
 }
 
+#ifdef CONFIG_NUMA
+static ssize_t
+numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return sprintf (buf, "%d\n", dev->numa_node);
+}
+#endif
+
 static ssize_t
 msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -194,6 +202,9 @@ struct device_attribute pci_dev_attrs[] = {
        __ATTR_RO(irq),
        __ATTR_RO(local_cpus),
        __ATTR_RO(modalias),
+#ifdef CONFIG_NUMA
+       __ATTR_RO(numa_node),
+#endif
        __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
        __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
                broken_parity_status_show,broken_parity_status_store),
index 8b44cff2c1767f3bef0287eb394b68c9988b9d60..1e74e1ee8bd89a4f90c4579e50dc033eace44028 100644 (file)
 
 unsigned int pci_pm_d3_delay = 10;
 
+#define DEFAULT_CARDBUS_IO_SIZE                (256)
+#define DEFAULT_CARDBUS_MEM_SIZE       (64*1024*1024)
+/* pci=cbmemsize=nnM,cbiosize=nn can override this */
+unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
+unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -1300,7 +1306,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 
 /**
  * pci_select_bars - Make BAR mask from the type of resource
- * @pdev: the PCI device for which BAR mask is made
+ * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
  *
  * This helper routine makes bar mask from the type of resource.
@@ -1333,6 +1339,10 @@ static int __devinit pci_setup(char *str)
                if (*str && (str = pcibios_setup(str)) && *str) {
                        if (!strcmp(str, "nomsi")) {
                                pci_no_msi();
+                       } else if (!strncmp(str, "cbiosize=", 9)) {
+                               pci_cardbus_io_size = memparse(str + 9, &str);
+                       } else if (!strncmp(str, "cbmemsize=", 10)) {
+                               pci_cardbus_mem_size = memparse(str + 10, &str);
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
index 6f5fabbd14e58f77453c112e9c77850af1d38b52..b164de050d4f2635e129070a3eca66b31343023b 100644 (file)
@@ -220,7 +220,7 @@ static int __devinit aer_probe (struct pcie_device *dev,
        }
 
        /* Request IRQ ISR */
-       if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
+       if ((status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv",
                                dev))) {
                printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
                        __FUNCTION__, device->bus_id);
index 3c0a58f64dd811d455051901ac1da239daa99b3a..bf655dbaf8e25b8b53e3a2dc303b560e0f31a8e7 100644 (file)
@@ -85,7 +85,7 @@ struct aer_rpc {
        struct mutex rpc_mutex;         /*
                                         * only one thread could do
                                         * recovery on the same
-                                        * root port hierachy
+                                        * root port hierarchy
                                         */
        wait_queue_head_t wait_release;
 };
index 89f3036f0de8866d46081fca800e146c3376b32b..3554f3948814aee7f23ea9db72523dc0fde9eeb1 100644 (file)
 
 #define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
 
-/*
- * FIXME: IO should be max 256 bytes.  However, since we may
- * have a P2P bridge below a cardbus bridge, we need 4K.
- */
-#define CARDBUS_IO_SIZE                (256)
-#define CARDBUS_MEM_SIZE       (64*1024*1024)
-
 static void __devinit
 pbus_assign_resources_sorted(struct pci_bus *bus)
 {
@@ -415,12 +408,12 @@ pci_bus_size_cardbus(struct pci_bus *bus)
         * Reserve some resources for CardBus.  We reserve
         * a fixed amount of bus space for CardBus bridges.
         */
-       b_res[0].start = CARDBUS_IO_SIZE;
-       b_res[0].end = b_res[0].start + CARDBUS_IO_SIZE - 1;
+       b_res[0].start = pci_cardbus_io_size;
+       b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
        b_res[0].flags |= IORESOURCE_IO;
 
-       b_res[1].start = CARDBUS_IO_SIZE;
-       b_res[1].end = b_res[1].start + CARDBUS_IO_SIZE - 1;
+       b_res[1].start = pci_cardbus_io_size;
+       b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
        b_res[1].flags |= IORESOURCE_IO;
 
        /*
@@ -440,16 +433,16 @@ pci_bus_size_cardbus(struct pci_bus *bus)
         * twice the size.
         */
        if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
-               b_res[2].start = CARDBUS_MEM_SIZE;
-               b_res[2].end = b_res[2].start + CARDBUS_MEM_SIZE - 1;
+               b_res[2].start = pci_cardbus_mem_size;
+               b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
                b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
 
-               b_res[3].start = CARDBUS_MEM_SIZE;
-               b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE - 1;
+               b_res[3].start = pci_cardbus_mem_size;
+               b_res[3].end = b_res[3].start + pci_cardbus_mem_size - 1;
                b_res[3].flags |= IORESOURCE_MEM;
        } else {
-               b_res[3].start = CARDBUS_MEM_SIZE * 2;
-               b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE * 2 - 1;
+               b_res[3].start = pci_cardbus_mem_size * 2;
+               b_res[3].end = b_res[3].start + pci_cardbus_mem_size * 2 - 1;
                b_res[3].flags |= IORESOURCE_MEM;
        }
 }
index a251289c9958e846ebc50d45254ec2bea6b14cf5..568f1877315c5532d39052e4e615f1304a48cb93 100644 (file)
@@ -24,7 +24,7 @@ pdev_fixup_irq(struct pci_dev *dev,
               int (*map_irq)(struct pci_dev *, u8, u8))
 {
        u8 pin, slot;
-       int irq;
+       int irq = 0;
 
        /* If this device is not on the primary bus, we need to figure out
           which interrupt pin it will come in on.   We know which slot it
@@ -33,16 +33,18 @@ pdev_fixup_irq(struct pci_dev *dev,
           apply the swizzle function.  */
 
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       /* Cope with 0 and illegal. */
-       if (pin == 0 || pin > 4)
+       /* Cope with illegal. */
+       if (pin > 4)
                pin = 1;
 
-       /* Follow the chain of bridges, swizzling as we go.  */
-       slot = (*swizzle)(dev, &pin);
+       if (pin != 0) {
+               /* Follow the chain of bridges, swizzling as we go.  */
+               slot = (*swizzle)(dev, &pin);
 
-       irq = (*map_irq)(dev, slot, pin);
-       if (irq == -1)
-               irq = 0;
+               irq = (*map_irq)(dev, slot, pin);
+               if (irq == -1)
+                       irq = 0;
+       }
        dev->irq = irq;
 
        pr_debug("PCI: fixup irq: (%s) got %d\n",
index 87fafc08cb9d6a3f31f861c29d260d842ae141d0..9d37fec27f24668d1ede8229439b82bb36561b61 100644 (file)
@@ -7,7 +7,6 @@
  * magic northbridge registers..
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
index 3334f22a86c0617f3a16471db8ffb064fadecbf9..99baabc23599129179fc814a519ba35b089135be 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -278,7 +277,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
                board->det_pin, board->irq_pin);
 
        cf->socket.owner = THIS_MODULE;
-       cf->socket.dev.dev = &pdev->dev;
+       cf->socket.dev.parent = &pdev->dev;
        cf->socket.ops = &at91_cf_ops;
        cf->socket.resource_ops = &pccard_static_ops;
        cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
index 2d7effe7990d9c67136a44617e31bed2290a7026..a1bd763b4e336e94b277a6fe650adf2107044807 100644 (file)
@@ -40,8 +40,6 @@
 
 /*====================================================================*/
 
-#define FIND_FIRST_BIT(n)      ((n) - ((n) & ((n)-1)))
-
 /* Offsets in the Expansion ROM Image Header */
 #define ROM_SIGNATURE          0x0000  /* 2 bytes */
 #define ROM_DATA_PTR           0x0018  /* 2 bytes */
index 912c03e5eb0a3d66448da64a26416d3d8a546dcf..d154dee76e7f5af7689cd9e644c3b111c859dd5b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
index 72ff2f615b3367a40765efce691568b123562472..71b33707117fb8b73c3518135cfc0b70a01b18e0 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
index 3c22ac4625c21ef1bec7c386cf2f2ca0c00beb16..e4a94108aab9578b0897510c6bc6e9a5196e1b5a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
index 4dbef07623764f421e2a01d7713d650b4df42aef..67d28ee80f220bc4e119b1ac2ebe9639e2459c46 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
index 3b72be880401398d93b6465c82333aa84af5e585..d059c9196172330ca02b307bc6ea51236fa73f0b 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
index e65a6b8188f6c896d715f56b71f09b05618a7a3c..76f7cbc62a8b95311ccc52ad610b45fecb39ff79 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index a92f11143c433df11b7f14f51ef9e39d3bd0c360..5e9b9a3fd027c062f4276dba2b090f4865e4d77b 100644 (file)
@@ -16,7 +16,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index 19b1e127622060dc9a0eacff062f0ec9c2bd852e..62bfc7566ec2a927396bbe48f993b5502fd63d16 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index eb89928f2338a52077f47b1c34158aaf20ed16c5..549a1529fe35800e9c6034a6a4940dcf3460caab 100644 (file)
@@ -7,7 +7,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index 64fd5e37f2d22d12617bc6066dcaab33a6e95098..e5491879acd9191a962293b0c83b12b65637b4e1 100644 (file)
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 7a87298bae993f0cadc5676a377f4ae2b65851c9..af485ae386024fbf560d260b52a83db25e1a5b2f 100644 (file)
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index 5e34b3e8e5db4acb3e3a3f888e1ce646421403ff..5bc9e9532b9d78f48f00ecd94fdcd5211118bd46 100644 (file)
@@ -5,7 +5,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index 7bc9e59c761f732c5b2fa737a996db4fc031460a..9456f5478d09251178534d354a947ffd38032be3 100644 (file)
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
index c2ecf1185e9e02f7df4aebe937d1c4aadc11fd3b..04d6f7f75f7806b6ea8fc66f4bc34b4163bbb3c3 100644 (file)
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
index d2a3bea55de20058a42d6775980c0c09cc0d896f..aa7779d89752681a05e5d10d0aa76c19ff08a648 100644 (file)
@@ -478,7 +478,7 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, char *buf)
+static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct soc_pcmcia_socket *skt =
                container_of(dev, struct soc_pcmcia_socket, socket.dev);
@@ -501,7 +501,7 @@ static ssize_t show_status(struct device *dev, char *buf)
 
        return p-buf;
 }
-static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 
 
 static struct pccard_operations soc_common_pcmcia_operations = {
@@ -660,7 +660,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 
                skt->socket.ops = &soc_common_pcmcia_operations;
                skt->socket.owner = ops->owner;
-               skt->socket.dev.dev = dev;
+               skt->socket.dev.parent = dev;
 
                init_timer(&skt->poll_timer);
                skt->poll_timer.function = soc_common_pcmcia_poll_event;
@@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 
                add_timer(&skt->poll_timer);
 
-               device_create_file(&skt->socket.dev, &device_attr_status);
+               device_create_file(&skt->socket.dev, &dev_attr_status);
        }
 
        dev_set_drvdata(dev, sinfo);
index e90d8e8c5fd686068aab91962cad29d89c5f10ad..206e26c918076bd578497429b7c1788997a0f661 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 
index a61d768f6e0ef063a0c9a631cac70f2add6c8d3b..20853a03202d16b2b6c8321ab715651d8274839f 100644 (file)
@@ -12,7 +12,6 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
index ad27e5e0101fd178bc9dbeeb84a94e855f0fc89e..b04767ce273e977d873cf19726afff22b6f87cb3 100644 (file)
@@ -2,17 +2,5 @@
 # Plug and Play ACPI configuration
 #
 config PNPACPI
-       bool "Plug and Play ACPI support"
-       depends on PNP && ACPI
-       default y
-       ---help---
-         Linux uses the PNPACPI to autodetect built-in
-         mainboard resources (e.g. parallel port resources).
-
-          Some features (e.g. real hotplug) are not currently
-          implemented.
-
-          If you would like the kernel to detect and allocate resources to
-          your mainboard devices (on some systems they are disabled by the
-          BIOS) say Y here.  Also the PNPACPI can help prevent resource
-          conflicts between mainboard devices and other bus devices.
+       bool
+       default (PNP && ACPI)
index 96958c03cf61f54fa8be4c54d4a8acfcb91d5541..e251d1c1171c18592e469105ee588346c02ae03e 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
 obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
new file mode 100644 (file)
index 0000000..0fc30be
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ *  PS3 System Manager.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/reboot.h>
+#include <asm/ps3.h>
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 System Manager");
+
+/**
+ * ps3_sys_manager - PS3 system manager driver.
+ *
+ * The system manager provides an asyncronous system event notification
+ * mechanism for reporting events like thermal alert and button presses to
+ * guests.  It also provides support to control system shutdown and startup.
+ *
+ * The actual system manager is implemented as an application running in the
+ * system policy module in lpar_1.  Guests communicate with the system manager
+ * through port 2 of the vuart using a simple packet message protocol.
+ * Messages are comprised of a fixed field header followed by a message
+ * specific payload.
+ */
+
+/**
+ * struct ps3_sys_manager_header - System manager message header.
+ * @version: Header version, currently 1.
+ * @size: Header size in bytes, curently 16.
+ * @payload_size: Message payload size in bytes.
+ * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ */
+
+struct ps3_sys_manager_header {
+       /* version 1 */
+       u8 version;
+       u8 size;
+       u16 reserved_1;
+       u32 payload_size;
+       u16 service_id;
+       u16 reserved_2[3];
+};
+
+/**
+ * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ *
+ * Currently all messages received from the system manager are the same length
+ * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
+ * simplify the logic.
+ */
+
+enum {
+       PS3_SM_RX_MSG_LEN = 32,
+};
+
+/**
+ * enum ps3_sys_manager_service_id - Message header service_id.
+ * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ */
+
+enum ps3_sys_manager_service_id {
+       /* version 1 */
+       PS3_SM_SERVICE_ID_REQUEST = 1,
+       PS3_SM_SERVICE_ID_RESPONSE = 2,
+       PS3_SM_SERVICE_ID_COMMAND = 3,
+       PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
+       PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+       PS3_SM_SERVICE_ID_SET_ATTR = 8,
+};
+
+/**
+ * enum ps3_sys_manager_attr - Notification attribute (bit position mask).
+ * @PS3_SM_ATTR_POWER: Power button.
+ * @PS3_SM_ATTR_RESET: Reset button, not available on retail console.
+ * @PS3_SM_ATTR_THERMAL: Sytem thermal alert.
+ * @PS3_SM_ATTR_CONTROLLER: Remote controller event.
+ * @PS3_SM_ATTR_ALL: Logical OR of all.
+ *
+ * The guest tells the system manager which events it is interested in receiving
+ * notice of by sending the system manager a logical OR of notification
+ * attributes via the ps3_sys_manager_send_attr() routine.
+ */
+
+enum ps3_sys_manager_attr {
+       /* version 1 */
+       PS3_SM_ATTR_POWER = 1,
+       PS3_SM_ATTR_RESET = 2,
+       PS3_SM_ATTR_THERMAL = 4,
+       PS3_SM_ATTR_CONTROLLER = 8, /* bogus? */
+       PS3_SM_ATTR_ALL = 0x0f,
+};
+
+/**
+ * enum ps3_sys_manager_event - External event type, reported by system manager.
+ * @PS3_SM_EVENT_POWER_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_POWER_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_RESET_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_RESET_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_THERMAL_ALERT: payload.value = thermal zone id.
+ * @PS3_SM_EVENT_THERMAL_CLEARED: payload.value = thermal zone id.
+ */
+
+enum ps3_sys_manager_event {
+       /* version 1 */
+       PS3_SM_EVENT_POWER_PRESSED = 3,
+       PS3_SM_EVENT_POWER_RELEASED = 4,
+       PS3_SM_EVENT_RESET_PRESSED = 5,
+       PS3_SM_EVENT_RESET_RELEASED = 6,
+       PS3_SM_EVENT_THERMAL_ALERT = 7,
+       PS3_SM_EVENT_THERMAL_CLEARED = 8,
+       /* no info on controller events */
+};
+
+/**
+ * enum ps3_sys_manager_next_op - Operation to perform after lpar is destroyed.
+ */
+
+enum ps3_sys_manager_next_op {
+       /* version 3 */
+       PS3_SM_NEXT_OP_SYS_SHUTDOWN = 1,
+       PS3_SM_NEXT_OP_SYS_REBOOT = 2,
+       PS3_SM_NEXT_OP_LPAR_REBOOT = 0x82,
+};
+
+/**
+ * enum ps3_sys_manager_wake_source - Next-op wakeup source (bit position mask).
+ * @PS3_SM_WAKE_DEFAULT: Disk insert, power button, eject button, IR
+ * controller, and bluetooth controller.
+ * @PS3_SM_WAKE_RTC:
+ * @PS3_SM_WAKE_RTC_ERROR:
+ * @PS3_SM_WAKE_P_O_R: Power on reset.
+ *
+ * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
+ * System will always wake from the PS3_SM_WAKE_DEFAULT sources.
+ */
+
+enum ps3_sys_manager_wake_source {
+       /* version 3 */
+       PS3_SM_WAKE_DEFAULT   = 0,
+       PS3_SM_WAKE_RTC       = 0x00000040,
+       PS3_SM_WAKE_RTC_ERROR = 0x00000080,
+       PS3_SM_WAKE_P_O_R     = 0x10000000,
+};
+
+/**
+ * enum ps3_sys_manager_cmd - Command from system manager to guest.
+ *
+ * The guest completes the actions needed, then acks or naks the command via
+ * ps3_sys_manager_send_response().  In the case of @PS3_SM_CMD_SHUTDOWN,
+ * the guest must be fully prepared for a system poweroff prior to acking the
+ * command.
+ */
+
+enum ps3_sys_manager_cmd {
+       /* version 1 */
+       PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */
+};
+
+/**
+ * ps3_sys_manager_write - Helper to write a two part message to the vuart.
+ *
+ */
+
+static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+       const struct ps3_sys_manager_header *header, const void *payload)
+{
+       int result;
+
+       BUG_ON(header->version != 1);
+       BUG_ON(header->size != 16);
+       BUG_ON(header->payload_size != 8 && header->payload_size != 16);
+       BUG_ON(header->service_id > 8);
+
+       result = ps3_vuart_write(dev, header,
+               sizeof(struct ps3_sys_manager_header));
+
+       if (!result)
+               result = ps3_vuart_write(dev, payload, header->payload_size);
+
+       return result;
+}
+
+/**
+ * ps3_sys_manager_send_attr - Send a 'set attribute' to the system manager.
+ *
+ */
+
+static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+       enum ps3_sys_manager_attr attr)
+{
+       static const struct ps3_sys_manager_header header = {
+               .version = 1,
+               .size = 16,
+               .payload_size = 16,
+               .service_id = PS3_SM_SERVICE_ID_SET_ATTR,
+       };
+       struct {
+               u8 version;
+               u8 reserved_1[3];
+               u32 attribute;
+       } payload;
+
+       BUILD_BUG_ON(sizeof(payload) != 8);
+
+       dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
+
+       memset(&payload, 0, sizeof(payload));
+       payload.version = 1;
+       payload.attribute = attr;
+
+       return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_next_op - Send a 'set next op' to the system manager.
+ *
+ * Tell the system manager what to do after this lpar is destroyed.
+ */
+
+static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+       enum ps3_sys_manager_next_op op,
+       enum ps3_sys_manager_wake_source wake_source)
+{
+       static const struct ps3_sys_manager_header header = {
+               .version = 1,
+               .size = 16,
+               .payload_size = 16,
+               .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
+       };
+       struct {
+               u8 version;
+               u8 type;
+               u8 gos_id;
+               u8 reserved_1;
+               u32 wake_source;
+               u8 reserved_2[8];
+       } payload;
+
+       BUILD_BUG_ON(sizeof(payload) != 16);
+
+       dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
+
+       memset(&payload, 0, sizeof(payload));
+       payload.version = 3;
+       payload.type = op;
+       payload.gos_id = 3; /* other os */
+       payload.wake_source = wake_source;
+
+       return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_request_shutdown - Send 'request' to the system manager.
+ *
+ * The guest sends this message to request an operation or action of the system
+ * manager.  The reply is a command message from the system manager.  In the
+ * command handler the guest performs the requested operation.  The result of
+ * the command is then communicated back to the system manager with a response
+ * message.
+ *
+ * Currently, the only supported request it the 'shutdown self' request.
+ */
+
+static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+{
+       static const struct ps3_sys_manager_header header = {
+               .version = 1,
+               .size = 16,
+               .payload_size = 16,
+               .service_id = PS3_SM_SERVICE_ID_REQUEST,
+       };
+       struct {
+               u8 version;
+               u8 type;
+               u8 gos_id;
+               u8 reserved_1[13];
+       } static const payload = {
+               .version = 1,
+               .type = 1, /* shutdown */
+               .gos_id = 0, /* self */
+       };
+
+       BUILD_BUG_ON(sizeof(payload) != 16);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_response - Send a 'response' to the system manager.
+ * @status: zero = success, others fail.
+ *
+ * The guest sends this message to the system manager to acnowledge success or
+ * failure of a command sent by the system manager.
+ */
+
+static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+       u64 status)
+{
+       static const struct ps3_sys_manager_header header = {
+               .version = 1,
+               .size = 16,
+               .payload_size = 16,
+               .service_id = PS3_SM_SERVICE_ID_RESPONSE,
+       };
+       struct {
+               u8 version;
+               u8 reserved_1[3];
+               u8 status;
+               u8 reserved_2[11];
+       } payload;
+
+       BUILD_BUG_ON(sizeof(payload) != 16);
+
+       dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+               (status ? "nak" : "ack"));
+
+       memset(&payload, 0, sizeof(payload));
+       payload.version = 1;
+       payload.status = status;
+
+       return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_handle_event - Second stage event msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+{
+       int result;
+       struct {
+               u8 version;
+               u8 type;
+               u8 reserved_1[2];
+               u32 value;
+               u8 reserved_2[8];
+       } event;
+
+       BUILD_BUG_ON(sizeof(event) != 16);
+
+       result = ps3_vuart_read(dev, &event, sizeof(event));
+       BUG_ON(result);
+
+       if (event.version != 1) {
+               dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
+                       __func__, __LINE__, event.version);
+               return -EIO;
+       }
+
+       switch (event.type) {
+       case PS3_SM_EVENT_POWER_PRESSED:
+               dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
+                       __func__, __LINE__);
+               break;
+       case PS3_SM_EVENT_POWER_RELEASED:
+               dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
+                       __func__, __LINE__, event.value);
+               kill_cad_pid(SIGINT, 1);
+               break;
+       case PS3_SM_EVENT_THERMAL_ALERT:
+               dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
+                       __func__, __LINE__, event.value);
+               printk(KERN_INFO "PS3 Thermal Alert Zone %u\n", event.value);
+               break;
+       case PS3_SM_EVENT_THERMAL_CLEARED:
+               dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
+                       __func__, __LINE__, event.value);
+               break;
+       default:
+               dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
+                       __func__, __LINE__, event.type);
+               return -EIO;
+       }
+
+       return 0;
+}
+/**
+ * ps3_sys_manager_handle_cmd - Second stage command msg handler.
+ *
+ * The system manager sends this in reply to a 'request' message from the guest.
+ */
+
+static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+{
+       int result;
+       struct {
+               u8 version;
+               u8 type;
+               u8 reserved_1[14];
+       } cmd;
+
+       BUILD_BUG_ON(sizeof(cmd) != 16);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+
+       if(result)
+               return result;
+
+       if (cmd.version != 1) {
+               dev_dbg(&dev->core, "%s:%d: unsupported cmd version (%u)\n",
+                       __func__, __LINE__, cmd.version);
+               return -EIO;
+       }
+
+       if (cmd.type != PS3_SM_CMD_SHUTDOWN) {
+               dev_dbg(&dev->core, "%s:%d: unknown cmd (%u)\n",
+                       __func__, __LINE__, cmd.type);
+               return -EIO;
+       }
+
+       ps3_sys_manager_send_response(dev, 0);
+       return 0;
+}
+
+/**
+ * ps3_sys_manager_handle_msg - First stage msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+{
+       int result;
+       struct ps3_sys_manager_header header;
+
+       result = ps3_vuart_read(dev, &header,
+               sizeof(struct ps3_sys_manager_header));
+
+       if(result)
+               return result;
+
+       if (header.version != 1) {
+               dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
+                       __func__, __LINE__, header.version);
+               goto fail_header;
+       }
+
+       BUILD_BUG_ON(sizeof(header) != 16);
+       BUG_ON(header.size != 16);
+       BUG_ON(header.payload_size != 16);
+
+       switch (header.service_id) {
+       case PS3_SM_SERVICE_ID_EXTERN_EVENT:
+               dev_dbg(&dev->core, "%s:%d: EVENT\n", __func__, __LINE__);
+               return ps3_sys_manager_handle_event(dev);
+       case PS3_SM_SERVICE_ID_COMMAND:
+               dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
+               return ps3_sys_manager_handle_cmd(dev);
+       default:
+               dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
+                       __func__, __LINE__, header.service_id);
+               break;
+       }
+       goto fail_id;
+
+fail_header:
+       ps3_vuart_clear_rx_bytes(dev, 0);
+       return -EIO;
+fail_id:
+       ps3_vuart_clear_rx_bytes(dev, header.payload_size);
+       return -EIO;
+}
+
+/**
+ * ps3_sys_manager_work - Asyncronous read handler.
+ *
+ * Signaled when a complete message arrives at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct work_struct *work)
+{
+       struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
+
+       ps3_sys_manager_handle_msg(dev);
+       ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
+}
+
+struct {
+       struct ps3_vuart_port_device *dev;
+} static drv_priv;
+
+/**
+ * ps3_sys_manager_restart - The final platform machine_restart routine.
+ *
+ * This routine never returns.  The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_restart().
+ */
+
+void ps3_sys_manager_restart(void)
+{
+       struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+       BUG_ON(!drv_priv.dev);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       ps3_vuart_cancel_async(dev);
+
+       ps3_sys_manager_send_attr(dev, 0);
+       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+               PS3_SM_WAKE_DEFAULT);
+       ps3_sys_manager_send_request_shutdown(dev);
+
+       printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+       while(1)
+               ps3_sys_manager_handle_msg(dev);
+}
+
+/**
+ * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ *
+ * This routine never returns.  The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_power_off().
+ */
+
+void ps3_sys_manager_power_off(void)
+{
+       struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+       BUG_ON(!drv_priv.dev);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       ps3_vuart_cancel_async(dev);
+
+       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+               PS3_SM_WAKE_DEFAULT);
+       ps3_sys_manager_send_request_shutdown(dev);
+
+       printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+       while(1)
+               ps3_sys_manager_handle_msg(dev);
+}
+
+static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+{
+       int result;
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       BUG_ON(drv_priv.dev);
+       drv_priv.dev = dev;
+
+       result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
+       BUG_ON(result);
+
+       result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
+               PS3_SM_RX_MSG_LEN);
+       BUG_ON(result);
+
+       return result;
+}
+
+static struct ps3_vuart_port_driver ps3_sys_manager = {
+       .match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+       .core = {
+               .name = "ps3_sys_manager",
+       },
+       .probe = ps3_sys_manager_probe,
+};
+
+static int __init ps3_sys_manager_init(void)
+{
+       return ps3_vuart_port_driver_register(&ps3_sys_manager);
+}
+
+module_init(ps3_sys_manager_init);
index ef8fd4c308757d34efc524d276055aeaaa4c653b..746298107d6fa97d5611f05a0e33d58b717281ed 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <asm/ps3.h>
 
+#include <asm/firmware.h>
 #include <asm/lv1call.h>
 #include <asm/bitops.h>
 
@@ -30,7 +32,7 @@
 
 MODULE_AUTHOR("Sony Corporation");
 MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ps3 vuart");
+MODULE_DESCRIPTION("PS3 vuart");
 
 /**
  * vuart - An inter-partition data link service.
@@ -157,7 +159,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
        unsigned long size;
        unsigned long val;
 
-       result = lv1_get_virtual_uart_param(dev->port_number,
+       result = lv1_get_virtual_uart_param(dev->priv->port_number,
                PARAM_TX_TRIGGER, &trig->tx);
 
        if (result) {
@@ -166,7 +168,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->port_number,
+       result = lv1_get_virtual_uart_param(dev->priv->port_number,
                PARAM_RX_BUF_SIZE, &size);
 
        if (result) {
@@ -175,7 +177,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->port_number,
+       result = lv1_get_virtual_uart_param(dev->priv->port_number,
                PARAM_RX_TRIGGER, &val);
 
        if (result) {
@@ -198,7 +200,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
        int result;
        unsigned long size;
 
-       result = lv1_set_virtual_uart_param(dev->port_number,
+       result = lv1_set_virtual_uart_param(dev->priv->port_number,
                PARAM_TX_TRIGGER, tx);
 
        if (result) {
@@ -207,7 +209,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->port_number,
+       result = lv1_get_virtual_uart_param(dev->priv->port_number,
                PARAM_RX_BUF_SIZE, &size);
 
        if (result) {
@@ -216,7 +218,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
                return result;
        }
 
-       result = lv1_set_virtual_uart_param(dev->port_number,
+       result = lv1_set_virtual_uart_param(dev->priv->port_number,
                PARAM_RX_TRIGGER, size - rx);
 
        if (result) {
@@ -232,9 +234,9 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
 }
 
 static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
-       unsigned long *bytes_waiting)
+       u64 *bytes_waiting)
 {
-       int result = lv1_get_virtual_uart_param(dev->port_number,
+       int result = lv1_get_virtual_uart_param(dev->priv->port_number,
                PARAM_RX_BYTES, bytes_waiting);
 
        if (result)
@@ -253,10 +255,10 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
 
        dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-       dev->interrupt_mask = mask;
+       dev->priv->interrupt_mask = mask;
 
-       result = lv1_set_virtual_uart_param(dev->port_number,
-               PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+       result = lv1_set_virtual_uart_param(dev->priv->port_number,
+               PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
 
        if (result)
                dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -265,62 +267,64 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
        return result;
 }
 
-static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
        unsigned long *status)
 {
-       int result = lv1_get_virtual_uart_param(dev->port_number,
-               PARAM_INTERRUPT_STATUS, status);
+       u64 tmp;
+       int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+               PARAM_INTERRUPT_STATUS, &tmp);
 
        if (result)
                dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
 
+       *status = tmp & dev->priv->interrupt_mask;
+
        dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-               __func__, __LINE__, dev->interrupt_mask, *status,
-               dev->interrupt_mask & *status);
+               __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
 
        return result;
 }
 
 int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                | INTERRUPT_MASK_TX);
 }
 
 int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                | INTERRUPT_MASK_RX);
 }
 
 int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                | INTERRUPT_MASK_DISCONNECT);
 }
 
 int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_TX)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                & ~INTERRUPT_MASK_TX) : 0;
 }
 
 int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_RX)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                & ~INTERRUPT_MASK_RX) : 0;
 }
 
 int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
 {
-       return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+       return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
                & ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
@@ -335,9 +339,7 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
 {
        int result;
 
-       dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
-
-       result = lv1_write_virtual_uart(dev->port_number,
+       result = lv1_write_virtual_uart(dev->priv->port_number,
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
        if (result) {
@@ -346,10 +348,10 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       dev->stats.bytes_written += *bytes_written;
+       dev->priv->stats.bytes_written += *bytes_written;
 
-       dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__,
-               __LINE__, *bytes_written, bytes, dev->stats.bytes_written);
+       dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
+               *bytes_written, bytes, dev->priv->stats.bytes_written);
 
        return result;
 }
@@ -367,7 +369,7 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
 
        dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-       result = lv1_read_virtual_uart(dev->port_number,
+       result = lv1_read_virtual_uart(dev->priv->port_number,
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
        if (result) {
@@ -376,14 +378,57 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
                return result;
        }
 
-       dev->stats.bytes_read += *bytes_read;
+       dev->priv->stats.bytes_read += *bytes_read;
 
        dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-               *bytes_read, bytes, dev->stats.bytes_read);
+               *bytes_read, bytes, dev->priv->stats.bytes_read);
 
        return result;
 }
 
+/**
+ * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @bytes: Max byte count to discard, zero = all pending.
+ *
+ * Used to clear pending rx interrupt source.  Will not block.
+ */
+
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+       unsigned int bytes)
+{
+       int result;
+       u64 bytes_waiting;
+       void* tmp;
+
+       result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting);
+
+       BUG_ON(result);
+
+       bytes = bytes ? min(bytes, (unsigned int)bytes_waiting) : bytes_waiting;
+
+       dev_dbg(&dev->core, "%s:%d: %u\n", __func__, __LINE__, bytes);
+
+       if (!bytes)
+               return;
+
+       /* Add some extra space for recently arrived data. */
+
+       bytes += 128;
+
+       tmp = kmalloc(bytes, GFP_KERNEL);
+
+       if (!tmp)
+               return;
+
+       ps3_vuart_raw_read(dev, tmp, bytes, &bytes_waiting);
+
+       kfree(tmp);
+
+       /* Don't include these bytes in the stats. */
+
+       dev->priv->stats.bytes_read -= bytes_waiting;
+}
+
 /**
  * struct list_buffer - An element for a port device fifo buffer list.
  */
@@ -416,14 +461,14 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
                bytes, bytes);
 
-       spin_lock_irqsave(&dev->tx_list.lock, flags);
+       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
 
-       if (list_empty(&dev->tx_list.head)) {
+       if (list_empty(&dev->priv->tx_list.head)) {
                unsigned long bytes_written;
 
                result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-               spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+               spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
                if (result) {
                        dev_dbg(&dev->core,
@@ -441,7 +486,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
                bytes -= bytes_written;
                buf += bytes_written;
        } else
-               spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+               spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
        lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -454,10 +499,10 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
        lb->tail = lb->data + bytes;
        lb->dbg_number = ++dbg_number;
 
-       spin_lock_irqsave(&dev->tx_list.lock, flags);
-       list_add_tail(&lb->link, &dev->tx_list.head);
+       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+       list_add_tail(&lb->link, &dev->priv->tx_list.head);
        ps3_vuart_enable_interrupt_tx(dev);
-       spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+       spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
        dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
                __func__, __LINE__, lb->dbg_number, bytes);
@@ -484,47 +529,83 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
                bytes, bytes);
 
-       spin_lock_irqsave(&dev->rx_list.lock, flags);
+       spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
 
-       if (dev->rx_list.bytes_held < bytes) {
-               spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+       if (dev->priv->rx_list.bytes_held < bytes) {
+               spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
                dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-                       __func__, __LINE__, bytes - dev->rx_list.bytes_held);
+                       __func__, __LINE__,
+                       bytes - dev->priv->rx_list.bytes_held);
                return -EAGAIN;
        }
 
-       list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) {
+       list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
                bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
                memcpy(buf, lb->head, bytes_read);
                buf += bytes_read;
                bytes -= bytes_read;
-               dev->rx_list.bytes_held -= bytes_read;
+               dev->priv->rx_list.bytes_held -= bytes_read;
 
                if (bytes_read < lb->tail - lb->head) {
                        lb->head += bytes_read;
-                       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
-
-                       dev_dbg(&dev->core,
-                               "%s:%d: dequeued buf_%lu, %lxh bytes\n",
-                               __func__, __LINE__, lb->dbg_number, bytes_read);
+                       dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
+                               "bytes\n", __func__, __LINE__, lb->dbg_number,
+                               bytes_read);
+                       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
                        return 0;
                }
 
-               dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
-                       lb->dbg_number);
+               dev_dbg(&dev->core, "%s:%d: buf_%lu: free, dequeued %lxh "
+                       "bytes\n", __func__, __LINE__, lb->dbg_number,
+                       bytes_read);
 
                list_del(&lb->link);
                kfree(lb);
        }
-       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
 
-       dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n",
-               __func__, __LINE__, lb->dbg_number, bytes);
+       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+       return 0;
+}
+
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+       unsigned int bytes)
+{
+       unsigned long flags;
+
+       if(dev->priv->work.trigger) {
+               dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
+                       __func__, __LINE__);
+               return -EAGAIN;
+       }
+
+       BUG_ON(!bytes);
+
+       PREPARE_WORK(&dev->priv->work.work, func);
+
+       spin_lock_irqsave(&dev->priv->work.lock, flags);
+       if(dev->priv->rx_list.bytes_held >= bytes) {
+               dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
+                       __func__, __LINE__, bytes);
+               schedule_work(&dev->priv->work.work);
+               spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+               return 0;
+       }
+
+       dev->priv->work.trigger = bytes;
+       spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+
+       dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
+               __LINE__, bytes, bytes);
 
        return 0;
 }
 
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+{
+       dev->priv->work.trigger = 0;
+}
+
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
  *
@@ -542,9 +623,9 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-       spin_lock_irqsave(&dev->tx_list.lock, flags);
+       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
 
-       list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+       list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
 
                unsigned long bytes_written;
 
@@ -578,7 +659,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
 
        ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-       spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+       spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
        dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
                __func__, __LINE__, bytes_total);
        return result;
@@ -609,7 +690,7 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
 
        BUG_ON(!bytes);
 
-       /* add some extra space for recently arrived data */
+       /* Add some extra space for recently arrived data. */
 
        bytes += 128;
 
@@ -624,14 +705,23 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
        lb->tail = lb->data + bytes;
        lb->dbg_number = ++dbg_number;
 
-       spin_lock_irqsave(&dev->rx_list.lock, flags);
-       list_add_tail(&lb->link, &dev->rx_list.head);
-       dev->rx_list.bytes_held += bytes;
-       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+       spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+       list_add_tail(&lb->link, &dev->priv->rx_list.head);
+       dev->priv->rx_list.bytes_held += bytes;
+       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
 
-       dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+       dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
                __func__, __LINE__, lb->dbg_number, bytes);
 
+       spin_lock_irqsave(&dev->priv->work.lock, flags);
+       if(dev->priv->work.trigger
+               && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+               dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
+                       __func__, __LINE__, dev->priv->work.trigger);
+               dev->priv->work.trigger = 0;
+               schedule_work(&dev->priv->work.work);
+       }
+       spin_unlock_irqrestore(&dev->priv->work.lock, flags);
        return 0;
 }
 
@@ -656,7 +746,7 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
        int result;
        unsigned long status;
 
-       result = ps3_vuart_get_interrupt_mask(dev, &status);
+       result = ps3_vuart_get_interrupt_status(dev, &status);
 
        if (result)
                return result;
@@ -665,21 +755,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
                status);
 
        if (status & INTERRUPT_MASK_DISCONNECT) {
-               dev->stats.disconnect_interrupts++;
+               dev->priv->stats.disconnect_interrupts++;
                result = ps3_vuart_handle_interrupt_disconnect(dev);
                if (result)
                        ps3_vuart_disable_interrupt_disconnect(dev);
        }
 
        if (status & INTERRUPT_MASK_TX) {
-               dev->stats.tx_interrupts++;
+               dev->priv->stats.tx_interrupts++;
                result = ps3_vuart_handle_interrupt_tx(dev);
                if (result)
                        ps3_vuart_disable_interrupt_tx(dev);
        }
 
        if (status & INTERRUPT_MASK_RX) {
-               dev->stats.rx_interrupts++;
+               dev->priv->stats.rx_interrupts++;
                result = ps3_vuart_handle_interrupt_rx(dev);
                if (result)
                        ps3_vuart_disable_interrupt_rx(dev);
@@ -688,12 +778,13 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
        return 0;
 }
 
-struct vuart_private {
-       unsigned int in_use;
+struct vuart_bus_priv {
+       const struct ports_bmp bmp;
        unsigned int virq;
+       struct semaphore probe_mutex;
+       int use_count;
        struct ps3_vuart_port_device *devices[PORT_COUNT];
-       const struct ports_bmp bmp;
-};
+} static vuart_bus_priv;
 
 /**
  * ps3_vuart_irq_handler - first stage interrupt handler
@@ -705,25 +796,25 @@ struct vuart_private {
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-       struct vuart_private *private;
+       struct vuart_bus_priv *bus_priv;
 
        BUG_ON(!_private);
-       private = (struct vuart_private *)_private;
+       bus_priv = (struct vuart_bus_priv *)_private;
 
        while (1) {
                unsigned int port;
 
-               dump_ports_bmp(&private->bmp);
+               dump_ports_bmp(&bus_priv->bmp);
 
-               port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+               port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
 
                if (port == BITS_PER_LONG)
                        break;
 
                BUG_ON(port >= PORT_COUNT);
-               BUG_ON(!private->devices[port]);
+               BUG_ON(!bus_priv->devices[port]);
 
-               ps3_vuart_handle_port_interrupt(private->devices[port]);
+               ps3_vuart_handle_port_interrupt(bus_priv->devices[port]);
        }
 
        return IRQ_HANDLED;
@@ -744,12 +835,10 @@ static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
        return result;
 }
 
-static struct vuart_private vuart_private;
-
 static int ps3_vuart_probe(struct device *_dev)
 {
        int result;
-       unsigned long tmp;
+       unsigned int port_number;
        struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
        struct ps3_vuart_port_driver *drv =
                to_ps3_vuart_port_driver(_dev->driver);
@@ -758,7 +847,12 @@ static int ps3_vuart_probe(struct device *_dev)
 
        BUG_ON(!drv);
 
-       result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+       down(&vuart_bus_priv.probe_mutex);
+
+       /* Setup vuart_bus_priv.devices[]. */
+
+       result = ps3_vuart_match_id_to_port(dev->match_id,
+               &port_number);
 
        if (result) {
                dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
@@ -767,24 +861,41 @@ static int ps3_vuart_probe(struct device *_dev)
                goto fail_match;
        }
 
-       if (vuart_private.devices[dev->port_number]) {
+       if (vuart_bus_priv.devices[port_number]) {
                dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-                       __LINE__, dev->port_number);
+                       __LINE__, port_number);
                result = -EBUSY;
                goto fail_match;
        }
 
-       vuart_private.devices[dev->port_number] = dev;
+       vuart_bus_priv.devices[port_number] = dev;
+
+       /* Setup dev->priv. */
+
+       dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+
+       if (!dev->priv) {
+               result = -ENOMEM;
+               goto fail_alloc;
+       }
 
-       INIT_LIST_HEAD(&dev->tx_list.head);
-       spin_lock_init(&dev->tx_list.lock);
-       INIT_LIST_HEAD(&dev->rx_list.head);
-       spin_lock_init(&dev->rx_list.lock);
+       dev->priv->port_number = port_number;
+
+       INIT_LIST_HEAD(&dev->priv->tx_list.head);
+       spin_lock_init(&dev->priv->tx_list.lock);
+
+       INIT_LIST_HEAD(&dev->priv->rx_list.head);
+       spin_lock_init(&dev->priv->rx_list.lock);
+
+       INIT_WORK(&dev->priv->work.work, NULL);
+       spin_lock_init(&dev->priv->work.lock);
+       dev->priv->work.trigger = 0;
+       dev->priv->work.dev = dev;
+
+       if (++vuart_bus_priv.use_count == 1) {
 
-       vuart_private.in_use++;
-       if (vuart_private.in_use == 1) {
                result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
-                       (void*)&vuart_private.bmp.status, &vuart_private.virq);
+                       (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
 
                if (result) {
                        dev_dbg(&dev->core,
@@ -794,8 +905,8 @@ static int ps3_vuart_probe(struct device *_dev)
                        goto fail_alloc_irq;
                }
 
-               result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
-                       IRQF_DISABLED, "vuart", &vuart_private);
+               result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+                       IRQF_DISABLED, "vuart", &vuart_bus_priv);
 
                if (result) {
                        dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
@@ -804,10 +915,11 @@ static int ps3_vuart_probe(struct device *_dev)
                }
        }
 
-       ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
-
        /* clear stale pending interrupts */
-       ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+       ps3_vuart_clear_rx_bytes(dev, 0);
+
+       ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
 
        ps3_vuart_set_triggers(dev, 1, 1);
 
@@ -822,20 +934,27 @@ static int ps3_vuart_probe(struct device *_dev)
        if (result) {
                dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
                        __func__, __LINE__);
+               down(&vuart_bus_priv.probe_mutex);
                goto fail_probe;
        }
 
+       up(&vuart_bus_priv.probe_mutex);
+
        return result;
 
 fail_probe:
+       ps3_vuart_set_interrupt_mask(dev, 0);
 fail_request_irq:
-       vuart_private.in_use--;
-       if (!vuart_private.in_use) {
-               ps3_free_vuart_irq(vuart_private.virq);
-               vuart_private.virq = NO_IRQ;
-       }
+       ps3_free_vuart_irq(vuart_bus_priv.virq);
+       vuart_bus_priv.virq = NO_IRQ;
 fail_alloc_irq:
+       --vuart_bus_priv.use_count;
+       kfree(dev->priv);
+       dev->priv = NULL;
+fail_alloc:
+       vuart_bus_priv.devices[port_number] = 0;
 fail_match:
+       up(&vuart_bus_priv.probe_mutex);
        dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
        return result;
 }
@@ -846,10 +965,12 @@ static int ps3_vuart_remove(struct device *_dev)
        struct ps3_vuart_port_driver *drv =
                to_ps3_vuart_port_driver(_dev->driver);
 
+       down(&vuart_bus_priv.probe_mutex);
+
        dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
                dev->core.bus_id);
 
-       BUG_ON(vuart_private.in_use < 1);
+       BUG_ON(vuart_bus_priv.use_count < 1);
 
        if (drv->remove)
                drv->remove(dev);
@@ -857,13 +978,19 @@ static int ps3_vuart_remove(struct device *_dev)
                dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
                        __LINE__, dev->core.bus_id);
 
-       vuart_private.in_use--;
+       vuart_bus_priv.devices[dev->priv->port_number] = 0;
 
-       if (!vuart_private.in_use) {
-               free_irq(vuart_private.virq, &vuart_private);
-               ps3_free_vuart_irq(vuart_private.virq);
-               vuart_private.virq = NO_IRQ;
+       if (--vuart_bus_priv.use_count == 0) {
+               BUG();
+               free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+               ps3_free_vuart_irq(vuart_bus_priv.virq);
+               vuart_bus_priv.virq = NO_IRQ;
        }
+
+       kfree(dev->priv);
+       dev->priv = NULL;
+
+       up(&vuart_bus_priv.probe_mutex);
        return 0;
 }
 
@@ -884,12 +1011,12 @@ static void ps3_vuart_shutdown(struct device *_dev)
 }
 
 /**
- * ps3_vuart - The vuart instance.
+ * ps3_vuart_bus - The vuart bus instance.
  *
  * The vuart is managed as a bus that port devices connect to.
  */
 
-struct bus_type ps3_vuart = {
+struct bus_type ps3_vuart_bus = {
         .name = "ps3_vuart",
        .match = ps3_vuart_match,
        .probe = ps3_vuart_probe,
@@ -897,24 +1024,30 @@ struct bus_type ps3_vuart = {
        .shutdown = ps3_vuart_shutdown,
 };
 
-int __init ps3_vuart_init(void)
+int __init ps3_vuart_bus_init(void)
 {
        int result;
 
        pr_debug("%s:%d:\n", __func__, __LINE__);
-       result = bus_register(&ps3_vuart);
+
+       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+               return 0;
+
+       init_MUTEX(&vuart_bus_priv.probe_mutex);
+       result = bus_register(&ps3_vuart_bus);
        BUG_ON(result);
+
        return result;
 }
 
-void __exit ps3_vuart_exit(void)
+void __exit ps3_vuart_bus_exit(void)
 {
        pr_debug("%s:%d:\n", __func__, __LINE__);
-       bus_unregister(&ps3_vuart);
+       bus_unregister(&ps3_vuart_bus);
 }
 
-core_initcall(ps3_vuart_init);
-module_exit(ps3_vuart_exit);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
 
 /**
  * ps3_vuart_port_release_device - Remove a vuart port device.
@@ -922,11 +1055,14 @@ module_exit(ps3_vuart_exit);
 
 static void ps3_vuart_port_release_device(struct device *_dev)
 {
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 #if defined(DEBUG)
-       memset(dev, 0xad, sizeof(struct ps3_vuart_port_device));
+       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       BUG_ON(dev->priv && "forgot to free");
+       memset(&dev->core, 0, sizeof(dev->core));
 #endif
-       kfree(dev);
 }
 
 /**
@@ -935,11 +1071,12 @@ static void ps3_vuart_port_release_device(struct device *_dev)
 
 int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
 {
-       int result;
        static unsigned int dev_count = 1;
 
+       BUG_ON(dev->priv && "forgot to free");
+
        dev->core.parent = NULL;
-       dev->core.bus = &ps3_vuart;
+       dev->core.bus = &ps3_vuart_bus;
        dev->core.release = ps3_vuart_port_release_device;
 
        snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
@@ -947,9 +1084,7 @@ int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
 
        dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
 
-       result = device_register(&dev->core);
-
-       return result;
+       return device_register(&dev->core);
 }
 
 EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
@@ -963,7 +1098,7 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
        int result;
 
        pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-       drv->core.bus = &ps3_vuart;
+       drv->core.bus = &ps3_vuart_bus;
        result = driver_register(&drv->core);
        return result;
 }
@@ -976,6 +1111,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
+       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
        driver_unregister(&drv->core);
 }
 
index 2cbf728a3a0bfaec295ea31a1d580390d13ed4a4..1be992d568c8344afe0d280886ae7e869ea9fcb8 100644 (file)
 #if !defined(_PS3_VUART_H)
 #define _PS3_VUART_H
 
+#include <asm/ps3.h>
+
+struct ps3_vuart_stats {
+       unsigned long bytes_written;
+       unsigned long bytes_read;
+       unsigned long tx_interrupts;
+       unsigned long rx_interrupts;
+       unsigned long disconnect_interrupts;
+};
+
+struct ps3_vuart_work {
+       struct work_struct work;
+       unsigned long trigger;
+       spinlock_t lock;
+       struct ps3_vuart_port_device* dev; /* to convert work to device */
+};
+
+/**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+       unsigned int port_number;
+       u64 interrupt_mask;
+
+       struct {
+               spinlock_t lock;
+               struct list_head head;
+       } tx_list;
+       struct {
+               unsigned long bytes_held;
+               spinlock_t lock;
+               struct list_head head;
+       } rx_list;
+       struct ps3_vuart_stats stats;
+       struct ps3_vuart_work work;
+};
+
 /**
  * struct ps3_vuart_port_driver - a driver for a device on a vuart port
  */
@@ -41,10 +79,6 @@ struct ps3_vuart_port_driver {
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev,
-       const void* buf, unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
-       unsigned int bytes);
 static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
        struct device_driver *_drv)
 {
@@ -55,5 +89,22 @@ static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
 {
        return container_of(_dev, struct ps3_vuart_port_device, core);
 }
+static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+       struct work_struct *_work)
+{
+       struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
+               work);
+       return vw->dev;
+}
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+       unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+       unsigned int bytes);
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+       unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+       unsigned int bytes);
 
 #endif
index 5687b8fcbf93d4f62e7a666704dc512cf06b3397..eed91434417d7d39e86a2bca4602700e8dfe3177 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/rio.h>
 #include <linux/rio_drv.h>
 #include <linux/stat.h>
-#include <linux/sched.h>       /* for capable() */
 
 #include "rio.h"
 
index d59880d44fba26e3555c46d000c13a65e12d3ec4..9de8d67f4f8d8ac71bcbc4c198d4b496d8c4dc27 100644 (file)
@@ -417,13 +417,13 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev)
                rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
 
        /* handle periodic and alarm irqs */
-       if (request_irq(omap_rtc_timer, rtc_irq, SA_INTERRUPT,
+       if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
                        rtc->class_dev.class_id, &rtc->class_dev)) {
                pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
                        pdev->name, omap_rtc_timer);
                goto fail0;
        }
-       if (request_irq(omap_rtc_alarm, rtc_irq, SA_INTERRUPT,
+       if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
                        rtc->class_dev.class_id, &rtc->class_dev)) {
                pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
                        pdev->name, omap_rtc_alarm);
index f406a2b55aea829b48e05b53180e40e8b1a48a04..9a79a24a74874189deab5885af6ea98c6de50746 100644 (file)
@@ -350,7 +350,7 @@ static int s3c_rtc_open(struct device *dev)
        int ret;
 
        ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
-                         SA_INTERRUPT,  "s3c2410-rtc alarm", rtc_dev);
+                         IRQF_DISABLED,  "s3c2410-rtc alarm", rtc_dev);
 
        if (ret) {
                dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
@@ -358,7 +358,7 @@ static int s3c_rtc_open(struct device *dev)
        }
 
        ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
-                         SA_INTERRUPT,  "s3c2410-rtc tick", rtc_dev);
+                         IRQF_DISABLED,  "s3c2410-rtc tick", rtc_dev);
 
        if (ret) {
                dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
index 90536f60bf502f0410c13607d0b0555c494ae374..076816b9d52874776ddb576dca5c3b6773a0ebe9 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/err.h>
index 544f137d70d7e184a04172330ddae4ce1d6561d6..f77dc33b5f8dfb0c83685ab4a11b472162f7d0fe 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/major.h>
index 5a84fbbc6611de06d3c51ce4a9c98218854e1848..0d6d5fcc128b8231d3b53d87ae762a4a83075bd8 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 
 #include <linux/signal.h>
index 6387b483f2bfe32fb7c7875fa28fe5b742222e67..594320ca1b7c96ae7e69284017e6d77edb0e691e 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 
 #include <linux/signal.h>
index 0cfd1e4c032c479c3ac7c5be5122e0195c4e45d9..022e869c44ddf77373370e4b0ee57e49342b9508 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/major.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
index e8776230782b28669606da71a427e591497142ed..eec28c142a590f28f7a9be87d4fbf7f74641d1ea 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 4d1a505e9e74e0bfe090fa557656dce8796ff178..45cf5bc0bbee210f1d3b9106a80194e4937aef66 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 37a04a0cecfa9449cdc6e1547e77a97eafa9d90c..8bfb67ccdcd46fef77963273ac055f8e1b539638 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
index ceec30648f4f65edd8f336536a28f79bdd2c1d4d..9efed771f6c03bab2e7187b01d3f772790fd177e 100644 (file)
@@ -14,7 +14,7 @@
 /* NOTE: It seems to me that the documentation regarding the
 pcd8584t/pcf8584 does not show the correct way to address the i2c bus.
 Based on the information on the I2C bus itself and the remainder of
-the Phillips docs the following algorithims apper to be correct.  I am
+the Phillips docs the following algorithms appear to be correct.  I am
 fairly certain that the flowcharts in the phillips docs are wrong. */
 
 
index 88e061d13d0bd69355e6f060b7a8b9c5e5e331fb..cb02656eb54c1e9592fd552f1014a556981ca8e0 100644 (file)
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
index 5bf3f07870ba14f86a5805e3e9f13260420ba564..4cd280e86966cfe9957a41ab1bdd12cf76223242 100644 (file)
@@ -230,6 +230,7 @@ config SCSI_SCAN_ASYNC
          The SCSI subsystem can probe for devices while the rest of the
          system continues booting, and even probe devices on different
          busses in parallel, leading to a significant speed-up.
+
          If you have built SCSI as modules, enabling this option can
          be a problem as the devices may not have been found by the
          time your system expects them to have been.  You can load the
@@ -237,8 +238,8 @@ config SCSI_SCAN_ASYNC
          If you build your SCSI drivers into the kernel, then everything
          will work fine if you say Y here.
 
-         You can override this choice by specifying scsi_mod.scan="sync"
-         or "async" on the kernel's command line.
+         You can override this choice by specifying "scsi_mod.scan=sync"
+         or async on the kernel's command line.
 
 menu "SCSI Transports"
        depends on SCSI
index 8578555d58fd08f79a4515af12c7f9e990d8cdd4..7c0b17f8690331fdb39390d29c939118fd2c3d0d 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
index 2650a5d0a161f34b03ba19e224e4752ea0e4dae7..7f4241bfb9c437dcadf63f21913f803cccfdbae7 100644 (file)
@@ -1067,7 +1067,7 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev,
                goto out_disable_device;
        }
 
-       /* <02> read from base address + 0x50 offset to get the bios balue. */
+       /* <02> read from base address + 0x50 offset to get the bios value. */
        bios = ORC_RDWORD(port, 0x50);
 
 
index f77016d31cabc2966af6714af61add4add1f4ffc..b7c5385e2efe2fb8c04d8892d936b46ae5570137 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
index 1299bc8edef18b3a435a004e307418fea27598ba..796f1c4d772e1f5933b700c0b23826fb5f6ed43d 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
index ddb33b06e0efffcbaf27b43b13c5102c34b1e7f2..d789e61bdc49f8cb1e6df119f93bcf8b4ec74b9a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index da1d3a9212f8083da498919fb956bc0c44b9eea7..e21070f4eac16a68c74926fbde4006fbc14dedba 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index df67ba686023d891a234c3ed9e577a632847e1db..ae34768987a4d28a565b9ab40001a4fce378fdf2 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index 8335f07b77205700c9184109d3a0039efdd1566f..d38b628be1ada395311d5b18265b66bcd1022c5d 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index c632d9354a261a5af10e9407f38d04bfcabd9bd3..d242e2611d672dc4df6a2a985187483cd99a2384 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index 8535db068c2f7de3dcd51a824a2ad47064083414..6f1a1780efce4e8e4a4a2f82564e81f498ad299f 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index 0cec742d12e9dc52bf4f895d2a20ec1feece0cae..4b4d1233ce8a95e60e885b9575b505dc4f34d9e1 100644 (file)
  **************************************************************************/
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <asm/irq.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
index c7fe478f481377d4b7add47574c6c3463dbd7b7a..2be03e975d97109e371a30b1668dd22d6eb345e5 100644 (file)
@@ -418,7 +418,6 @@ ahd_linux_info(struct Scsi_Host *host)
        strcat(bp, "        ");
        ahd_controller_info(ahd, ahd_info);
        strcat(bp, ahd_info);
-       strcat(bp, "\n");
 
        return (bp);
 }
index 7d1fec620948bd11f1c90c043fbb88b450a5b6e1..a988d5abf7022eb8b8bac46785798ffedf3eff1a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
index bc7744e35ad0369a27d7e3b38a3e0048bf047ce2..27852b43b9044a829ffc2d3c4bc3ff5fe09885a4 100644 (file)
@@ -653,7 +653,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
        if (use_msi)
                pci_enable_msi(asd_ha->pcidev);
 
-       err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, SA_SHIRQ,
+       err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, IRQF_SHARED,
                          ASD_DRIVER_NAME, asd_ha);
        if (err) {
                asd_printk("couldn't get irq %d for %s\n",
index eae7a247becebf8d6f512dcd7fba384aa5aa7957..c750fbf7013bb74b525cb77641e5c5daae246420 100644 (file)
@@ -44,7 +44,6 @@
 #define PAUSE_TRIES 1000
 
 static const struct firmware *sequencer_fw;
-static const char *sequencer_version;
 static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task,
        cseq_idle_loop, lseq_idle_loop;
 static u8 *cseq_code, *lseq_code;
@@ -1276,7 +1275,6 @@ static int asd_request_firmware(struct asd_ha_struct *asd_ha)
        header.csum = le32_to_cpu(hdr_ptr->csum);
        header.major = le32_to_cpu(hdr_ptr->major);
        header.minor = le32_to_cpu(hdr_ptr->minor);
-       sequencer_version = hdr_ptr->version;
        header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset);
        header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size);
        header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset);
@@ -1303,6 +1301,16 @@ static int asd_request_firmware(struct asd_ha_struct *asd_ha)
                return -EINVAL;
        }
 
+       asd_printk("Found sequencer Firmware version %d.%d (%s)\n",
+                  header.major, header.minor, hdr_ptr->version);
+
+       if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) {
+               asd_printk("Firmware Major Version Mismatch;"
+                          "driver requires version %d.X",
+                          SAS_RAZOR_SEQUENCER_FW_MAJOR);
+               return -EINVAL;
+       }
+
        ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset];
        ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset];
        mode2_task = header.mode2_task;
@@ -1335,7 +1343,6 @@ int asd_init_seqs(struct asd_ha_struct *asd_ha)
                return err;
        }
 
-       asd_printk("using sequencer %s\n", sequencer_version);
        err = asd_seq_download_seqs(asd_ha);
        if (err) {
                asd_printk("couldn't download sequencers for %s\n",
index 9437ff0ae3a4f6ce9852c8c08a2b48588db3ea2b..2ea6a0d5220896aec7426b60155bc701cd937718 100644 (file)
@@ -31,6 +31,7 @@
 #define LSEQ_NUM_VECS  11
 
 #define SAS_RAZOR_SEQUENCER_FW_FILE "aic94xx-seq.fw"
+#define SAS_RAZOR_SEQUENCER_FW_MAJOR   1
 
 /* Note:  All quantites in the sequencer file are little endian */
 struct sequencer_file_header {
index 9099d531d5a4402cb401ee0f97bf6f2efe96e51d..d5d3c4d5a253966986eedbfd0ed0a618153ac2aa 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/zorro.h>
 #include <linux/stat.h>
 
index 086cc97eee8c31e393cc19949eb8cc93391ca47f..8b46158cc0454a31e7ebd7128aa54d946ad33877 100644 (file)
@@ -322,7 +322,7 @@ static int arcmsr_probe(struct pci_dev *pdev,
                goto out_iounmap;
 
        error = request_irq(pdev->irq, arcmsr_do_interrupt,
-                       SA_INTERRUPT | SA_SHIRQ, "arcmsr", acb);
+                       IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
        if (error)
                goto out_free_ccb_pool;
 
index 9cf902b7a12686923e036905d43acd2138eebcdd..eceacf6d49eacb6da78c9c9e180f3e05ef641345 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index 4385e9e3ded68abbe895189866e415c989f5c5f5..7e132c5bacf83a705bdfcf767b5e93c78de7155e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
index 3bdfc36481ae8f8e7c8b0ea1c7ddba83f4465db7..cf9a21cea6d9309b88aa4cb69b2d2addc53aa7a1 100644 (file)
@@ -5,7 +5,6 @@
  */
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
index 19edd9c853d9fe35fd9406afedb3e58c49aa4c28..d2d51dc51ab83727f8761ab7c25425ac32ad77a3 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 6adcccbf444b1a34b5ec0c0f2fa1b2abea6bb20e..378e7af0c5d6760750fe18c9105b1707fdf05527 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
index 3f876fb754693c7ab61496ad49dcda5f66656dd0..d4136524fc46aafc3f794a5f3a37975177535636 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -197,7 +196,7 @@ static void eesoxscsi_buffer_in(void *buf, int length, void __iomem *base)
        const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
        const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
        const void __iomem *reg_dmadata = base + EESOX_DMADATA;
-       const register unsigned long mask = 0xffff;
+       register const unsigned long mask = 0xffff;
 
        do {
                unsigned int status;
index e05f0c2fc9123a7948216d785c0c6d36e172b533..2969cc0ff2599229e8e092de1d35f86c30daa6df 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
index d806b024c3bda264126f0b679389c11c91a5a8d9..c21b8392c92837ec2af15d43acbb8acdd1bbe22d 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
index ce159c15bc86eae5e711136616e8f68aaf20f985..f9cd20bfb95890f9ae79cb1d162e41865bf12f4f 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index dfb1bcfae82ebe834812e3dd8738b227110fc8c9..642de7b2b7a2596bdeac54bc1ea05105ad6c08ae 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/nvram.h>
index 2958b8c2bfb7080aff8830f0a705a05bb59043f6..599b400a3c432267689c1e8155906355f2a9bbbd 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/zorro.h>
 
 #include <asm/setup.h>
index d02759f1346988245509e0bdb64afc92ba952e1b..2a2cc6cf1182a9cdaa2ebf0df1c2b9e15b4b37e3 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/major.h>
 #include <linux/string.h>
index 54756722dd5f74c000fde0fb1661eec92fe512c0..9d52e45c7d36170a47f6e7da98ee179093a28336 100644 (file)
@@ -75,7 +75,6 @@
 #include <asm/system.h>
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/stat.h>
index 2dbb66d2f0a7398c791e3f51be5f256d06182cf9..f33ad01064a9d8b0f8696331bd6d90da1fbbef3a 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
index cdd893bb4e28156e43a1d83b5eda37592b2b1bd6..880f70d24e6511e9fe92d5db66abe27b8aab4487 100644 (file)
 #include <asm/system.h>
 #include <asm/io.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/blkdev.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
index a1992928e6710ec4ff4dc2a0ab5f93a10b4e7bfa..8c81cec852982cf1a116991e42cd22ec07360d00 100644 (file)
 #include <linux/ctype.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/proc_fs.h>
index 2f6c1137a6e5ffb5fa45c39728be80e954b0bb4f..37741e9b5c3b297380f4203376041333b4958ad2 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
index e28260f05d6be7fa511824d9cf6815ec0d280b11..4368ca0e8270b7a4b9b8d75596dcbb79d906c0c6 100644 (file)
@@ -580,7 +580,7 @@ static int crq_queue_create(struct crq_queue *queue, struct srp_target *target)
        }
 
        err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt,
-                         SA_INTERRUPT, "ibmvstgt", target);
+                         IRQF_DISABLED, "ibmvstgt", target);
        if (err)
                goto req_irq_failed;
 
index 8f6b5bf580f6757fdcace40c5a41eb5359827d98..2b5b8a93bc10756ed801eb7ea06f31265cb0ecbb 100644 (file)
@@ -801,15 +801,10 @@ static int idescsi_ide_open(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct ide_scsi_obj *scsi;
-       ide_drive_t *drive;
 
        if (!(scsi = ide_scsi_get(disk)))
                return -ENXIO;
 
-       drive = scsi->drive;
-
-       drive->usage++;
-
        return 0;
 }
 
@@ -817,9 +812,6 @@ static int idescsi_ide_release(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct ide_scsi_obj *scsi = ide_scsi_g(disk);
-       ide_drive_t *drive = scsi->drive;
-
-       drive->usage--;
 
        ide_scsi_put(scsi);
 
index d561663fb4e41cfcce5716a9be8adf362a10f7a6..7e7635ca78f1835c12db4db76fd4bcccf69be0b7 100644 (file)
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/dma-mapping.h>
index 2aae1b081fcf405ee864f0284effe43ff3e45aec..5c32a69e41badc764b7b5143fdf24a703895a46c 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/dma-mapping.h>
 
index afca45cdbcefa0b29356ec8267697c8c029be4ef..9d014e5a81c4ca438dce73dfde3d295acdbf166d 100644 (file)
@@ -518,6 +518,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
        uint32_t event_data;
+       /* If the pci channel is offline, ignore possible errors,
+        * since we cannot communicate with the pci card anyway. */
+       if (pci_channel_offline(phba->pcidev))
+               return;
 
        if (phba->work_hs & HS_FFER6 ||
            phba->work_hs & HS_FFER5) {
@@ -1797,6 +1801,92 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
+/**
+ * lpfc_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
+                               pci_channel_state_t state)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring  *pring;
+
+       if (state == pci_channel_io_perm_failure) {
+               lpfc_pci_remove_one(pdev);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       pci_disable_device(pdev);
+       /*
+        * There may be I/Os dropped by the firmware.
+        * Error iocb (I/O) on txcmplq and let the SCSI layer
+        * retry it after re-establishing link.
+        */
+       pring = &psli->ring[psli->fcp_ring];
+       lpfc_sli_abort_iocb_ring(phba, pring);
+
+       /* Request a slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * lpfc_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ */
+static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+       struct lpfc_sli *psli = &phba->sli;
+       int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+       dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
+       if (pci_enable_device_bars(pdev, bars)) {
+               printk(KERN_ERR "lpfc: Cannot re-enable "
+                       "PCI device after reset.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       pci_set_master(pdev);
+
+       /* Re-establishing Link */
+       spin_lock_irq(phba->host->host_lock);
+       phba->fc_flag |= FC_ESTABLISH_LINK;
+       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+       spin_unlock_irq(phba->host->host_lock);
+
+
+       /* Take device offline; this will perform cleanup */
+       lpfc_offline(phba);
+       lpfc_sli_brdrestart(phba);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * lpfc_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation.
+ */
+static void lpfc_io_resume(struct pci_dev *pdev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+
+       if (lpfc_online(phba) == 0) {
+               mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+       }
+}
+
 static struct pci_device_id lpfc_id_table[] = {
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
                PCI_ANY_ID, PCI_ANY_ID, },
@@ -1857,11 +1947,18 @@ static struct pci_device_id lpfc_id_table[] = {
 
 MODULE_DEVICE_TABLE(pci, lpfc_id_table);
 
+static struct pci_error_handlers lpfc_err_handler = {
+       .error_detected = lpfc_io_error_detected,
+       .slot_reset = lpfc_io_slot_reset,
+       .resume = lpfc_io_resume,
+};
+
 static struct pci_driver lpfc_driver = {
        .name           = LPFC_DRIVER_NAME,
        .id_table       = lpfc_id_table,
        .probe          = lpfc_pci_probe_one,
        .remove         = __devexit_p(lpfc_pci_remove_one),
+       .err_handler = &lpfc_err_handler,
 };
 
 static int __init
index a4128e19338af4e74e843cfcc1588c74eadde0fe..9fb6960a8adaca023b7faad67187f5c378c50e00 100644 (file)
@@ -2104,6 +2104,10 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
        volatile uint32_t word0, ldata;
        void __iomem *to_slim;
 
+       /* If the PCI channel is in offline state, do not post mbox. */
+       if (unlikely(pci_channel_offline(phba->pcidev)))
+               return MBX_NOT_FINISHED;
+
        psli = &phba->sli;
 
        spin_lock_irqsave(phba->host->host_lock, drvr_flag);
@@ -2407,6 +2411,10 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        struct lpfc_iocbq *nextiocb;
        IOCB_t *iocb;
 
+       /* If the PCI channel is in offline state, do not post iocbs. */
+       if (unlikely(pci_channel_offline(phba->pcidev)))
+               return IOCB_ERROR;
+
        /*
         * We should never get an IOCB if we are in a < LINK_DOWN state
         */
@@ -3154,6 +3162,10 @@ lpfc_intr_handler(int irq, void *dev_id)
        if (unlikely(!phba))
                return IRQ_NONE;
 
+       /* If the pci channel is offline, ignore all the interrupts. */
+       if (unlikely(pci_channel_offline(phba->pcidev)))
+               return IRQ_NONE;
+
        phba->sli.slistat.sli_intr++;
 
        /*
index a942a21dd87eaf78610e04f86933ce76b0ef7815..cdbcaa5ad6cfbcd2b7cb89f34828515784bf12e5 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
index 808a1b8c40431946982847dd446223e396f87b8d..0aa3304f6b9be310982fe2e8ba80c1c841c9c8a4 100644 (file)
@@ -5072,7 +5072,7 @@ static int __init megaraid_init(void)
                                "megaraid: failed to create megaraid root\n");
        }
 #endif
-       error = pci_module_init(&megaraid_pci_driver);
+       error = pci_register_driver(&megaraid_pci_driver);
        if (error) {
 #ifdef CONFIG_PROC_FS
                remove_proc_entry("megaraid", &proc_root);
index 15e24fcc84f3b871f9f69c0621419ea91d61e60c..7a812677ff8a4de0f2e3dbb8c8a9e00a2d9af409 100644 (file)
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_sas.c
- * Version     : v00.00.03.05
+ * Version     : v00.00.03.10-rc1
  *
  * Authors:
- *     Sreenivas Bagalkote     <Sreenivas.Bagalkote@lsi.com>
- *     Sumant Patro            <Sumant.Patro@lsi.com>
+ *     (email-id : megaraidlinux@lsi.com)
+ *     Sreenivas Bagalkote
+ *     Sumant Patro
+ *     Bo Yang
  *
  * List of supported controllers
  *
@@ -35,6 +37,7 @@
 #include <asm/uaccess.h>
 #include <linux/fs.h>
 #include <linux/compat.h>
+#include <linux/blkdev.h>
 #include <linux/mutex.h>
 
 #include <scsi/scsi.h>
@@ -841,6 +844,11 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 
        instance = (struct megasas_instance *)
            scmd->device->host->hostdata;
+
+       /* Don't process if we have already declared adapter dead */
+       if (instance->hw_crit_error)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
        scmd->scsi_done = done;
        scmd->result = 0;
 
@@ -850,6 +858,18 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
                goto out_done;
        }
 
+       switch (scmd->cmnd[0]) {
+       case SYNCHRONIZE_CACHE:
+               /*
+                * FW takes care of flush cache on its own
+                * No need to send it down
+                */
+               scmd->result = DID_OK << 16;
+               goto out_done;
+       default:
+               break;
+       }
+
        cmd = megasas_get_cmd(instance);
        if (!cmd)
                return SCSI_MLQUEUE_HOST_BUSY;
@@ -1009,6 +1029,49 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
        return ret;
 }
 
+/**
+ * megasas_bios_param - Returns disk geometry for a disk
+ * @sdev:              device handle
+ * @bdev:              block device
+ * @capacity:          drive capacity
+ * @geom:              geometry parameters
+ */
+static int
+megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+                sector_t capacity, int geom[])
+{
+       int heads;
+       int sectors;
+       sector_t cylinders;
+       unsigned long tmp;
+       /* Default heads (64) & sectors (32) */
+       heads = 64;
+       sectors = 32;
+
+       tmp = heads * sectors;
+       cylinders = capacity;
+
+       sector_div(cylinders, tmp);
+
+       /*
+        * Handle extended translation size for logical drives > 1Gb
+        */
+
+       if (capacity >= 0x200000) {
+               heads = 255;
+               sectors = 63;
+               tmp = heads*sectors;
+               cylinders = capacity;
+               sector_div(cylinders, tmp);
+       }
+
+       geom[0] = heads;
+       geom[1] = sectors;
+       geom[2] = cylinders;
+
+       return 0;
+}
+
 /**
  * megasas_service_aen -       Processes an event notification
  * @instance:                  Adapter soft state
@@ -1049,6 +1112,7 @@ static struct scsi_host_template megasas_template = {
        .eh_device_reset_handler = megasas_reset_device,
        .eh_bus_reset_handler = megasas_reset_bus_host,
        .eh_host_reset_handler = megasas_reset_bus_host,
+       .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
 };
 
@@ -1282,11 +1346,13 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
        if(instance->instancet->clear_intr(instance->reg_set))
                return IRQ_NONE;
 
+       if (instance->hw_crit_error)
+               goto out_done;
         /*
         * Schedule the tasklet for cmd completion
         */
        tasklet_schedule(&instance->isr_tasklet);
-
+out_done:
        return IRQ_HANDLED;
 }
 
@@ -1741,6 +1807,10 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
        struct megasas_cmd *cmd;
        struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
 
+       /* If we have already declared adapter dead, donot complete cmds */
+       if (instance->hw_crit_error)
+               return;
+
        producer = *instance->producer;
        consumer = *instance->consumer;
 
@@ -2655,9 +2725,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
         * For each user buffer, create a mirror buffer and copy in
         */
        for (i = 0; i < ioc->sge_count; i++) {
-               kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
+               kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
                                                    ioc->sgl[i].iov_len,
-                                                   &buf_handle);
+                                                   &buf_handle, GFP_KERNEL);
                if (!kbuff_arr[i]) {
                        printk(KERN_DEBUG "megasas: Failed to alloc "
                               "kernel SGL buffer for IOCTL \n");
@@ -2684,8 +2754,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        }
 
        if (ioc->sense_len) {
-               sense = pci_alloc_consistent(instance->pdev, ioc->sense_len,
-                                            &sense_handle);
+               sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
+                                            &sense_handle, GFP_KERNEL);
                if (!sense) {
                        error = -ENOMEM;
                        goto out;
@@ -2744,12 +2814,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 
       out:
        if (sense) {
-               pci_free_consistent(instance->pdev, ioc->sense_len,
+               dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
                                    sense, sense_handle);
        }
 
        for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
-               pci_free_consistent(instance->pdev,
+               dma_free_coherent(&instance->pdev->dev,
                                    kern_sge32[i].length,
                                    kbuff_arr[i], kern_sge32[i].phys_addr);
        }
index cacb3ad92527cd44eac2a31a7b4007fdaac4ee17..e862992ee37783c8d09b615cd5c95be4363fe68d 100644 (file)
@@ -18,9 +18,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.03.05"
-#define MEGASAS_RELDATE                                "Oct 02, 2006"
-#define MEGASAS_EXT_VERSION                    "Mon Oct 02 11:21:32 PDT 2006"
+#define MEGASAS_VERSION                                "00.00.03.10-rc1"
+#define MEGASAS_RELDATE                                "Feb 14, 2007"
+#define MEGASAS_EXT_VERSION                    "Wed Feb 14 10:14:25 PST 2007"
 
 /*
  * Device IDs
index 1ddd7a11a9588a22330abe898e0045af4a0862d6..be41aadccae569918dd7259c5290133bd1cf3997 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 #include <asm/page.h>
index 890e9e232dab9afba81463f0cbe3b04cfbafc406..575fe6f7e0ec6d965f848c62f9733aabbea77a90 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 7c13f6f4a4c653d77596ed9cc005820041068180..f6f561d26bf0c9c317d133e9ee9110444856eb6a 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
index 9668b73872c785e419e656919abc5bdc5424a2a3..a967fadb7439a90be85775551c2ce4fea93bbc54 100644 (file)
@@ -5574,14 +5574,14 @@ static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
 
 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
 
-static int osst_create_driverfs_files(struct device_driver *driverfs)
+static int osst_create_sysfs_files(struct device_driver *sysfs)
 {
-       return driver_create_file(driverfs, &driver_attr_version);
+       return driver_create_file(sysfs, &driver_attr_version);
 }
 
-static void osst_remove_driverfs_files(struct device_driver *driverfs)
+static void osst_remove_sysfs_files(struct device_driver *sysfs)
 {
-       driver_remove_file(driverfs, &driver_attr_version);
+       driver_remove_file(sysfs, &driver_attr_version);
 }
 
 /*
@@ -5953,7 +5953,7 @@ static int __init init_osst(void)
        if (err)
                goto err_out_chrdev;
 
-       err = osst_create_driverfs_files(&osst_template.gendrv);
+       err = osst_create_sysfs_files(&osst_template.gendrv);
        if (err)
                goto err_out_scsidrv;
 
@@ -5973,7 +5973,7 @@ static void __exit exit_osst (void)
        int i;
        struct osst_tape * STp;
 
-       osst_remove_driverfs_files(&osst_template.gendrv);
+       osst_remove_sysfs_files(&osst_template.gendrv);
        scsi_unregister_driver(&osst_template.gendrv);
        unregister_chrdev(OSST_MAJOR, "osst");
        osst_sysfs_cleanup();
index 1434209a8ac54a99dc618310d7065490b2de5988..ee59656599714e25bf47cdd2eb1ed875e252fa54 100644 (file)
 #include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/blkdev.h>
index aad362ba02e0d81f93978bf61a7801775c773181..370802d24acd1157ea6421bcaabdc17c9b079ed0 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
index a1c5f265069f0b7d6db2b8e6e7688a57f381a40d..4b82b2021981a5598c4861867d6d31236bc8f532 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
index e16fe361436e845f1a295ba8ae433f3ff7901d2a..c6f8c6e65e057105a9d240cf7db8dbfa21313682 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
index 9d431fe7f47ff97bf29757e88f608a8540384f08..697cfb76c3a4171412789ab8f563a15223a4c44a 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
index 5b458d2478f7f92eea58a059cfdc6fa0b8ce0dd6..ffe75c431b2561e7aaa7fd9fbd0d9061eb22a3ca 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
index 1548d42a3b4390781320fde64dddec2ae4316b8b..6777e8a69153a9a7c6eabc671ac4ea8a7ae2d642 100644 (file)
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
index 81fb7bd44f0167131a9eb7cc8f21a0d00172d91e..0bfddf893ed0eba06e1362e0a4f06016eafcf86c 100644 (file)
@@ -1270,7 +1270,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
        INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
 
        ret = request_irq(pdev->irq, qla4xxx_intr_handler,
-                         SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha);
+                         IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha);
        if (ret) {
                dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d"
                        " already in use.\n", pdev->irq);
index f33e2eb9f1b9b657ce0ea582a6007681c53f5b86..1c89ee3e69ba972752e1e9acf6b50812783499f2 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/slab.h>
index 5adbbeedec38ce485d9f7269a4e2efb1320976f9..3e2930b7ee2397bef4207dbf545a75667907893c 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/types.h>
index 69d6e9b198c42fa6aceb7ebace35e19f305deffc..bb6f051beda82b569a611d330df99c7042be22f0 100644 (file)
@@ -179,9 +179,8 @@ static int proc_print_scsidevice(struct device *dev, void *data)
        seq_printf(s, "\n");
 
        seq_printf(s, "  Type:   %s ", scsi_device_type(sdev->type));
-       seq_printf(s, "               ANSI"
-                    " SCSI revision: %02x", (sdev->scsi_level - 1) ?
-                    sdev->scsi_level - 1 : 1);
+       seq_printf(s, "               ANSI  SCSI revision: %02x",
+                       sdev->scsi_level - (sdev->scsi_level > 1));
        if (sdev->scsi_level == 2)
                seq_printf(s, " CCS\n");
        else
index a43b9ec3aefd66f2953841c964cb2fd2c5746106..0949145304eaaeba8f17554feaaf87e55453acb7 100644 (file)
@@ -54,7 +54,7 @@
 #define SCSI_TIMEOUT (2*HZ)
 
 /*
- * Prefix values for the SCSI id's (stored in driverfs name field)
+ * Prefix values for the SCSI id's (stored in sysfs name field)
  */
 #define SCSI_UID_SER_NUM 'S'
 #define SCSI_UID_UNKNOWN 'Z'
@@ -385,6 +385,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        INIT_LIST_HEAD(&starget->siblings);
        INIT_LIST_HEAD(&starget->devices);
        starget->state = STARGET_RUNNING;
+       starget->scsi_level = SCSI_2;
  retry:
        spin_lock_irqsave(shost->host_lock, flags);
 
@@ -654,6 +655,19 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
         * short INQUIRY), an abort here prevents any further use of the
         * device, including spin up.
         *
+        * On the whole, the best approach seems to be to assume the first
+        * 36 bytes are valid no matter what the device says.  That's
+        * better than copying < 36 bytes to the inquiry-result buffer
+        * and displaying garbage for the Vendor, Product, or Revision
+        * strings.
+        */
+       if (sdev->inquiry_len < 36) {
+               printk(KERN_INFO "scsi scan: INQUIRY result too short (%d),"
+                               " using 36\n", sdev->inquiry_len);
+               sdev->inquiry_len = 36;
+       }
+
+       /*
         * Related to the above issue:
         *
         * XXX Devices (disk or all?) should be sent a TEST UNIT READY,
index 04d06c25132b39076648429077614efc9879c1c1..6cfaaa2d0c819a1478f4b31a80503a24db71f652 100644 (file)
@@ -41,7 +41,7 @@ static struct ctl_table_header *scsi_table_header;
 
 int __init scsi_init_sysctl(void)
 {
-       scsi_table_header = register_sysctl_table(scsi_root_table, 1);
+       scsi_table_header = register_sysctl_table(scsi_root_table);
        if (!scsi_table_header)
                return -ENOMEM;
        return 0;
index 259c90cfa367027a29e812645fa5ab9e856ff28d..c275dcac3f18b7b4abc1bd984cb1601de3f0a770 100644 (file)
@@ -922,7 +922,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
        snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
                 "%d:%d:%d:%d", sdev->host->host_no,
                 sdev->channel, sdev->id, sdev->lun);
-       sdev->scsi_level = SCSI_2;
+       sdev->scsi_level = starget->scsi_level;
        transport_setup_device(&sdev->sdev_gendev);
        spin_lock_irqsave(shost->host_lock, flags);
        list_add_tail(&sdev->same_target_siblings, &starget->devices);
index f2344ab8deff882b3dc00f20351626562c0085f3..0e08817fdecff73540e2c35bbddb1c4f266acb42 100644 (file)
 
 #include "scsi_tgt_priv.h"
 
+#if TGT_RING_SIZE < PAGE_SIZE
+#  define TGT_RING_SIZE PAGE_SIZE
+#endif
+
+#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
+#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
+#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
+
 struct tgt_ring {
        u32 tr_idx;
        unsigned long tr_pages[TGT_RING_PAGES];
index 3571ce8934e7af15f8924a832c6be7047fbbecb4..58afdb401703d6b65474b10741adcd7ee03a73a2 100644 (file)
@@ -26,7 +26,6 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>       /* workqueue stuff, HZ */
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
@@ -856,7 +855,7 @@ static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
 
 /*
  * Note: in the target show function we recognize when the remote
- *  port is in the heirarchy and do not allow the driver to get
+ *  port is in the hierarchy and do not allow the driver to get
  *  involved in sysfs functions. The driver only gets involved if
  *  it's the "old" style that doesn't use rports.
  */
index 6d39150e205be19593e71406f672bee539ca9368..b2ef71a86292c6477dacc38ee7e4f37c960be9f2 100644 (file)
@@ -500,7 +500,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
 EXPORT_SYMBOL(sas_phy_alloc);
 
 /**
- * sas_phy_add  --  add a SAS PHY to the device hierachy
+ * sas_phy_add  --  add a SAS PHY to the device hierarchy
  * @phy:       The PHY to be added
  *
  * Publishes a SAS PHY to the rest of the system.
@@ -1265,7 +1265,7 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
 EXPORT_SYMBOL(sas_expander_alloc);
 
 /**
- * sas_rphy_add  --  add a SAS remote PHY to the device hierachy
+ * sas_rphy_add  --  add a SAS remote PHY to the device hierarchy
  * @rphy:      The remote PHY to be added
  *
  * Publishes a SAS remote PHY to the rest of the system.
index b781a90d6699038f4f2a0e819ca6d2a93dd619bb..5a8f55fea5ff3da628eaed926786b0713d1a8565 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/genhd.h>
@@ -1270,9 +1269,18 @@ repeat:
 
        /* Some devices return the total number of sectors, not the
         * highest sector number.  Make the necessary adjustment. */
-       if (sdp->fix_capacity)
+       if (sdp->fix_capacity) {
                --sdkp->capacity;
 
+       /* Some devices have version which report the correct sizes
+        * and others which do not. We guess size according to a heuristic
+        * and err on the side of lowering the capacity. */
+       } else {
+               if (sdp->guess_capacity)
+                       if (sdkp->capacity & 0x01) /* odd sizes are odd */
+                               --sdkp->capacity;
+       }
+
 got_data:
        if (sector_size == 0) {
                sector_size = 512;
index e81f97a35bc8775d6bc9ae34d676c0d680345df0..a15752b379906b3b50464ee72f4110578f93d2e4 100644 (file)
@@ -244,9 +244,10 @@ static struct Scsi_Host * __init sgiwd93_setup_scsi(
        regs.SASR = wdregs + 3;
        regs.SCMD = wdregs + 7;
 
-       wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20);
+       wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
 
-       hdata->wh.no_sync = 0;
+       if (hdata->wh.no_sync == 0xff)
+               hdata->wh.no_sync = 0;
 
        if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) {
                printk(KERN_WARNING "sgiwd93: Could not register irq %d "
index 89e9b36b17882daecaa73660647abd87ba8d9553..1857d68e7195e5b9c19a20afa3fd1ed6af08e790 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/string.h>
index 0578ba42718b125ead70d8a9d599934d18f5e1fe..e1589f91706a2f18187b2229599e8a1ecc744e46 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
index 3d2e02381e92257618050314a2e358957e204221..98d8411bbccc1108fe09aa018f7dae17032387f7 100644 (file)
@@ -195,8 +195,8 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
 static int st_probe(struct device *);
 static int st_remove(struct device *);
 
-static int do_create_driverfs_files(void);
-static void do_remove_driverfs_files(void);
+static int do_create_sysfs_files(void);
+static void do_remove_sysfs_files(void);
 static int do_create_class_files(struct scsi_tape *, int, int);
 
 static struct scsi_driver st_template = {
@@ -4193,7 +4193,7 @@ static int __init init_st(void)
        if (err)
                goto err_chrdev;
 
-       err = do_create_driverfs_files();
+       err = do_create_sysfs_files();
        if (err)
                goto err_scsidrv;
 
@@ -4211,7 +4211,7 @@ err_class:
 
 static void __exit exit_st(void)
 {
-       do_remove_driverfs_files();
+       do_remove_sysfs_files();
        scsi_unregister_driver(&st_template.gendrv);
        unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
                                 ST_MAX_TAPE_ENTRIES);
@@ -4249,43 +4249,43 @@ static ssize_t st_version_show(struct device_driver *ddd, char *buf)
 }
 static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
 
-static int do_create_driverfs_files(void)
+static int do_create_sysfs_files(void)
 {
-       struct device_driver *driverfs = &st_template.gendrv;
+       struct device_driver *sysfs = &st_template.gendrv;
        int err;
 
-       err = driver_create_file(driverfs, &driver_attr_try_direct_io);
+       err = driver_create_file(sysfs, &driver_attr_try_direct_io);
        if (err)
                return err;
-       err = driver_create_file(driverfs, &driver_attr_fixed_buffer_size);
+       err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
        if (err)
                goto err_try_direct_io;
-       err = driver_create_file(driverfs, &driver_attr_max_sg_segs);
+       err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
        if (err)
                goto err_attr_fixed_buf;
-       err = driver_create_file(driverfs, &driver_attr_version);
+       err = driver_create_file(sysfs, &driver_attr_version);
        if (err)
                goto err_attr_max_sg;
 
        return 0;
 
 err_attr_max_sg:
-       driver_remove_file(driverfs, &driver_attr_max_sg_segs);
+       driver_remove_file(sysfs, &driver_attr_max_sg_segs);
 err_attr_fixed_buf:
-       driver_remove_file(driverfs, &driver_attr_fixed_buffer_size);
+       driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
 err_try_direct_io:
-       driver_remove_file(driverfs, &driver_attr_try_direct_io);
+       driver_remove_file(sysfs, &driver_attr_try_direct_io);
        return err;
 }
 
-static void do_remove_driverfs_files(void)
+static void do_remove_sysfs_files(void)
 {
-       struct device_driver *driverfs = &st_template.gendrv;
+       struct device_driver *sysfs = &st_template.gendrv;
 
-       driver_remove_file(driverfs, &driver_attr_version);
-       driver_remove_file(driverfs, &driver_attr_max_sg_segs);
-       driver_remove_file(driverfs, &driver_attr_fixed_buffer_size);
-       driver_remove_file(driverfs, &driver_attr_try_direct_io);
+       driver_remove_file(sysfs, &driver_attr_version);
+       driver_remove_file(sysfs, &driver_attr_max_sg_segs);
+       driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
+       driver_remove_file(sysfs, &driver_attr_try_direct_io);
 }
 
 
index ba6bcdaf2a6afdaf896da7c8a49ab982741d0ca6..69be1324b114ffc274cadd4e805b8e89c4ea1bd3 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/pci.h>
 #include <linux/blkdev.h>
index 69ee3e4a820e0dfc1a38b7b2537af29e84fe00bd..5e46d842c6f9b3912092b0efa105da6b785b4657 100644 (file)
@@ -58,7 +58,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
index bb0c9fd99e68646617e94fb6aa8cdffc91d7bedd..7cb4a31453e6e3cb73813ddcec50beb2fa8b82fa 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
index 32c883f1efa1aecbd5f525af8354f552bf5d1e6c..2ca950582bc336ca0edd1817f702a9feb69efb6c 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
index 7b39f4a35e9885eb2b0ad219659985524c749731..7b08d6caaa99b35c58afb1b071385287acf67c6f 100644 (file)
@@ -1020,7 +1020,7 @@ static struct SYM_FWA_SCR SYM_FWA_SCR = {
         *  It shall be a tagged command.
         *  Read SIMPLE+TAG.
         *  The C code will deal with errors.
-        *  Agressive optimization, is'nt it? :)
+        *  Aggressive optimization, isn't it? :)
         */
        SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
                HADDR_1 (msgin),
@@ -1044,7 +1044,7 @@ static struct SYM_FWA_SCR SYM_FWA_SCR = {
                RADDR_1 (dsa),
        /*
         *  The SIDL still contains the TAG value.
-        *  Agressive optimization, isn't it? :):)
+        *  Aggressive optimization, isn't it? :):)
         */
        SCR_REG_SFBR (sidl, SCR_SHL, 0),
                0,
index 851f2706f220942c417041eaa1f1589b24d8d353..6e5b952312e364bcd8f9d7c73fdbcb1183486fd5 100644 (file)
@@ -956,7 +956,7 @@ static struct SYM_FWA_SCR SYM_FWA_SCR = {
         *  It shall be a tagged command.
         *  Read SIMPLE+TAG.
         *  The C code will deal with errors.
-        *  Agressive optimization, is'nt it? :)
+        *  Aggressive optimization, isn't it? :)
         */
        SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
                HADDR_1 (msgin),
@@ -968,7 +968,7 @@ static struct SYM_FWA_SCR SYM_FWA_SCR = {
                offsetof(struct sym_lcb, head.itlq_tbl_sa),
        /*
         *  The SIDL still contains the TAG value.
-        *  Agressive optimization, isn't it? :):)
+        *  Aggressive optimization, isn't it? :):)
         */
        SCR_REG_SFBR (sidl, SCR_SHL, 0),
                0,
index 0b7a70f61e0d973112c251bd74087b635f26c358..248d60b8d8994f235c1e01102cabb960243a3f37 100644 (file)
 
 #include <asm/system.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
index fa5382e354be71edcd50437386d446979283283b..a583e89238fcf7297b06f6a36b59692badd86ef8 100644 (file)
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
index 2083454db511d7daf260eb8ceace3f2580cc47bc..fa4e08e508ad68b35c7c2d490e0639c64f7c4384 100644 (file)
  * Added support for pre -A chips, which don't have advanced features
  * and will generate CSR_RESEL rather than CSR_RESEL_AM.
  *     Richard Hirst <richard@sleepie.demon.co.uk>  August 2000
+ *
+ * Added support for Burst Mode DMA and Fast SCSI. Enabled the use of
+ * default_sx_per for asynchronous data transfers. Added adjustment
+ * of transfer periods in sx_table to the actual input-clock.
+ *  peter fuerst <post@pfrst.de>  February 2007
  */
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
 #include "wd33c93.h"
 
+#define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns
+
 
-#define WD33C93_VERSION    "1.26"
-#define WD33C93_DATE       "22/Feb/2003"
+#define WD33C93_VERSION    "1.26++"
+#define WD33C93_DATE       "10/Feb/2007"
 
 MODULE_AUTHOR("John Shifflett");
 MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
@@ -123,6 +129,13 @@ MODULE_LICENSE("GPL");
  *                    defines in wd33c93.h
  * -  clock:x        -x = clock input in MHz for WD33c93 chip. Normal values
  *                    would be from 8 through 20. Default is 8.
+ * -  burst:x        -x = 1 to use Burst Mode (or Demand-Mode) DMA, x = 0 to use
+ *                    Single Byte DMA, which is the default. Argument is
+ *                    optional - if not present, same as "burst:1".
+ * -  fast:x         -x = 1 to enable Fast SCSI, which is only effective with
+ *                    input-clock divisor 4 (WD33C93_FS_16_20), x = 0 to disable
+ *                    it, which is the default.  Argument is optional - if not
+ *                    present, same as "fast:1".
  * -  next           -No argument. Used to separate blocks of keywords when
  *                    there's more than one host adapter in the system.
  *
@@ -149,7 +162,7 @@ MODULE_LICENSE("GPL");
  */
 
 /* Normally, no defaults are specified */
-static char *setup_args[] = { "", "", "", "", "", "", "", "", "" };
+static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" };
 
 static char *setup_strings;
 module_param(setup_strings, charp, 0);
@@ -299,20 +312,8 @@ read_1_byte(const wd33c93_regs regs)
        return x;
 }
 
-static struct sx_period sx_table[] = {
-       {1, 0x20},
-       {252, 0x20},
-       {376, 0x30},
-       {500, 0x40},
-       {624, 0x50},
-       {752, 0x60},
-       {876, 0x70},
-       {1000, 0x00},
-       {0, 0}
-};
-
 static int
-round_period(unsigned int period)
+round_period(unsigned int period, const struct sx_period *sx_table)
 {
        int x;
 
@@ -325,17 +326,49 @@ round_period(unsigned int period)
        return 7;
 }
 
+/*
+ * Calculate Synchronous Transfer Register value from SDTR code.
+ */
 static uchar
-calc_sync_xfer(unsigned int period, unsigned int offset)
+calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast,
+               const struct sx_period *sx_table)
 {
+       /* When doing Fast SCSI synchronous data transfers, the corresponding
+        * value in 'sx_table' is two times the actually used transfer period.
+        */
        uchar result;
 
+       if (offset && fast) {
+               fast = STR_FSS;
+               period *= 2;
+       } else {
+               fast = 0;
+       }
        period *= 4;            /* convert SDTR code to ns */
-       result = sx_table[round_period(period)].reg_value;
+       result = sx_table[round_period(period,sx_table)].reg_value;
        result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
+       result |= fast;
        return result;
 }
 
+/*
+ * Calculate SDTR code bytes [3],[4] from period and offset.
+ */
+static inline void
+calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
+                uchar  msg[2])
+{
+       /* 'period' is a "normal"-mode value, like the ones in 'sx_table'. The
+        * actually used transfer period for Fast SCSI synchronous data
+        * transfers is half that value.
+        */
+       period /= 4;
+       if (offset && fast)
+               period /= 2;
+       msg[0] = period;
+       msg[1] = offset;
+}
+
 int
 wd33c93_queuecommand(struct scsi_cmnd *cmd,
                void (*done)(struct scsi_cmnd *))
@@ -633,7 +666,7 @@ wd33c93_execute(struct Scsi_Host *instance)
                                write_wd33c93_count(regs,
                                                    cmd->SCp.this_residual);
                                write_wd33c93(regs, WD_CONTROL,
-                                             CTRL_IDI | CTRL_EDI | CTRL_DMA);
+                                             CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
                                hostdata->dma = D_DMA_RUNNING;
                        }
                } else
@@ -713,6 +746,8 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
                cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
                    cmd->SCp.buffer->offset;
        }
+       if (!cmd->SCp.this_residual) /* avoid bogus setups */
+               return;
 
        write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
                      hostdata->sync_xfer[cmd->device->id]);
@@ -745,7 +780,7 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
 #ifdef PROC_STATISTICS
                hostdata->dma_cnt++;
 #endif
-               write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
+               write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
                write_wd33c93_count(regs, cmd->SCp.this_residual);
 
                if ((hostdata->level2 >= L2_DATA) ||
@@ -863,9 +898,6 @@ wd33c93_intr(struct Scsi_Host *instance)
                        hostdata->outgoing_msg[0] |= 0x40;
 
                if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
-#ifdef SYNC_DEBUG
-                       printk(" sending SDTR ");
-#endif
 
                        hostdata->sync_stat[cmd->device->id] = SS_WAITING;
 
@@ -879,14 +911,20 @@ wd33c93_intr(struct Scsi_Host *instance)
                        hostdata->outgoing_msg[2] = 3;
                        hostdata->outgoing_msg[3] = EXTENDED_SDTR;
                        if (hostdata->no_sync & (1 << cmd->device->id)) {
-                               hostdata->outgoing_msg[4] =
-                                   hostdata->default_sx_per / 4;
-                               hostdata->outgoing_msg[5] = 0;
+                               calc_sync_msg(hostdata->default_sx_per, 0,
+                                               0, hostdata->outgoing_msg + 4);
                        } else {
-                               hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4;
-                               hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
+                               calc_sync_msg(optimum_sx_per(hostdata),
+                                               OPTIMUM_SX_OFF,
+                                               hostdata->fast,
+                                               hostdata->outgoing_msg + 4);
                        }
                        hostdata->outgoing_len = 6;
+#ifdef SYNC_DEBUG
+                       ucp = hostdata->outgoing_msg + 1;
+                       printk(" sending SDTR %02x03%02x%02x%02x ",
+                               ucp[0], ucp[2], ucp[3], ucp[4]);
+#endif
                } else
                        hostdata->outgoing_len = 1;
 
@@ -1002,8 +1040,13 @@ wd33c93_intr(struct Scsi_Host *instance)
 #ifdef SYNC_DEBUG
                            printk("-REJ-");
 #endif
-                       if (hostdata->sync_stat[cmd->device->id] == SS_WAITING)
+                       if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) {
                                hostdata->sync_stat[cmd->device->id] = SS_SET;
+                               /* we want default_sx_per, not DEFAULT_SX_PER */
+                               hostdata->sync_xfer[cmd->device->id] =
+                                       calc_sync_xfer(hostdata->default_sx_per
+                                               / 4, 0, 0, hostdata->sx_table);
+                       }
                        write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
                        hostdata->state = S_CONNECTED;
                        break;
@@ -1023,7 +1066,10 @@ wd33c93_intr(struct Scsi_Host *instance)
 
                                switch (ucp[2]) {       /* what's the EXTENDED code? */
                                case EXTENDED_SDTR:
-                                       id = calc_sync_xfer(ucp[3], ucp[4]);
+                                       /* default to default async period */
+                                       id = calc_sync_xfer(hostdata->
+                                                       default_sx_per / 4, 0,
+                                                       0, hostdata->sx_table);
                                        if (hostdata->sync_stat[cmd->device->id] !=
                                            SS_WAITING) {
 
@@ -1042,20 +1088,22 @@ wd33c93_intr(struct Scsi_Host *instance)
                                                hostdata->outgoing_msg[1] = 3;
                                                hostdata->outgoing_msg[2] =
                                                    EXTENDED_SDTR;
-                                               hostdata->outgoing_msg[3] =
-                                                   hostdata->default_sx_per /
-                                                   4;
-                                               hostdata->outgoing_msg[4] = 0;
+                                               calc_sync_msg(hostdata->
+                                                       default_sx_per, 0,
+                                                       0, hostdata->outgoing_msg + 3);
                                                hostdata->outgoing_len = 5;
-                                               hostdata->sync_xfer[cmd->device->id] =
-                                                   calc_sync_xfer(hostdata->
-                                                                  default_sx_per
-                                                                  / 4, 0);
                                        } else {
-                                               hostdata->sync_xfer[cmd->device->id] = id;
+                                               if (ucp[4]) /* well, sync transfer */
+                                                       id = calc_sync_xfer(ucp[3], ucp[4],
+                                                                       hostdata->fast,
+                                                                       hostdata->sx_table);
+                                               else if (ucp[3]) /* very unlikely... */
+                                                       id = calc_sync_xfer(ucp[3], ucp[4],
+                                                                       0, hostdata->sx_table);
                                        }
+                                       hostdata->sync_xfer[cmd->device->id] = id;
 #ifdef SYNC_DEBUG
-                                       printk("sync_xfer=%02x",
+                                       printk(" sync_xfer=%02x\n",
                                               hostdata->sync_xfer[cmd->device->id]);
 #endif
                                        hostdata->sync_stat[cmd->device->id] =
@@ -1487,7 +1535,7 @@ reset_wd33c93(struct Scsi_Host *instance)
        write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
                      calc_sync_xfer(hostdata->default_sx_per / 4,
-                                    DEFAULT_SX_OFF));
+                                    DEFAULT_SX_OFF, 0, hostdata->sx_table));
        write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
 
 
@@ -1513,6 +1561,9 @@ reset_wd33c93(struct Scsi_Host *instance)
        } else
                hostdata->chip = C_UNKNOWN_CHIP;
 
+       if (hostdata->chip != C_WD33C93B)       /* Fast SCSI unavailable */
+               hostdata->fast = 0;
+
        write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
        write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 }
@@ -1534,7 +1585,8 @@ wd33c93_host_reset(struct scsi_cmnd * SCpnt)
        for (i = 0; i < 8; i++) {
                hostdata->busy[i] = 0;
                hostdata->sync_xfer[i] =
-                   calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
+                       calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
+                                       0, hostdata->sx_table);
                hostdata->sync_stat[i] = SS_UNSET;      /* using default sync values */
        }
        hostdata->input_Q = NULL;
@@ -1783,6 +1835,98 @@ check_setup_args(char *key, int *flags, int *val, char *buf)
        return ++x;
 }
 
+/*
+ * Calculate internal data-transfer-clock cycle from input-clock
+ * frequency (/MHz) and fill 'sx_table'.
+ *
+ * The original driver used to rely on a fixed sx_table, containing periods
+ * for (only) the lower limits of the respective input-clock-frequency ranges
+ * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with
+ * this setting so far, it might be desirable to adjust the transfer periods
+ * closer to the really attached, possibly 25% higher, input-clock, since
+ * - the wd33c93 may really use a significant shorter period, than it has
+ *   negotiated (eg. thrashing the target, which expects 4/8MHz, with 5/10MHz
+ *   instead).
+ * - the wd33c93 may ask the target for a lower transfer rate, than the target
+ *   is capable of (eg. negotiating for an assumed minimum of 252ns instead of
+ *   possible 200ns, which indeed shows up in tests as an approx. 10% lower
+ *   transfer rate).
+ */
+static inline unsigned int
+round_4(unsigned int x)
+{
+       switch (x & 3) {
+               case 1: --x;
+                       break;
+               case 2: ++x;
+               case 3: ++x;
+       }
+       return x;
+}
+
+static void
+calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
+{
+       unsigned int d, i;
+       if (mhz < 11)
+               d = 2;  /* divisor for  8-10 MHz input-clock */
+       else if (mhz < 16)
+               d = 3;  /* divisor for 12-15 MHz input-clock */
+       else
+               d = 4;  /* divisor for 16-20 MHz input-clock */
+
+       d = (100000 * d) / 2 / mhz; /* 100 x DTCC / nanosec */
+
+       sx_table[0].period_ns = 1;
+       sx_table[0].reg_value = 0x20;
+       for (i = 1; i < 8; i++) {
+               sx_table[i].period_ns = round_4((i+1)*d / 100);
+               sx_table[i].reg_value = (i+1)*0x10;
+       }
+       sx_table[7].reg_value = 0;
+       sx_table[8].period_ns = 0;
+       sx_table[8].reg_value = 0;
+}
+
+/*
+ * check and, maybe, map an init- or "clock:"- argument.
+ */
+static uchar
+set_clk_freq(int freq, int *mhz)
+{
+       int x = freq;
+       if (WD33C93_FS_8_10 == freq)
+               freq = 8;
+       else if (WD33C93_FS_12_15 == freq)
+               freq = 12;
+       else if (WD33C93_FS_16_20 == freq)
+               freq = 16;
+       else if (freq > 7 && freq < 11)
+               x = WD33C93_FS_8_10;
+               else if (freq > 11 && freq < 16)
+               x = WD33C93_FS_12_15;
+               else if (freq > 15 && freq < 21)
+               x = WD33C93_FS_16_20;
+       else {
+                       /* Hmm, wouldn't it be safer to assume highest freq here? */
+               x = WD33C93_FS_8_10;
+               freq = 8;
+       }
+       *mhz = freq;
+       return x;
+}
+
+/*
+ * to be used with the resync: fast: ... options
+ */
+static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
+{
+       int i;
+       for (i = 0; i < 8; i++)
+               if (mask & (1 << i))
+                       hd->sync_stat[i] = SS_UNSET;
+}
+
 void
 wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
             dma_setup_t setup, dma_stop_t stop, int clock_freq)
@@ -1799,7 +1943,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
        hostdata = (struct WD33C93_hostdata *) instance->hostdata;
 
        hostdata->regs = regs;
-       hostdata->clock_freq = clock_freq;
+       hostdata->clock_freq = set_clk_freq(clock_freq, &i);
+       calc_sx_table(i, hostdata->sx_table);
        hostdata->dma_setup = setup;
        hostdata->dma_stop = stop;
        hostdata->dma_bounce_buffer = NULL;
@@ -1807,7 +1952,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
        for (i = 0; i < 8; i++) {
                hostdata->busy[i] = 0;
                hostdata->sync_xfer[i] =
-                   calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
+                       calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
+                                       0, hostdata->sx_table);
                hostdata->sync_stat[i] = SS_UNSET;      /* using default sync values */
 #ifdef PROC_STATISTICS
                hostdata->cmd_cnt[i] = 0;
@@ -1829,6 +1975,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
        hostdata->default_sx_per = DEFAULT_SX_PER;
        hostdata->no_sync = 0xff;       /* sync defaults to off */
        hostdata->no_dma = 0;   /* default is DMA enabled */
+       hostdata->fast = 0;     /* default is Fast SCSI transfers disabled */
+       hostdata->dma_mode = CTRL_DMA;  /* default is Single Byte DMA */
 
 #ifdef PROC_INTERFACE
        hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
@@ -1840,6 +1988,11 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
 #endif
 #endif
 
+       if (check_setup_args("clock", &flags, &val, buf)) {
+               hostdata->clock_freq = set_clk_freq(val, &val);
+               calc_sx_table(val, hostdata->sx_table);
+       }
+
        if (check_setup_args("nosync", &flags, &val, buf))
                hostdata->no_sync = val;
 
@@ -1848,7 +2001,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
 
        if (check_setup_args("period", &flags, &val, buf))
                hostdata->default_sx_per =
-                   sx_table[round_period((unsigned int) val)].period_ns;
+                   hostdata->sx_table[round_period((unsigned int) val,
+                                                   hostdata->sx_table)].period_ns;
 
        if (check_setup_args("disconnect", &flags, &val, buf)) {
                if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
@@ -1863,17 +2017,12 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
        if (check_setup_args("debug", &flags, &val, buf))
                hostdata->args = val & DB_MASK;
 
-       if (check_setup_args("clock", &flags, &val, buf)) {
-               if (val > 7 && val < 11)
-                       val = WD33C93_FS_8_10;
-               else if (val > 11 && val < 16)
-                       val = WD33C93_FS_12_15;
-               else if (val > 15 && val < 21)
-                       val = WD33C93_FS_16_20;
-               else
-                       val = WD33C93_FS_8_10;
-               hostdata->clock_freq = val;
-       }
+       if (check_setup_args("burst", &flags, &val, buf))
+               hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
+
+       if (WD33C93_FS_16_20 == hostdata->clock_freq /* divisor 4 */
+               && check_setup_args("fast", &flags, &val, buf))
+               hostdata->fast = !!val;
 
        if ((i = check_setup_args("next", &flags, &val, buf))) {
                while (i)
@@ -1918,53 +2067,65 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
        char tbuf[128];
        struct WD33C93_hostdata *hd;
        struct scsi_cmnd *cmd;
-       int x, i;
+       int x;
        static int stop = 0;
 
        hd = (struct WD33C93_hostdata *) instance->hostdata;
 
 /* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
+ * keywords (same format as command-line, but arguments are not optional):
  *    debug
  *    disconnect
  *    period
  *    resync
  *    proc
  *    nodma
+ *    level2
+ *    burst
+ *    fast
+ *    nosync
  */
 
        if (in) {
                buf[len] = '\0';
-               bp = buf;
+               for (bp = buf; *bp; ) {
+                       while (',' == *bp || ' ' == *bp)
+                               ++bp;
                if (!strncmp(bp, "debug:", 6)) {
-                       bp += 6;
-                       hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+                               hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
                } else if (!strncmp(bp, "disconnect:", 11)) {
-                       bp += 11;
-                       x = simple_strtoul(bp, NULL, 0);
+                               x = simple_strtoul(bp+11, &bp, 0);
                        if (x < DIS_NEVER || x > DIS_ALWAYS)
                                x = DIS_ADAPTIVE;
                        hd->disconnect = x;
                } else if (!strncmp(bp, "period:", 7)) {
-                       bp += 7;
-                       x = simple_strtoul(bp, NULL, 0);
+                       x = simple_strtoul(bp+7, &bp, 0);
                        hd->default_sx_per =
-                           sx_table[round_period((unsigned int) x)].period_ns;
+                               hd->sx_table[round_period((unsigned int) x,
+                                                         hd->sx_table)].period_ns;
                } else if (!strncmp(bp, "resync:", 7)) {
-                       bp += 7;
-                       x = simple_strtoul(bp, NULL, 0);
-                       for (i = 0; i < 7; i++)
-                               if (x & (1 << i))
-                                       hd->sync_stat[i] = SS_UNSET;
+                               set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
                } else if (!strncmp(bp, "proc:", 5)) {
-                       bp += 5;
-                       hd->proc = simple_strtoul(bp, NULL, 0);
+                               hd->proc = simple_strtoul(bp+5, &bp, 0);
                } else if (!strncmp(bp, "nodma:", 6)) {
-                       bp += 6;
-                       hd->no_dma = simple_strtoul(bp, NULL, 0);
+                               hd->no_dma = simple_strtoul(bp+6, &bp, 0);
                } else if (!strncmp(bp, "level2:", 7)) {
-                       bp += 7;
-                       hd->level2 = simple_strtoul(bp, NULL, 0);
+                               hd->level2 = simple_strtoul(bp+7, &bp, 0);
+                       } else if (!strncmp(bp, "burst:", 6)) {
+                               hd->dma_mode =
+                                       simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
+                       } else if (!strncmp(bp, "fast:", 5)) {
+                               x = !!simple_strtol(bp+5, &bp, 0);
+                               if (x != hd->fast)
+                                       set_resync(hd, 0xff);
+                               hd->fast = x;
+                       } else if (!strncmp(bp, "nosync:", 7)) {
+                               x = simple_strtoul(bp+7, &bp, 0);
+                               set_resync(hd, x ^ hd->no_sync);
+                               hd->no_sync = x;
+                       } else {
+                               break; /* unknown keyword,syntax-error,... */
+                       }
                }
                return len;
        }
@@ -1978,8 +2139,9 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
                strcat(bp, tbuf);
        }
        if (hd->proc & PR_INFO) {
-               sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d",
-                       hd->clock_freq, hd->no_sync, hd->no_dma);
+               sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
+                       " dma_mode=%02x fast=%d",
+                       hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
                strcat(bp, tbuf);
                strcat(bp, "\nsync_xfer[] =       ");
                for (x = 0; x < 7; x++) {
index edcb0365cf0c4d88a3bbff42fed3970da8ba704d..61ffb860dacc78dd5484953145413d1563312129 100644 (file)
 #define WD33C93_FS_12_15 OWNID_FS_12
 #define WD33C93_FS_16_20 OWNID_FS_16
 
+   /* pass input-clock explicitely. accepted mhz values are 8-10,12-20 */
+#define WD33C93_FS_MHZ(mhz) (mhz)
+
    /* Control register */
 #define CTRL_HSP     0x01
 #define CTRL_HA      0x02
@@ -253,6 +256,9 @@ struct WD33C93_hostdata {
     uchar            sync_stat[8];     /* status of sync negotiation per target */
     uchar            no_sync;          /* bitmask: don't do sync on these targets */
     uchar            no_dma;           /* set this flag to disable DMA */
+    uchar            dma_mode;         /* DMA Burst Mode or Single Byte DMA */
+    uchar            fast;             /* set this flag to enable Fast SCSI */
+    struct sx_period sx_table[9];      /* transfer periods for actual DTC-setting */
 #ifdef PROC_INTERFACE
     uchar            proc;             /* bitmask: what's in proc output */
 #ifdef PROC_STATISTICS
index 2964ca9df5a010f9cebb264e4115d5a588e5c234..98ec861853280672d0828342184c73025dc555cc 100644 (file)
@@ -364,6 +364,23 @@ serial_out(struct uart_8250_port *up, int offset, int value)
        }
 }
 
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+       switch (up->port.iotype) {
+       case UPIO_MEM:
+       case UPIO_MEM32:
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       case UPIO_AU:
+#endif
+               serial_out(up, offset, value);
+               serial_in(up, UART_LCR);        /* safe, no side-effects */
+               break;
+       default:
+               serial_out(up, offset, value);
+       }
+}
+
 /*
  * We used to support using pause I/O for certain machines.  We
  * haven't supported this for a while, but just in case it's badly
@@ -1045,7 +1062,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 #endif
        serial_outp(up, UART_MCR, save_mcr);
        serial8250_clear_fifos(up);
-       (void)serial_in(up, UART_RX);
+       serial_in(up, UART_RX);
        if (up->capabilities & UART_CAP_UUE)
                serial_outp(up, UART_IER, UART_IER_UUE);
        else
@@ -1451,6 +1468,12 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
        serial_do_unlink(i, up);
 }
 
+/* Base timer interval for polling */
+static inline int poll_timeout(int timeout)
+{
+       return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1460,16 +1483,51 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
 static void serial8250_timeout(unsigned long data)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)data;
-       unsigned int timeout;
        unsigned int iir;
 
        iir = serial_in(up, UART_IIR);
        if (!(iir & UART_IIR_NO_INT))
                serial8250_handle_port(up);
+       mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+}
+
+static void serial8250_backup_timeout(unsigned long data)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
+       unsigned int iir, ier = 0;
+
+       /*
+        * Must disable interrupts or else we risk racing with the interrupt
+        * based handler.
+        */
+       if (is_real_interrupt(up->port.irq)) {
+               ier = serial_in(up, UART_IER);
+               serial_out(up, UART_IER, 0);
+       }
 
-       timeout = up->port.timeout;
-       timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-       mod_timer(&up->timer, jiffies + timeout);
+       iir = serial_in(up, UART_IIR);
+
+       /*
+        * This should be a safe test for anyone who doesn't trust the
+        * IIR bits on their UART, but it's specifically designed for
+        * the "Diva" UART used on the management processor on many HP
+        * ia64 and parisc boxes.
+        */
+       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+           (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+           (serial_in(up, UART_LSR) & UART_LSR_THRE)) {
+               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+               iir |= UART_IIR_THRI;
+       }
+
+       if (!(iir & UART_IIR_NO_INT))
+               serial8250_handle_port(up);
+
+       if (is_real_interrupt(up->port.irq))
+               serial_out(up, UART_IER, ier);
+
+       /* Standard timer interval plus 0.2s to keep the port running */
+       mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1540,6 +1598,37 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ *     Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       do {
+               status = serial_in(up, UART_LSR);
+
+               if (status & UART_LSR_BI)
+                       up->lsr_break_flag = UART_LSR_BI;
+
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while ((status & bits) != bits);
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               tmout = 1000000;
+               while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) {
+                       udelay(1);
+                       touch_nmi_watchdog();
+               }
+       }
+}
+
 static int serial8250_startup(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1613,18 +1702,50 @@ static int serial8250_startup(struct uart_port *port)
                serial_outp(up, UART_LCR, 0);
        }
 
+       if (is_real_interrupt(up->port.irq)) {
+               /*
+                * Test for UARTs that do not reassert THRE when the
+                * transmitter is idle and the interrupt has already
+                * been cleared.  Real 16550s should always reassert
+                * this interrupt whenever the transmitter is idle and
+                * the interrupt is enabled.  Delays are necessary to
+                * allow register changes to become visible.
+                */
+               spin_lock_irqsave(&up->port.lock, flags);
+
+               wait_for_xmitr(up, UART_LSR_THRE);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow THRE to set */
+               serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow a working UART time to re-assert THRE */
+               iir = serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+
+               spin_unlock_irqrestore(&up->port.lock, flags);
+
+               /*
+                * If the interrupt is not reasserted, setup a timer to
+                * kick the UART on a regular basis.
+                */
+               if (iir & UART_IIR_NO_INT) {
+                       pr_debug("ttyS%d - using backup timer\n", port->line);
+                       up->timer.function = serial8250_backup_timeout;
+                       up->timer.data = (unsigned long)up;
+                       mod_timer(&up->timer, jiffies +
+                                 poll_timeout(up->port.timeout) + HZ/5);
+               }
+       }
+
        /*
         * If the "interrupt" for this port doesn't correspond with any
         * hardware interrupt, we use a timer-based system.  The original
         * driver used to do this with IRQ0.
         */
        if (!is_real_interrupt(up->port.irq)) {
-               unsigned int timeout = up->port.timeout;
-
-               timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
                up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + timeout);
+               mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
        } else {
                retval = serial_link_irq_chain(up);
                if (retval)
@@ -1740,9 +1861,9 @@ static void serial8250_shutdown(struct uart_port *port)
         */
        (void) serial_in(up, UART_RX);
 
-       if (!is_real_interrupt(up->port.irq))
-               del_timer_sync(&up->timer);
-       else
+       del_timer_sync(&up->timer);
+       up->timer.function = serial8250_timeout;
+       if (is_real_interrupt(up->port.irq))
                serial_unlink_irq_chain(up);
 }
 
@@ -2212,37 +2333,6 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *     Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
-       unsigned int status, tmout = 10000;
-
-       /* Wait up to 10ms for the character(s) to be sent. */
-       do {
-               status = serial_in(up, UART_LSR);
-
-               if (status & UART_LSR_BI)
-                       up->lsr_break_flag = UART_LSR_BI;
-
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       } while ((status & bits) != bits);
-
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               tmout = 1000000;
-               while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) {
-                       udelay(1);
-                       touch_nmi_watchdog();
-               }
-       }
-}
-
 static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
index ef8cc8a70c6092e018a7e34b98a7c66426140bec..562ba745a044ae7f30d46ace434d6ba4af72b3d6 100644 (file)
@@ -47,11 +47,10 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
        unsigned long bus_addr;
        unsigned int i;
 
-       info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+       info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       memset(info, 0, sizeof(struct serial_card_info));
        info->num_ports = type->num_ports;
 
        bus_addr = ecard_resource_start(ec, type->type);
index a2dac378bda9199a94eeb2a5793cd989df360458..6d7d616e9ccde48400049a84f62125d1914358fd 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -1628,7 +1627,7 @@ pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
                        nr_ports = rc;
        }
 
-       priv = kmalloc(sizeof(struct serial_private) +
+       priv = kzalloc(sizeof(struct serial_private) +
                       sizeof(unsigned int) * nr_ports,
                       GFP_KERNEL);
        if (!priv) {
@@ -1636,9 +1635,6 @@ pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
                goto err_deinit;
        }
 
-       memset(priv, 0, sizeof(struct serial_private) +
-                       sizeof(unsigned int) * nr_ports);
-
        priv->dev = dev;
        priv->quirk = quirk;
 
index d3d6b82706b5edbb548211187e96e28956859a4a..cde5db44abf6f136b601f65bf070ac1c31318ded 100644 (file)
@@ -450,11 +450,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
        port.dev = &dev->dev;
 
        line = serial8250_register_port(&port);
+       if (line < 0)
+               return -ENODEV;
 
-       if (line >= 0)
-               pnp_set_drvdata(dev, (void *)((long)line + 1));
-       return line >= 0 ? 0 : -ENODEV;
-
+       pnp_set_drvdata(dev, (void *)((long)line + 1));
+       return 0;
 }
 
 static void __devexit serial_pnp_remove(struct pnp_dev *dev)
index d0edbaacb1f7a8b6277a566f0d5ed2c15c389ba8..ad9f321968e1d24061272ece20db34b0b12d3084 100644 (file)
@@ -262,7 +262,8 @@ config SERIAL_AMBA_PL010
        select SERIAL_CORE
        help
          This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
-         an Integrator/AP or Integrator/PP2 platform, say Y or M here.
+         an Integrator/AP or Integrator/PP2 platform, or if you have a
+         Cirrus Logic EP93xx CPU, say Y or M here.
 
          If unsure, say N.
 
@@ -686,6 +687,22 @@ config SERIAL_SH_SCI_CONSOLE
        depends on SERIAL_SH_SCI=y
        select SERIAL_CORE_CONSOLE
 
+config SERIAL_PNX8XXX
+       bool "Enable PNX8XXX SoCs' UART Support"
+       depends on MIPS && SOC_PNX8550
+       select SERIAL_CORE
+       help
+         If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
+         and you want to use serial ports, say Y.  Otherwise, say N.
+
+config SERIAL_PNX8XXX_CONSOLE
+       bool "Enable PNX8XX0 serial console"
+       depends on SERIAL_PNX8XXX
+       select SERIAL_CORE_CONSOLE
+       help
+         If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
+         and you want to use serial console, say Y. Otherwise, say N.
+
 config SERIAL_CORE
        tristate
 
index f3f82587b5fa2389a4ae5a4cc31a36e9b9191930..6b3560c5749aae039eb015f9f6cf5964ec72ccd3 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
 obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
index df45a7ac773f8fd5b7409b64bc4b764480dbe0fa..935f48fa501d5b398a3913281b5740e160ec4b85 100644 (file)
 #include <linux/sysrq.h>
 #include <linux/tty_flip.h>
 #include <linux/platform_device.h>
+#include <linux/atmel_pdc.h>
 
 #include <asm/io.h>
 
 #include <asm/mach/serial_at91.h>
 #include <asm/arch/board.h>
-#include <asm/arch/at91_pdc.h>
+
 #ifdef CONFIG_ARM
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
index 787a8f134677c0a1b7f0f8ab17778bb267dd247a..fa455996ad8fb30b46004f16bf4feaa2f7a76efc 100644 (file)
@@ -285,7 +285,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
 int __init cpm_uart_init_portdesc(void)
 {
 #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
-       u32 addr;
+       u16 *addr;
 #endif
        pr_debug("CPM uart[-]:init portdesc\n");
 
index 71e6a24d8c28f18b8c6420ca5ffab0fef011651d..41431d0d5512633f184f6fb8c92cd5aad6ed343a 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -1417,14 +1416,12 @@ static int __devinit icom_alloc_adapter(struct icom_adapter
        struct list_head *tmp;
 
        icom_adapter = (struct icom_adapter *)
-           kmalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+           kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
 
        if (!icom_adapter) {
                return -ENOMEM;
        }
 
-       memset(icom_adapter, 0, sizeof(struct icom_adapter));
-
        list_for_each(tmp, &icom_adapter_head) {
                cur_adapter_entry =
                    list_entry(tmp, struct icom_adapter,
index e216dcf29376582776418cf2ccfb825885a91124..04cc88cc528cec7eb742eee9e5e952e3662be502 100644 (file)
@@ -154,7 +154,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 {
        struct circ_buf *xmit = &sport->port.info->xmit;
 
-       do {
+       while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
                URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
@@ -163,7 +163,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
                sport->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
-       } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
+       }
 
        if (uart_circ_empty(xmit))
                imx_stop_tx(&sport->port);
@@ -178,8 +178,7 @@ static void imx_start_tx(struct uart_port *port)
 
        UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
 
-       if(UTS((u32)sport->port.membase) & UTS_TXEMPTY)
-               imx_transmit_buffer(sport);
+       imx_transmit_buffer(sport);
 }
 
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
@@ -404,7 +403,8 @@ static int imx_startup(struct uart_port *port)
        if (retval) goto error_out2;
 
        retval = request_irq(sport->rtsirq, imx_rtsint,
-                            IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+                            (sport->rtsirq < IMX_IRQS) ? 0 :
+                              IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                             DRIVER_NAME, sport);
        if (retval) goto error_out3;
 
@@ -678,7 +678,7 @@ static struct imx_port imx_ports[] = {
                .mapbase        = IMX_UART1_BASE, /* FIXME */
                .irq            = UART1_MINT_RX,
                .uartclk        = 16000000,
-               .fifosize       = 8,
+               .fifosize       = 32,
                .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 0,
@@ -694,7 +694,7 @@ static struct imx_port imx_ports[] = {
                .mapbase        = IMX_UART2_BASE, /* FIXME */
                .irq            = UART2_MINT_RX,
                .uartclk        = 16000000,
-               .fifosize       = 8,
+               .fifosize       = 32,
                .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 1,
index 9cc0be932316e86545de429622e9ebbe5f837215..168073f12cec94b9b39b4684bb6f0e37a7e78c0a 100644 (file)
@@ -2019,13 +2019,12 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
        DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
 
-       card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL);
+       card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
        if (!card_ptr) {
                printk(KERN_WARNING "ioc3_attach_one"
                       ": unable to get memory for the IOC3\n");
                return -ENOMEM;
        }
-       memset(card_ptr, 0, sizeof(struct ioc3_card));
        idd->data[is->id] = card_ptr;
        Submodule_slot = is->id;
 
@@ -2040,13 +2039,12 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
        /* Create port structures for each port */
        for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
-               port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL);
+               port = kzalloc(sizeof(struct ioc3_port), GFP_KERNEL);
                if (!port) {
                        printk(KERN_WARNING
                               "IOC3 serial memory not available for port\n");
                        goto out4;
                }
-               memset(port, 0, sizeof(struct ioc3_port));
                spin_lock_init(&port->ip_lock);
 
                /* we need to remember the previous ones, to point back to
index f540212e7409fe79971c85bed38a93ea1ca4c988..0c179384fb0cae34049bda432e8f349a910d3694 100644 (file)
@@ -1076,13 +1076,12 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
        /* Create port structures for each port */
        for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
                                                        port_number++) {
-               port = kmalloc(sizeof(struct ioc4_port), GFP_KERNEL);
+               port = kzalloc(sizeof(struct ioc4_port), GFP_KERNEL);
                if (!port) {
                        printk(KERN_WARNING
                                "IOC4 serial memory not available for port\n");
                        return -ENOMEM;
                }
-               memset(port, 0, sizeof(struct ioc4_port));
                spin_lock_init(&port->ip_lock);
 
                /* we need to remember the previous ones, to point back to
@@ -2811,7 +2810,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
                                (void *)serial));
 
        /* Get memory for the new card */
-       control = kmalloc(sizeof(struct ioc4_control), GFP_KERNEL);
+       control = kzalloc(sizeof(struct ioc4_control), GFP_KERNEL);
 
        if (!control) {
                printk(KERN_WARNING "ioc4_attach_one"
@@ -2819,11 +2818,10 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
                ret = -ENOMEM;
                goto out2;
        }
-       memset(control, 0, sizeof(struct ioc4_control));
        idd->idd_serial_data = control;
 
        /* Allocate the soft structure */
-       soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
+       soft = kzalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
        if (!soft) {
                printk(KERN_WARNING
                       "ioc4 (%p): unable to get memory for the soft struct\n",
@@ -2831,7 +2829,6 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
                ret = -ENOMEM;
                goto out3;
        }
-       memset(soft, 0, sizeof(struct ioc4_soft));
 
        spin_lock_init(&soft->is_ir_lock);
        soft->is_ioc4_misc_addr = idd->idd_misc_regs;
index 0746c9446ae018c13273505fc5abbd5b1dc6a852..c3abfb39f31650c207b16fe17d6ed778f5932bc9 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
@@ -922,13 +921,7 @@ static int zilog_irq = -1;
 
 static void * __init alloc_one_table(unsigned long size)
 {
-       void *ret;
-
-       ret = kmalloc(size, GFP_KERNEL);
-       if (ret != NULL)
-               memset(ret, 0, size);
-
-       return ret;
+       return kzalloc(size, GFP_KERNEL);
 }
 
 static void __init ip22zilog_alloc_tables(void)
index 244f63be3a03f777819ba5471563af8bd7e4a936..81792e6eeb2d045bf27069a10f58417a84805642 100644 (file)
@@ -71,14 +71,13 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_disable_device;
        }
 
-       brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL);
+       brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL);
        if (!brd) {
                dev_err(&pdev->dev,
                        "memory allocation for board structure failed\n");
                rc = -ENOMEM;
                goto out_release_regions;
        }
-       memset(brd, 0, sizeof(struct jsm_board));
 
        /* store the info for the board we've found */
        brd->boardnum = adapter_count++;
@@ -152,7 +151,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
         * Okay to malloc with GFP_KERNEL, we are not at interrupt
         * context, and there are no locks held.
         */
-       brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+       brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
        if (!brd->flipbuf) {
                /* XXX: leaking all resources from jsm_tty_init and
                        jsm_uart_port_init here! */
@@ -160,7 +159,6 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                retval = -ENOMEM;
                goto out_free_irq;
        }
-       memset(brd->flipbuf, 0, MYFLIPLEN);
 
        pci_set_drvdata(pdev, brd);
 
index 7cf1c60027f842022a72e3f6dfed1c9ee35ea6d1..be22bbdbc8e5e3532cf385e7ea0a7bc2812a6926 100644 (file)
@@ -194,31 +194,28 @@ static int jsm_tty_open(struct uart_port *port)
        /* Drop locks, as malloc with GFP_KERNEL can sleep */
 
        if (!channel->ch_rqueue) {
-               channel->ch_rqueue = (u8 *) kmalloc(RQUEUESIZE, GFP_KERNEL);
+               channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
                if (!channel->ch_rqueue) {
                        jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
                                "unable to allocate read queue buf");
                        return -ENOMEM;
                }
-               memset(channel->ch_rqueue, 0, RQUEUESIZE);
        }
        if (!channel->ch_equeue) {
-               channel->ch_equeue = (u8 *) kmalloc(EQUEUESIZE, GFP_KERNEL);
+               channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
                if (!channel->ch_equeue) {
                        jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
                                "unable to allocate error queue buf");
                        return -ENOMEM;
                }
-               memset(channel->ch_equeue, 0, EQUEUESIZE);
        }
        if (!channel->ch_wqueue) {
-               channel->ch_wqueue = (u8 *) kmalloc(WQUEUESIZE, GFP_KERNEL);
+               channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL);
                if (!channel->ch_wqueue) {
                        jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
                                "unable to allocate write queue buf");
                        return -ENOMEM;
                }
-               memset(channel->ch_wqueue, 0, WQUEUESIZE);
        }
 
        channel->ch_flags &= ~(CH_OPENING);
@@ -392,13 +389,12 @@ int jsm_tty_init(struct jsm_board *brd)
                         * Okay to malloc with GFP_KERNEL, we are not at
                         * interrupt context, and there are no locks held.
                         */
-                       brd->channels[i] = kmalloc(sizeof(struct jsm_channel), GFP_KERNEL);
+                       brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
                        if (!brd->channels[i]) {
                                jsm_printk(CORE, ERR, &brd->pci_dev,
                                        "%s:%d Unable to allocate memory for channel struct\n",
                                                         __FILE__, __LINE__);
                        }
-                       memset(brd->channels[i], 0, sizeof(struct jsm_channel));
                }
        }
 
index 955bbd653e22c0c94764c1503c7f3c1818bcdb9a..8d24cd521056793828df902ce864210653ca408d 100644 (file)
@@ -995,8 +995,10 @@ mpc52xx_uart_of_remove(struct of_device *op)
        struct uart_port *port = dev_get_drvdata(&op->dev);
        dev_set_drvdata(&op->dev, NULL);
 
-       if (port)
+       if (port) {
                uart_remove_one_port(&mpc52xx_uart_driver, port);
+               irq_dispose_mapping(port->irq);
+       }
 
        return 0;
 }
diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c
new file mode 100644 (file)
index 0000000..8d01c59
--- /dev/null
@@ -0,0 +1,852 @@
+/*
+ * UART driver for PNX8XXX SoCs
+ *
+ * Author: Per Hallsmark per.hallsmark@mvista.com
+ * Ported to 2.6 kernel by EmbeddedAlley
+ * Reworked by Vitaly Wool <vitalywool@gmail.com>
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#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/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_pnx8xxx.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/* We'll be using StrongARM sa1100 serial port major/minor */
+#define SERIAL_PNX8XXX_MAJOR   204
+#define MINOR_START            5
+
+#define NR_PORTS               2
+
+#define PNX8XXX_ISR_PASS_LIMIT 256
+
+/*
+ * Convert from ignore_status_mask or read_status_mask to FIFO
+ * and interrupt status bits
+ */
+#define SM_TO_FIFO(x)  ((x) >> 10)
+#define SM_TO_ISTAT(x) ((x) & 0x000001ff)
+#define FIFO_TO_SM(x)  ((x) << 10)
+#define ISTAT_TO_SM(x) ((x) & 0x000001ff)
+
+/*
+ * This is the size of our serial port register set.
+ */
+#define UART_PORT_SIZE 0x1000
+
+/*
+ * This determines how often we check the modem status signals
+ * for any change.  They generally aren't connected to an IRQ
+ * so we have to poll them.  We also check immediately before
+ * filling the TX fifo incase CTS has been dropped.
+ */
+#define MCTRL_TIMEOUT  (250*HZ/1000)
+
+extern struct pnx8xxx_port pnx8xxx_ports[];
+
+static inline int serial_in(struct pnx8xxx_port *sport, int offset)
+{
+       return (__raw_readl(sport->port.membase + offset));
+}
+
+static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value)
+{
+       __raw_writel(value, sport->port.membase + offset);
+}
+
+/*
+ * Handle any change of modem status signal since we were last called.
+ */
+static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport)
+{
+       unsigned int status, changed;
+
+       status = sport->port.ops->get_mctrl(&sport->port);
+       changed = status ^ sport->old_status;
+
+       if (changed == 0)
+               return;
+
+       sport->old_status = status;
+
+       if (changed & TIOCM_RI)
+               sport->port.icount.rng++;
+       if (changed & TIOCM_DSR)
+               sport->port.icount.dsr++;
+       if (changed & TIOCM_CAR)
+               uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
+       if (changed & TIOCM_CTS)
+               uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
+
+       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+}
+
+/*
+ * This is our per-port timeout handler, for checking the
+ * modem status signals.
+ */
+static void pnx8xxx_timeout(unsigned long data)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)data;
+       unsigned long flags;
+
+       if (sport->port.info) {
+               spin_lock_irqsave(&sport->port.lock, flags);
+               pnx8xxx_mctrl_check(sport);
+               spin_unlock_irqrestore(&sport->port.lock, flags);
+
+               mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
+       }
+}
+
+/*
+ * interrupts disabled on entry
+ */
+static void pnx8xxx_stop_tx(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       u32 ien;
+
+       /* Disable TX intr */
+       ien = serial_in(sport, PNX8XXX_IEN);
+       serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX);
+
+       /* Clear all pending TX intr */
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
+}
+
+/*
+ * interrupts may not be disabled on entry
+ */
+static void pnx8xxx_start_tx(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       u32 ien;
+
+       /* Clear all pending TX intr */
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
+
+       /* Enable TX intr */
+       ien = serial_in(sport, PNX8XXX_IEN);
+       serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX);
+}
+
+/*
+ * Interrupts enabled
+ */
+static void pnx8xxx_stop_rx(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       u32 ien;
+
+       /* Disable RX intr */
+       ien = serial_in(sport, PNX8XXX_IEN);
+       serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX);
+
+       /* Clear all pending RX intr */
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX);
+}
+
+/*
+ * Set the modem control timer to fire immediately.
+ */
+static void pnx8xxx_enable_ms(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+       mod_timer(&sport->timer, jiffies);
+}
+
+static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
+{
+       struct tty_struct *tty = sport->port.info->tty;
+       unsigned int status, ch, flg;
+
+       status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
+                ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
+       while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
+               ch = serial_in(sport, PNX8XXX_FIFO);
+
+               sport->port.icount.rx++;
+
+               flg = TTY_NORMAL;
+
+               /*
+                * note that the error handling code is
+                * out of the main execution path
+                */
+               if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
+                                       PNX8XXX_UART_FIFO_RXPAR) |
+                             ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
+                       if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+                               sport->port.icount.parity++;
+                       else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
+                               sport->port.icount.frame++;
+                       if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))
+                               sport->port.icount.overrun++;
+
+                       status &= sport->port.read_status_mask;
+
+                       if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+                               flg = TTY_PARITY;
+                       else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
+                               flg = TTY_FRAME;
+
+#ifdef SUPPORT_SYSRQ
+                       sport->port.sysrq = 0;
+#endif
+               }
+
+               if (uart_handle_sysrq_char(&sport->port, ch))
+                       goto ignore_char;
+
+               uart_insert_char(&sport->port, status,
+                               ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg);
+
+       ignore_char:
+               serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) |
+                               PNX8XXX_UART_LCR_RX_NEXT);
+               status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
+                        ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
+       }
+       tty_flip_buffer_push(tty);
+}
+
+static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
+{
+       struct circ_buf *xmit = &sport->port.info->xmit;
+
+       if (sport->port.x_char) {
+               serial_out(sport, PNX8XXX_FIFO, sport->port.x_char);
+               sport->port.icount.tx++;
+               sport->port.x_char = 0;
+               return;
+       }
+
+       /*
+        * Check the modem control lines before
+        * transmitting anything.
+        */
+       pnx8xxx_mctrl_check(sport);
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+               pnx8xxx_stop_tx(&sport->port);
+               return;
+       }
+
+       /*
+        * TX while bytes available
+        */
+       while (((serial_in(sport, PNX8XXX_FIFO) &
+                                       PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) {
+               serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               sport->port.icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&sport->port);
+
+       if (uart_circ_empty(xmit))
+               pnx8xxx_stop_tx(&sport->port);
+}
+
+static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
+{
+       struct pnx8xxx_port *sport = dev_id;
+       unsigned int status;
+
+       spin_lock(&sport->port.lock);
+       /* Get the interrupts */
+       status  = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
+
+       /* Break signal received */
+       if (status & PNX8XXX_UART_INT_BREAK) {
+               sport->port.icount.brk++;
+               uart_handle_break(&sport->port);
+       }
+
+       /* Byte received */
+       if (status & PNX8XXX_UART_INT_RX)
+               pnx8xxx_rx_chars(sport);
+
+       /* TX holding register empty - transmit a byte */
+       if (status & PNX8XXX_UART_INT_TX)
+               pnx8xxx_tx_chars(sport);
+
+       /* Clear the ISTAT register */
+       serial_out(sport, PNX8XXX_ICLR, status);
+
+       spin_unlock(&sport->port.lock);
+       return IRQ_HANDLED;
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int pnx8xxx_tx_empty(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+       return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int pnx8xxx_get_mctrl(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       unsigned int mctrl = TIOCM_DSR;
+       unsigned int msr;
+
+       /* REVISIT */
+
+       msr = serial_in(sport, PNX8XXX_MCR);
+
+       mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0;
+       mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0;
+
+       return mctrl;
+}
+
+static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+#if    0       /* FIXME */
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       unsigned int msr;
+#endif
+}
+
+/*
+ * Interrupts always disabled.
+ */
+static void pnx8xxx_break_ctl(struct uart_port *port, int break_state)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       unsigned long flags;
+       unsigned int lcr;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+       lcr = serial_in(sport, PNX8XXX_LCR);
+       if (break_state == -1)
+               lcr |= PNX8XXX_UART_LCR_TXBREAK;
+       else
+               lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
+       serial_out(sport, PNX8XXX_LCR, lcr);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int pnx8xxx_startup(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       int retval;
+
+       /*
+        * Allocate the IRQ
+        */
+       retval = request_irq(sport->port.irq, pnx8xxx_int, 0,
+                            "pnx8xxx-uart", sport);
+       if (retval)
+               return retval;
+
+       /*
+        * Finally, clear and enable interrupts
+        */
+
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
+                            PNX8XXX_UART_INT_ALLTX);
+
+       serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) |
+                           PNX8XXX_UART_INT_ALLRX |
+                           PNX8XXX_UART_INT_ALLTX);
+
+       /*
+        * Enable modem status interrupts
+        */
+       spin_lock_irq(&sport->port.lock);
+       pnx8xxx_enable_ms(&sport->port);
+       spin_unlock_irq(&sport->port.lock);
+
+       return 0;
+}
+
+static void pnx8xxx_shutdown(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       int lcr;
+
+       /*
+        * Stop our timer.
+        */
+       del_timer_sync(&sport->timer);
+
+       /*
+        * Disable all interrupts
+        */
+       serial_out(sport, PNX8XXX_IEN, 0);
+
+       /*
+        * Reset the Tx and Rx FIFOS, disable the break condition
+        */
+       lcr = serial_in(sport, PNX8XXX_LCR);
+       lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
+       lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST;
+       serial_out(sport, PNX8XXX_LCR, lcr);
+
+       /*
+        * Clear all interrupts
+        */
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
+                            PNX8XXX_UART_INT_ALLTX);
+
+       /*
+        * Free the interrupt
+        */
+       free_irq(sport->port.irq, sport);
+}
+
+static void
+pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       unsigned long flags;
+       unsigned int lcr_fcr, old_ien, baud, quot;
+       unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+       /*
+        * We only support CS7 and CS8.
+        */
+       while ((termios->c_cflag & CSIZE) != CS7 &&
+              (termios->c_cflag & CSIZE) != CS8) {
+               termios->c_cflag &= ~CSIZE;
+               termios->c_cflag |= old_csize;
+               old_csize = CS8;
+       }
+
+       if ((termios->c_cflag & CSIZE) == CS8)
+               lcr_fcr = PNX8XXX_UART_LCR_8BIT;
+       else
+               lcr_fcr = 0;
+
+       if (termios->c_cflag & CSTOPB)
+               lcr_fcr |= PNX8XXX_UART_LCR_2STOPB;
+       if (termios->c_cflag & PARENB) {
+               lcr_fcr |= PNX8XXX_UART_LCR_PAREN;
+               if (!(termios->c_cflag & PARODD))
+                       lcr_fcr |= PNX8XXX_UART_LCR_PAREVN;
+       }
+
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+       quot = uart_get_divisor(port, baud);
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+
+       sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) |
+                               ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) |
+                               ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
+       if (termios->c_iflag & INPCK)
+               sport->port.read_status_mask |=
+                       FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+                       FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               sport->port.read_status_mask |=
+                       ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
+
+       /*
+        * Characters to ignore
+        */
+       sport->port.ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               sport->port.ignore_status_mask |=
+                       FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+                       FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
+       if (termios->c_iflag & IGNBRK) {
+               sport->port.ignore_status_mask |=
+                       ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       sport->port.ignore_status_mask |=
+                               ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN);
+       }
+
+       /*
+        * ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               sport->port.ignore_status_mask |=
+                       ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
+
+       del_timer_sync(&sport->timer);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       /*
+        * disable interrupts and drain transmitter
+        */
+       old_ien = serial_in(sport, PNX8XXX_IEN);
+       serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
+                                       PNX8XXX_UART_INT_ALLRX));
+
+       while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA)
+               barrier();
+
+       /* then, disable everything */
+       serial_out(sport, PNX8XXX_IEN, 0);
+
+       /* Reset the Rx and Tx FIFOs too */
+       lcr_fcr |= PNX8XXX_UART_LCR_TX_RST;
+       lcr_fcr |= PNX8XXX_UART_LCR_RX_RST;
+
+       /* set the parity, stop bits and data size */
+       serial_out(sport, PNX8XXX_LCR, lcr_fcr);
+
+       /* set the baud rate */
+       quot -= 1;
+       serial_out(sport, PNX8XXX_BAUD, quot);
+
+       serial_out(sport, PNX8XXX_ICLR, -1);
+
+       serial_out(sport, PNX8XXX_IEN, old_ien);
+
+       if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
+               pnx8xxx_enable_ms(&sport->port);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static const char *pnx8xxx_type(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+       return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void pnx8xxx_release_port(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+       release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int pnx8xxx_request_port(struct uart_port *port)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+                       "pnx8xxx-uart") != NULL ? 0 : -EBUSY;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void pnx8xxx_config_port(struct uart_port *port, int flags)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+       if (flags & UART_CONFIG_TYPE &&
+           pnx8xxx_request_port(&sport->port) == 0)
+               sport->port.type = PORT_PNX8XXX;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ * The only change we allow are to the flags and type, and
+ * even then only between PORT_PNX8XXX and PORT_UNKNOWN
+ */
+static int
+pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       int ret = 0;
+
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX)
+               ret = -EINVAL;
+       if (sport->port.irq != ser->irq)
+               ret = -EINVAL;
+       if (ser->io_type != SERIAL_IO_MEM)
+               ret = -EINVAL;
+       if (sport->port.uartclk / 16 != ser->baud_base)
+               ret = -EINVAL;
+       if ((void *)sport->port.mapbase != ser->iomem_base)
+               ret = -EINVAL;
+       if (sport->port.iobase != ser->port)
+               ret = -EINVAL;
+       if (ser->hub6 != 0)
+               ret = -EINVAL;
+       return ret;
+}
+
+static struct uart_ops pnx8xxx_pops = {
+       .tx_empty       = pnx8xxx_tx_empty,
+       .set_mctrl      = pnx8xxx_set_mctrl,
+       .get_mctrl      = pnx8xxx_get_mctrl,
+       .stop_tx        = pnx8xxx_stop_tx,
+       .start_tx       = pnx8xxx_start_tx,
+       .stop_rx        = pnx8xxx_stop_rx,
+       .enable_ms      = pnx8xxx_enable_ms,
+       .break_ctl      = pnx8xxx_break_ctl,
+       .startup        = pnx8xxx_startup,
+       .shutdown       = pnx8xxx_shutdown,
+       .set_termios    = pnx8xxx_set_termios,
+       .type           = pnx8xxx_type,
+       .release_port   = pnx8xxx_release_port,
+       .request_port   = pnx8xxx_request_port,
+       .config_port    = pnx8xxx_config_port,
+       .verify_port    = pnx8xxx_verify_port,
+};
+
+
+/*
+ * Setup the PNX8XXX serial ports.
+ *
+ * Note also that we support "console=ttySx" where "x" is either 0 or 1.
+ */
+static void __init pnx8xxx_init_ports(void)
+{
+       static int first = 1;
+       int i;
+
+       if (!first)
+               return;
+       first = 0;
+
+       for (i = 0; i < NR_PORTS; i++) {
+               init_timer(&pnx8xxx_ports[i].timer);
+               pnx8xxx_ports[i].timer.function = pnx8xxx_timeout;
+               pnx8xxx_ports[i].timer.data     = (unsigned long)&pnx8xxx_ports[i];
+               pnx8xxx_ports[i].port.ops = &pnx8xxx_pops;
+       }
+}
+
+#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE
+
+static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
+{
+       struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+       int status;
+
+       do {
+               /* Wait for UART_TX register to empty */
+               status = serial_in(sport, PNX8XXX_FIFO);
+       } while (status & PNX8XXX_UART_FIFO_TXFIFO);
+       serial_out(sport, PNX8XXX_FIFO, ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */static void
+pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
+{
+       struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
+       unsigned int old_ien, status;
+
+       /*
+        *      First, save IEN and then disable interrupts
+        */
+       old_ien = serial_in(sport, PNX8XXX_IEN);
+       serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
+                                       PNX8XXX_UART_INT_ALLRX));
+
+       uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar);
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore IEN
+        */
+       do {
+               /* Wait for UART_TX register to empty */
+               status = serial_in(sport, PNX8XXX_FIFO);
+       } while (status & PNX8XXX_UART_FIFO_TXFIFO);
+
+       /* Clear TX and EMPTY interrupt */
+       serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX |
+                            PNX8XXX_UART_INT_EMPTY);
+
+       serial_out(sport, PNX8XXX_IEN, old_ien);
+}
+
+static int __init
+pnx8xxx_console_setup(struct console *co, char *options)
+{
+       struct pnx8xxx_port *sport;
+       int baud = 38400;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index == -1 || co->index >= NR_PORTS)
+               co->index = 0;
+       sport = &pnx8xxx_ports[co->index];
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver pnx8xxx_reg;
+static struct console pnx8xxx_console = {
+       .name           = "ttyS",
+       .write          = pnx8xxx_console_write,
+       .device         = uart_console_device,
+       .setup          = pnx8xxx_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &pnx8xxx_reg,
+};
+
+static int __init pnx8xxx_rs_console_init(void)
+{
+       pnx8xxx_init_ports();
+       register_console(&pnx8xxx_console);
+       return 0;
+}
+console_initcall(pnx8xxx_rs_console_init);
+
+#define PNX8XXX_CONSOLE        &pnx8xxx_console
+#else
+#define PNX8XXX_CONSOLE        NULL
+#endif
+
+static struct uart_driver pnx8xxx_reg = {
+       .owner                  = THIS_MODULE,
+       .driver_name            = "ttyS",
+       .dev_name               = "ttyS",
+       .major                  = SERIAL_PNX8XXX_MAJOR,
+       .minor                  = MINOR_START,
+       .nr                     = NR_PORTS,
+       .cons                   = PNX8XXX_CONSOLE,
+};
+
+static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+       return uart_suspend_port(&pnx8xxx_reg, &sport->port);
+}
+
+static int pnx8xxx_serial_resume(struct platform_device *pdev)
+{
+       struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+       return uart_resume_port(&pnx8xxx_reg, &sport->port);
+}
+
+static int pnx8xxx_serial_probe(struct platform_device *pdev)
+{
+       struct resource *res = pdev->resource;
+       int i;
+
+       for (i = 0; i < pdev->num_resources; i++, res++) {
+               if (!(res->flags & IORESOURCE_MEM))
+                       continue;
+
+               for (i = 0; i < NR_PORTS; i++) {
+                       if (pnx8xxx_ports[i].port.mapbase != res->start)
+                               continue;
+
+                       pnx8xxx_ports[i].port.dev = &pdev->dev;
+                       uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port);
+                       platform_set_drvdata(pdev, &pnx8xxx_ports[i]);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int pnx8xxx_serial_remove(struct platform_device *pdev)
+{
+       struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (sport)
+               uart_remove_one_port(&pnx8xxx_reg, &sport->port);
+
+       return 0;
+}
+
+static struct platform_driver pnx8xxx_serial_driver = {
+       .driver         = {
+               .name   = "pnx8xxx-uart",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = pnx8xxx_serial_probe,
+       .remove         = pnx8xxx_serial_remove,
+       .suspend        = pnx8xxx_serial_suspend,
+       .resume         = pnx8xxx_serial_resume,
+};
+
+static int __init pnx8xxx_serial_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "Serial: PNX8XXX driver $Revision: 1.2 $\n");
+
+       pnx8xxx_init_ports();
+
+       ret = uart_register_driver(&pnx8xxx_reg);
+       if (ret == 0) {
+               ret = platform_driver_register(&pnx8xxx_serial_driver);
+               if (ret)
+                       uart_unregister_driver(&pnx8xxx_reg);
+       }
+       return ret;
+}
+
+static void __exit pnx8xxx_serial_exit(void)
+{
+       platform_driver_unregister(&pnx8xxx_serial_driver);
+       uart_unregister_driver(&pnx8xxx_reg);
+}
+
+module_init(pnx8xxx_serial_init);
+module_exit(pnx8xxx_serial_exit);
+
+MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
+MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR);
index f84982e508c7efc7e2eb6bcdca37f95ee22e8b67..0422c0f1f85207715ebe221d182de4f48f85b655 100644 (file)
@@ -1523,9 +1523,8 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
        }
 
        if (!state->info) {
-               state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
+               state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL);
                if (state->info) {
-                       memset(state->info, 0, sizeof(struct uart_info));
                        init_waitqueue_head(&state->info->open_wait);
                        init_waitqueue_head(&state->info->delta_msr_wait);
 
@@ -1660,6 +1659,7 @@ static const char *uart_type(struct uart_port *port)
 static int uart_line_info(char *buf, struct uart_driver *drv, int i)
 {
        struct uart_state *state = drv->state + i;
+       int pm_state;
        struct uart_port *port = state->port;
        char stat_buf[32];
        unsigned int status;
@@ -1682,9 +1682,16 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i)
 
        if(capable(CAP_SYS_ADMIN))
        {
+               mutex_lock(&state->mutex);
+               pm_state = state->pm_state;
+               if (pm_state)
+                       uart_change_pm(state, 0);
                spin_lock_irq(&port->lock);
                status = port->ops->get_mctrl(port);
                spin_unlock_irq(&port->lock);
+               if (pm_state)
+                       uart_change_pm(state, pm_state);
+               mutex_unlock(&state->mutex);
 
                ret += sprintf(buf + ret, " tx:%d rx:%d",
                                port->icount.tx, port->icount.rx);
@@ -2100,6 +2107,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
 
                uart_report_port(drv, port);
 
+               /* Power up port for set_mctrl() */
+               uart_change_pm(state, 0);
+
                /*
                 * Ensure that the modem control lines are de-activated.
                 * We probably don't need a spinlock around this, but
@@ -2167,13 +2177,11 @@ int uart_register_driver(struct uart_driver *drv)
         * Maybe we should be using a slab cache for this, especially if
         * we have a large number of ports to handle.
         */
-       drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+       drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
        retval = -ENOMEM;
        if (!drv->state)
                goto out;
 
-       memset(drv->state, 0, sizeof(struct uart_state) * drv->nr);
-
        normal  = alloc_tty_driver(drv->nr);
        if (!normal)
                goto out;
index 431433f4dd6d3983a02bb8be5c2b09cd983e8c51..6b76babc7fbf5ece40cce4444c7c9438f76e7597 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -247,6 +246,10 @@ static const struct serial_quirk quirks[] = {
                .manfid = MANFID_QUATECH,
                .prodid = PRODID_QUATECH_DUAL_RS232_D1,
                .multi  = 2,
+       }, {
+               .manfid = MANFID_QUATECH,
+               .prodid = PRODID_QUATECH_DUAL_RS232_G,
+               .multi  = 2,
        }, {
                .manfid = MANFID_QUATECH,
                .prodid = PRODID_QUATECH_QUAD_RS232,
@@ -334,10 +337,9 @@ static int serial_probe(struct pcmcia_device *link)
        DEBUG(0, "serial_attach()\n");
 
        /* Create new serial device */
-       info = kmalloc(sizeof (*info), GFP_KERNEL);
+       info = kzalloc(sizeof (*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
-       memset(info, 0, sizeof (*info));
        info->p_dev = link;
        link->priv = info;
 
@@ -893,6 +895,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("OEM      ", "C288MX     ", 0xb572d360, 0xd2385b7a),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
        PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
+       PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
index 145d6236954b4d67b5618e318f3d8c6a2a0f3e0a..deb9ab4b5a0b6b53c3167c842a833e71d4fcc4fe 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
index 3ec3df21816be03e551f81e2a43cf2ba7d0a9342..96a852aa1903a87e6a888cda7c61587464ab1611 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
index 244f796dc62595a80f1bc34cea3cfe60b5a8239a..da73205e54cded364297a9df504316229e7f7c6c 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
index 9052f4c3493b3f9c3c567fcd4156d6e4127f1c69..7e54e48efd5cb6af7c9451811871f303bef7c854 100644 (file)
@@ -51,6 +51,13 @@ config SPI_MASTER
 comment "SPI Master Controller Drivers"
        depends on SPI_MASTER
 
+config SPI_ATMEL
+       tristate "Atmel SPI Controller"
+       depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+       help
+         This selects a driver for the Atmel SPI Controller, present on
+         many AT32 (AVR32) and AT91 (ARM) chips.
+
 config SPI_BITBANG
        tristate "Bitbanging SPI master"
        depends on SPI_MASTER && EXPERIMENTAL
index bf271fe4e536c345edf630bbeaf3cbc41e4899db..3c280ad892026bedacdb966c3c98a726a7ad4157 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_MASTER)              += spi.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_BITBANG)              += spi_bitbang.o
+obj-$(CONFIG_SPI_ATMEL)                        += atmel_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi_butterfly.o
 obj-$(CONFIG_SPI_IMX)                  += spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)               += pxa2xx_spi.o
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
new file mode 100644 (file)
index 0000000..c2a9fef
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Driver for Atmel AT32 and AT91 SPI Controllers
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+
+#include <asm/io.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "atmel_spi.h"
+
+/*
+ * The core SPI transfer engine just talks to a register bank to set up
+ * DMA transfers; transfer queue progress is driven by IRQs.  The clock
+ * framework provides the base clock, subdivided for each spi_device.
+ *
+ * Newer controllers, marked with "new_1" flag, have:
+ *  - CR.LASTXFER
+ *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
+ *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
+ *  - SPI_CSRx.CSAAT
+ *  - SPI_CSRx.SBCR allows faster clocking
+ */
+struct atmel_spi {
+       spinlock_t              lock;
+
+       void __iomem            *regs;
+       int                     irq;
+       struct clk              *clk;
+       struct platform_device  *pdev;
+       unsigned                new_1:1;
+
+       u8                      stopping;
+       struct list_head        queue;
+       struct spi_transfer     *current_transfer;
+       unsigned long           remaining_bytes;
+
+       void                    *buffer;
+       dma_addr_t              buffer_dma;
+};
+
+#define BUFFER_SIZE            PAGE_SIZE
+#define INVALID_DMA_ADDRESS    0xffffffff
+
+/*
+ * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
+ * they assume that spi slave device state will not change on deselect, so
+ * that automagic deselection is OK.  Not so!  Workaround uses nCSx pins
+ * as GPIOs; or newer controllers have CSAAT and friends.
+ *
+ * Since the CSAAT functionality is a bit weird on newer controllers
+ * as well, we use GPIO to control nCSx pins on all controllers.
+ */
+
+static inline void cs_activate(struct spi_device *spi)
+{
+       unsigned gpio = (unsigned) spi->controller_data;
+       unsigned active = spi->mode & SPI_CS_HIGH;
+
+       dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
+       gpio_set_value(gpio, active);
+}
+
+static inline void cs_deactivate(struct spi_device *spi)
+{
+       unsigned gpio = (unsigned) spi->controller_data;
+       unsigned active = spi->mode & SPI_CS_HIGH;
+
+       dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
+       gpio_set_value(gpio, !active);
+}
+
+/*
+ * Submit next transfer for DMA.
+ * lock is held, spi irq is blocked
+ */
+static void atmel_spi_next_xfer(struct spi_master *master,
+                               struct spi_message *msg)
+{
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+       struct spi_transfer     *xfer;
+       u32                     len;
+       dma_addr_t              tx_dma, rx_dma;
+
+       xfer = as->current_transfer;
+       if (!xfer || as->remaining_bytes == 0) {
+               if (xfer)
+                       xfer = list_entry(xfer->transfer_list.next,
+                                       struct spi_transfer, transfer_list);
+               else
+                       xfer = list_entry(msg->transfers.next,
+                                       struct spi_transfer, transfer_list);
+               as->remaining_bytes = xfer->len;
+               as->current_transfer = xfer;
+       }
+
+       len = as->remaining_bytes;
+
+       tx_dma = xfer->tx_dma;
+       rx_dma = xfer->rx_dma;
+
+       /* use scratch buffer only when rx or tx data is unspecified */
+       if (rx_dma == INVALID_DMA_ADDRESS) {
+               rx_dma = as->buffer_dma;
+               if (len > BUFFER_SIZE)
+                       len = BUFFER_SIZE;
+       }
+       if (tx_dma == INVALID_DMA_ADDRESS) {
+               tx_dma = as->buffer_dma;
+               if (len > BUFFER_SIZE)
+                       len = BUFFER_SIZE;
+               memset(as->buffer, 0, len);
+               dma_sync_single_for_device(&as->pdev->dev,
+                               as->buffer_dma, len, DMA_TO_DEVICE);
+       }
+
+       spi_writel(as, RPR, rx_dma);
+       spi_writel(as, TPR, tx_dma);
+
+       as->remaining_bytes -= len;
+       if (msg->spi->bits_per_word > 8)
+               len >>= 1;
+
+       /* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
+        * mechanism might help avoid the IRQ latency between transfers
+        *
+        * We're also waiting for ENDRX before we start the next
+        * transfer because we need to handle some difficult timing
+        * issues otherwise. If we wait for ENDTX in one transfer and
+        * then starts waiting for ENDRX in the next, it's difficult
+        * to tell the difference between the ENDRX interrupt we're
+        * actually waiting for and the ENDRX interrupt of the
+        * previous transfer.
+        *
+        * It should be doable, though. Just not now...
+        */
+       spi_writel(as, TNCR, 0);
+       spi_writel(as, RNCR, 0);
+       spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
+
+       dev_dbg(&msg->spi->dev,
+               "  start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
+               xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+               xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
+
+       spi_writel(as, TCR, len);
+       spi_writel(as, RCR, len);
+       spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
+}
+
+static void atmel_spi_next_message(struct spi_master *master)
+{
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+       struct spi_message      *msg;
+       u32                     mr;
+
+       BUG_ON(as->current_transfer);
+
+       msg = list_entry(as->queue.next, struct spi_message, queue);
+
+       /* Select the chip */
+       mr = spi_readl(as, MR);
+       mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
+       spi_writel(as, MR, mr);
+       cs_activate(msg->spi);
+
+       atmel_spi_next_xfer(master, msg);
+}
+
+static void
+atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
+{
+       xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
+       if (xfer->tx_buf)
+               xfer->tx_dma = dma_map_single(&as->pdev->dev,
+                               (void *) xfer->tx_buf, xfer->len,
+                               DMA_TO_DEVICE);
+       if (xfer->rx_buf)
+               xfer->rx_dma = dma_map_single(&as->pdev->dev,
+                               xfer->rx_buf, xfer->len,
+                               DMA_FROM_DEVICE);
+}
+
+static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
+                                    struct spi_transfer *xfer)
+{
+       if (xfer->tx_dma != INVALID_DMA_ADDRESS)
+               dma_unmap_single(master->cdev.dev, xfer->tx_dma,
+                                xfer->len, DMA_TO_DEVICE);
+       if (xfer->rx_dma != INVALID_DMA_ADDRESS)
+               dma_unmap_single(master->cdev.dev, xfer->rx_dma,
+                                xfer->len, DMA_FROM_DEVICE);
+}
+
+static void
+atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
+                  struct spi_message *msg, int status)
+{
+       cs_deactivate(msg->spi);
+       list_del(&msg->queue);
+       msg->status = status;
+
+       dev_dbg(master->cdev.dev,
+               "xfer complete: %u bytes transferred\n",
+               msg->actual_length);
+
+       spin_unlock(&as->lock);
+       msg->complete(msg->context);
+       spin_lock(&as->lock);
+
+       as->current_transfer = NULL;
+
+       /* continue if needed */
+       if (list_empty(&as->queue) || as->stopping)
+               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+       else
+               atmel_spi_next_message(master);
+}
+
+static irqreturn_t
+atmel_spi_interrupt(int irq, void *dev_id)
+{
+       struct spi_master       *master = dev_id;
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+       struct spi_message      *msg;
+       struct spi_transfer     *xfer;
+       u32                     status, pending, imr;
+       int                     ret = IRQ_NONE;
+
+       spin_lock(&as->lock);
+
+       xfer = as->current_transfer;
+       msg = list_entry(as->queue.next, struct spi_message, queue);
+
+       imr = spi_readl(as, IMR);
+       status = spi_readl(as, SR);
+       pending = status & imr;
+
+       if (pending & SPI_BIT(OVRES)) {
+               int timeout;
+
+               ret = IRQ_HANDLED;
+
+               spi_writel(as, IDR, (SPI_BIT(ENDTX) | SPI_BIT(ENDRX)
+                                    | SPI_BIT(OVRES)));
+
+               /*
+                * When we get an overrun, we disregard the current
+                * transfer. Data will not be copied back from any
+                * bounce buffer and msg->actual_len will not be
+                * updated with the last xfer.
+                *
+                * We will also not process any remaning transfers in
+                * the message.
+                *
+                * First, stop the transfer and unmap the DMA buffers.
+                */
+               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+               if (!msg->is_dma_mapped)
+                       atmel_spi_dma_unmap_xfer(master, xfer);
+
+               /* REVISIT: udelay in irq is unfriendly */
+               if (xfer->delay_usecs)
+                       udelay(xfer->delay_usecs);
+
+               dev_warn(master->cdev.dev, "fifo overrun (%u/%u remaining)\n",
+                        spi_readl(as, TCR), spi_readl(as, RCR));
+
+               /*
+                * Clean up DMA registers and make sure the data
+                * registers are empty.
+                */
+               spi_writel(as, RNCR, 0);
+               spi_writel(as, TNCR, 0);
+               spi_writel(as, RCR, 0);
+               spi_writel(as, TCR, 0);
+               for (timeout = 1000; timeout; timeout--)
+                       if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
+                               break;
+               if (!timeout)
+                       dev_warn(master->cdev.dev,
+                                "timeout waiting for TXEMPTY");
+               while (spi_readl(as, SR) & SPI_BIT(RDRF))
+                       spi_readl(as, RDR);
+
+               /* Clear any overrun happening while cleaning up */
+               spi_readl(as, SR);
+
+               atmel_spi_msg_done(master, as, msg, -EIO);
+       } else if (pending & SPI_BIT(ENDRX)) {
+               ret = IRQ_HANDLED;
+
+               spi_writel(as, IDR, pending);
+
+               if (as->remaining_bytes == 0) {
+                       msg->actual_length += xfer->len;
+
+                       if (!msg->is_dma_mapped)
+                               atmel_spi_dma_unmap_xfer(master, xfer);
+
+                       /* REVISIT: udelay in irq is unfriendly */
+                       if (xfer->delay_usecs)
+                               udelay(xfer->delay_usecs);
+
+                       if (msg->transfers.prev == &xfer->transfer_list) {
+                               /* report completed message */
+                               atmel_spi_msg_done(master, as, msg, 0);
+                       } else {
+                               if (xfer->cs_change) {
+                                       cs_deactivate(msg->spi);
+                                       udelay(1);
+                                       cs_activate(msg->spi);
+                               }
+
+                               /*
+                                * Not done yet. Submit the next transfer.
+                                *
+                                * FIXME handle protocol options for xfer
+                                */
+                               atmel_spi_next_xfer(master, msg);
+                       }
+               } else {
+                       /*
+                        * Keep going, we still have data to send in
+                        * the current transfer.
+                        */
+                       atmel_spi_next_xfer(master, msg);
+               }
+       }
+
+       spin_unlock(&as->lock);
+
+       return ret;
+}
+
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int atmel_spi_setup(struct spi_device *spi)
+{
+       struct atmel_spi        *as;
+       u32                     scbr, csr;
+       unsigned int            bits = spi->bits_per_word;
+       unsigned long           bus_hz, sck_hz;
+       unsigned int            npcs_pin;
+       int                     ret;
+
+       as = spi_master_get_devdata(spi->master);
+
+       if (as->stopping)
+               return -ESHUTDOWN;
+
+       if (spi->chip_select > spi->master->num_chipselect) {
+               dev_dbg(&spi->dev,
+                               "setup: invalid chipselect %u (%u defined)\n",
+                               spi->chip_select, spi->master->num_chipselect);
+               return -EINVAL;
+       }
+
+       if (bits == 0)
+               bits = 8;
+       if (bits < 8 || bits > 16) {
+               dev_dbg(&spi->dev,
+                               "setup: invalid bits_per_word %u (8 to 16)\n",
+                               bits);
+               return -EINVAL;
+       }
+
+       if (spi->mode & ~MODEBITS) {
+               dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+                       spi->mode & ~MODEBITS);
+               return -EINVAL;
+       }
+
+       /* speed zero convention is used by some upper layers */
+       bus_hz = clk_get_rate(as->clk);
+       if (spi->max_speed_hz) {
+               /* assume div32/fdiv/mbz == 0 */
+               if (!as->new_1)
+                       bus_hz /= 2;
+               scbr = ((bus_hz + spi->max_speed_hz - 1)
+                       / spi->max_speed_hz);
+               if (scbr >= (1 << SPI_SCBR_SIZE)) {
+                       dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
+                                       spi->max_speed_hz, scbr);
+                       return -EINVAL;
+               }
+       } else
+               scbr = 0xff;
+       sck_hz = bus_hz / scbr;
+
+       csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+       if (spi->mode & SPI_CPOL)
+               csr |= SPI_BIT(CPOL);
+       if (!(spi->mode & SPI_CPHA))
+               csr |= SPI_BIT(NCPHA);
+
+       /* TODO: DLYBS and DLYBCT */
+       csr |= SPI_BF(DLYBS, 10);
+       csr |= SPI_BF(DLYBCT, 10);
+
+       /* chipselect must have been muxed as GPIO (e.g. in board setup) */
+       npcs_pin = (unsigned int)spi->controller_data;
+       if (!spi->controller_state) {
+               ret = gpio_request(npcs_pin, "spi_npcs");
+               if (ret)
+                       return ret;
+               spi->controller_state = (void *)npcs_pin;
+               gpio_direction_output(npcs_pin);
+       }
+
+       dev_dbg(&spi->dev,
+               "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
+               sck_hz, bits, spi->mode, spi->chip_select, csr);
+
+       spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+
+       return 0;
+}
+
+static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+       struct atmel_spi        *as;
+       struct spi_transfer     *xfer;
+       unsigned long           flags;
+       struct device           *controller = spi->master->cdev.dev;
+
+       as = spi_master_get_devdata(spi->master);
+
+       dev_dbg(controller, "new message %p submitted for %s\n",
+                       msg, spi->dev.bus_id);
+
+       if (unlikely(list_empty(&msg->transfers)
+                       || !spi->max_speed_hz))
+               return -EINVAL;
+
+       if (as->stopping)
+               return -ESHUTDOWN;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (!(xfer->tx_buf || xfer->rx_buf)) {
+                       dev_dbg(&spi->dev, "missing rx or tx buf\n");
+                       return -EINVAL;
+               }
+
+               /* FIXME implement these protocol options!! */
+               if (xfer->bits_per_word || xfer->speed_hz) {
+                       dev_dbg(&spi->dev, "no protocol options yet\n");
+                       return -ENOPROTOOPT;
+               }
+       }
+
+       /* scrub dcache "early" */
+       if (!msg->is_dma_mapped) {
+               list_for_each_entry(xfer, &msg->transfers, transfer_list)
+                       atmel_spi_dma_map_xfer(as, xfer);
+       }
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               dev_dbg(controller,
+                       "  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+                       xfer, xfer->len,
+                       xfer->tx_buf, xfer->tx_dma,
+                       xfer->rx_buf, xfer->rx_dma);
+       }
+
+       msg->status = -EINPROGRESS;
+       msg->actual_length = 0;
+
+       spin_lock_irqsave(&as->lock, flags);
+       list_add_tail(&msg->queue, &as->queue);
+       if (!as->current_transfer)
+               atmel_spi_next_message(spi->master);
+       spin_unlock_irqrestore(&as->lock, flags);
+
+       return 0;
+}
+
+static void atmel_spi_cleanup(const struct spi_device *spi)
+{
+       if (spi->controller_state)
+               gpio_free((unsigned int)spi->controller_data);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init atmel_spi_probe(struct platform_device *pdev)
+{
+       struct resource         *regs;
+       int                     irq;
+       struct clk              *clk;
+       int                     ret;
+       struct spi_master       *master;
+       struct atmel_spi        *as;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs)
+               return -ENXIO;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       clk = clk_get(&pdev->dev, "spi_clk");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       /* setup spi core then atmel-specific driver state */
+       ret = -ENOMEM;
+       master = spi_alloc_master(&pdev->dev, sizeof *as);
+       if (!master)
+               goto out_free;
+
+       master->bus_num = pdev->id;
+       master->num_chipselect = 4;
+       master->setup = atmel_spi_setup;
+       master->transfer = atmel_spi_transfer;
+       master->cleanup = atmel_spi_cleanup;
+       platform_set_drvdata(pdev, master);
+
+       as = spi_master_get_devdata(master);
+
+       as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
+                                       &as->buffer_dma, GFP_KERNEL);
+       if (!as->buffer)
+               goto out_free;
+
+       spin_lock_init(&as->lock);
+       INIT_LIST_HEAD(&as->queue);
+       as->pdev = pdev;
+       as->regs = ioremap(regs->start, (regs->end - regs->start) + 1);
+       if (!as->regs)
+               goto out_free_buffer;
+       as->irq = irq;
+       as->clk = clk;
+#ifdef CONFIG_ARCH_AT91
+       if (!cpu_is_at91rm9200())
+               as->new_1 = 1;
+#endif
+
+       ret = request_irq(irq, atmel_spi_interrupt, 0,
+                       pdev->dev.bus_id, master);
+       if (ret)
+               goto out_unmap_regs;
+
+       /* Initialize the hardware */
+       clk_enable(clk);
+       spi_writel(as, CR, SPI_BIT(SWRST));
+       spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
+       spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+       spi_writel(as, CR, SPI_BIT(SPIEN));
+
+       /* go! */
+       dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
+                       (unsigned long)regs->start, irq);
+
+       ret = spi_register_master(master);
+       if (ret)
+               goto out_reset_hw;
+
+       return 0;
+
+out_reset_hw:
+       spi_writel(as, CR, SPI_BIT(SWRST));
+       clk_disable(clk);
+       free_irq(irq, master);
+out_unmap_regs:
+       iounmap(as->regs);
+out_free_buffer:
+       dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+                       as->buffer_dma);
+out_free:
+       clk_put(clk);
+       spi_master_put(master);
+       return ret;
+}
+
+static int __exit atmel_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master       *master = platform_get_drvdata(pdev);
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+       struct spi_message      *msg;
+
+       /* reset the hardware and block queue progress */
+       spin_lock_irq(&as->lock);
+       as->stopping = 1;
+       spi_writel(as, CR, SPI_BIT(SWRST));
+       spi_readl(as, SR);
+       spin_unlock_irq(&as->lock);
+
+       /* Terminate remaining queued transfers */
+       list_for_each_entry(msg, &as->queue, queue) {
+               /* REVISIT unmapping the dma is a NOP on ARM and AVR32
+                * but we shouldn't depend on that...
+                */
+               msg->status = -ESHUTDOWN;
+               msg->complete(msg->context);
+       }
+
+       dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+                       as->buffer_dma);
+
+       clk_disable(as->clk);
+       clk_put(as->clk);
+       free_irq(as->irq, master);
+       iounmap(as->regs);
+
+       spi_unregister_master(master);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct spi_master       *master = platform_get_drvdata(pdev);
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+
+       clk_disable(as->clk);
+       return 0;
+}
+
+static int atmel_spi_resume(struct platform_device *pdev)
+{
+       struct spi_master       *master = platform_get_drvdata(pdev);
+       struct atmel_spi        *as = spi_master_get_devdata(master);
+
+       clk_enable(as->clk);
+       return 0;
+}
+
+#else
+#define        atmel_spi_suspend       NULL
+#define        atmel_spi_resume        NULL
+#endif
+
+
+static struct platform_driver atmel_spi_driver = {
+       .driver         = {
+               .name   = "atmel_spi",
+               .owner  = THIS_MODULE,
+       },
+       .suspend        = atmel_spi_suspend,
+       .resume         = atmel_spi_resume,
+       .remove         = __exit_p(atmel_spi_remove),
+};
+
+static int __init atmel_spi_init(void)
+{
+       return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
+}
+module_init(atmel_spi_init);
+
+static void __exit atmel_spi_exit(void)
+{
+       platform_driver_unregister(&atmel_spi_driver);
+}
+module_exit(atmel_spi_exit);
+
+MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
new file mode 100644 (file)
index 0000000..6e06b6a
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Register definitions for Atmel Serial Peripheral Interface (SPI)
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ATMEL_SPI_H__
+#define __ATMEL_SPI_H__
+
+/* SPI register offsets */
+#define SPI_CR                                 0x0000
+#define SPI_MR                                 0x0004
+#define SPI_RDR                                        0x0008
+#define SPI_TDR                                        0x000c
+#define SPI_SR                                 0x0010
+#define SPI_IER                                        0x0014
+#define SPI_IDR                                        0x0018
+#define SPI_IMR                                        0x001c
+#define SPI_CSR0                               0x0030
+#define SPI_CSR1                               0x0034
+#define SPI_CSR2                               0x0038
+#define SPI_CSR3                               0x003c
+#define SPI_RPR                                        0x0100
+#define SPI_RCR                                        0x0104
+#define SPI_TPR                                        0x0108
+#define SPI_TCR                                        0x010c
+#define SPI_RNPR                               0x0110
+#define SPI_RNCR                               0x0114
+#define SPI_TNPR                               0x0118
+#define SPI_TNCR                               0x011c
+#define SPI_PTCR                               0x0120
+#define SPI_PTSR                               0x0124
+
+/* Bitfields in CR */
+#define SPI_SPIEN_OFFSET                       0
+#define SPI_SPIEN_SIZE                         1
+#define SPI_SPIDIS_OFFSET                      1
+#define SPI_SPIDIS_SIZE                                1
+#define SPI_SWRST_OFFSET                       7
+#define SPI_SWRST_SIZE                         1
+#define SPI_LASTXFER_OFFSET                    24
+#define SPI_LASTXFER_SIZE                      1
+
+/* Bitfields in MR */
+#define SPI_MSTR_OFFSET                                0
+#define SPI_MSTR_SIZE                          1
+#define SPI_PS_OFFSET                          1
+#define SPI_PS_SIZE                            1
+#define SPI_PCSDEC_OFFSET                      2
+#define SPI_PCSDEC_SIZE                                1
+#define SPI_FDIV_OFFSET                                3
+#define SPI_FDIV_SIZE                          1
+#define SPI_MODFDIS_OFFSET                     4
+#define SPI_MODFDIS_SIZE                       1
+#define SPI_LLB_OFFSET                         7
+#define SPI_LLB_SIZE                           1
+#define SPI_PCS_OFFSET                         16
+#define SPI_PCS_SIZE                           4
+#define SPI_DLYBCS_OFFSET                      24
+#define SPI_DLYBCS_SIZE                                8
+
+/* Bitfields in RDR */
+#define SPI_RD_OFFSET                          0
+#define SPI_RD_SIZE                            16
+
+/* Bitfields in TDR */
+#define SPI_TD_OFFSET                          0
+#define SPI_TD_SIZE                            16
+
+/* Bitfields in SR */
+#define SPI_RDRF_OFFSET                                0
+#define SPI_RDRF_SIZE                          1
+#define SPI_TDRE_OFFSET                                1
+#define SPI_TDRE_SIZE                          1
+#define SPI_MODF_OFFSET                                2
+#define SPI_MODF_SIZE                          1
+#define SPI_OVRES_OFFSET                       3
+#define SPI_OVRES_SIZE                         1
+#define SPI_ENDRX_OFFSET                       4
+#define SPI_ENDRX_SIZE                         1
+#define SPI_ENDTX_OFFSET                       5
+#define SPI_ENDTX_SIZE                         1
+#define SPI_RXBUFF_OFFSET                      6
+#define SPI_RXBUFF_SIZE                                1
+#define SPI_TXBUFE_OFFSET                      7
+#define SPI_TXBUFE_SIZE                                1
+#define SPI_NSSR_OFFSET                                8
+#define SPI_NSSR_SIZE                          1
+#define SPI_TXEMPTY_OFFSET                     9
+#define SPI_TXEMPTY_SIZE                       1
+#define SPI_SPIENS_OFFSET                      16
+#define SPI_SPIENS_SIZE                                1
+
+/* Bitfields in CSR0 */
+#define SPI_CPOL_OFFSET                                0
+#define SPI_CPOL_SIZE                          1
+#define SPI_NCPHA_OFFSET                       1
+#define SPI_NCPHA_SIZE                         1
+#define SPI_CSAAT_OFFSET                       3
+#define SPI_CSAAT_SIZE                         1
+#define SPI_BITS_OFFSET                                4
+#define SPI_BITS_SIZE                          4
+#define SPI_SCBR_OFFSET                                8
+#define SPI_SCBR_SIZE                          8
+#define SPI_DLYBS_OFFSET                       16
+#define SPI_DLYBS_SIZE                         8
+#define SPI_DLYBCT_OFFSET                      24
+#define SPI_DLYBCT_SIZE                                8
+
+/* Bitfields in RCR */
+#define SPI_RXCTR_OFFSET                       0
+#define SPI_RXCTR_SIZE                         16
+
+/* Bitfields in TCR */
+#define SPI_TXCTR_OFFSET                       0
+#define SPI_TXCTR_SIZE                         16
+
+/* Bitfields in RNCR */
+#define SPI_RXNCR_OFFSET                       0
+#define SPI_RXNCR_SIZE                         16
+
+/* Bitfields in TNCR */
+#define SPI_TXNCR_OFFSET                       0
+#define SPI_TXNCR_SIZE                         16
+
+/* Bitfields in PTCR */
+#define SPI_RXTEN_OFFSET                       0
+#define SPI_RXTEN_SIZE                         1
+#define SPI_RXTDIS_OFFSET                      1
+#define SPI_RXTDIS_SIZE                                1
+#define SPI_TXTEN_OFFSET                       8
+#define SPI_TXTEN_SIZE                         1
+#define SPI_TXTDIS_OFFSET                      9
+#define SPI_TXTDIS_SIZE                                1
+
+/* Constants for BITS */
+#define SPI_BITS_8_BPT                         0
+#define SPI_BITS_9_BPT                         1
+#define SPI_BITS_10_BPT                                2
+#define SPI_BITS_11_BPT                                3
+#define SPI_BITS_12_BPT                                4
+#define SPI_BITS_13_BPT                                5
+#define SPI_BITS_14_BPT                                6
+#define SPI_BITS_15_BPT                                7
+#define SPI_BITS_16_BPT                                8
+
+/* Bit manipulation macros */
+#define SPI_BIT(name) \
+       (1 << SPI_##name##_OFFSET)
+#define SPI_BF(name,value) \
+       (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
+#define SPI_BFEXT(name,value) \
+       (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
+#define SPI_BFINS(name,value,old) \
+       ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+         | SPI_BF(name,value))
+
+/* Register access macros */
+#define spi_readl(port,reg) \
+       __raw_readl((port)->regs + SPI_##reg)
+#define spi_writel(port,reg,value) \
+       __raw_writel((value), (port)->regs + SPI_##reg)
+
+#endif /* __ATMEL_SPI_H__ */
index 757dec9c7ee9fc89b11d05dd7253ea3993c70eb8..a90c255f079d40477ff56a287353af51117117c0 100644 (file)
@@ -10,7 +10,6 @@
 
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
index 164a5dcf1f1e69a31d01a28348ab393e30100d1d..3e658dc7c2d8fba9710ae34bc0b251750f640674 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/module.h>
 
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>      /* printk() */
 #include <linux/fs.h>          /* everything... */
 #include <linux/errno.h>       /* error codes */
index 825bf884537a2204ecdd6019093be9f52bfe4e96..8b7ff467d26242a2b08a55a4055e25d26bf17d49 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL)      += serial/
 obj-$(CONFIG_USB_ADUTUX)       += misc/
 obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
 obj-$(CONFIG_USB_AUERSWALD)    += misc/
+obj-$(CONFIG_USB_BERRY_CHARGE) += misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)      += misc/
 obj-$(CONFIG_USB_EMI26)                += misc/
index dae4ef1e8fe592f6338a3d75917134c3198f5e4c..4973e147bc79ea441e6a48875cfa00c60cc15d3a 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
index 98199628e394e66df0e3c1c7a42e0874d420d3c4..d38a25f36ea5839557b0328cd72940962d2d0dda 100644 (file)
@@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm)
        struct tty_struct *tty = acm->tty;
        struct acm_ru *rcv;
        unsigned long flags;
-       int i = 0;
+       unsigned char throttled;
        dbg("Entering acm_rx_tasklet");
 
-       if (!ACM_READY(acm) || acm->throttle)
+       if (!ACM_READY(acm))
+               return;
+
+       spin_lock(&acm->throttle_lock);
+       throttled = acm->throttle;
+       spin_unlock(&acm->throttle_lock);
+       if (throttled)
                return;
 
 next_buffer:
@@ -346,22 +352,20 @@ next_buffer:
        dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
        tty_buffer_request_room(tty, buf->size);
-       if (!acm->throttle)
+       spin_lock(&acm->throttle_lock);
+       throttled = acm->throttle;
+       spin_unlock(&acm->throttle_lock);
+       if (!throttled)
                tty_insert_flip_string(tty, buf->base, buf->size);
        tty_flip_buffer_push(tty);
 
-       spin_lock(&acm->throttle_lock);
-       if (acm->throttle) {
-               dbg("Throtteling noticed");
-               memmove(buf->base, buf->base + i, buf->size - i);
-               buf->size -= i;
-               spin_unlock(&acm->throttle_lock);
+       if (throttled) {
+               dbg("Throttling noticed");
                spin_lock_irqsave(&acm->read_lock, flags);
                list_add(&buf->list, &acm->filled_read_bufs);
                spin_unlock_irqrestore(&acm->read_lock, flags);
                return;
        }
-       spin_unlock(&acm->throttle_lock);
 
        spin_lock_irqsave(&acm->read_lock, flags);
        list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
                goto bail_out;
        }
 
-       if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
+       if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
+           (acm->ctrl_caps & USB_CDC_CAP_LINE))
                goto full_bailout;
 
        INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
                list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
        }
 
+       acm->throttle = 0;
+
        tasklet_schedule(&acm->urb_task);
 
 done:
@@ -1092,6 +1099,10 @@ static struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
        .driver_info = SINGLE_RX_URB, /* firmware bug */
        },
+       { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
+       .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+       },
+
        /* control interfaces with various AT-command sets */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
                USB_CDC_ACM_PROTO_AT_V25TER) },
index a47c30b2d7645cfc1cdde964a31753596961c5e1..aefc7987120d37bfa4d67c11bfb37f84b5dc18bc 100644 (file)
@@ -604,10 +604,6 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
        lock_kernel();
        if (!st) {
                st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-               if (!st) {
-                       unlock_kernel();
-                       return POLLIN;
-               }
 
                /* we may have dropped BKL - need to check for having lost the race */
                if (file->private_data) {
@@ -615,6 +611,11 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
                        st = file->private_data;
                        goto lost_race;
                }
+               /* we haven't lost - check for allocation failure now */
+               if (!st) {
+                       unlock_kernel();
+                       return POLLIN;
+               }
 
                /*
                 * need to prevent the module from being unloaded, since
index 2087766f9e88e059aa240c89e77f7e7d93939602..274f14f1633e8f348baff7c4ff8f138b3b2a803c 100644 (file)
@@ -857,11 +857,11 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
 
 static int proc_setconfig(struct dev_state *ps, void __user *arg)
 {
-       unsigned int u;
+       int u;
        int status = 0;
        struct usb_host_config *actconfig;
 
-       if (get_user(u, (unsigned int __user *)arg))
+       if (get_user(u, (int __user *)arg))
                return -EFAULT;
 
        actconfig = ps->dev->actconfig;
index 600d1bc8272a9503caf399171775c3bf05bb4ff9..2aded261f42c3acb5ffdd8a605a6c36b70049a6e 100644 (file)
@@ -743,6 +743,7 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
  * usb_register_driver - register a USB interface driver
  * @new_driver: USB operations for the interface driver
  * @owner: module owner of this driver.
+ * @mod_name: module name string
  *
  * Registers a USB interface driver with the USB core.  The list of
  * unattached interfaces will be rescanned whenever a new driver is
index 5e628ae3aec714ba9469df02ed3f2bae4989c129..e0ec7045e865d93772edc95bd6ccc6e1e0176786 100644 (file)
@@ -229,7 +229,7 @@ static int init_endpoint_class(void)
        kref_init(&ep_class->kref);
        ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
        if (IS_ERR(ep_class->class)) {
-               result = IS_ERR(ep_class->class);
+               result = PTR_ERR(ep_class->class);
                goto class_create_error;
        }
 
index b531a4fd30c228b47fda66611fa304c75657eea2..9bbcb20e2d94c3bf5ca96f77d0c1050d87d14eb2 100644 (file)
@@ -184,7 +184,7 @@ static void generic_disconnect(struct usb_device *udev)
        /* if this is only an unbind, not a physical disconnect, then
         * unconfigure the device */
        if (udev->actconfig)
-               usb_set_configuration(udev, 0);
+               usb_set_configuration(udev, -1);
 
        usb_remove_sysfs_dev_files(udev);
 }
index 590ec82d051514e02fc15c415c8ee8aa6ed3fd8d..50c0db15304aef513c30262b585b41db670c567e 100644 (file)
@@ -44,6 +44,7 @@ struct usb_hub {
                struct usb_hub_status   hub;
                struct usb_port_status  port;
        }                       *status;        /* buffer for status reports */
+       struct mutex            status_mutex;   /* for the status buffer */
 
        int                     error;          /* last reported error */
        int                     nerrors;        /* track consecutive errors */
@@ -535,6 +536,7 @@ static int hub_hub_status(struct usb_hub *hub,
 {
        int ret;
 
+       mutex_lock(&hub->status_mutex);
        ret = get_hub_status(hub->hdev, &hub->status->hub);
        if (ret < 0)
                dev_err (hub->intfdev,
@@ -544,6 +546,7 @@ static int hub_hub_status(struct usb_hub *hub,
                *change = le16_to_cpu(hub->status->hub.wHubChange); 
                ret = 0;
        }
+       mutex_unlock(&hub->status_mutex);
        return ret;
 }
 
@@ -617,6 +620,7 @@ static int hub_configure(struct usb_hub *hub,
                ret = -ENOMEM;
                goto fail;
        }
+       mutex_init(&hub->status_mutex);
 
        hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
        if (!hub->descriptor) {
@@ -1396,6 +1400,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
 {
        int ret;
 
+       mutex_lock(&hub->status_mutex);
        ret = get_port_status(hub->hdev, port1, &hub->status->port);
        if (ret < 4) {
                dev_err (hub->intfdev,
@@ -1407,6 +1412,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
                *change = le16_to_cpu(hub->status->port.wPortChange); 
                ret = 0;
        }
+       mutex_unlock(&hub->status_mutex);
        return ret;
 }
 
@@ -1904,6 +1910,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
        struct usb_hub          *hub = usb_get_intfdata (intf);
        struct usb_device       *hdev = hub->hdev;
        unsigned                port1;
+       int                     status = 0;
 
        /* fail if children aren't already suspended */
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1927,24 +1934,18 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 
        dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
 
+       /* stop khubd and related activity */
+       hub_quiesce(hub);
+
        /* "global suspend" of the downstream HC-to-USB interface */
        if (!hdev->parent) {
-               struct usb_bus  *bus = hdev->bus;
-               if (bus) {
-                       int     status = hcd_bus_suspend (bus);
-
-                       if (status != 0) {
-                               dev_dbg(&hdev->dev, "'global' suspend %d\n",
-                                       status);
-                               return status;
-                       }
-               } else
-                       return -EOPNOTSUPP;
+               status = hcd_bus_suspend(hdev->bus);
+               if (status != 0) {
+                       dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
+                       hub_activate(hub);
+               }
        }
-
-       /* stop khubd and related activity */
-       hub_quiesce(hub);
-       return 0;
+       return status;
 }
 
 static int hub_resume(struct usb_interface *intf)
index 8aca3574c2b5f4c715e5ea70052c0fea328695d7..74edaea5665d58367f6f62e48cec2d4a2b63313e 100644 (file)
@@ -1316,6 +1316,14 @@ static void release_interface(struct device *dev)
  * use this kind of configurability; many devices only have one
  * configuration.
  *
+ * @configuration is the value of the configuration to be installed.
+ * According to the USB spec (e.g. section 9.1.1.5), configuration values
+ * must be non-zero; a value of zero indicates that the device in
+ * unconfigured.  However some devices erroneously use 0 as one of their
+ * configuration values.  To help manage such devices, this routine will
+ * accept @configuration = -1 as indicating the device should be put in
+ * an unconfigured state.
+ *
  * USB device configurations may affect Linux interoperability,
  * power consumption and the functionality available.  For example,
  * the default configuration is limited to using 100mA of bus power,
@@ -1347,10 +1355,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        struct usb_interface **new_interfaces = NULL;
        int n, nintf;
 
-       for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-               if (dev->config[i].desc.bConfigurationValue == configuration) {
-                       cp = &dev->config[i];
-                       break;
+       if (configuration == -1)
+               configuration = 0;
+       else {
+               for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+                       if (dev->config[i].desc.bConfigurationValue ==
+                                       configuration) {
+                               cp = &dev->config[i];
+                               break;
+                       }
                }
        }
        if ((!cp && configuration != 0))
@@ -1359,6 +1372,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        /* The USB spec says configuration 0 means unconfigured.
         * But if a device includes a configuration numbered 0,
         * we will accept it as a correctly configured state.
+        * Use -1 if you really want to unconfigure the device.
         */
        if (cp && configuration == 0)
                dev_warn(&dev->dev, "config 0 descriptor??\n");
index 627a5a2fc9cf340e5320df56af3857b880ca3f5d..7f31a495a25d31f327f3bbf63239a9cd5d6a5349 100644 (file)
@@ -31,7 +31,7 @@ static struct usb_device_id whitelist_table [] = {
 { USB_DEVICE_INFO(7, 1, 3) },
 #endif
 
-#ifdef CONFIG_USB_CDCETHER
+#ifdef CONFIG_USB_NET_CDCETHER
 /* Linux-USB CDC Ethernet gadget */
 { USB_DEVICE(0x0525, 0xa4a1), },
 /* Linux-USB CDC Ethernet + RNDIS gadget */
index 4eaa0ee8e72f6186f8b5996631f57fd29f3e0b10..0edfbafd702cced2fcda7638f2002be4c055fb52 100644 (file)
@@ -63,7 +63,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
        struct usb_device       *udev = to_usb_device(dev);
        int                     config, value;
 
-       if (sscanf(buf, "%u", &config) != 1 || config > 255)
+       if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
                return -EINVAL;
        usb_lock_device(udev);
        value = usb_set_configuration(udev, config);
index f39050145f1f9be9f5b47cfa6760eb25fc202c13..a4677802fb208dde66c4be9cd85500acfa9074e1 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
@@ -785,7 +784,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
        return status;
 }
 
-static struct usb_ep_ops at91_ep_ops = {
+static const struct usb_ep_ops at91_ep_ops = {
        .enable         = at91_ep_enable,
        .disable        = at91_ep_disable,
        .alloc_request  = at91_ep_alloc_request,
@@ -913,7 +912,7 @@ static void pullup(struct at91_udc *udc, int is_on)
                at91_udp_write(udc, AT91_UDP_TXVC, 0);
                if (cpu_is_at91rm9200())
                        at91_set_gpio_value(udc->board.pullup_pin, 1);
-               else if (cpu_is_at91sam9260()) {
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
                        u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
                        txvc |= AT91_UDP_TXVC_PUON;
@@ -930,7 +929,7 @@ static void pullup(struct at91_udc *udc, int is_on)
                at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
                if (cpu_is_at91rm9200())
                        at91_set_gpio_value(udc->board.pullup_pin, 0);
-               else if (cpu_is_at91sam9260()) {
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
                        u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
                        txvc &= ~AT91_UDP_TXVC_PUON;
@@ -1652,7 +1651,7 @@ static void at91udc_shutdown(struct platform_device *dev)
        pullup(platform_get_drvdata(dev), 0);
 }
 
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int __init at91udc_probe(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        struct at91_udc *udc;
@@ -1763,7 +1762,7 @@ fail0:
        return retval;
 }
 
-static int __devexit at91udc_remove(struct platform_device *pdev)
+static int __exit at91udc_remove(struct platform_device *pdev)
 {
        struct at91_udc *udc = platform_get_drvdata(pdev);
        struct resource *res;
@@ -1837,8 +1836,7 @@ static int at91udc_resume(struct platform_device *pdev)
 #endif
 
 static struct platform_driver at91_udc = {
-       .probe          = at91udc_probe,
-       .remove         = __devexit_p(at91udc_remove),
+       .remove         = __exit_p(at91udc_remove),
        .shutdown       = at91udc_shutdown,
        .suspend        = at91udc_suspend,
        .resume         = at91udc_resume,
@@ -1848,13 +1846,13 @@ static struct platform_driver at91_udc = {
        },
 };
 
-static int __devinit udc_init_module(void)
+static int __init udc_init_module(void)
 {
-       return platform_driver_register(&at91_udc);
+       return platform_driver_probe(&at91_udc, at91udc_probe);
 }
 module_init(udc_init_module);
 
-static void __devexit udc_exit_module(void)
+static void __exit udc_exit_module(void)
 {
        platform_driver_unregister(&at91_udc);
 }
index 3c2bc075ef4f31260ddadaa659e7ea840b2e0d1c..7d7909cf25583802d2e5a390507fc2d06fb71b24 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
index 22e3c9443641a8b83e88a92c32ce43c62f3a58b5..04e6b8508fb63f094705dc59ce65e595c0527ba6 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
index e873cf4882462fe7aed7e50571cad7fe561e0414..7b3a326b57ab55e7099675857f91a2aeb409be74 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
index 7617ff7bd5ac916397822f2f7d007c57bb58cffe..49d737725f7068df54cc8b4022aa3a06c650708d 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
index 140104341db473ba0c513e785202e86bb561d2fb..8f9a2b615422602a25178c03294bad5479796a46 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 0d225369847d06258c383eb34125abfd14dc3f17..f01890dc87515493393dcbf1ea05a8dd0dcd418f 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/timer.h>
@@ -156,7 +155,7 @@ static int is_vbus_present(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_vbus)
-               return pxa_gpio_get(mach->gpio_vbus);
+               return udc_gpio_get(mach->gpio_vbus);
        if (mach->udc_is_connected)
                return mach->udc_is_connected();
        return 1;
@@ -168,7 +167,7 @@ static void pullup_off(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_pullup)
-               pxa_gpio_set(mach->gpio_pullup, 0);
+               udc_gpio_set(mach->gpio_pullup, 0);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -178,7 +177,7 @@ static void pullup_on(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_pullup)
-               pxa_gpio_set(mach->gpio_pullup, 1);
+               udc_gpio_set(mach->gpio_pullup, 1);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -1756,7 +1755,7 @@ lubbock_vbus_irq(int irq, void *_dev)
 static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
        struct pxa2xx_udc       *dev = _dev;
-       int                     vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+       int                     vbus = udc_gpio_get(dev->mach->gpio_vbus);
 
        pxa2xx_udc_vbus_session(&dev->gadget, vbus);
        return IRQ_HANDLED;
@@ -2546,15 +2545,13 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        dev->dev = &pdev->dev;
        dev->mach = pdev->dev.platform_data;
        if (dev->mach->gpio_vbus) {
-               vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
-               pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
-                               | GPIO_IN);
+               udc_gpio_init_vbus(dev->mach->gpio_vbus);
+               vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
                set_irq_type(vbus_irq, IRQT_BOTHEDGE);
        } else
                vbus_irq = 0;
        if (dev->mach->gpio_pullup)
-               pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
-                               | GPIO_OUT | GPIO_DFLT_LOW);
+               udc_gpio_init_pullup(dev->mach->gpio_pullup);
 
        init_timer(&dev->timer);
        dev->timer.function = udc_watchdog;
@@ -2614,7 +2611,7 @@ lubbock_fail0:
 #endif
        if (vbus_irq) {
                retval = request_irq(vbus_irq, udc_vbus_irq,
-                               SA_INTERRUPT | SA_SAMPLE_RANDOM,
+                               IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                                driver_name, dev);
                if (retval != 0) {
                        printk(KERN_ERR "%s: can't get irq %i, err %d\n",
index 8e598c8bf4e388da20c6672b3a0f54a95e296e6e..773e549aff3f721eb1f7b0ace82b45ff51b4c470 100644 (file)
@@ -177,21 +177,6 @@ struct pxa2xx_udc {
 
 static struct pxa2xx_udc *the_controller;
 
-static inline int pxa_gpio_get(unsigned gpio)
-{
-       return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void pxa_gpio_set(unsigned gpio, int is_on)
-{
-       int mask = GPIO_bit(gpio);
-
-       if (is_on)
-               GPSR(gpio) = mask;
-       else
-               GPCR(gpio) = mask;
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
index 6c742a90922580e37f69ba6bee59017ab3fb93d8..e552668d36b323a3ad06941cefe1c66a196b8353 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
@@ -1700,6 +1699,7 @@ static int gs_setup_class(struct usb_gadget *gadget,
                        memcpy(&port->port_line_coding, req->buf, ret);
                        spin_unlock(&port->port_lock);
                }
+               ret = 0;
                break;
 
        case USB_CDC_REQ_GET_LINE_CODING:
index ebe04e0d2879de0c8b09a873d27aa20743e4a181..8c85e33f74a4b2f5c4cbba4aa7a0ea9630408635 100644 (file)
@@ -66,7 +66,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
index 246afea9e83b28320d2e7ed4fb9c9f77617795ac..43eddaecc3dd520da48e9dcb7367157d8f7ff565 100644 (file)
@@ -322,7 +322,7 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
 
 #else
 
-/* troubleshooting help: expose state in driverfs */
+/* troubleshooting help: expose state in sysfs */
 
 #define speed_char(info1) ({ char tmp; \
                switch (info1 & (3 << 12)) { \
index 185721dba42be006384012184eb38bf256b257c8..a740564882347c301fe1d2050bb9263261c3365c 100644 (file)
@@ -42,6 +42,9 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 
 /*-------------------------------------------------------------------------*/
@@ -299,6 +302,19 @@ static void ehci_watchdog (unsigned long param)
        spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+{
+       int     port = HCS_N_PORTS(ehci->hcs_params);
+
+       while (port--)
+               ehci_writel(ehci, PORT_RWC_BITS,
+                               &ehci->regs->port_status[port]);
+}
+
 /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
@@ -310,9 +326,13 @@ ehci_shutdown (struct usb_hcd *hcd)
 
        ehci = hcd_to_ehci (hcd);
        (void) ehci_halt (ehci);
+       ehci_turn_off_all_ports(ehci);
 
        /* make BIOS/etc use companion controller during reboot */
        ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+
+       /* unblock posted writes */
+       ehci_readl(ehci, &ehci->regs->configured_flag);
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -951,15 +971,18 @@ static int __init ehci_hcd_init(void)
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-       if (retval < 0) {
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+               retval = ps3_system_bus_driver_register(
+                               &PS3_SYSTEM_BUS_DRIVER);
+               if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-               platform_driver_unregister(&PLATFORM_DRIVER);
+                       platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-               pci_unregister_driver(&PCI_DRIVER);
+                       pci_unregister_driver(&PCI_DRIVER);
 #endif
-               return retval;
+                       return retval;
+               }
        }
 #endif
 
@@ -976,7 +999,8 @@ static void __exit ehci_hcd_cleanup(void)
        pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
index 0d83c6df1a3b2554272ed4680365cdfee09a4d4a..9af529d22b3e609ee8af02b5fa9fc5c03021f13a 100644 (file)
@@ -36,6 +36,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        int                     port;
        int                     mask;
 
+       ehci_dbg(ehci, "suspend root hub\n");
+
        if (time_before (jiffies, ehci->next_statechange))
                msleep(5);
 
index f0ffb8907f292df3b9e39a32b92809e7ae498f06..32f7caf24747cb7d18a05ed1be4976d5549d5378 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 2718b5dc4ec1d9825cd0fe6a38fea384c17b1b4e..46873f2534b5d152d3b277e424a5c046ae402b3f 100644 (file)
@@ -1577,7 +1577,7 @@ static int isp116x_remove(struct platform_device *pdev)
 
 #define resource_len(r) (((r)->end - (r)->start) + 1)
 
-static int __init isp116x_probe(struct platform_device *pdev)
+static int __devinit isp116x_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
        struct isp116x *isp116x;
index 930346487278e7598618cc16c62ebf8b62eccb0c..d849c809acbdca97394fa7b8dcd8225733a91f5a 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #ifndef CONFIG_ARCH_AT91
 #error "CONFIG_ARCH_AT91 must be defined."
 #endif
 
-/* interface and function clocks */
-static struct clk *iclk, *fclk;
+/* interface and function clocks; sometimes also an AHB clock */
+static struct clk *iclk, *fclk, *hclk;
 static int clocked;
 
 extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
 
+static void at91_start_clock(void)
+{
+       if (cpu_is_at91sam9261())
+               clk_enable(hclk);
+       clk_enable(iclk);
+       clk_enable(fclk);
+       clocked = 1;
+}
+
+static void at91_stop_clock(void)
+{
+       clk_disable(fclk);
+       clk_disable(iclk);
+       if (cpu_is_at91sam9261())
+               clk_disable(hclk);
+       clocked = 0;
+}
+
 static void at91_start_hc(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -41,9 +60,7 @@ static void at91_start_hc(struct platform_device *pdev)
        /*
         * Start the USB clocks.
         */
-       clk_enable(iclk);
-       clk_enable(fclk);
-       clocked = 1;
+       at91_start_clock();
 
        /*
         * The USB host controller must remain in reset.
@@ -66,9 +83,7 @@ static void at91_stop_hc(struct platform_device *pdev)
        /*
         * Stop the USB clocks.
         */
-       clk_disable(fclk);
-       clk_disable(iclk);
-       clocked = 0;
+       at91_stop_clock();
 }
 
 
@@ -126,6 +141,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 
        iclk = clk_get(&pdev->dev, "ohci_clk");
        fclk = clk_get(&pdev->dev, "uhpck");
+       if (cpu_is_at91sam9261())
+               hclk = clk_get(&pdev->dev, "hck0");
 
        at91_start_hc(pdev);
        ohci_hcd_init(hcd_to_ohci(hcd));
@@ -137,6 +154,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        /* Error handling */
        at91_stop_hc(pdev);
 
+       if (cpu_is_at91sam9261())
+               clk_put(hclk);
        clk_put(fclk);
        clk_put(iclk);
 
@@ -171,9 +190,11 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd,
        iounmap(hcd->regs);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
+       if (cpu_is_at91sam9261())
+               clk_put(hclk);
        clk_put(fclk);
        clk_put(iclk);
-       fclk = iclk = NULL;
+       fclk = iclk = hclk = NULL;
 
        dev_set_drvdata(&pdev->dev, NULL);
        return 0;
@@ -280,9 +301,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
         */
        if (at91_suspend_entering_slow_clock()) {
                ohci_usb_reset (ohci);
-               clk_disable(fclk);
-               clk_disable(iclk);
-               clocked = 0;
+               at91_stop_clock();
        }
 
        return 0;
@@ -295,11 +314,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (device_may_wakeup(&pdev->dev))
                disable_irq_wake(hcd->irq);
 
-       if (!clocked) {
-               clk_enable(iclk);
-               clk_enable(fclk);
-               clocked = 1;
-       }
+       if (!clocked)
+               at91_start_clock();
 
        return 0;
 }
index 44c60fba76e166b68a5be67a9b47f6fc7fd5d526..a68ce9d3c525b66df1bf53f5ac477e1395f4ea33 100644 (file)
@@ -78,7 +78,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
 
        ohci_hcd_init(hcd_to_ohci(hcd));
 
-       retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+       retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED);
        if (retval == 0)
                return retval;
 
index fa6a7ceaa0db0a28330b0ff8c644d063538cf2fb..f0d29eda3c6da72ede3d82a2937e1d3ccbf98de8 100644 (file)
@@ -42,6 +42,9 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 #include "../core/hcd.h"
 
@@ -944,9 +947,12 @@ static int __init ohci_hcd_mod_init(void)
                sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-       if (retval < 0)
-               goto error_ps3;
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+               retval = ps3_system_bus_driver_register(
+                               &PS3_SYSTEM_BUS_DRIVER);
+               if (retval < 0)
+                       goto error_ps3;
+       }
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -992,7 +998,8 @@ static int __init ohci_hcd_mod_init(void)
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
        return retval;
@@ -1014,7 +1021,8 @@ static void __exit ohci_hcd_mod_exit(void)
        platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
index 893b172384da65f223dba59ecd46ed8484e08fbb..d601bbb9387bb5205d6c29aed3208a405c186bfc 100644 (file)
@@ -421,7 +421,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
        ohci_hcd_init(ohci);
 
        dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
-       ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
        if (ret == 0)
                return ret;
 
index de45eb0051a7624d52112c19acb6943d252c5164..85fdfd2a7ad0a7d8a33f2d331767dc3b3d2dfe0a 100644 (file)
@@ -107,7 +107,7 @@ int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
 
        ohci_hcd_init(hcd_to_ohci(hcd));
 
-       retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+       retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
        if (retval == 0)
                return retval;
 
index ac9f11d19817d93e2fedcaf9cb26496a529df301..2d0e73b200996571a40249eb1181687425153ee1 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 49b9d390b95f4f2082a0164ad110f7e1bd3bce25..ded4df30a63131f85e36096bfffca16237c36215 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
index 8ccddf74534a8e35db419c35030a58524385b7b9..896cb2b71020d99f2c61a95721add5dc87e54602 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/random.h>
index 2e71d3cca198732ca12043ab24508b7dba88186f..69a9f3b6d0a9eaedb2d6c63078c02cc57ab0f4e3 100644 (file)
@@ -58,13 +58,17 @@ config HID_PID
          devices.
 
 config LOGITECH_FF
-       bool "Logitech WingMan *3D support"
+       bool "Logitech devices support"
        depends on HID_FF
        select INPUT_FF_MEMLESS if USB_HID
        help
          Say Y here if you have one of these devices:
          - Logitech WingMan Cordless RumblePad
+         - Logitech WingMan Cordless RumblePad 2
          - Logitech WingMan Force 3D
+         - Logitech Formula Force EX
+         - Logitech MOMO Force wheel
+
          and if you want to enable force feedback for them.
          Note: if you say N here, this device will still be supported, but without
          force feedback.
index 9f52429ce6543156d328ef4ac947201bf87a726b..f857935e615c9d70e829b891f706059c4ccd8b09 100644 (file)
@@ -76,7 +76,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
index 84983d1b71644a09ef3b7e7b5954f0e7b05968ae..ef09952f20393aea387a031be84b45f3fcc6f99f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
@@ -516,6 +515,7 @@ void usbhid_close(struct hid_device *hid)
 
 #define USB_VENDOR_ID_TURBOX           0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
+#define USB_VENDOR_ID_CIDC             0x1677
 
 /*
  * Initialize all reports
@@ -549,7 +549,6 @@ void usbhid_init_reports(struct hid_device *hid)
 }
 
 #define USB_VENDOR_ID_GTCO             0x078c
-#define USB_VENDOR_ID_GTCO_IPANEL_2     0x5543
 #define USB_DEVICE_ID_GTCO_90          0x0090
 #define USB_DEVICE_ID_GTCO_100         0x0100
 #define USB_DEVICE_ID_GTCO_101         0x0101
@@ -595,8 +594,6 @@ void usbhid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_GTCO_1004                0x1004
 #define USB_DEVICE_ID_GTCO_1005                0x1005
 #define USB_DEVICE_ID_GTCO_1006                0x1006
-#define USB_DEVICE_ID_GTCO_8           0x0008
-#define USB_DEVICE_ID_GTCO_d            0x000d
 
 #define USB_VENDOR_ID_WACOM            0x056a
 
@@ -855,8 +852,6 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
@@ -954,6 +949,8 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
 
+       { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
+
        { 0, 0 }
 };
 
index bc7f8e6f8c97a12066b6ec7cf2294de0490ec442..e431faaa6abc8f3d392e91a482d4a6afe5e89c5a 100644 (file)
@@ -54,9 +54,10 @@ struct hid_ff_initializer {
 static struct hid_ff_initializer inits[] = {
 #ifdef CONFIG_LOGITECH_FF
        { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
+       { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
        { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
+       { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
        { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
-       { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
        { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
 #endif
 #ifdef CONFIG_PANTHERLORD_FF
index 4df0968f852e6d7686a6f731b94cef775cd41fb0..e6f3af3e66d17f561114c556c296b51c24905271 100644 (file)
@@ -52,8 +52,9 @@ static const struct dev_type devices[] = {
        { 0x046d, 0xc211, ff_rumble },
        { 0x046d, 0xc219, ff_rumble },
        { 0x046d, 0xc283, ff_joystick },
+       { 0x046d, 0xc294, ff_joystick },
+       { 0x046d, 0xc295, ff_joystick },
        { 0x046d, 0xca03, ff_joystick },
-       { 0x0000, 0x0000, ff_joystick }
 };
 
 static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
@@ -105,8 +106,9 @@ int hid_lgff_init(struct hid_device* hid)
        struct input_dev *dev = hidinput->input;
        struct hid_report *report;
        struct hid_field *field;
+       const signed short *ff_bits = ff_joystick;
        int error;
-       int i, j;
+       int i;
 
        /* Find the report to use */
        if (list_empty(report_list)) {
@@ -130,12 +132,14 @@ int hid_lgff_init(struct hid_device* hid)
        for (i = 0; i < ARRAY_SIZE(devices); i++) {
                if (dev->id.vendor == devices[i].idVendor &&
                    dev->id.product == devices[i].idProduct) {
-                       for (j = 0; devices[i].ff[j] >= 0; j++)
-                               set_bit(devices[i].ff[j], dev->ffbit);
+                       ff_bits = devices[i].ff;
                        break;
                }
        }
 
+       for (i = 0; ff_bits[i] >= 0; i++)
+               set_bit(ff_bits[i], dev->ffbit);
+
        error = input_ff_create_memless(dev, NULL, hid_lgff_play);
        if (error)
                return error;
index cbd2d53fefff532223f7f3a00139f0ce09162b76..f5a90e950e6b54cfcd48381f89d8b38e141b1aea 100644 (file)
@@ -24,7 +24,6 @@
 
 #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg)
 
-#include <linux/sched.h>
 #include <linux/input.h>
 #include <linux/usb.h>
 
index a74bf8617e7f3f11cbb67397e0bd6cef9b160483..4907e8b8007087b37a3141135312acd43b2b4f90 100644 (file)
@@ -88,6 +88,17 @@ config USB_LCD
          To compile this driver as a module, choose M here: the
          module will be called usblcd.
 
+config USB_BERRY_CHARGE
+       tristate "USB BlackBerry recharge support"
+       depends on USB
+       help
+         Say Y here if you want to connect a BlackBerry device to your
+         computer's USB port and have it automatically switch to "recharge"
+         mode.
+
+         To compile this driver as a module, choose M here: the
+         module will be called berry_charge.
+
 config USB_LED
        tristate "USB LED driver support"
        depends on USB
index 2cba07d31971abdef2483f0a4501e1e3e4b2e683..dac2d5b715666492aa75d446d4b2acd16bcef067 100644 (file)
@@ -6,6 +6,7 @@
 obj-$(CONFIG_USB_ADUTUX)       += adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
 obj-$(CONFIG_USB_AUERSWALD)    += auerswald.o
+obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)      += cytherm.o
 obj-$(CONFIG_USB_EMI26)                += emi26.o
index 32f0e3a5b022390a8551c087855e5f11ad853fe3..e573c8ba978545d164095dc634407daf4f859c2a 100644 (file)
@@ -281,8 +281,8 @@ static int appledisplay_probe(struct usb_interface *iface,
        /* Register backlight device */
        snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
                atomic_inc_return(&count_displays) - 1);
-       pdata->bd = backlight_device_register(bl_name, NULL,
-               pdata, &appledisplay_bl_data);
+       pdata->bd = backlight_device_register(bl_name, NULL, pdata,
+                                               &appledisplay_bl_data);
        if (IS_ERR(pdata->bd)) {
                err("appledisplay: Backlight registration failed");
                goto error;
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
new file mode 100644 (file)
index 0000000..60893c6
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * USB BlackBerry charging module
+ *
+ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ * Information on how to switch configs was taken by the bcharge.cc file
+ * created by the barry.sf.net project.
+ *
+ * bcharge.cc has the following copyright:
+ *     Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
+ * and is released under the GPLv2.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define RIM_VENDOR             0x0fca
+#define BLACKBERRY             0x0001
+
+static int debug;
+
+#ifdef dbg
+#undef dbg
+#endif
+#define dbg(dev, format, arg...)                               \
+       if (debug)                                              \
+               dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+       { },                                    /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int magic_charge(struct usb_device *udev)
+{
+       char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+       int retval;
+
+       if (!dummy_buffer)
+               return -ENOMEM;
+
+       /* send two magic commands and then set the configuration.  The device
+        * will then reset itself with the new power usage and should start
+        * charging. */
+
+       /* Note, with testing, it only seems that the first message is really
+        * needed (at least for the 8700c), but to be safe, we emulate what
+        * other operating systems seem to be sending to their device.  We
+        * really need to get some specs for this device to be sure about what
+        * is going on here.
+        */
+       dbg(&udev->dev, "Sending first magic command\n");
+       retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
+       if (retval != 2) {
+               dev_err(&udev->dev, "First magic command failed: %d.\n",
+                       retval);
+               return retval;
+       }
+
+       dbg(&udev->dev, "Sending first magic command\n");
+       retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
+       if (retval != 0) {
+               dev_err(&udev->dev, "Second magic command failed: %d.\n",
+                       retval);
+               return retval;
+       }
+
+       dbg(&udev->dev, "Calling set_configuration\n");
+       retval = usb_driver_set_configuration(udev, 1);
+       if (retval)
+               dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+       return retval;
+}
+
+static int berry_probe(struct usb_interface *intf,
+                      const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+
+       dbg(&udev->dev, "Power is set to %dmA\n",
+           udev->actconfig->desc.bMaxPower * 2);
+
+       /* check the power usage so we don't try to enable something that is
+        * already enabled */
+       if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
+               dbg(&udev->dev, "device is already charging, power is "
+                   "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
+               return -ENODEV;
+       }
+
+       /* turn the power on */
+       magic_charge(udev);
+
+       /* we don't really want to bind to the device, userspace programs can
+        * handle the syncing just fine, so get outta here. */
+       return -ENODEV;
+}
+
+static void berry_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver berry_driver = {
+       .name =         "berry_charge",
+       .probe =        berry_probe,
+       .disconnect =   berry_disconnect,
+       .id_table =     id_table,
+};
+
+static int __init berry_init(void)
+{
+       return usb_register(&berry_driver);
+}
+
+static void __exit berry_exit(void)
+{
+       usb_deregister(&berry_driver);
+}
+
+module_init(berry_init);
+module_exit(berry_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index 0398908b15d482589eb4225ca192163fd9b3b297..6f8b134a79cb8c89d495cb81ad75fc65401cdc39 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
index 9148694627d586d16c0445b083dfbfdda8e0f3a8..1730d8642a47dd31276b72ac06be26217d58396f 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/tty.h>
 #include <linux/console.h>
index a2b94ef512bce95551add149d0edc0ec9f7acd67..0f3d7dbb537f43dca627e3544606562c5ff07e16 100644 (file)
@@ -84,6 +84,7 @@ config USB_PEGASUS
 config USB_RTL8150
        tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
        depends on EXPERIMENTAL
+       select MII
        help
          Say Y here if you have RTL8150 based usb-ethernet adapter.
          Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -98,7 +99,7 @@ config USB_USBNET_MII
 
 config USB_USBNET
        tristate "Multi-purpose USB Networking Framework"
-       select MII if USBNET_MII != n
+       select MII if USB_USBNET_MII != n
        ---help---
          This driver supports several kinds of network links over USB,
          with "minidrivers" built around a common network driver core
@@ -239,6 +240,7 @@ config USB_NET_RNDIS_HOST
 config USB_NET_CDC_SUBSET
        tristate "Simple USB Network Links (CDC Ethernet subset)"
        depends on USB_USBNET
+       default y
        help
          This driver module supports USB network devices that can work
          without any device-specific information.  Select it if you have
@@ -298,6 +300,13 @@ config USB_EPSON2888
          Choose this option to support the usb networking links used
          by some sample firmware from Epson.
 
+config USB_KC2190
+       boolean "KT Technology KC2190 based cables (InstaNet)"
+       depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
+       help
+        Â Choose this option if you're using a host-to-host cable
+        Â with one of these chips.
+
 config USB_NET_ZAURUS
        tristate "Sharp Zaurus (stock ROMs) and compatible"
        depends on USB_USBNET
index 4206df2d61b70f673d50bf86d6f56647826a80e7..7ef2e4b5e39bf986d559854458df5d6ea5bd5257 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/kmod.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -352,9 +351,11 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        skb_push(skb, 4);
        packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+       cpu_to_le32s(&packet_len);
        memcpy(skb->data, &packet_len, sizeof(packet_len));
 
        if ((skb->len % 512) == 0) {
+               cpu_to_le32s(&padbytes);
                memcpy( skb->tail, &padbytes, sizeof(padbytes));
                skb_put(skb, sizeof(padbytes));
        }
index e5cdafa258dd5e8955a3e2449fe5f605d9567fc7..5a21f06bf8a54fab20e2bb70dd0f599b4be910c2 100644 (file)
@@ -22,7 +22,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index e2fae85851a3e654117f61308866ad888654d150..bc62b012602b0a6a85bd6dda00d7702743b8a98e 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/kmod.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -80,13 +79,19 @@ static int always_connected (struct usbnet *dev)
  *
  * ALi M5632 driver ... does high speed
  *
+ * NOTE that the MS-Windows drivers for this chip use some funky and
+ * (naturally) undocumented 7-byte prefix to each packet, so this is a
+ * case where we don't currently interoperate.  Also, once you unplug
+ * one end of the cable, you need to replug the other end too ... since
+ * chip docs are unavailable, there's no way to reset the relevant state
+ * short of a power cycle.
+ *
  *-------------------------------------------------------------------------*/
 
 static const struct driver_info        ali_m5632_info = {
        .description =  "ALi M5632",
 };
 
-
 #endif
 
 \f
@@ -160,6 +165,11 @@ static const struct driver_info    epson2888_info = {
 #endif /* CONFIG_USB_EPSON2888 */
 
 \f
+/*-------------------------------------------------------------------------
+ *
+ * info from Jonathan McDowell <noodles@earth.li>
+ *
+ *-------------------------------------------------------------------------*/
 #ifdef CONFIG_USB_KC2190
 #define HAVE_HARDWARE
 static const struct driver_info kc2190_info = {
@@ -224,6 +234,10 @@ static const struct usb_device_id  products [] = {
        USB_DEVICE (0x0402, 0x5632),    // ALi defaults
        .driver_info =  (unsigned long) &ali_m5632_info,
 },
+{
+       USB_DEVICE (0x182d,0x207c),     // SiteCom CN-124
+       .driver_info =  (unsigned long) &ali_m5632_info,
+},
 #endif
 
 #ifdef CONFIG_USB_AN2720
@@ -315,13 +329,13 @@ static struct usb_driver cdc_subset_driver = {
 
 static int __init cdc_subset_init(void)
 {
-       return usb_register(&cdc_subset_driver);
+       return usb_register(&cdc_subset_driver);
 }
 module_init(cdc_subset_init);
 
 static void __exit cdc_subset_exit(void)
 {
-       usb_deregister(&cdc_subset_driver);
+       usb_deregister(&cdc_subset_driver);
 }
 module_exit(cdc_subset_exit);
 
index 31e5fe363fdc0d2547309c99a8829375867b18f3..d257a8e026d6182b77fea025a60376eb842b063b 100644 (file)
@@ -22,7 +22,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 36a989160a684ccba108d06a706008d5500a8941..de95268ae4b8a3bb17f232f5fb9fe5a0ef11c3d5 100644 (file)
@@ -46,7 +46,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
index 4936359545134db670434fbba9e011a97f943184..ccebfdef4751f945f7577d7097f9c4540b8b4eb9 100644 (file)
@@ -21,7 +21,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 5d17cdfc7bab00e468f8beafe466533b1815596e..45300939d185403e46bd7a73388c7c4e2e85398e 100644 (file)
@@ -21,7 +21,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index be888d2d813ca4293d5b74a816fcbc40915728ca..39a21c74fdf4af34e900900e8ab01fb3d0666df7 100644 (file)
@@ -21,7 +21,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 670262a38a0f25e8471ad9073ac970901f1c981f..ea153dc9b0ac3d620b49e2f91b04e4c0774a98ed 100644 (file)
@@ -6,7 +6,6 @@
  * version 2 as published by the Free Software Foundation.
  */
 
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
index 6e39e998825914acfaf899c5a9d77e2b13b59d31..de69b183bd2f96d714a68f94c0bb07785d65c1d9 100644 (file)
@@ -34,7 +34,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -148,7 +147,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
                if (tmp < 0)
                        return tmp;
        }
-       
+
        dev->in = usb_rcvbulkpipe (dev->udev,
                        in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
        dev->out = usb_sndbulkpipe (dev->udev,
@@ -328,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
        if (netif_running (dev->net)
                        && netif_device_present (dev->net)
                        && !test_bit (EVENT_RX_HALT, &dev->flags)) {
-               switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ 
+               switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
                case -EPIPE:
                        usbnet_defer_kevent (dev, EVENT_RX_HALT);
                        break;
@@ -444,7 +443,7 @@ block:
            case -EOVERFLOW:
                dev->stats.rx_over_errors++;
                // FALLTHROUGH
-           
+
            default:
                entry->state = rx_cleanup;
                dev->stats.rx_errors++;
@@ -561,7 +560,7 @@ static int usbnet_stop (struct net_device *net)
 
        if (netif_msg_ifdown (dev))
                devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-                       dev->stats.rx_packets, dev->stats.tx_packets, 
+                       dev->stats.rx_packets, dev->stats.tx_packets,
                        dev->stats.rx_errors, dev->stats.tx_errors
                        );
 
@@ -579,7 +578,7 @@ static int usbnet_stop (struct net_device *net)
                        devdbg (dev, "waited for %d urb completions", temp);
        }
        dev->wait = NULL;
-       remove_wait_queue (&unlink_wakeup, &wait); 
+       remove_wait_queue (&unlink_wakeup, &wait);
 
        usb_kill_urb(dev->interrupt);
 
@@ -835,7 +834,7 @@ kevent (struct work_struct *work)
        }
 
        if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
-               struct driver_info      *info = dev->driver_info;
+               struct driver_info      *info = dev->driver_info;
                int                     retval = 0;
 
                clear_bit (EVENT_LINK_RESET, &dev->flags);
@@ -1067,7 +1066,7 @@ static void usbnet_bh (unsigned long param)
  * USB Device Driver support
  *
  *-------------------------------------------------------------------------*/
+
 // precondition: never called in_interrupt
 
 void usbnet_disconnect (struct usb_interface *intf)
@@ -1088,7 +1087,7 @@ void usbnet_disconnect (struct usb_interface *intf)
                        intf->dev.driver->name,
                        xdev->bus->bus_name, xdev->devpath,
                        dev->driver_info->description);
-       
+
        net = dev->net;
        unregister_netdev (net);
 
@@ -1112,7 +1111,7 @@ int
 usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 {
        struct usbnet                   *dev;
-       struct net_device               *net;
+       struct net_device               *net;
        struct usb_host_interface       *interface;
        struct driver_info              *info;
        struct usb_device               *xdev;
@@ -1182,6 +1181,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        // NOTE net->name still not usable ...
        if (info->bind) {
                status = info->bind (dev, udev);
+               if (status < 0)
+                       goto out1;
+
                // heuristic:  "usb%d" for links we know are two-host,
                // else "eth%d" when there's reasonable doubt.  userspace
                // can rename the link if it knows better.
@@ -1208,12 +1210,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        if (status == 0 && dev->status)
                status = init_status (dev, udev);
        if (status < 0)
-               goto out1;
+               goto out3;
 
        if (!dev->rx_urb_size)
                dev->rx_urb_size = dev->hard_mtu;
        dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
-       
+
        SET_NETDEV_DEV(net, &udev->dev);
        status = register_netdev (net);
        if (status)
@@ -1256,7 +1258,7 @@ EXPORT_SYMBOL_GPL(usbnet_probe);
 int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet           *dev = usb_get_intfdata(intf);
-       
+
        /* accelerate emptying of the rx and queues, to avoid
         * having everything error out.
         */
@@ -1287,7 +1289,7 @@ static int __init usbnet_init(void)
                        < sizeof (struct skb_data));
 
        random_ether_addr(node_id);
-       return 0;
+       return 0;
 }
 module_init(usbnet_init);
 
index 144566bda583aa26b029de28ee8eeb7d27a65727..9f98e8ce487ab389694353ae31de484537087cad 100644 (file)
@@ -21,7 +21,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
index 0af42e32fa0a9d1673940e0fe4155d62d9d00447..18816bf96a4d6152da19a062c5f21d3247eaca60 100644 (file)
@@ -58,11 +58,6 @@ static void airprime_read_bulk_callback(struct urb *urb)
        if (urb->status) {
                dbg("%s - nonzero read bulk status received: %d",
                    __FUNCTION__, urb->status);
-               /* something happened, so free up the memory for this urb */
-               if (urb->transfer_buffer) {
-                       kfree (urb->transfer_buffer);
-                       urb->transfer_buffer = NULL;
-               }
                return;
        }
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -146,6 +141,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                                  airprime_read_bulk_callback, port);
                result = usb_submit_urb(urb, GFP_KERNEL);
                if (result) {
+                       usb_free_urb(urb);
+                       kfree(buffer);
                        dev_err(&port->dev,
                                "%s - failed submitting read urb %d for port %d, error %d\n",
                                __FUNCTION__, i, port->number, result);
@@ -160,27 +157,12 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
        /* some error happened, cancel any submitted urbs and clean up anything that
           got allocated successfully */
 
-       for ( ; i >= 0; --i) {
+       while (i-- != 0) {
                urb = priv->read_urbp[i];
-               if (urb) {
-                       /* This urb was submitted successfully. So we have to
-                          cancel it.
-                          Unlinking the urb will invoke read_bulk_callback()
-                          with an error status, so its transfer buffer will
-                          be freed there */
-                       if (usb_unlink_urb (urb) != -EINPROGRESS) {
-                               /* comments in drivers/usb/core/urb.c say this
-                                  can only happen if the urb was never submitted,
-                                  or has completed already.
-                                  Either way we may have to free the transfer
-                                  buffer here. */
-                               if (urb->transfer_buffer) {
-                                       kfree (urb->transfer_buffer);
-                                       urb->transfer_buffer = NULL;
-                               }
-                       }
-                       usb_free_urb (urb);
-               }
+               buffer = urb->transfer_buffer;
+               usb_kill_urb (urb);
+               usb_free_urb (urb);
+               kfree (buffer);
        }
 
  out:
@@ -194,10 +176,9 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       /* killing the urb will invoke read_bulk_callback() with an error status,
-          so the transfer buffer will be freed there */
        for (i = 0; i < NUM_READ_URBS; ++i) {
                usb_kill_urb (priv->read_urbp[i]);
+               kfree (priv->read_urbp[i]->transfer_buffer);
                usb_free_urb (priv->read_urbp[i]);
        }
 
index 3ec24870bca995edfd1c180ae7f1781c452ada5e..db623e754899859bc88e043a23ee593bdd3a14cf 100644 (file)
@@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+       { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
        { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
        { } /* Terminating Entry */
index 601e0648dec68fbaaa4ecc10e3306820ed9ae154..53baeec8f265a041bc45ae3a3010cd6c30d71c7d 100644 (file)
@@ -66,6 +66,8 @@ struct usb_serial_driver usb_serial_generic_device = {
        .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .shutdown =             usb_serial_generic_shutdown,
+       .throttle =             usb_serial_generic_throttle,
+       .unthrottle =           usb_serial_generic_unthrottle,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -115,6 +117,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
 {
        struct usb_serial *serial = port->serial;
        int result = 0;
+       unsigned long flags;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -124,7 +127,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
        if (port->tty)
                port->tty->low_latency = 1;
 
-       /* if we have a bulk interrupt, start reading from it */
+       /* clear the throttle flags */
+       spin_lock_irqsave(&port->lock, flags);
+       port->throttled = 0;
+       port->throttle_req = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       /* if we have a bulk endpoint, start reading from it */
        if (serial->num_bulk_in) {
                /* Start reading from the device */
                usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -253,31 +262,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
        return (chars);
 }
 
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = port->serial;
-       struct tty_struct *tty;
-       unsigned char *data = urb->transfer_buffer;
+       struct urb *urb = port->read_urb;
+       struct tty_struct *tty = port->tty;
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
-
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-               return;
-       }
-
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-
-       tty = port->tty;
+       /* Push data to tty */
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
-               tty_insert_flip_string(tty, data, urb->actual_length);
-               tty_flip_buffer_push(tty);
+               tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
+               tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
        }
 
-       /* Continue trying to always read  */
+       /* Continue reading from device */
        usb_fill_bulk_urb (port->read_urb, serial->dev,
                           usb_rcvbulkpipe (serial->dev,
                                            port->bulk_in_endpointAddress),
@@ -290,6 +290,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
        if (result)
                dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
+
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       unsigned char *data = urb->transfer_buffer;
+       int is_throttled;
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+               return;
+       }
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+       /* Throttle the device if requested by tty */
+       if (urb->actual_length) {
+               spin_lock_irqsave(&port->lock, flags);
+               is_throttled = port->throttled = port->throttle_req;
+               spin_unlock_irqrestore(&port->lock, flags);
+               if (is_throttled) {
+                       /* Let the received data linger in the read URB;
+                        * usb_serial_generic_unthrottle() will pick it
+                        * up later. */
+                       dbg("%s - throttling device", __FUNCTION__);
+                       return;
+               }
+       }
+
+       /* Handle data and continue reading from device */
+       flush_and_resubmit_read_urb(port);
+}
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
@@ -308,6 +342,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb)
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
+void usb_serial_generic_throttle (struct usb_serial_port *port)
+{
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* Set the throttle request flag. It will be picked up
+        * by usb_serial_generic_read_bulk_callback(). */
+       spin_lock_irqsave(&port->lock, flags);
+       port->throttle_req = 1;
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+{
+       int was_throttled;
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* Clear the throttle flags */
+       spin_lock_irqsave(&port->lock, flags);
+       was_throttled = port->throttled;
+       port->throttled = port->throttle_req = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       if (was_throttled) {
+               /* Handle pending data and resume reading from device */
+               flush_and_resubmit_read_urb(port);
+       }
+}
+
 void usb_serial_generic_shutdown (struct usb_serial *serial)
 {
        int i;
index ced9f32b29d9eb0a5f30b715e98e1318153aed65..9963a8b758401aed14435230348c8f9a07e41fab 100644 (file)
@@ -69,7 +69,6 @@ static int  option_send_setup(struct usb_serial_port *port);
 /* Vendor and product IDs */
 #define OPTION_VENDOR_ID                0x0AF0
 #define HUAWEI_VENDOR_ID                0x12D1
-#define AUDIOVOX_VENDOR_ID              0x0F3D
 #define NOVATELWIRELESS_VENDOR_ID       0x1410
 #define ANYDATA_VENDOR_ID               0x16d5
 
@@ -81,7 +80,6 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define OPTION_PRODUCT_GTMAX36          0x6701
 #define HUAWEI_PRODUCT_E600             0x1001
 #define HUAWEI_PRODUCT_E220             0x1003
-#define AUDIOVOX_PRODUCT_AIRCARD        0x0112
 #define NOVATELWIRELESS_PRODUCT_U740    0x1400
 #define ANYDATA_PRODUCT_ID              0x6501
 
@@ -94,7 +92,6 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-       { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
        { } /* Terminating entry */
@@ -109,7 +106,6 @@ static struct usb_device_id option_ids1[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-       { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
        { } /* Terminating entry */
index 6c083d4e2c9b854b9f0f73dc3b0edac29e1eec81..83dfae93a45db37278ee130e3b99fb30a2328a23 100644 (file)
@@ -83,6 +83,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
        { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
+       { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
 
index 65a5039665e71d31610d5d73645321dd6389b0f0..f9a71d0c102e7c54cafd3edb7747dbf5ceea0eb9 100644 (file)
@@ -97,3 +97,8 @@
 /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
 #define HUAWEI_VENDOR_ID       0x12d1
 #define HUAWEI_PRODUCT_ID      0x1001
+
+/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
+#define WS002IN_VENDOR_ID      0x11f6
+#define WS002IN_PRODUCT_ID     0x2001
+
index 01d8971ad7db3cfe5830aff3adade86f10e7586a..c87ad1bae1d6327b3f131af80cf04033ebbf78cf 100644 (file)
@@ -50,7 +50,6 @@
  * in that routine.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
index 5b06f9240d05caa2b348c7cf55cf520ff2ca2240..3a41740cad97d38b6e04c385fd64dd82f9c85133 100644 (file)
@@ -37,7 +37,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 
 #include "usb.h"
index 5031aa98f6a977d13760cc9cde790e0e79751018..003fcf5458882d3ec90f07251ea5f7aa2f437d34 100644 (file)
@@ -47,7 +47,6 @@
   * in that routine.
   */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
index 70234f5dbeeb473f60ab08da59e07438a1977033..e227f64d5641be64dc009c34da147be8c0a61a69 100644 (file)
@@ -153,6 +153,12 @@ static int slave_configure(struct scsi_device *sdev)
                if (us->flags & US_FL_FIX_CAPACITY)
                        sdev->fix_capacity = 1;
 
+               /* A few disks have two indistinguishable version, one of
+                * which reports the correct capacity and the other does not.
+                * The sd driver has to guess which is the case. */
+               if (us->flags & US_FL_CAPACITY_HEURISTICS)
+                       sdev->guess_capacity = 1;
+
                /* Some devices report a SCSI revision level above 2 but are
                 * unable to handle the REPORT LUNS command (for which
                 * support is mandatory at level 3).  Since we already have
index e3528eca29a54d7ddb67866cc66261db95d18b20..b2ed2a3e6fcae4499bc5d930169bdf16af93ad64 100644 (file)
@@ -41,7 +41,6 @@
  * EF: compute checksum (?)
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
index 8fcec01dc622f29f9fb3f8e6c50030b523b16730..5e27297c0175cb9017973b5e9e1c82de5c48056a 100644 (file)
@@ -43,7 +43,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/cdrom.h>
index f49a62fc32d2cfe0daf546027c43f59693d6c2a9..9644a8ea4aa71adfe794abf9cc75bdae12122b98 100644 (file)
@@ -1101,6 +1101,15 @@ UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN),
 
+/* Submitted by Dylan Taft <d13f00l@gmail.com>
+ * US_FL_IGNORE_RESIDUE Needed
+ */
+UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
+                "AIPTEK",
+                "Aiptek USB Keychain MP3 Player",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_IGNORE_RESIDUE),
+
 /* Entry needed for flags. Moreover, all devices with this ID use
  * bulk-only transport, but _some_ falsely report Control/Bulk instead.
  * One example is "Trumpion Digital Research MYMP3".
@@ -1311,12 +1320,13 @@ UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_NO_WP_DETECT ),
 
-/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+/* Reported by Jan Mate <mate@fiit.stuba.sk>
+ * and by Soeren Sonnenburg <kernel@nn7.de> */
 UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
                "Sony Ericsson",
                "P990i",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_FIX_CAPACITY ),
+               US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
@@ -1385,6 +1395,16 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Thomas Baechler <thomas@archlinux.org>
+ * Fixes I/O errors with Teac HD-35PU devices
+ */
+
+UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
+               "Super Top",
+               "USB 2.0  IDE DEVICE",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE),
+
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
  * and Renato Perini <rperini@email.it>
  */
@@ -1423,7 +1443,7 @@ UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
                "DataStor",
                "USB4500 FW1.04",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_FIX_CAPACITY),
+               US_FL_CAPACITY_HEURISTICS),
 
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
index 296b091cf168c7e460ec70db19ac7dcc18a777c1..46929a1b6f24e44ba8566c46d0db993dfd113439 100644 (file)
@@ -90,13 +90,15 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
+       /* increment our usage count for the device */
+       kref_get(&dev->kref);
+
        /* prevent the device from being autosuspended */
        retval = usb_autopm_get_interface(interface);
-       if (retval)
+       if (retval) {
+               kref_put(&dev->kref, skel_delete);
                goto exit;
-
-       /* increment our usage count for the device */
-       kref_get(&dev->kref);
+       }
 
        /* save our object in the file's private structure */
        file->private_data = dev;
index 602db660bc73d7bb2ef41a8246bd05e10afdd609..bffe2b946344b37881f0fed387965562b357724d 100644 (file)
@@ -49,7 +49,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 1490e5e1c23292a82be44e842ee7ec1cff19cc31..a8f60c33863c6f7df1e239e66de510347a107c22 100644 (file)
@@ -3,7 +3,6 @@
  *  ATI Mach64 Hardware Acceleration
  */
 
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <video/mach64.h>
index 2045639cb671b1ecded8b03f2104ff868a8741d6..10c988aef58ec13df19580244b1a08651d4b9c8e 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/sched.h>
 
 #include <asm/io.h>
 
index e7c5b219ad1b6baa8d01d67086caa816c280c770..5084799207056941f1fc3a6c03aa6529801a2460 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index ce5ac268074e49d77cec208915e12eb3eed06fac..be3f2c3f132c22d9f148da488aa9a9f5958ad32c 100644 (file)
@@ -60,7 +60,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>       /* MSch: for IRQ probe */
index eb4d03fa53915612f40158a82d06f549eec4f595..124ecbe6f88cf37dc00152e393ecddc2b4b568a2 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 4a9bde2c839b41dae6922ff71965928833908b7b..91a20785108aa26b962fd4412afb51ae427476bb 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
index 3cfea315a48ff1305c5202a09dd577c709a79fd1..28225265159a7c42b36239918695d7e20bc1f399 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
index 1b981b6356757a7cf9b26ea5f179ddeb6febf559..ca93a75f299740e38d1b2feb258bcbb6f6499b93 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/module.h>
 #include <linux/console.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
index 3dc49424dc75b43e6cc5d2860c5c258011d3162a..756c0ce85911fa8d5c27b6a2254d52cac6323488 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 9ab9b839a0f5e57cbf643c9bd7c238388d33ba9a..b18486ad8e17fc11fbea0d9c9e657602c10a13da 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 961f4d40446799ac1fdcbec9f15e533f2ee2abc5..7787c3322ffbf82fcf80abc00189a2a9a45d9c8a 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index 0f9b2fdc28b19f4117c01f4b96e98728936b865c..267c1ff9ebd9b8b841bc448cbf8b0005c9df1710 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
index 33bc41f50540e8a419ac216a0d7bdff7d4af7dda..f4ede5f6b588da583e43545566737fc736545104 100644 (file)
@@ -27,7 +27,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index a95836839e1e965d29739662a1e7ca95a70edef0..c1eb18bf088392655f81886e9ccc9015ebcf6bd2 100644 (file)
@@ -1990,7 +1990,8 @@ int
 intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {
 
        if (!test_and_set_bit(0, &dinfo->irq_flags)) {
-               if (request_irq(dinfo->pdev->irq, intelfbhw_irq, SA_SHIRQ, "intelfb", dinfo)) {
+               if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
+                    "intelfb", dinfo)) {
                        clear_bit(0, &dinfo->irq_flags);
                        return -EINVAL;
                }
index f0d614a80f1f797dd394dd1c9d3e7a52406cb5c8..1c5579907397ea7e248ce38d0b227c09e6153a68 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/string.h>
index 180d94c2b4d232e21d02a5b6d90ff8825018da5a..f7d647dda978a7b404b988cbcfc71bee95dbd43f 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 38c8d38de4fdd5566d065c6e697aa8c6c57637ca..5e91c2b30af9113edc6fc37d2b22752f59caae62 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 5162eab955394150baa2ede448dfe17e0ddc37fa..3e517940c5a581cdd30f960803e001176bd4b88d 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/fb.h>
-#include <linux/sched.h>
 
 #undef DEBUG
 
index 8454adf2d178abb9cc49bebf56226d17db804c77..b8588973e400936eec3f3dccd2c3400affcf298b 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index 181875fe35c662899e5964d52da76d7ca6a483ce..163a774a1b30bdbfb95471b1b56d16dc7edca209 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index 68ca3cc40770ccda101cd79097f28a6d6952f980..a864438b6008bcde0d9baba19821f13fff1b6435 100644 (file)
@@ -24,7 +24,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/timer.h>
index 01b85e3b0ae1efb8ad4b1779109d52ffc311d5fb..0405e839ff939f5dc9e13d33f02dd4f1cd51ca06 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index ccef56d0c15794fced4c4c71b93a2ce21288f0a3..ed3426062a8b5c136784b988f7abaa2c52c043b7 100644 (file)
@@ -791,6 +791,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
 
        info = fbinfo->par;
        info->fb = fbinfo;
+       info->dev = &pdev->dev;
+
        platform_set_drvdata(pdev, fbinfo);
 
        dprintk("devinit\n");
index 1411f3b6a0099871f589554793a483daa27614eb..8db066ccca6b8ccd314120851f5e9245246199da 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
index b604859b4ddbcd3ed2b4619284b7daa3b562d932..7478d0e3e21153e998dc23800bd4c31bd44dc9cd 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index a9b6301a04fcce2d0c5302ecfbb66a0de9cf8770..90419715c7e95cc52187d5b362967b0c1d8e0e4d 100644 (file)
@@ -136,7 +136,8 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
 }
 
 /**
- * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
+ *                     release it
  * @dentry: dentry to look for fid in
  *
  * find a fid in the dentry and then clone to a new private fid
index 147ceef8e5370ad3a57c3b87c027bcb08d95bbac..c783874a9cafb3b55080d99eed02ce03c4b4b148 100644 (file)
@@ -256,7 +256,7 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
        vpt->muxnum--;
        if (!vpt->muxnum) {
                dprintk(DEBUG_MUX, "destroy proc %p\n", vpt);
-               send_sig(SIGKILL, vpt->task, 1);
+               kthread_stop(vpt->task);
                vpt->task = NULL;
                v9fs_mux_poll_task_num--;
        }
@@ -438,11 +438,8 @@ static int v9fs_poll_proc(void *a)
 
        vpt = a;
        dprintk(DEBUG_MUX, "start %p %p\n", current, vpt);
-       allow_signal(SIGKILL);
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (signal_pending(current))
-                       break;
 
                list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
                        v9fs_poll_mux(m);
index d9b561ba5e581cfeda7728e8c072428d40a85433..6ad6f192b6e45db7c66df77a170779512c34c29f 100644 (file)
@@ -53,6 +53,8 @@ enum {
        Opt_uname, Opt_remotename,
        /* Options that take no arguments */
        Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+       /* Cache options */
+       Opt_cache_loose,
        /* Error token */
        Opt_err
 };
@@ -76,6 +78,8 @@ static match_table_t tokens = {
        {Opt_fd, "fd"},
        {Opt_legacy, "noextend"},
        {Opt_nodevmap, "nodevmap"},
+       {Opt_cache_loose, "cache=loose"},
+       {Opt_cache_loose, "loose"},
        {Opt_err, NULL}
 };
 
@@ -106,6 +110,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
        v9ses->debug = 0;
        v9ses->rfdno = ~0;
        v9ses->wfdno = ~0;
+       v9ses->cache = 0;
 
        if (!options)
                return;
@@ -121,7 +126,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
                                        "integer field, but no integer?\n");
                                continue;
                        }
-
                }
                switch (token) {
                case Opt_port:
@@ -169,6 +173,9 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
                case Opt_nodevmap:
                        v9ses->nodev = 1;
                        break;
+               case Opt_cache_loose:
+                       v9ses->cache = CACHE_LOOSE;
+                       break;
                default:
                        continue;
                }
index c134d104cb28f56b606d51886a7e34f93f02c378..820bf5ca35d88b8dd2c03ac619b88b16d8ac45c2 100644 (file)
@@ -47,7 +47,7 @@ struct v9fs_session_info {
        unsigned int afid;      /* authentication fid */
        unsigned int rfdno;     /* read file descriptor number */
        unsigned int wfdno;     /* write file descriptor number */
-
+       unsigned int cache;     /* cache mode */
 
        char *name;             /* user name to mount as */
        char *remotename;       /* name of remote hierarchy being mounted */
@@ -73,6 +73,13 @@ enum {
        PROTO_FD,
 };
 
+/* possible values of ->cache */
+/* eventually support loose, tight, time, session, default always none */
+enum {
+       CACHE_NONE,             /* default */
+       CACHE_LOOSE,            /* no consistency */
+};
+
 extern struct dentry *v9fs_debugfs_root;
 
 int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
index 450b0c1b385e62f31db2d74ce6990fd67f8aeedc..8ada4c5c5d70b47abf82297ec8337c9bcb403e98 100644 (file)
 extern struct file_system_type v9fs_fs_type;
 extern const struct address_space_operations v9fs_addr_operations;
 extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_cached_file_operations;
 extern const struct file_operations v9fs_dir_operations;
 extern struct dentry_operations v9fs_dentry_operations;
+extern struct dentry_operations v9fs_cached_dentry_operations;
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
 ino_t v9fs_qid2ino(struct v9fs_qid *qid);
index cc24abf232d5818c375836b744759916b88f24ac..bed48fa96521862d6aa26d503df589bbc4993bdd 100644 (file)
@@ -63,6 +63,8 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
        int total = 0;
        int result = 0;
 
+       dprintk(DEBUG_VFS, "\n");
+
        buffer = kmap(page);
        do {
                if (count < rsize)
index 062daa6000ab55a33441b8bcac7aa4375727fe14..ddffd8aa902d65d1c389fc3a86d845ca62238210 100644 (file)
 static int v9fs_dentry_delete(struct dentry *dentry)
 {
        dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
        return 1;
 }
 
+/**
+ * v9fs_cached_dentry_delete - called when dentry refcount equals 0
+ * @dentry:  dentry in question
+ *
+ * Only return 1 if our inode is invalid.  Only non-synthetic files
+ * (ones without mtime == 0) should be calling this function.
+ *
+ */
+
+static int v9fs_cached_dentry_delete(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+       if(!inode)
+               return 1;
+
+       return 0;
+}
+
 /**
  * v9fs_dentry_release - called when dentry is going to be freed
  * @dentry:  dentry that is being release
@@ -87,6 +108,11 @@ void v9fs_dentry_release(struct dentry *dentry)
        }
 }
 
+struct dentry_operations v9fs_cached_dentry_operations = {
+       .d_delete = v9fs_cached_dentry_delete,
+       .d_release = v9fs_dentry_release,
+};
+
 struct dentry_operations v9fs_dentry_operations = {
        .d_delete = v9fs_dentry_delete,
        .d_release = v9fs_dentry_release,
index 6c78343cf69023e5220c6a50127b33325c0f1c97..653dfa5b253174bcf4712211ece50540beed06e8 100644 (file)
@@ -79,6 +79,13 @@ int v9fs_file_open(struct inode *inode, struct file *file)
        vfid->filp = file;
        kfree(fcall);
 
+       if((vfid->qid.version) && (v9ses->cache)) {
+               dprintk(DEBUG_VFS, "cached");
+               /* enable cached file options */
+               if(file->f_op == &v9fs_file_operations)
+                       file->f_op = &v9fs_cached_file_operations;
+       }
+
        return 0;
 
 Clunk_Fid:
@@ -238,6 +245,17 @@ v9fs_file_write(struct file *filp, const char __user * data,
        return total;
 }
 
+const struct file_operations v9fs_cached_file_operations = {
+       .llseek = generic_file_llseek,
+       .read = do_sync_read,
+       .aio_read = generic_file_aio_read,
+       .write = v9fs_file_write,
+       .open = v9fs_file_open,
+       .release = v9fs_dir_release,
+       .lock = v9fs_file_lock,
+       .mmap = generic_file_mmap,
+};
+
 const struct file_operations v9fs_file_operations = {
        .llseek = generic_file_llseek,
        .read = v9fs_file_read,
index 5cf22134826bded20a24b57be206f2ff3624f3b4..124a085d1f2e16265da9658cb339bbfb87e15287 100644 (file)
@@ -504,7 +504,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
                goto error;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
 
        if (nd && nd->flags & LOOKUP_OPEN) {
@@ -589,7 +592,10 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                goto error;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        return 0;
 
@@ -626,7 +632,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
        sb = dir->i_sb;
        v9ses = v9fs_inode2v9ses(dir);
-       dentry->d_op = &v9fs_dentry_operations;
        dirfid = v9fs_fid_lookup(dentry->d_parent);
 
        if(IS_ERR(dirfid))
@@ -697,6 +702,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
        fid->qid = fcall->params.rstat.stat.qid;
        v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
+       if((fid->qid.version)&&(v9ses->cache))
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
 
        d_add(dentry, inode);
        kfree(fcall);
@@ -1184,7 +1193,10 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
                goto free_vfid;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        return 0;
 
index a722b5a3f752f1701c4f172fb1ac94dd8c576836..3c4886b849f57e21d4fbde30fd7b633139165790 100644 (file)
@@ -1189,32 +1189,6 @@ config EFS_FS
          To compile the EFS file system support as a module, choose M here: the
          module will be called efs.
 
-config JFFS_FS
-       tristate "Journalling Flash File System (JFFS) support"
-       depends on MTD && BLOCK && BROKEN
-       help
-         JFFS is the Journalling Flash File System developed by Axis
-         Communications in Sweden, aimed at providing a crash/powerdown-safe
-         file system for disk-less embedded devices. Further information is
-         available at (<http://developer.axis.com/software/jffs/>).
-
-         NOTE: This filesystem is deprecated and is scheduled for removal in
-         2.6.21.  See Documentation/feature-removal-schedule.txt
-
-config JFFS_FS_VERBOSE
-       int "JFFS debugging verbosity (0 = quiet, 3 = noisy)"
-       depends on JFFS_FS
-       default "0"
-       help
-         Determines the verbosity level of the JFFS debugging messages.
-
-config JFFS_PROC_FS
-       bool "JFFS stats available in /proc filesystem"
-       depends on JFFS_FS && PROC_FS
-       help
-         Enabling this option will cause statistics from mounted JFFS file systems
-         to be made available to the user in the /proc/fs/jffs/ directory.
-
 config JFFS2_FS
        tristate "Journalling Flash File System v2 (JFFS2) support"
        select CRC32
index b9ffa63f77fc266afde9a7d0c43daebcef4bca16..9edf4112bee0512a081b1666b3a1e426905cece3 100644 (file)
@@ -94,7 +94,6 @@ obj-$(CONFIG_HPFS_FS)         += hpfs/
 obj-$(CONFIG_NTFS_FS)          += ntfs/
 obj-$(CONFIG_UFS_FS)           += ufs/
 obj-$(CONFIG_EFS_FS)           += efs/
-obj-$(CONFIG_JFFS_FS)          += jffs/
 obj-$(CONFIG_JFFS2_FS)         += jffs2/
 obj-$(CONFIG_AFFS_FS)          += affs/
 obj-$(CONFIG_ROMFS_FS)         += romfs/
index bfc1fd22d5b10578088aaf12e527e87c7bf163ee..1fc5783727596ca4b239f8e10bdcb891ef1f21c5 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <rxrpc/peer.h>
 #include <rxrpc/connection.h>
index 9908462bcadc2fcd6ccc113aafc9dbf2d0569f13..b6dc2ebe47a885cea444ccb8f2ed1fa7586faf40 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
index eeff14c3f748e2df1486450dc6b92e7509f31273..b17634541f677f573971f426aa59bb40c862ac4a 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
index 6f37754906c201cb49940b2efbd57b5c6b9a978f..9d9bca6c28b5be5542c421d47df747595dcedeea 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
index 913c689bdb357d3a8550ab573cd4a69386820575..f2704ba5385735f598f4378a7591d05042ac7214 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/completion.h>
 #include <rxrpc/rxrpc.h>
 #include <rxrpc/transport.h>
index fdf23b2a21120493a9a6ab6a37155149a853b055..68495f0de7b39bcadd574d11fed907816ce8f88a 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
index 86463ec9ccb496cea5907ec1de2075c982d4849d..ae6b85b1e484b26494546f0eaa136de071dea69c 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
index 669dbe5b0317707f65e9ce374864cf789b9276f9..51db1182b27e4470edbc6945574aa1158a110bea 100644 (file)
@@ -76,7 +76,8 @@ static struct linux_binfmt elf_format = {
                .load_binary    = load_elf_binary,
                .load_shlib     = load_elf_library,
                .core_dump      = elf_core_dump,
-               .min_coredump   = ELF_EXEC_PAGESIZE
+               .min_coredump   = ELF_EXEC_PAGESIZE,
+               .hasvdso        = 1
 };
 
 #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
index 432e515431c4ca20aa4dd1e4e87d0908676752e1..080c5eba112b982f5879d128d6af9a9b15a4719f 100644 (file)
@@ -1,5 +1,5 @@
 The CIFS VFS support for Linux supports many advanced network filesystem 
-features such as heirarchical dfs like namespace, hardlinks, locking and more.  
+features such as hierarchical dfs like namespace, hardlinks, locking and more.  
 It was designed to comply with the SNIA CIFS Technical Reference (which 
 supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
 practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
index b8e91470c27f895e8b583741cfc5d30ff7062cde..24364106b8f9d6883bc1dd6d29975bc22b50e5f8 100644 (file)
@@ -2824,10 +2824,10 @@ GetExtAttrOut:
 
 
 /* security id for everyone */
-const static struct cifs_sid sid_everyone = 
+static const struct cifs_sid sid_everyone =
                {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
 /* group users */
-const static struct cifs_sid sid_user = 
+static const struct cifs_sid sid_user =
                {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
 
 /* Convert CIFS ACL to POSIX form */
index db3b1a9c9a5b9d7ea36075a0d5e1d9df320ebb00..c57a1fa7cf232eb73b554acc4d95c1669f0a67ab 100644 (file)
@@ -33,8 +33,6 @@
 
 static struct ctl_table_header *fs_table_header;
 
-#define FS_CODA         1       /* Coda file system */
-
 #define CODA_TIMEOUT    3       /* timeout on upcalls to become intrble */
 #define CODA_HARD       5       /* mount type "hard" or "soft" */
 #define CODA_VFS        6       /* vfs statistics */
@@ -183,17 +181,57 @@ static const struct file_operations proc_cache_inv_stats_fops = {
 };
 
 static ctl_table coda_table[] = {
-       {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
-       {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
-       {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
-       {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
-       {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
-       { 0 }
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "timeout",
+               .data           = &coda_timeout,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "hard",
+               .data           = &coda_hard,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "vfs_stats",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0644,
+               .proc_handler   = &do_reset_coda_vfs_stats
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "cache_inv_stats",
+               .data           = NULL,
+               .maxlen         = 0,
+               .mode           = 0644,
+               .proc_handler   = &do_reset_coda_cache_inv_stats
+       },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "fake_statfs",
+               .data           = &coda_fake_statfs,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = &proc_dointvec
+       },
+       {}
 };
 
 static ctl_table fs_table[] = {
-       {FS_CODA, "coda",    NULL, 0, 0555, coda_table},
-       {0}
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "coda",
+               .mode           = 0555,
+               .child          = coda_table
+       },
+       {}
 };
 
 
@@ -233,7 +271,7 @@ void coda_sysctl_init(void)
 
 #ifdef CONFIG_SYSCTL
        if ( !fs_table_header )
-               fs_table_header = register_sysctl_table(fs_table, 0);
+               fs_table_header = register_sysctl_table(fs_table);
 #endif 
 }
 
index 8d130cc8532248893f2bf5e9af3cf152ad08d3b5..682f928b7f4d09e1950ff185f0447dea0869a466 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/namei.h>
 #include <linux/debugfs.h>
 
 static ssize_t default_read_file(struct file *file, char __user *buf,
@@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = {
        .open =         default_open,
 };
 
+static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       nd_set_link(nd, dentry->d_inode->i_private);
+       return NULL;
+}
+
+const struct inode_operations debugfs_link_operations = {
+       .readlink       = generic_readlink,
+       .follow_link    = debugfs_follow_link,
+};
+
 static void debugfs_u8_set(void *data, u64 val)
 {
        *(u8 *)data = val;
index c692487346eaa324fb1f1d5950a4af5a5503d184..7b324cfebcb1e3782a9b1a329e54ffd2aec5a795 100644 (file)
 #include <linux/namei.h>
 #include <linux/debugfs.h>
 #include <linux/fsnotify.h>
+#include <linux/string.h>
 
 #define DEBUGFS_MAGIC  0x64626720
 
 /* declared over in file.c */
 extern struct file_operations debugfs_file_operations;
+extern struct inode_operations debugfs_link_operations;
 
 static struct vfsmount *debugfs_mount;
 static int debugfs_mount_count;
@@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
                case S_IFREG:
                        inode->i_fop = &debugfs_file_operations;
                        break;
+               case S_IFLNK:
+                       inode->i_op = &debugfs_link_operations;
+                       break;
                case S_IFDIR:
                        inode->i_op = &simple_dir_inode_operations;
                        inode->i_fop = &simple_dir_operations;
@@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        return res;
 }
 
+static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
+{
+       mode = (mode & S_IALLUGO) | S_IFLNK;
+       return debugfs_mknod(dir, dentry, mode, 0);
+}
+
 static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
        int res;
@@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
        mutex_lock(&parent->d_inode->i_mutex);
        *dentry = lookup_one_len(name, parent, strlen(name));
        if (!IS_ERR(*dentry)) {
-               if ((mode & S_IFMT) == S_IFDIR)
+               switch (mode & S_IFMT) {
+               case S_IFDIR:
                        error = debugfs_mkdir(parent->d_inode, *dentry, mode);
-               else 
+                       break;
+               case S_IFLNK:
+                       error = debugfs_link(parent->d_inode, *dentry, mode);
+                       break;
+               default:
                        error = debugfs_create(parent->d_inode, *dentry, mode);
+                       break;
+               }
                dput(*dentry);
        } else
                error = PTR_ERR(*dentry);
@@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
  * you are responsible here.)  If an error occurs, %NULL will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned.  It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
  */
 struct dentry *debugfs_create_file(const char *name, mode_t mode,
                                   struct dentry *parent, void *data,
@@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  * you are responsible here.)  If an error occurs, %NULL will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned.  It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 {
@@ -258,6 +272,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 }
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
 
+/**
+ * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the symbolic link to
+ *        create.
+ * @parent: a pointer to the parent dentry for this symbolic link.  This
+ *          should be a directory dentry if set.  If this paramater is NULL,
+ *          then the symbolic link will be created in the root of the debugfs
+ *          filesystem.
+ * @target: a pointer to a string containing the path to the target of the
+ *          symbolic link.
+ *
+ * This function creates a symbolic link with the given name in debugfs that
+ * links to the given target path.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the debugfs_remove() function when the symbolic
+ * link is to be removed (no automatic cleanup happens if your module is
+ * unloaded, you are responsible here.)  If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+                                     const char *target)
+{
+       struct dentry *result;
+       char *link;
+
+       link = kstrdup(target, GFP_KERNEL);
+       if (!link)
+               return NULL;
+
+       result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
+                                    NULL);
+       if (!result)
+               kfree(link);
+       return result;
+}
+EXPORT_SYMBOL_GPL(debugfs_create_symlink);
+
 /**
  * debugfs_remove - removes a file or directory from the debugfs filesystem
  * @dentry: a pointer to a the dentry of the file or directory to be
@@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry)
        if (debugfs_positive(dentry)) {
                if (dentry->d_inode) {
                        dget(dentry);
-                       if (S_ISDIR(dentry->d_inode->i_mode)) {
+                       switch (dentry->d_inode->i_mode & S_IFMT) {
+                       case S_IFDIR:
                                ret = simple_rmdir(parent->d_inode, dentry);
                                if (ret)
                                        printk(KERN_ERR
                                                "DebugFS rmdir on %s failed : "
                                                "directory not empty.\n",
                                                dentry->d_name.name);
-                       } else
+                               break;
+                       case S_IFLNK:
+                               kfree(dentry->d_inode->i_private);
+                               /* fall through */
+                       default:
                                simple_unlink(parent->d_inode, dentry);
+                               break;
+                       }
                        if (!ret)
                                d_delete(dentry);
                        dput(dentry);
index 9eb166f91489498422f5b813f1956f3a7f67a221..b16f991662c1b5d58db4dde3fc982125a015472f 100644 (file)
@@ -1841,7 +1841,7 @@ static int __init dquot_init(void)
 
        printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
 
-       register_sysctl_table(sys_table, 0);
+       register_sysctl_table(sys_table);
 
        dquot_cachep = kmem_cache_create("dquot", 
                        sizeof(struct dquot), sizeof(unsigned long) * 4,
index b3609b7cdf11b2fa75b8d5e6b088e14d3155c488..403e3bad1455ae95a079a919306ecfe13cf73793 100644 (file)
@@ -467,6 +467,7 @@ extern struct kmem_cache *ecryptfs_header_cache_1;
 extern struct kmem_cache *ecryptfs_header_cache_2;
 extern struct kmem_cache *ecryptfs_xattr_cache;
 extern struct kmem_cache *ecryptfs_lower_page_cache;
+extern struct kmem_cache *ecryptfs_key_record_cache;
 
 int ecryptfs_interpose(struct dentry *hidden_dentry,
                       struct dentry *this_dentry, struct super_block *sb,
index c209f67e7a26a2e3e4ef4267cf99c7633c2a49e4..b550dea8eee6bf8828e6383633c37685e4c3b950 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/pagemap.h>
 #include <linux/key.h>
@@ -1639,6 +1638,8 @@ out:
        return rc;
 }
 
+struct kmem_cache *ecryptfs_key_record_cache;
+
 /**
  * ecryptfs_generate_key_packet_set
  * @dest: Virtual address from which to write the key record set
@@ -1665,50 +1666,55 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                &ecryptfs_superblock_to_private(
                        ecryptfs_dentry->d_sb)->mount_crypt_stat;
        size_t written;
-       struct ecryptfs_key_record key_rec;
+       struct ecryptfs_key_record *key_rec;
        int rc = 0;
 
        (*len) = 0;
+       key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL);
+       if (!key_rec) {
+               rc = -ENOMEM;
+               goto out;
+       }
        if (mount_crypt_stat->global_auth_tok) {
                auth_tok = mount_crypt_stat->global_auth_tok;
                if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
                        rc = write_tag_3_packet((dest_base + (*len)),
                                                max, auth_tok,
-                                               crypt_stat, &key_rec,
+                                               crypt_stat, key_rec,
                                                &written);
                        if (rc) {
                                ecryptfs_printk(KERN_WARNING, "Error "
                                                "writing tag 3 packet\n");
-                               goto out;
+                               goto out_free;
                        }
                        (*len) += written;
                        /* Write auth tok signature packet */
                        rc = write_tag_11_packet(
                                (dest_base + (*len)),
                                (max - (*len)),
-                               key_rec.sig, ECRYPTFS_SIG_SIZE, &written);
+                               key_rec->sig, ECRYPTFS_SIG_SIZE, &written);
                        if (rc) {
                                ecryptfs_printk(KERN_ERR, "Error writing "
                                                "auth tok signature packet\n");
-                               goto out;
+                               goto out_free;
                        }
                        (*len) += written;
                } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
                        rc = write_tag_1_packet(dest_base + (*len),
                                                max, auth_tok,
                                                crypt_stat,mount_crypt_stat,
-                                               &key_rec, &written);
+                                               key_rec, &written);
                        if (rc) {
                                ecryptfs_printk(KERN_WARNING, "Error "
                                                "writing tag 1 packet\n");
-                               goto out;
+                               goto out_free;
                        }
                        (*len) += written;
                } else {
                        ecryptfs_printk(KERN_WARNING, "Unsupported "
                                        "authentication token type\n");
                        rc = -EINVAL;
-                       goto out;
+                       goto out_free;
                }
        } else
                BUG();
@@ -1718,6 +1724,9 @@ ecryptfs_generate_key_packet_set(char *dest_base,
                ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
                rc = -EIO;
        }
+
+out_free:
+       kmem_cache_free(ecryptfs_key_record_cache, key_rec);
 out:
        if (rc)
                (*len) = 0;
index 26fe405a57637864c02be1a10fd8f0b6b94e69b2..80044d196fe06b7b82ae3c6dc0cacaddc3e1a2f6 100644 (file)
@@ -651,6 +651,11 @@ static struct ecryptfs_cache_info {
                .name = "ecryptfs_lower_page_cache",
                .size = PAGE_CACHE_SIZE,
        },
+       {
+               .cache = &ecryptfs_key_record_cache,
+               .name = "ecryptfs_key_record_cache",
+               .size = sizeof(struct ecryptfs_key_record),
+       },
 };
 
 static void ecryptfs_free_kmem_caches(void)
index 47d7e7b611f7d5ed6a143b748f9fdd889101a4c3..3baf253be95ad5f6e641cedbeb0f9c6a679c04eb 100644 (file)
@@ -169,7 +169,8 @@ int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
        if (!new_id) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
-                               "to register daemon [%d] for user\n", pid, uid);
+                               "to register daemon [%d] for user [%d]\n",
+                               pid, uid);
                goto unlock;
        }
        if (!ecryptfs_find_daemon_id(uid, &old_id)) {
index deeb27b5ba833d25009c33c3c31752fec8d79dd3..c30e149fbd2e682a8f13cdddefee32becb61941c 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/fs.h>
 #include <linux/jbd.h>
-#include <linux/sched.h>
 #include <linux/ext3_fs.h>
 #include <linux/cryptohash.h>
 
index b73cba12f79c0512cb62362a3d5181217b184e22..ecf89904c1134800e609486cee2c74ff489e1f90 100644 (file)
@@ -11,7 +11,6 @@
 
 #define EXT3FS_DEBUG
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 
index dc2724fa7622b2b1492d0d547425e6dcc1e7e35c..7916b50f9a13ffe0122689b69b4865eec064de4a 100644 (file)
@@ -222,7 +222,7 @@ static int ext4_ext_space_block(struct inode *inode)
 
        size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
                        / sizeof(struct ext4_extent);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
        if (size > 6)
                size = 6;
 #endif
@@ -235,7 +235,7 @@ static int ext4_ext_space_block_idx(struct inode *inode)
 
        size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
                        / sizeof(struct ext4_extent_idx);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
        if (size > 5)
                size = 5;
 #endif
@@ -249,7 +249,7 @@ static int ext4_ext_space_root(struct inode *inode)
        size = sizeof(EXT4_I(inode)->i_data);
        size -= sizeof(struct ext4_extent_header);
        size /= sizeof(struct ext4_extent);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
        if (size > 3)
                size = 3;
 #endif
@@ -263,7 +263,7 @@ static int ext4_ext_space_root_idx(struct inode *inode)
        size = sizeof(EXT4_I(inode)->i_data);
        size -= sizeof(struct ext4_extent_header);
        size /= sizeof(struct ext4_extent_idx);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
        if (size > 4)
                size = 4;
 #endif
@@ -1118,7 +1118,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
         */
        if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN)
                return 0;
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
        if (le16_to_cpu(ex1->ee_len) >= 4)
                return 0;
 #endif
@@ -1891,8 +1891,8 @@ void ext4_ext_init(struct super_block *sb)
 
        if (test_opt(sb, EXTENTS)) {
                printk("EXT4-fs: file extents enabled");
-#ifdef AGRESSIVE_TEST
-               printk(", agressive tests");
+#ifdef AGGRESSIVE_TEST
+               printk(", aggressive tests");
 #endif
 #ifdef CHECK_BINSEARCH
                printk(", check binsearch");
index a67966385e0639a9323c155021ed677993136ba3..1555024e3b36b26a56f8a7c47f191740171f9934 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/sched.h>
 #include <linux/ext4_fs.h>
 #include <linux/cryptohash.h>
 
index 4fe49c3661b286990b76b2bc939325804565f9b6..ea99f6c97f565fe0e2911c8a082265380ad9551c 100644 (file)
@@ -11,7 +11,6 @@
 
 #define EXT4FS_DEBUG
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 
index e3fa77c6ed56dce64e3fe68892022edaa85d0e56..7a4f61aa05f8a63697be13231d69316ef5c365a9 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>       /* for 'current' */
 #include <asm/uaccess.h>
 
 /*
index 113f6c9110c745c31a6759a613ef628b4a3f68cb..c53a5d2d0590ea0a90fc38ff5d470df88736b57e 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index c93ca8f361b55fa09bcd72cd9a2d21e1a3014393..82a1ac7895a2d02926eaded3be2182b993c1d8bf 100644 (file)
@@ -53,7 +53,6 @@
  * but never before the maximum hash table size has been reached.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/buffer_head.h>
index cd747c00f670363db6f2dbe41164858e56b4778f..c1f44009853f26a65930e28536055f406660494f 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 0c83c7f4dda85f4d7c12cce58c4cf1dbcb8db9a6..5b83ca6acab1e5f93829722844a7333f43c305fd 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index c4b0391b7aa23cbb5433d2235cc202793cf5797e..46af553555135f362d47a957faeb0418d7f8a46f 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index e30673dd37e017565d801492dda8248754c8e6a8..cfcc39b86a5369287e78b6f658c41374964122ee 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 7c1a9e22a526e0c0203d8d1426c2125fe81fcf70..6e8a59809abf835e7a14f80a54293ca93a055e53 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index ef3092e29607c5db08289597305388449ffff7b0..32caecd20300f757671b01e0e972d04a109e9a06 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index f2495f1e21adc0fde6f4a51ff73ff1fa8376bb43..d9ecfd23a49e339e1b74bdc0dc5aab9f3f38fcfb 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 9187eb174b43a0c91547bbbe36760a8cd9d65789..c6bac6b694204b010cad1bd18460f5fa38b522a5 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 4855e8cca62269e01b1c5e70433771747c64b95c..1de05b63d43affea74c9c1ebf6d7da81de64d599 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index c996aa739a0515f5c11229591a83805a4abb6f99..b50180e227790115f0e6b12570b0c9bedc14614c 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 60f47bf2e8e8cabf86c38d2e94c77c6a2893a72c..d85f6e05cb955d99cebcad6aa3bd660871cef49f 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index 14b380fb060290a77f24a96872e8b6b439707128..aa0dbd2aac1bd31bdd3cb4ebf8265fe9b874d47d 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index d0c806b85c864387cffec4a7a82a9dd8d5deb329..8bc182c7e2ef22c2bad269743f15bab5f27a4914 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index ff0846528d5475cb9cc6ec5021c8aad42a96128c..8d9c08b5c4b600bab2bee1cf635bb9849847740e 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index e5707a9f78c2091901813acee8d4db23a1e06029..601eaa1b9ed63f9c50dc72b104af2985cf01a276 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
index f2d7c49ce7595d16ed12e3ae834dbe6e93b54c6d..ba117c445e78d8127e9835fd37a1bd50c07791f0 100644 (file)
@@ -8,7 +8,6 @@
  * Handling of catalog records
  */
 
-#include <linux/sched.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
index 78137007ccc1f2ce2415f616997b6c5c935094a7..80b5682a2273446f72ba062bd744f31800f1f36a 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 
index 5a282f64c637e5188d50495c127959cf603d71a2..1a97f9293447c559758a1b4b00bdc05e1281e855 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vfs.h>
 #include <linux/nls.h>
diff --git a/fs/jffs/Makefile b/fs/jffs/Makefile
deleted file mode 100644 (file)
index 9c1c0bb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux Journalling Flash FileSystem (JFFS) routines.
-#
-# $Id: Makefile,v 1.11 2001/09/25 20:59:41 dwmw2 Exp $
-#
-
-obj-$(CONFIG_JFFS_FS) += jffs.o
-
-jffs-y                                 := jffs_fm.o intrep.o inode-v23.o
-jffs-$(CONFIG_JFFS_PROC_FS)    += jffs_proc.o
-jffs-objs                      := $(jffs-y)
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
deleted file mode 100644 (file)
index 9602b92..0000000
+++ /dev/null
@@ -1,1847 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- * Copyright 2000, 2001  Red Hat, Inc.
- */
-
-/* inode.c -- Contains the code that is called from the VFS.  */
-
-/* TODO-ALEX:
- * uid and gid are just 16 bit.
- * jffs_file_write reads from user-space pointers without xx_from_user
- * maybe other stuff do to.
- */
-
-#include <linux/time.h>
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/ioctl.h>
-#include <linux/stat.h>
-#include <linux/blkdev.h>
-#include <linux/quotaops.h>
-#include <linux/highmem.h>
-#include <linux/vfs.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#include "jffs_fm.h"
-#include "intrep.h"
-#ifdef CONFIG_JFFS_PROC_FS
-#include "jffs_proc.h"
-#endif
-
-static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-
-static const struct super_operations jffs_ops;
-static const struct file_operations jffs_file_operations;
-static const struct inode_operations jffs_file_inode_operations;
-static const struct file_operations jffs_dir_operations;
-static const struct inode_operations jffs_dir_inode_operations;
-static const struct address_space_operations jffs_address_operations;
-
-struct kmem_cache     *node_cache = NULL;
-struct kmem_cache     *fm_cache = NULL;
-
-/* Called by the VFS at mount time to initialize the whole file system.  */
-static int jffs_fill_super(struct super_block *sb, void *data, int silent)
-{
-       struct inode *root_inode;
-       struct jffs_control *c;
-
-       sb->s_flags |= MS_NODIRATIME;
-
-       D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
-                 sb->s_id));
-
-       if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
-               printk(KERN_WARNING "JFFS: Trying to mount a "
-                      "non-mtd device.\n");
-               return -EINVAL;
-       }
-
-       sb->s_blocksize = PAGE_CACHE_SIZE;
-       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-       sb->s_fs_info = (void *) 0;
-       sb->s_maxbytes = 0xFFFFFFFF;
-
-       /* Build the file system.  */
-       if (jffs_build_fs(sb) < 0) {
-               goto jffs_sb_err1;
-       }
-
-       /*
-        * set up enough so that we can read an inode
-        */
-       sb->s_magic = JFFS_MAGIC_SB_BITMASK;
-       sb->s_op = &jffs_ops;
-
-       root_inode = iget(sb, JFFS_MIN_INO);
-       if (!root_inode)
-               goto jffs_sb_err2;
-
-       /* Get the root directory of this file system.  */
-       if (!(sb->s_root = d_alloc_root(root_inode))) {
-               goto jffs_sb_err3;
-       }
-
-       c = (struct jffs_control *) sb->s_fs_info;
-
-#ifdef CONFIG_JFFS_PROC_FS
-       /* Set up the jffs proc file system.  */
-       if (jffs_register_jffs_proc_dir(MINOR(sb->s_dev), c) < 0) {
-               printk(KERN_WARNING "JFFS: Failed to initialize the JFFS "
-                       "proc file system for device %s.\n",
-                       sb->s_id);
-       }
-#endif
-
-       /* Set the Garbage Collection thresholds */
-
-       /* GC if free space goes below 5% of the total size */
-       c->gc_minfree_threshold = c->fmc->flash_size / 20;
-
-       if (c->gc_minfree_threshold < c->fmc->sector_size)
-               c->gc_minfree_threshold = c->fmc->sector_size;
-
-       /* GC if dirty space exceeds 33% of the total size. */
-       c->gc_maxdirty_threshold = c->fmc->flash_size / 3;
-
-       if (c->gc_maxdirty_threshold < c->fmc->sector_size)
-               c->gc_maxdirty_threshold = c->fmc->sector_size;
-
-
-       c->thread_pid = kernel_thread (jffs_garbage_collect_thread, 
-                                       (void *) c, 
-                                       CLONE_KERNEL);
-       D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
-
-       D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
-              sb->s_id));
-       return 0;
-
-jffs_sb_err3:
-       iput(root_inode);
-jffs_sb_err2:
-       jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
-jffs_sb_err1:
-       printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
-              sb->s_id);
-       return -EINVAL;
-}
-
-
-/* This function is called when the file system is umounted.  */
-static void
-jffs_put_super(struct super_block *sb)
-{
-       struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
-
-       D2(printk("jffs_put_super()\n"));
-
-#ifdef CONFIG_JFFS_PROC_FS
-       jffs_unregister_jffs_proc_dir(c);
-#endif
-
-       if (c->gc_task) {
-               D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
-               send_sig(SIGKILL, c->gc_task, 1);
-       }
-       wait_for_completion(&c->gc_thread_comp);
-
-       D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
-
-       jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
-       D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
-              sb->s_id));
-}
-
-
-/* This function is called when user commands like chmod, chgrp and
-   chown are executed. System calls like trunc() results in a call
-   to this function.  */
-static int
-jffs_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-       struct inode *inode = dentry->d_inode;
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_fmcontrol *fmc;
-       struct jffs_file *f;
-       struct jffs_node *new_node;
-       int update_all;
-       int res = 0;
-       int recoverable = 0;
-
-       lock_kernel();
-
-       if ((res = inode_change_ok(inode, iattr))) 
-               goto out;
-
-       c = (struct jffs_control *)inode->i_sb->s_fs_info;
-       fmc = c->fmc;
-
-       D3(printk (KERN_NOTICE "notify_change(): down biglock\n"));
-       mutex_lock(&fmc->biglock);
-
-       f = jffs_find_file(c, inode->i_ino);
-
-       ASSERT(if (!f) {
-               printk("jffs_setattr(): Invalid inode number: %lu\n",
-                      inode->i_ino);
-               D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
-               mutex_unlock(&fmc->biglock);
-               res = -EINVAL;
-               goto out;
-       });
-
-       D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
-                 f->name, f->ino));
-
-       update_all = iattr->ia_valid & ATTR_FORCE;
-
-       if ( (update_all || iattr->ia_valid & ATTR_SIZE)
-            && (iattr->ia_size + 128 < f->size) ) {
-               /* We're shrinking the file by more than 128 bytes.
-                  We'll be able to GC and recover this space, so
-                  allow it to go into the reserved space. */
-               recoverable = 1;
-        }
-
-       if (!(new_node = jffs_alloc_node())) {
-               D(printk("jffs_setattr(): Allocation failed!\n"));
-               D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
-               mutex_unlock(&fmc->biglock);
-               res = -ENOMEM;
-               goto out;
-       }
-
-       new_node->data_offset = 0;
-       new_node->removed_size = 0;
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = f->ino;
-       raw_inode.pino = f->pino;
-       raw_inode.mode = f->mode;
-       raw_inode.uid = f->uid;
-       raw_inode.gid = f->gid;
-       raw_inode.atime = f->atime;
-       raw_inode.mtime = f->mtime;
-       raw_inode.ctime = f->ctime;
-       raw_inode.dsize = 0;
-       raw_inode.offset = 0;
-       raw_inode.rsize = 0;
-       raw_inode.dsize = 0;
-       raw_inode.nsize = f->nsize;
-       raw_inode.nlink = f->nlink;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       if (update_all || iattr->ia_valid & ATTR_MODE) {
-               raw_inode.mode = iattr->ia_mode;
-               inode->i_mode = iattr->ia_mode;
-       }
-       if (update_all || iattr->ia_valid & ATTR_UID) {
-               raw_inode.uid = iattr->ia_uid;
-               inode->i_uid = iattr->ia_uid;
-       }
-       if (update_all || iattr->ia_valid & ATTR_GID) {
-               raw_inode.gid = iattr->ia_gid;
-               inode->i_gid = iattr->ia_gid;
-       }
-       if (update_all || iattr->ia_valid & ATTR_SIZE) {
-               int len;
-               D1(printk("jffs_notify_change(): Changing size "
-                         "to %lu bytes!\n", (long)iattr->ia_size));
-               raw_inode.offset = iattr->ia_size;
-
-               /* Calculate how many bytes need to be removed from
-                  the end.  */
-               if (f->size < iattr->ia_size) {
-                       len = 0;
-               }
-               else {
-                       len = f->size - iattr->ia_size;
-               }
-
-               raw_inode.rsize = len;
-
-               /* The updated node will be a removal node, with
-                  base at the new size and size of the nbr of bytes
-                  to be removed.  */
-               new_node->data_offset = iattr->ia_size;
-               new_node->removed_size = len;
-               inode->i_size = iattr->ia_size;
-               inode->i_blocks = (inode->i_size + 511) >> 9;
-
-               if (len) {
-                       invalidate_mapping_pages(inode->i_mapping, 0, -1);
-               }
-               inode->i_ctime = CURRENT_TIME_SEC;
-               inode->i_mtime = inode->i_ctime;
-       }
-       if (update_all || iattr->ia_valid & ATTR_ATIME) {
-               raw_inode.atime = iattr->ia_atime.tv_sec;
-               inode->i_atime = iattr->ia_atime;
-       }
-       if (update_all || iattr->ia_valid & ATTR_MTIME) {
-               raw_inode.mtime = iattr->ia_mtime.tv_sec;
-               inode->i_mtime = iattr->ia_mtime;
-       }
-       if (update_all || iattr->ia_valid & ATTR_CTIME) {
-               raw_inode.ctime = iattr->ia_ctime.tv_sec;
-               inode->i_ctime = iattr->ia_ctime;
-       }
-
-       /* Write this node to the flash.  */
-       if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) {
-               D(printk("jffs_notify_change(): The write failed!\n"));
-               jffs_free_node(new_node);
-               D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
-               mutex_unlock(&c->fmc->biglock);
-               goto out;
-       }
-
-       jffs_insert_node(c, f, &raw_inode, NULL, new_node);
-
-       mark_inode_dirty(inode);
-       D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-out:
-       unlock_kernel();
-       return res;
-} /* jffs_notify_change()  */
-
-
-static struct inode *
-jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
-              int * err)
-{
-       struct super_block * sb;
-       struct inode * inode;
-       struct jffs_control *c;
-       struct jffs_file *f;
-
-       sb = dir->i_sb;
-       inode = new_inode(sb);
-       if (!inode) {
-               *err = -ENOMEM;
-               return NULL;
-       }
-
-       c = (struct jffs_control *)sb->s_fs_info;
-
-       inode->i_ino = raw_inode->ino;
-       inode->i_mode = raw_inode->mode;
-       inode->i_nlink = raw_inode->nlink;
-       inode->i_uid = raw_inode->uid;
-       inode->i_gid = raw_inode->gid;
-       inode->i_size = raw_inode->dsize;
-       inode->i_atime.tv_sec = raw_inode->atime;
-       inode->i_mtime.tv_sec = raw_inode->mtime;
-       inode->i_ctime.tv_sec = raw_inode->ctime;
-       inode->i_ctime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
-       inode->i_atime.tv_nsec = 0;
-       inode->i_blocks = (inode->i_size + 511) >> 9;
-
-       f = jffs_find_file(c, raw_inode->ino);
-
-       inode->i_private = (void *)f;
-       insert_inode_hash(inode);
-
-       return inode;
-}
-
-/* Get statistics of the file system.  */
-static int
-jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-       struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
-       struct jffs_fmcontrol *fmc;
-
-       lock_kernel();
-
-       fmc = c->fmc;
-
-       D2(printk("jffs_statfs()\n"));
-
-       buf->f_type = JFFS_MAGIC_SB_BITMASK;
-       buf->f_bsize = PAGE_CACHE_SIZE;
-       buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
-                      - (fmc->min_free_size / PAGE_CACHE_SIZE);
-       buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) +
-                      fmc->dirty_size - fmc->min_free_size)
-                              >> PAGE_CACHE_SHIFT;
-       buf->f_bavail = buf->f_bfree;
-
-       /* Find out how many files there are in the filesystem.  */
-       buf->f_files = jffs_foreach_file(c, jffs_file_count);
-       buf->f_ffree = buf->f_bfree;
-       /* buf->f_fsid = 0; */
-       buf->f_namelen = JFFS_MAX_NAME_LEN;
-
-       unlock_kernel();
-
-       return 0;
-}
-
-
-/* Rename a file.  */
-static int
-jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
-           struct inode *new_dir, struct dentry *new_dentry)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_file *old_dir_f;
-       struct jffs_file *new_dir_f;
-       struct jffs_file *del_f;
-       struct jffs_file *f;
-       struct jffs_node *node;
-       struct inode *inode;
-       int result = 0;
-       __u32 rename_data = 0;
-
-       D2(printk("***jffs_rename()\n"));
-
-       D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
-                "new_dir: 0x%p, new name: 0x%p\n",
-                old_dir, old_dentry->d_name.name,
-                new_dir, new_dentry->d_name.name));
-
-       lock_kernel();
-       c = (struct jffs_control *)old_dir->i_sb->s_fs_info;
-       ASSERT(if (!c) {
-               printk(KERN_ERR "jffs_rename(): The old_dir inode "
-                      "didn't have a reference to a jffs_file struct\n");
-               unlock_kernel();
-               return -EIO;
-       });
-
-       result = -ENOTDIR;
-       if (!(old_dir_f = old_dir->i_private)) {
-               D(printk("jffs_rename(): Old dir invalid.\n"));
-               goto jffs_rename_end;
-       }
-
-       /* Try to find the file to move.  */
-       result = -ENOENT;
-       if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
-                                 old_dentry->d_name.len))) {
-               goto jffs_rename_end;
-       }
-
-       /* Find the new directory.  */
-       result = -ENOTDIR;
-       if (!(new_dir_f = new_dir->i_private)) {
-               D(printk("jffs_rename(): New dir invalid.\n"));
-               goto jffs_rename_end;
-       }
-       D3(printk (KERN_NOTICE "rename(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-       /* Create a node and initialize as much as needed.  */
-       result = -ENOMEM;
-       if (!(node = jffs_alloc_node())) {
-               D(printk("jffs_rename(): Allocation failed: node == 0\n"));
-               goto jffs_rename_end;
-       }
-       node->data_offset = 0;
-       node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = f->ino;
-       raw_inode.pino = new_dir_f->ino;
-/*     raw_inode.version = f->highest_version + 1; */
-       raw_inode.mode = f->mode;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = current->fsgid;
-#if 0
-       raw_inode.uid = f->uid;
-       raw_inode.gid = f->gid;
-#endif
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = f->ctime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = 0;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = new_dentry->d_name.len;
-       raw_inode.nlink = f->nlink;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       /* See if there already exists a file with the same name as
-          new_name.  */
-       if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
-                                    new_dentry->d_name.len))) {
-               raw_inode.rename = 1;
-               raw_inode.dsize = sizeof(__u32);
-               rename_data = del_f->ino;
-       }
-
-       /* Write the new node to the flash memory.  */
-       if ((result = jffs_write_node(c, node, &raw_inode,
-                                     new_dentry->d_name.name,
-                                     (unsigned char*)&rename_data, 0, f)) < 0) {
-               D(printk("jffs_rename(): Failed to write node to flash.\n"));
-               jffs_free_node(node);
-               goto jffs_rename_end;
-       }
-       raw_inode.dsize = 0;
-
-       if (raw_inode.rename) {
-               /* The file with the same name must be deleted.  */
-               //FIXME deadlock                down(&c->fmc->gclock);
-               if ((result = jffs_remove(new_dir, new_dentry,
-                                         del_f->mode)) < 0) {
-                       /* This is really bad.  */
-                       printk(KERN_ERR "JFFS: An error occurred in "
-                              "rename().\n");
-               }
-               //              up(&c->fmc->gclock);
-       }
-
-       if (old_dir_f != new_dir_f) {
-               /* Remove the file from its old position in the
-                  filesystem tree.  */
-               jffs_unlink_file_from_tree(f);
-       }
-
-       /* Insert the new node into the file system.  */
-       if ((result = jffs_insert_node(c, f, &raw_inode,
-                                      new_dentry->d_name.name, node)) < 0) {
-               D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
-                        "failed!\n"));
-       }
-
-       if (old_dir_f != new_dir_f) {
-               /* Insert the file to its new position in the
-                  file system.  */
-               jffs_insert_file_into_tree(f);
-       }
-
-       /* This is a kind of update of the inode we're about to make
-          here.  This is what they do in ext2fs.  Kind of.  */
-       if ((inode = iget(new_dir->i_sb, f->ino))) {
-               inode->i_ctime = CURRENT_TIME_SEC;
-               mark_inode_dirty(inode);
-               iput(inode);
-       }
-
-jffs_rename_end:
-       D3(printk (KERN_NOTICE "rename(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return result;
-} /* jffs_rename()  */
-
-
-/* Read the contents of a directory.  Used by programs like `ls'
-   for instance.  */
-static int
-jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
-       struct jffs_file *f;
-       struct dentry *dentry = filp->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
-       struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
-       int j;
-       int ddino;
-       lock_kernel();
-       D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
-       if (filp->f_pos == 0) {
-               D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
-               if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
-                       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-                       mutex_unlock(&c->fmc->biglock);
-                       unlock_kernel();
-                       return 0;
-               }
-               filp->f_pos = 1;
-       }
-       if (filp->f_pos == 1) {
-               if (inode->i_ino == JFFS_MIN_INO) {
-                       ddino = JFFS_MIN_INO;
-               }
-               else {
-                       ddino = ((struct jffs_file *)
-                                inode->i_private)->pino;
-               }
-               D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
-               if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
-                       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-                       mutex_unlock(&c->fmc->biglock);
-                       unlock_kernel();
-                       return 0;
-               }
-               filp->f_pos++;
-       }
-       f = ((struct jffs_file *)inode->i_private)->children;
-
-       j = 2;
-       while(f && (f->deleted || j++ < filp->f_pos )) {
-               f = f->sibling_next;
-       }
-
-       while (f) {
-               D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
-                         (f->name ? f->name : ""), f->ino));
-               if (filldir(dirent, f->name, f->nsize,
-                           filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
-                       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-                       mutex_unlock(&c->fmc->biglock);
-                       unlock_kernel();
-                       return 0;
-               }
-               filp->f_pos++;
-               do {
-                       f = f->sibling_next;
-               } while(f && f->deleted);
-       }
-       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return filp->f_pos;
-} /* jffs_readdir()  */
-
-
-/* Find a file in a directory. If the file exists, return its
-   corresponding dentry.  */
-static struct dentry *
-jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-       struct jffs_file *d;
-       struct jffs_file *f;
-       struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-       int len;
-       int r = 0;
-       const char *name;
-       struct inode *inode = NULL;
-
-       len = dentry->d_name.len;
-       name = dentry->d_name.name;
-
-       lock_kernel();
-
-       D3({
-               char *s = kmalloc(len + 1, GFP_KERNEL);
-               memcpy(s, name, len);
-               s[len] = '\0';
-               printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
-               kfree(s);
-       });
-
-       D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       r = -ENAMETOOLONG;
-       if (len > JFFS_MAX_NAME_LEN) {
-               goto jffs_lookup_end;
-       }
-
-       r = -EACCES;
-       if (!(d = (struct jffs_file *)dir->i_private)) {
-               D(printk("jffs_lookup(): No such inode! (%lu)\n",
-                        dir->i_ino));
-               goto jffs_lookup_end;
-       }
-
-       /* Get the corresponding inode to the file.  */
-
-       /* iget calls jffs_read_inode, so we need to drop the biglock
-           before calling iget.  Unfortunately, the GC has a tendency
-           to sneak in here, because iget sometimes calls schedule ().
-       */
-
-       if ((len == 1) && (name[0] == '.')) {
-               D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-               mutex_unlock(&c->fmc->biglock);
-               if (!(inode = iget(dir->i_sb, d->ino))) {
-                       D(printk("jffs_lookup(): . iget() ==> NULL\n"));
-                       goto jffs_lookup_end_no_biglock;
-               }
-               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-               mutex_lock(&c->fmc->biglock);
-       } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
-               D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-               mutex_unlock(&c->fmc->biglock);
-               if (!(inode = iget(dir->i_sb, d->pino))) {
-                       D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
-                       goto jffs_lookup_end_no_biglock;
-               }
-               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-               mutex_lock(&c->fmc->biglock);
-       } else if ((f = jffs_find_child(d, name, len))) {
-               D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-               mutex_unlock(&c->fmc->biglock);
-               if (!(inode = iget(dir->i_sb, f->ino))) {
-                       D(printk("jffs_lookup(): iget() ==> NULL\n"));
-                       goto jffs_lookup_end_no_biglock;
-               }
-               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-               mutex_lock(&c->fmc->biglock);
-       } else {
-               D3(printk("jffs_lookup(): Couldn't find the file. "
-                         "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
-                         f, name, d, d->ino));
-               inode = NULL;
-       }
-
-       d_add(dentry, inode);
-       D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return NULL;
-
-jffs_lookup_end:
-       D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-
-jffs_lookup_end_no_biglock:
-       unlock_kernel();
-       return ERR_PTR(r);
-} /* jffs_lookup()  */
-
-
-/* Try to read a page of data from a file.  */
-static int
-jffs_do_readpage_nolock(struct file *file, struct page *page)
-{
-       void *buf;
-       unsigned long read_len;
-       int result;
-       struct inode *inode = (struct inode*)page->mapping->host;
-       struct jffs_file *f = (struct jffs_file *)inode->i_private;
-       struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
-       int r;
-       loff_t offset;
-
-       D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
-                 (f->name ? f->name : ""), (long)page->index));
-
-       get_page(page);
-       /* Don't SetPageLocked(page), should be locked already */
-       ClearPageUptodate(page);
-       ClearPageError(page);
-
-       D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       read_len = 0;
-       result = 0;
-       offset = page_offset(page);
-
-       kmap(page);
-       buf = page_address(page);
-       if (offset < inode->i_size) {
-               read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
-               r = jffs_read_data(f, buf, offset, read_len);
-               if (r != read_len) {
-                       result = -EIO;
-                       D(
-                               printk("***jffs_readpage(): Read error! "
-                                      "Wanted to read %lu bytes but only "
-                                      "read %d bytes.\n", read_len, r);
-                         );
-               }
-
-       }
-
-       /* This handles the case of partial or no read in above */
-       if(read_len < PAGE_SIZE)
-               memset(buf + read_len, 0, PAGE_SIZE - read_len);
-       flush_dcache_page(page);
-       kunmap(page);
-
-       D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-
-       if (result) {
-               SetPageError(page);
-       }else {
-               SetPageUptodate(page);          
-       }
-
-       page_cache_release(page);
-
-       D3(printk("jffs_readpage(): Leaving...\n"));
-
-       return result;
-} /* jffs_do_readpage_nolock()  */
-
-static int jffs_readpage(struct file *file, struct page *page)
-{
-       int ret = jffs_do_readpage_nolock(file, page);
-       unlock_page(page);
-       return ret;
-}
-
-/* Create a new directory.  */
-static int
-jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_node *node;
-       struct jffs_file *dir_f;
-       struct inode *inode;
-       int dir_mode;
-       int result = 0;
-       int err;
-
-       D1({
-               int len = dentry->d_name.len;
-               char *_name = kmalloc(len + 1, GFP_KERNEL);
-               memcpy(_name, dentry->d_name.name, len);
-               _name[len] = '\0';
-               printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
-                      "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
-               kfree(_name);
-       });
-
-       lock_kernel();
-       dir_f = dir->i_private;
-
-       ASSERT(if (!dir_f) {
-               printk(KERN_ERR "jffs_mkdir(): No reference to a "
-                      "jffs_file struct in inode.\n");
-               unlock_kernel();
-               return -EIO;
-       });
-
-       c = dir_f->c;
-       D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
-                             & ~current->fs->umask);
-       if (dir->i_mode & S_ISGID) {
-               dir_mode |= S_ISGID;
-       }
-
-       /* Create a node and initialize it as much as needed.  */
-       if (!(node = jffs_alloc_node())) {
-               D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
-               result = -ENOMEM;
-               goto jffs_mkdir_end;
-       }
-       node->data_offset = 0;
-       node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = c->next_ino++;
-       raw_inode.pino = dir_f->ino;
-       raw_inode.version = 1;
-       raw_inode.mode = dir_mode;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-       /*      raw_inode.gid = current->fsgid; */
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = raw_inode.atime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = 0;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = dentry->d_name.len;
-       raw_inode.nlink = 1;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       /* Write the new node to the flash.  */
-       if ((result = jffs_write_node(c, node, &raw_inode,
-                                    dentry->d_name.name, NULL, 0, NULL)) < 0) {
-               D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
-               jffs_free_node(node);
-               goto jffs_mkdir_end;
-       }
-
-       /* Insert the new node into the file system.  */
-       if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-                                      node)) < 0) {
-               goto jffs_mkdir_end;
-       }
-
-       inode = jffs_new_inode(dir, &raw_inode, &err);
-       if (inode == NULL) {
-               result = err;
-               goto jffs_mkdir_end;
-       }
-
-       inode->i_op = &jffs_dir_inode_operations;
-       inode->i_fop = &jffs_dir_operations;
-
-       mark_inode_dirty(dir);
-       d_instantiate(dentry, inode);
-
-       result = 0;
-jffs_mkdir_end:
-       D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return result;
-} /* jffs_mkdir()  */
-
-
-/* Remove a directory.  */
-static int
-jffs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-       struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-       int ret;
-       D3(printk("***jffs_rmdir()\n"));
-       D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
-       lock_kernel();
-       mutex_lock(&c->fmc->biglock);
-       ret = jffs_remove(dir, dentry, S_IFDIR);
-       D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return ret;
-}
-
-
-/* Remove any kind of file except for directories.  */
-static int
-jffs_unlink(struct inode *dir, struct dentry *dentry)
-{
-       struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-       int ret; 
-
-       lock_kernel();
-       D3(printk("***jffs_unlink()\n"));
-       D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-       ret = jffs_remove(dir, dentry, 0);
-       D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return ret;
-}
-
-
-/* Remove a JFFS entry, i.e. plain files, directories, etc.  Here we
-   shouldn't test for free space on the device.  */
-static int
-jffs_remove(struct inode *dir, struct dentry *dentry, int type)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_file *dir_f; /* The file-to-remove's parent.  */
-       struct jffs_file *del_f; /* The file to remove.  */
-       struct jffs_node *del_node;
-       struct inode *inode = NULL;
-       int result = 0;
-
-       D1({
-               int len = dentry->d_name.len;
-               const char *name = dentry->d_name.name;
-               char *_name = kmalloc(len + 1, GFP_KERNEL);
-               memcpy(_name, name, len);
-               _name[len] = '\0';
-               printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
-               kfree(_name);
-       });
-
-       dir_f = dir->i_private;
-       c = dir_f->c;
-
-       result = -ENOENT;
-       if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
-                                     dentry->d_name.len))) {
-               D(printk("jffs_remove(): jffs_find_child() failed.\n"));
-               goto jffs_remove_end;
-       }
-
-       if (S_ISDIR(type)) {
-               struct jffs_file *child = del_f->children;
-               while(child) {
-                       if( !child->deleted ) {
-                               result = -ENOTEMPTY;
-                               goto jffs_remove_end;
-                       }
-                       child = child->sibling_next;
-               }
-       }            
-       else if (S_ISDIR(del_f->mode)) {
-               D(printk("jffs_remove(): node is a directory "
-                        "but it shouldn't be.\n"));
-               result = -EPERM;
-               goto jffs_remove_end;
-       }
-
-       inode = dentry->d_inode;
-
-       result = -EIO;
-       if (del_f->ino != inode->i_ino)
-               goto jffs_remove_end;
-
-       if (!inode->i_nlink) {
-               printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
-                      inode->i_ino, inode->i_nlink);
-               inode->i_nlink=1;
-       }
-
-       /* Create a node for the deletion.  */
-       result = -ENOMEM;
-       if (!(del_node = jffs_alloc_node())) {
-               D(printk("jffs_remove(): Allocation failed!\n"));
-               goto jffs_remove_end;
-       }
-       del_node->data_offset = 0;
-       del_node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = del_f->ino;
-       raw_inode.pino = del_f->pino;
-/*     raw_inode.version = del_f->highest_version + 1; */
-       raw_inode.mode = del_f->mode;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = current->fsgid;
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = del_f->mtime;
-       raw_inode.ctime = raw_inode.atime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = 0;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = 0;
-       raw_inode.nlink = del_f->nlink;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 1;
-
-       /* Write the new node to the flash memory.  */
-       if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) {
-               jffs_free_node(del_node);
-               result = -EIO;
-               goto jffs_remove_end;
-       }
-
-       /* Update the file.  This operation will make the file disappear
-          from the in-memory file system structures.  */
-       jffs_insert_node(c, del_f, &raw_inode, NULL, del_node);
-
-       dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-       mark_inode_dirty(dir);
-       inode->i_ctime = dir->i_ctime;
-       inode_dec_link_count(inode);
-
-       d_delete(dentry);       /* This also frees the inode */
-
-       result = 0;
-jffs_remove_end:
-       return result;
-} /* jffs_remove()  */
-
-
-static int
-jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_file *dir_f;
-       struct jffs_node *node = NULL;
-       struct jffs_control *c;
-       struct inode *inode;
-       int result = 0;
-       u16 data = old_encode_dev(rdev);
-       int err;
-
-       D1(printk("***jffs_mknod()\n"));
-
-       if (!old_valid_dev(rdev))
-               return -EINVAL;
-       lock_kernel();
-       dir_f = dir->i_private;
-       c = dir_f->c;
-
-       D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       /* Create and initialize a new node.  */
-       if (!(node = jffs_alloc_node())) {
-               D(printk("jffs_mknod(): Allocation failed!\n"));
-               result = -ENOMEM;
-               goto jffs_mknod_err;
-       }
-       node->data_offset = 0;
-       node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = c->next_ino++;
-       raw_inode.pino = dir_f->ino;
-       raw_inode.version = 1;
-       raw_inode.mode = mode;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-       /*      raw_inode.gid = current->fsgid; */
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = raw_inode.atime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = 2;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = dentry->d_name.len;
-       raw_inode.nlink = 1;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       /* Write the new node to the flash.  */
-       if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-                                  (unsigned char *)&data, 0, NULL)) < 0) {
-               D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
-               result = err;
-               goto jffs_mknod_err;
-       }
-
-       /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-                                   node)) < 0) {
-               result = err;
-               goto jffs_mknod_end;
-       }
-
-       inode = jffs_new_inode(dir, &raw_inode, &err);
-       if (inode == NULL) {
-               result = err;
-               goto jffs_mknod_end;
-       }
-
-       init_special_inode(inode, mode, rdev);
-
-       d_instantiate(dentry, inode);
-
-       goto jffs_mknod_end;
-
-jffs_mknod_err:
-       if (node) {
-               jffs_free_node(node);
-       }
-
-jffs_mknod_end:
-       D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return result;
-} /* jffs_mknod()  */
-
-
-static int
-jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_file *dir_f;
-       struct jffs_node *node;
-       struct inode *inode;
-
-       int symname_len = strlen(symname);
-       int err;
-
-       lock_kernel();
-       D1({
-               int len = dentry->d_name.len; 
-               char *_name = kmalloc(len + 1, GFP_KERNEL);
-               char *_symname = kmalloc(symname_len + 1, GFP_KERNEL);
-               memcpy(_name, dentry->d_name.name, len);
-               _name[len] = '\0';
-               memcpy(_symname, symname, symname_len);
-               _symname[symname_len] = '\0';
-               printk("***jffs_symlink(): dir = 0x%p, "
-                      "dentry->dname.name = \"%s\", "
-                      "symname = \"%s\"\n", dir, _name, _symname);
-               kfree(_name);
-               kfree(_symname);
-       });
-
-       dir_f = dir->i_private;
-       ASSERT(if (!dir_f) {
-               printk(KERN_ERR "jffs_symlink(): No reference to a "
-                      "jffs_file struct in inode.\n");
-               unlock_kernel();
-               return -EIO;
-       });
-
-       c = dir_f->c;
-
-       /* Create a node and initialize it as much as needed.  */
-       if (!(node = jffs_alloc_node())) {
-               D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
-               unlock_kernel();
-               return -ENOMEM;
-       }
-       D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       node->data_offset = 0;
-       node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = c->next_ino++;
-       raw_inode.pino = dir_f->ino;
-       raw_inode.version = 1;
-       raw_inode.mode = S_IFLNK | S_IRWXUGO;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = raw_inode.atime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = symname_len;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = dentry->d_name.len;
-       raw_inode.nlink = 1;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       /* Write the new node to the flash.  */
-       if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-                                  (const unsigned char *)symname, 0, NULL)) < 0) {
-               D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
-               jffs_free_node(node);
-               goto jffs_symlink_end;
-       }
-
-       /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-                                   node)) < 0) {
-               goto jffs_symlink_end;
-       }
-
-       inode = jffs_new_inode(dir, &raw_inode, &err);
-       if (inode == NULL) {
-               goto jffs_symlink_end;
-       }
-       err = 0;
-       inode->i_op = &page_symlink_inode_operations;
-       inode->i_mapping->a_ops = &jffs_address_operations;
-
-       d_instantiate(dentry, inode);
- jffs_symlink_end:
-       D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return err;
-} /* jffs_symlink()  */
-
-
-/* Create an inode inside a JFFS directory (dir) and return it.
- *
- * By the time this is called, we already have created
- * the directory cache entry for the new file, but it
- * is so far negative - it has no inode.
- *
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
-static int
-jffs_create(struct inode *dir, struct dentry *dentry, int mode,
-               struct nameidata *nd)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_node *node;
-       struct jffs_file *dir_f; /* JFFS representation of the directory.  */
-       struct inode *inode;
-       int err;
-
-       lock_kernel();
-       D1({
-               int len = dentry->d_name.len;
-               char *s = kmalloc(len + 1, GFP_KERNEL);
-               memcpy(s, dentry->d_name.name, len);
-               s[len] = '\0';
-               printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
-               kfree(s);
-       });
-
-       dir_f = dir->i_private;
-       ASSERT(if (!dir_f) {
-               printk(KERN_ERR "jffs_create(): No reference to a "
-                      "jffs_file struct in inode.\n");
-               unlock_kernel();
-               return -EIO;
-       });
-
-       c = dir_f->c;
-
-       /* Create a node and initialize as much as needed.  */
-       if (!(node = jffs_alloc_node())) {
-               D(printk("jffs_create(): Allocation failed: node == 0\n"));
-               unlock_kernel();
-               return -ENOMEM;
-       }
-       D3(printk (KERN_NOTICE "create(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       node->data_offset = 0;
-       node->removed_size = 0;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = c->next_ino++;
-       raw_inode.pino = dir_f->ino;
-       raw_inode.version = 1;
-       raw_inode.mode = mode;
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-       raw_inode.atime = get_seconds();
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = raw_inode.atime;
-       raw_inode.offset = 0;
-       raw_inode.dsize = 0;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = dentry->d_name.len;
-       raw_inode.nlink = 1;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
-
-       /* Write the new node to the flash.  */
-       if ((err = jffs_write_node(c, node, &raw_inode,
-                                  dentry->d_name.name, NULL, 0, NULL)) < 0) {
-               D(printk("jffs_create(): jffs_write_node() failed.\n"));
-               jffs_free_node(node);
-               goto jffs_create_end;
-       }
-
-       /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-                                   node)) < 0) {
-               goto jffs_create_end;
-       }
-
-       /* Initialize an inode.  */
-       inode = jffs_new_inode(dir, &raw_inode, &err);
-       if (inode == NULL) {
-               goto jffs_create_end;
-       }
-       err = 0;
-       inode->i_op = &jffs_file_inode_operations;
-       inode->i_fop = &jffs_file_operations;
-       inode->i_mapping->a_ops = &jffs_address_operations;
-       inode->i_mapping->nrpages = 0;
-
-       d_instantiate(dentry, inode);
- jffs_create_end:
-       D3(printk (KERN_NOTICE "create(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       unlock_kernel();
-       return err;
-} /* jffs_create()  */
-
-
-/* Write, append or rewrite data to an existing file.  */
-static ssize_t
-jffs_file_write(struct file *filp, const char *buf, size_t count,
-               loff_t *ppos)
-{
-       struct jffs_raw_inode raw_inode;
-       struct jffs_control *c;
-       struct jffs_file *f;
-       struct jffs_node *node;
-       struct dentry *dentry = filp->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
-       int recoverable = 0;
-       size_t written = 0;
-       __u32 thiscount = count;
-       loff_t pos = *ppos;
-       int err;
-
-       inode = filp->f_path.dentry->d_inode;
-
-       D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
-                 "filp: 0x%p, buf: 0x%p, count: %d\n",
-                 inode, inode->i_ino, filp, buf, count));
-
-#if 0
-       if (inode->i_sb->s_flags & MS_RDONLY) {
-               D(printk("jffs_file_write(): MS_RDONLY\n"));
-               err = -EROFS;
-               goto out_isem;
-       }
-#endif 
-       err = -EINVAL;
-
-       if (!S_ISREG(inode->i_mode)) {
-               D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
-                               inode->i_mode));
-               goto out_isem;
-       }
-
-       if (!(f = inode->i_private)) {
-               D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
-                               inode->i_private));
-               goto out_isem;
-       }
-
-       c = f->c;
-
-       /*
-        * This will never trigger with sane page sizes.  leave it in
-        * anyway, since I'm thinking about how to merge larger writes
-        * (the current idea is to poke a thread that does the actual
-        * I/O and starts by doing a mutex_lock(&inode->i_mutex).  then we
-        * would need to get the page cache pages and have a list of
-        * I/O requests and do write-merging here.
-        * -- prumpf
-        */
-       thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
-
-       D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       /* Urgh. POSIX says we can do short writes if we feel like it. 
-        * In practice, we can't. Nothing will cope. So we loop until
-        * we're done.
-        *
-        * <_Anarchy_> posix and reality are not interconnected on this issue
-        */
-       while (count) {
-               /* Things are going to be written so we could allocate and
-                  initialize the necessary data structures now.  */
-               if (!(node = jffs_alloc_node())) {
-                       D(printk("jffs_file_write(): node == 0\n"));
-                       err = -ENOMEM;
-                       goto out;
-               }
-
-               node->data_offset = pos;
-               node->removed_size = 0;
-
-               /* Initialize the raw inode.  */
-               raw_inode.magic = JFFS_MAGIC_BITMASK;
-               raw_inode.ino = f->ino;
-               raw_inode.pino = f->pino;
-
-               raw_inode.mode = f->mode;
-
-               raw_inode.uid = f->uid;
-               raw_inode.gid = f->gid;
-               raw_inode.atime = get_seconds();
-               raw_inode.mtime = raw_inode.atime;
-               raw_inode.ctime = f->ctime;
-               raw_inode.offset = pos;
-               raw_inode.dsize = thiscount;
-               raw_inode.rsize = 0;
-               raw_inode.nsize = f->nsize;
-               raw_inode.nlink = f->nlink;
-               raw_inode.spare = 0;
-               raw_inode.rename = 0;
-               raw_inode.deleted = 0;
-
-               if (pos < f->size) {
-                       node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos));
-
-                       /* If this node is going entirely over the top of old data,
-                          we can allow it to go into the reserved space, because
-                          we know that GC can reclaim the space later.
-                       */
-                       if (pos + thiscount < f->size) {
-                               /* If all the data we're overwriting are _real_,
-                                  not just holes, then:
-                                  recoverable = 1;
-                               */
-                       }
-               }
-
-               /* Write the new node to the flash.  */
-               /* NOTE: We would be quite happy if jffs_write_node() wrote a
-                  smaller node than we were expecting. There's no need for it
-                  to waste the space at the end of the flash just because it's
-                  a little smaller than what we asked for. But that's a whole
-                  new can of worms which I'm not going to open this week. 
-                  -- dwmw2.
-               */
-               if ((err = jffs_write_node(c, node, &raw_inode, f->name,
-                                          (const unsigned char *)buf,
-                                          recoverable, f)) < 0) {
-                       D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
-                       jffs_free_node(node);
-                       goto out;
-               }
-
-               written += err;
-               buf += err;
-               count -= err;
-               pos += err;
-
-               /* Insert the new node into the file system.  */
-               if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) {
-                       goto out;
-               }
-
-               D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
-
-               thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
-       }
- out:
-       D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-
-       /* Fix things in the real inode.  */
-       if (pos > inode->i_size) {
-               inode->i_size = pos;
-               inode->i_blocks = (inode->i_size + 511) >> 9;
-       }
-       inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
-       mark_inode_dirty(inode);
-       invalidate_mapping_pages(inode->i_mapping, 0, -1);
-
- out_isem:
-       return err;
-} /* jffs_file_write()  */
-
-static int
-jffs_prepare_write(struct file *filp, struct page *page,
-                  unsigned from, unsigned to)
-{
-       /* FIXME: we should detect some error conditions here */
-
-       /* Bugger that. We should make sure the page is uptodate */
-       if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE))
-               return jffs_do_readpage_nolock(filp, page);
-
-       return 0;
-} /* jffs_prepare_write() */
-
-static int
-jffs_commit_write(struct file *filp, struct page *page,
-                 unsigned from, unsigned to)
-{
-       void *addr = page_address(page) + from;
-       /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
-       loff_t pos = page_offset(page) + from;
-
-       return jffs_file_write(filp, addr, to-from, &pos);
-} /* jffs_commit_write() */
-
-/* This is our ioctl() routine.  */
-static int
-jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-          unsigned long arg)
-{
-       struct jffs_control *c;
-       int ret = 0;
-
-       D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
-                 cmd, arg));
-
-       if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) {
-               printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
-                      "(cmd = 0x%08x)\n", cmd);
-               return -EIO;
-       }
-       D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-
-       switch (cmd) {
-       case JFFS_PRINT_HASH:
-               jffs_print_hash_table(c);
-               break;
-       case JFFS_PRINT_TREE:
-               jffs_print_tree(c->root, 0);
-               break;
-       case JFFS_GET_STATUS:
-               {
-                       struct jffs_flash_status fst;
-                       struct jffs_fmcontrol *fmc = c->fmc;
-                       printk("Flash status -- ");
-                       if (!access_ok(VERIFY_WRITE,
-                                      (struct jffs_flash_status __user *)arg,
-                                      sizeof(struct jffs_flash_status))) {
-                               D(printk("jffs_ioctl(): Bad arg in "
-                                        "JFFS_GET_STATUS ioctl!\n"));
-                               ret = -EFAULT;
-                               break;
-                       }
-                       fst.size = fmc->flash_size;
-                       fst.used = fmc->used_size;
-                       fst.dirty = fmc->dirty_size;
-                       fst.begin = fmc->head->offset;
-                       fst.end = fmc->tail->offset + fmc->tail->size;
-                       printk("size: %d, used: %d, dirty: %d, "
-                              "begin: %d, end: %d\n",
-                              fst.size, fst.used, fst.dirty,
-                              fst.begin, fst.end);
-                       if (copy_to_user((struct jffs_flash_status __user *)arg,
-                                        &fst,
-                                        sizeof(struct jffs_flash_status))) {
-                               ret = -EFAULT;
-                       }
-               }
-               break;
-       default:
-               ret = -ENOTTY;
-       }
-       D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-       return ret;
-} /* jffs_ioctl()  */
-
-
-static const struct address_space_operations jffs_address_operations = {
-       .readpage       = jffs_readpage,
-       .prepare_write  = jffs_prepare_write,
-       .commit_write   = jffs_commit_write,
-};
-
-static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
-{
-       /* We currently have O_SYNC operations at all times.
-          Do nothing.
-       */
-       return 0;
-}
-
-
-static const struct file_operations jffs_file_operations =
-{
-       .open           = generic_file_open,
-       .llseek         = generic_file_llseek,
-       .read           = do_sync_read,
-       .aio_read       = generic_file_aio_read,
-       .write          = do_sync_write,
-       .aio_write      = generic_file_aio_write,
-       .ioctl          = jffs_ioctl,
-       .mmap           = generic_file_readonly_mmap,
-       .fsync          = jffs_fsync,
-       .sendfile       = generic_file_sendfile,
-};
-
-
-static const struct inode_operations jffs_file_inode_operations =
-{
-       .lookup         = jffs_lookup,          /* lookup */
-       .setattr        = jffs_setattr,
-};
-
-
-static const struct file_operations jffs_dir_operations =
-{
-       .readdir        = jffs_readdir,
-};
-
-
-static const struct inode_operations jffs_dir_inode_operations =
-{
-       .create         = jffs_create,
-       .lookup         = jffs_lookup,
-       .unlink         = jffs_unlink,
-       .symlink        = jffs_symlink,
-       .mkdir          = jffs_mkdir,
-       .rmdir          = jffs_rmdir,
-       .mknod          = jffs_mknod,
-       .rename         = jffs_rename,
-       .setattr        = jffs_setattr,
-};
-
-
-/* Initialize an inode for the VFS.  */
-static void
-jffs_read_inode(struct inode *inode)
-{
-       struct jffs_file *f;
-       struct jffs_control *c;
-
-       D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
-
-       if (!inode->i_sb) {
-               D(printk("jffs_read_inode(): !inode->i_sb ==> "
-                        "No super block!\n"));
-               return;
-       }
-       c = (struct jffs_control *)inode->i_sb->s_fs_info;
-       D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
-       mutex_lock(&c->fmc->biglock);
-       if (!(f = jffs_find_file(c, inode->i_ino))) {
-               D(printk("jffs_read_inode(): No such inode (%lu).\n",
-                        inode->i_ino));
-               D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
-               mutex_unlock(&c->fmc->biglock);
-               return;
-       }
-       inode->i_private = f;
-       inode->i_mode = f->mode;
-       inode->i_nlink = f->nlink;
-       inode->i_uid = f->uid;
-       inode->i_gid = f->gid;
-       inode->i_size = f->size;
-       inode->i_atime.tv_sec = f->atime;
-       inode->i_mtime.tv_sec = f->mtime;
-       inode->i_ctime.tv_sec = f->ctime;
-       inode->i_atime.tv_nsec = 
-       inode->i_mtime.tv_nsec = 
-       inode->i_ctime.tv_nsec = 0;
-
-       inode->i_blocks = (inode->i_size + 511) >> 9;
-       if (S_ISREG(inode->i_mode)) {
-               inode->i_op = &jffs_file_inode_operations;
-               inode->i_fop = &jffs_file_operations;
-               inode->i_mapping->a_ops = &jffs_address_operations;
-       }
-       else if (S_ISDIR(inode->i_mode)) {
-               inode->i_op = &jffs_dir_inode_operations;
-               inode->i_fop = &jffs_dir_operations;
-       }
-       else if (S_ISLNK(inode->i_mode)) {
-               inode->i_op = &page_symlink_inode_operations;
-               inode->i_mapping->a_ops = &jffs_address_operations;
-       }
-       else {
-               /* If the node is a device of some sort, then the number of
-                  the device should be read from the flash memory and then
-                  added to the inode's i_rdev member.  */
-               u16 val;
-               jffs_read_data(f, (char *)&val, 0, 2);
-               init_special_inode(inode, inode->i_mode,
-                       old_decode_dev(val));
-       }
-
-       D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
-       mutex_unlock(&c->fmc->biglock);
-}
-
-
-static void
-jffs_delete_inode(struct inode *inode)
-{
-       struct jffs_file *f;
-       struct jffs_control *c;
-       D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
-                 inode->i_ino));
-
-       truncate_inode_pages(&inode->i_data, 0);
-       lock_kernel();
-       inode->i_size = 0;
-       inode->i_blocks = 0;
-       inode->i_private = NULL;
-       clear_inode(inode);
-       if (inode->i_nlink == 0) {
-               c = (struct jffs_control *) inode->i_sb->s_fs_info;
-               f = (struct jffs_file *) jffs_find_file (c, inode->i_ino);
-               jffs_possibly_delete_file(f);
-       }
-
-       unlock_kernel();
-}
-
-
-static void
-jffs_write_super(struct super_block *sb)
-{
-       struct jffs_control *c = (struct jffs_control *)sb->s_fs_info;
-       lock_kernel();
-       jffs_garbage_collect_trigger(c);
-       unlock_kernel();
-}
-
-static int jffs_remount(struct super_block *sb, int *flags, char *data)
-{
-       *flags |= MS_NODIRATIME;
-       return 0;
-}
-
-static const struct super_operations jffs_ops =
-{
-       .read_inode     = jffs_read_inode,
-       .delete_inode   = jffs_delete_inode,
-       .put_super      = jffs_put_super,
-       .write_super    = jffs_write_super,
-       .statfs         = jffs_statfs,
-       .remount_fs     = jffs_remount,
-};
-
-static int jffs_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
-{
-       return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
-                          mnt);
-}
-
-static struct file_system_type jffs_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "jffs",
-       .get_sb         = jffs_get_sb,
-       .kill_sb        = kill_block_super,
-       .fs_flags       = FS_REQUIRES_DEV,
-};
-
-static int __init
-init_jffs_fs(void)
-{
-       printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING
-               ", (C) 1999, 2000  Axis Communications AB\n");
-       
-#ifdef CONFIG_JFFS_PROC_FS
-       jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
-       if (!jffs_proc_root) {
-               printk(KERN_WARNING "cannot create /proc/jffs entry\n");
-       }
-#endif
-       fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
-                      0,
-                      SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
-                      NULL, NULL);
-       if (!fm_cache) {
-               return -ENOMEM;
-       }
-
-       node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
-                      0,
-                      SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
-                      NULL, NULL);
-       if (!node_cache) {
-               kmem_cache_destroy(fm_cache);
-               return -ENOMEM;
-       }
-
-       return register_filesystem(&jffs_fs_type);
-}
-
-static void __exit
-exit_jffs_fs(void)
-{
-       unregister_filesystem(&jffs_fs_type);
-       kmem_cache_destroy(fm_cache);
-       kmem_cache_destroy(node_cache);
-}
-
-module_init(init_jffs_fs)
-module_exit(exit_jffs_fs)
-
-MODULE_DESCRIPTION("The Journalling Flash File System");
-MODULE_AUTHOR("Axis Communications AB.");
-MODULE_LICENSE("GPL");
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
deleted file mode 100644 (file)
index 6dd1891..0000000
+++ /dev/null
@@ -1,3449 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications, Inc.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-/* This file contains the code for the internal structure of the
-   Journaling Flash File System, JFFS.  */
-
-/*
- * Todo list:
- *
- * memcpy_to_flash() and memcpy_from_flash() functions.
- *
- * Implementation of hard links.
- *
- * Organize the source code in a better way. Against the VFS we could
- * have jffs_ext.c, and against the block device jffs_int.c.
- * A better file-internal organization too.
- *
- * A better checksum algorithm.
- *
- * Consider endianness stuff. ntohl() etc.
- *
- * Are we handling the atime, mtime, ctime members of the inode right?
- *
- * Remove some duplicated code. Take a look at jffs_write_node() and
- * jffs_rewrite_data() for instance.
- *
- * Implement more meaning of the nlink member in various data structures.
- * nlink could be used in conjunction with hard links for instance.
- *
- * Better memory management. Allocate data structures in larger chunks
- * if possible.
- *
- * If too much meta data is stored, a garbage collect should be issued.
- * We have experienced problems with too much meta data with for instance
- * log files.
- *
- * Improve the calls to jffs_ioctl(). We would like to retrieve more
- * information to be able to debug (or to supervise) JFFS during run-time.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <linux/smp_lock.h>
-#include <linux/time.h>
-#include <linux/ctype.h>
-#include <linux/freezer.h>
-
-#include "intrep.h"
-#include "jffs_fm.h"
-
-long no_jffs_node = 0;
-static long no_jffs_file = 0;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-long no_jffs_control = 0;
-long no_jffs_raw_inode = 0;
-long no_jffs_node_ref = 0;
-long no_jffs_fm = 0;
-long no_jffs_fmcontrol = 0;
-long no_hash = 0;
-long no_name = 0;
-#endif
-
-static int jffs_scan_flash(struct jffs_control *c);
-static int jffs_update_file(struct jffs_file *f, struct jffs_node *node);
-static int jffs_build_file(struct jffs_file *f);
-static int jffs_free_file(struct jffs_file *f);
-static int jffs_free_node_list(struct jffs_file *f);
-static int jffs_garbage_collect_now(struct jffs_control *c);
-static int jffs_insert_file_into_hash(struct jffs_file *f);
-static int jffs_remove_redundant_nodes(struct jffs_file *f);
-
-/* Is there enough space on the flash?  */
-static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-
-       while (1) {
-               if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
-                       >= fmc->min_free_size + space) {
-                       return 1;
-               }
-               if (fmc->dirty_size < fmc->sector_size)
-                       return 0;
-
-               if (jffs_garbage_collect_now(c)) {
-                 D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
-                 return 0;
-               }
-       }
-}
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-static __u8
-flash_read_u8(struct mtd_info *mtd, loff_t from)
-{
-       size_t retlen;
-       __u8 ret;
-       int res;
-
-       res = MTD_READ(mtd, from, 1, &retlen, &ret);
-       if (retlen != 1) {
-               printk("Didn't read a byte in flash_read_u8(). Returned %d\n", res);
-               return 0;
-       }
-
-       return ret;
-}
-
-static void
-jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
-{
-       char line[16];
-       int j = 0;
-
-       while (size > 0) {
-               int i;
-
-               printk("%ld:", (long) pos);
-               for (j = 0; j < 16; j++) {
-                       line[j] = flash_read_u8(mtd, pos++);
-               }
-               for (i = 0; i < j; i++) {
-                       if (!(i & 1)) {
-                               printk(" %.2x", line[i] & 0xff);
-                       }
-                       else {
-                               printk("%.2x", line[i] & 0xff);
-                       }
-               }
-
-               /* Print empty space */
-               for (; i < 16; i++) {
-                       if (!(i & 1)) {
-                               printk("   ");
-                       }
-                       else {
-                               printk("  ");
-                       }
-               }
-               printk("  ");
-
-               for (i = 0; i < j; i++) {
-                       if (isgraph(line[i])) {
-                               printk("%c", line[i]);
-                       }
-                       else {
-                               printk(".");
-                       }
-               }
-               printk("\n");
-               size -= 16;
-       }
-}
-
-/* Print the contents of a node.  */
-static void
-jffs_print_node(struct jffs_node *n)
-{
-       D(printk("jffs_node: 0x%p\n", n));
-       D(printk("{\n"));
-       D(printk("        0x%08x, /* version  */\n", n->version));
-       D(printk("        0x%08x, /* data_offset  */\n", n->data_offset));
-       D(printk("        0x%08x, /* data_size  */\n", n->data_size));
-       D(printk("        0x%08x, /* removed_size  */\n", n->removed_size));
-       D(printk("        0x%08x, /* fm_offset  */\n", n->fm_offset));
-       D(printk("        0x%02x,       /* name_size  */\n", n->name_size));
-       D(printk("        0x%p, /* fm,  fm->offset: %u  */\n",
-                n->fm, (n->fm ? n->fm->offset : 0)));
-       D(printk("        0x%p, /* version_prev  */\n", n->version_prev));
-       D(printk("        0x%p, /* version_next  */\n", n->version_next));
-       D(printk("        0x%p, /* range_prev  */\n", n->range_prev));
-       D(printk("        0x%p, /* range_next  */\n", n->range_next));
-       D(printk("}\n"));
-}
-
-#endif
-
-/* Print the contents of a raw inode.  */
-static void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
-       D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
-       D(printk("{\n"));
-       D(printk("        0x%08x, /* magic  */\n", raw_inode->magic));
-       D(printk("        0x%08x, /* ino  */\n", raw_inode->ino));
-       D(printk("        0x%08x, /* pino  */\n", raw_inode->pino));
-       D(printk("        0x%08x, /* version  */\n", raw_inode->version));
-       D(printk("        0x%08x, /* mode  */\n", raw_inode->mode));
-       D(printk("        0x%04x,     /* uid  */\n", raw_inode->uid));
-       D(printk("        0x%04x,     /* gid  */\n", raw_inode->gid));
-       D(printk("        0x%08x, /* atime  */\n", raw_inode->atime));
-       D(printk("        0x%08x, /* mtime  */\n", raw_inode->mtime));
-       D(printk("        0x%08x, /* ctime  */\n", raw_inode->ctime));
-       D(printk("        0x%08x, /* offset  */\n", raw_inode->offset));
-       D(printk("        0x%08x, /* dsize  */\n", raw_inode->dsize));
-       D(printk("        0x%08x, /* rsize  */\n", raw_inode->rsize));
-       D(printk("        0x%02x,       /* nsize  */\n", raw_inode->nsize));
-       D(printk("        0x%02x,       /* nlink  */\n", raw_inode->nlink));
-       D(printk("        0x%02x,       /* spare  */\n",
-                raw_inode->spare));
-       D(printk("        %u,          /* rename  */\n",
-                raw_inode->rename));
-       D(printk("        %u,          /* deleted  */\n",
-                raw_inode->deleted));
-       D(printk("        0x%02x,       /* accurate  */\n",
-                raw_inode->accurate));
-       D(printk("        0x%08x, /* dchksum  */\n", raw_inode->dchksum));
-       D(printk("        0x%04x,     /* nchksum  */\n", raw_inode->nchksum));
-       D(printk("        0x%04x,     /* chksum  */\n", raw_inode->chksum));
-       D(printk("}\n"));
-}
-
-#define flash_safe_acquire(arg)
-#define flash_safe_release(arg)
-
-
-static int
-flash_safe_read(struct mtd_info *mtd, loff_t from,
-               u_char *buf, size_t count)
-{
-       size_t retlen;
-       int res;
-
-       D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
-                 mtd, (unsigned int) from, buf, count));
-
-       res = mtd->read(mtd, from, count, &retlen, buf);
-       if (retlen != count) {
-               panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
-       }
-       return res?res:retlen;
-}
-
-
-static __u32
-flash_read_u32(struct mtd_info *mtd, loff_t from)
-{
-       size_t retlen;
-       __u32 ret;
-       int res;
-
-       res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
-       if (retlen != 4) {
-               printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
-               return 0;
-       }
-
-       return ret;
-}
-
-
-static int
-flash_safe_write(struct mtd_info *mtd, loff_t to,
-                const u_char *buf, size_t count)
-{
-       size_t retlen;
-       int res;
-
-       D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
-                 mtd, (unsigned int) to, buf, count));
-
-       res = mtd->write(mtd, to, count, &retlen, buf);
-       if (retlen != count) {
-               printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
-       }
-       return res?res:retlen;
-}
-
-
-static int
-flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
-                       unsigned long iovec_cnt, loff_t to)
-{
-       size_t retlen, retlen_a;
-       int i;
-       int res;
-
-       D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
-                 mtd, (unsigned int) to, vecs));
-
-       if (mtd->writev) {
-               res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
-               return res ? res : retlen;
-       }
-       /* Not implemented writev. Repeatedly use write - on the not so
-          unreasonable assumption that the mtd driver doesn't care how
-          many write cycles we use. */
-       res=0;
-       retlen=0;
-
-       for (i=0; !res && i<iovec_cnt; i++) {
-               res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
-                                vecs[i].iov_base);
-               if (retlen_a != vecs[i].iov_len) {
-                       printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
-                       if (i != iovec_cnt-1)
-                               return -EIO;
-               }
-               /* If res is non-zero, retlen_a is undefined, but we don't
-                  care because in that case it's not going to be 
-                  returned anyway.
-               */
-               to += retlen_a;
-               retlen += retlen_a;
-       }
-       return res?res:retlen;
-}
-
-
-static int
-flash_memset(struct mtd_info *mtd, loff_t to,
-            const u_char c, size_t size)
-{
-       static unsigned char pattern[64];
-       int i;
-
-       /* fill up pattern */
-
-       for(i = 0; i < 64; i++)
-               pattern[i] = c;
-
-       /* write as many 64-byte chunks as we can */
-
-       while (size >= 64) {
-               flash_safe_write(mtd, to, pattern, 64);
-               size -= 64;
-               to += 64;
-       }
-
-       /* and the rest */
-
-       if(size)
-               flash_safe_write(mtd, to, pattern, size);
-
-       return size;
-}
-
-
-static void
-intrep_erase_callback(struct erase_info *done)
-{
-       wait_queue_head_t *wait_q;
-
-       wait_q = (wait_queue_head_t *)done->priv;
-
-       wake_up(wait_q);
-}
-
-
-static int
-flash_erase_region(struct mtd_info *mtd, loff_t start,
-                  size_t size)
-{
-       struct erase_info *erase;
-       DECLARE_WAITQUEUE(wait, current);
-       wait_queue_head_t wait_q;
-
-       erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
-       if (!erase)
-               return -ENOMEM;
-
-       init_waitqueue_head(&wait_q);
-
-       erase->mtd = mtd;
-       erase->callback = intrep_erase_callback;
-       erase->addr = start;
-       erase->len = size;
-       erase->priv = (u_long)&wait_q;
-
-       /* FIXME: Use TASK_INTERRUPTIBLE and deal with being interrupted */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&wait_q, &wait);
-
-       if (mtd->erase(mtd, erase) < 0) {
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&wait_q, &wait);
-               kfree(erase);
-
-               printk(KERN_WARNING "flash: erase of region [0x%lx, 0x%lx] "
-                      "totally failed\n", (long)start, (long)start + size);
-
-               return -1;
-       }
-
-       schedule(); /* Wait for flash to finish. */
-       remove_wait_queue(&wait_q, &wait);
-
-       kfree(erase);
-
-       return 0;
-}
-
-/* This routine calculates checksums in JFFS.  */
-static __u32
-jffs_checksum(const void *data, int size)
-{
-       __u32 sum = 0;
-       __u8 *ptr = (__u8 *)data;
-       while (size-- > 0) {
-               sum += *ptr++;
-       }
-       D3(printk(", result: 0x%08x\n", sum));
-       return sum;
-}
-
-
-static int
-jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
-{
-       __u32 sum = 0;
-       loff_t ptr = start;
-       __u8 *read_buf;
-       int i, length;
-
-       /* Allocate read buffer */
-       read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
-       if (!read_buf) {
-               printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
-               return -ENOMEM;
-       }
-       /* Loop until checksum done */
-       while (size) {
-               /* Get amount of data to read */
-               if (size < 4096)
-                       length = size;
-               else
-                       length = 4096;
-
-               /* Perform flash read */
-               D3(printk(KERN_NOTICE "jffs_checksum_flash\n"));
-               flash_safe_read(mtd, ptr, &read_buf[0], length);
-
-               /* Compute checksum */
-               for (i=0; i < length ; i++)
-                       sum += read_buf[i];
-
-               /* Update pointer and size */
-               size -= length;
-               ptr += length;
-       }
-
-       /* Free read buffer */
-       kfree(read_buf);
-
-       /* Return result */
-       D3(printk("checksum result: 0x%08x\n", sum));
-       *result = sum;
-       return 0;
-}
-
-static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
-{
-  //   down(&fmc->wlock);
-}
-
-static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
-{
-  //   up(&fmc->wlock);
-}
-
-
-/* Create and initialize a new struct jffs_file.  */
-static struct jffs_file *
-jffs_create_file(struct jffs_control *c,
-                const struct jffs_raw_inode *raw_inode)
-{
-       struct jffs_file *f;
-
-       if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) {
-               D(printk("jffs_create_file(): Failed!\n"));
-               return NULL;
-       }
-       no_jffs_file++;
-       f->ino = raw_inode->ino;
-       f->pino = raw_inode->pino;
-       f->nlink = raw_inode->nlink;
-       f->deleted = raw_inode->deleted;
-       f->c = c;
-
-       return f;
-}
-
-
-/* Build a control block for the file system.  */
-static struct jffs_control *
-jffs_create_control(struct super_block *sb)
-{
-       struct jffs_control *c;
-       register int s = sizeof(struct jffs_control);
-       int i;
-       D(char *t = 0);
-
-       D2(printk("jffs_create_control()\n"));
-
-       if (!(c = kmalloc(s, GFP_KERNEL))) {
-               goto fail_control;
-       }
-       DJM(no_jffs_control++);
-       c->root = NULL;
-       c->gc_task = NULL;
-       c->hash_len = JFFS_HASH_SIZE;
-       s = sizeof(struct list_head) * c->hash_len;
-       if (!(c->hash = kmalloc(s, GFP_KERNEL))) {
-               goto fail_hash;
-       }
-       DJM(no_hash++);
-       for (i = 0; i < c->hash_len; i++)
-               INIT_LIST_HEAD(&c->hash[i]);
-       if (!(c->fmc = jffs_build_begin(c, MINOR(sb->s_dev)))) {
-               goto fail_fminit;
-       }
-       c->next_ino = JFFS_MIN_INO + 1;
-       c->delete_list = (struct jffs_delete_list *) 0;
-       return c;
-
-fail_fminit:
-       D(t = "c->fmc");
-fail_hash:
-       kfree(c);
-       DJM(no_jffs_control--);
-       D(t = t ? t : "c->hash");
-fail_control:
-       D(t = t ? t : "control");
-       D(printk("jffs_create_control(): Allocation failed: (%s)\n", t));
-       return (struct jffs_control *)0;
-}
-
-
-/* Clean up all data structures associated with the file system.  */
-void
-jffs_cleanup_control(struct jffs_control *c)
-{
-       D2(printk("jffs_cleanup_control()\n"));
-
-       if (!c) {
-               D(printk("jffs_cleanup_control(): c == NULL !!!\n"));
-               return;
-       }
-
-       while (c->delete_list) {
-               struct jffs_delete_list *delete_list_element;
-               delete_list_element = c->delete_list;
-               c->delete_list = c->delete_list->next;
-               kfree(delete_list_element);
-       }
-
-       /* Free all files and nodes.  */
-       if (c->hash) {
-               jffs_foreach_file(c, jffs_free_node_list);
-               jffs_foreach_file(c, jffs_free_file);
-               kfree(c->hash);
-               DJM(no_hash--);
-       }
-       jffs_cleanup_fmcontrol(c->fmc);
-       kfree(c);
-       DJM(no_jffs_control--);
-       D3(printk("jffs_cleanup_control(): Leaving...\n"));
-}
-
-
-/* This function adds a virtual root node to the in-RAM representation.
-   Called by jffs_build_fs().  */
-static int
-jffs_add_virtual_root(struct jffs_control *c)
-{
-       struct jffs_file *root;
-       struct jffs_node *node;
-
-       D2(printk("jffs_add_virtual_root(): "
-                 "Creating a virtual root directory.\n"));
-
-       if (!(root = kzalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
-               return -ENOMEM;
-       }
-       no_jffs_file++;
-       if (!(node = jffs_alloc_node())) {
-               kfree(root);
-               no_jffs_file--;
-               return -ENOMEM;
-       }
-       DJM(no_jffs_node++);
-       memset(node, 0, sizeof(struct jffs_node));
-       node->ino = JFFS_MIN_INO;
-       root->ino = JFFS_MIN_INO;
-       root->mode = S_IFDIR | S_IRWXU | S_IRGRP
-                    | S_IXGRP | S_IROTH | S_IXOTH;
-       root->atime = root->mtime = root->ctime = get_seconds();
-       root->nlink = 1;
-       root->c = c;
-       root->version_head = root->version_tail = node;
-       jffs_insert_file_into_hash(root);
-       return 0;
-}
-
-
-/* This is where the file system is built and initialized.  */
-int
-jffs_build_fs(struct super_block *sb)
-{
-       struct jffs_control *c;
-       int err = 0;
-
-       D2(printk("jffs_build_fs()\n"));
-
-       if (!(c = jffs_create_control(sb))) {
-               return -ENOMEM;
-       }
-       c->building_fs = 1;
-       c->sb = sb;
-       if ((err = jffs_scan_flash(c)) < 0) {
-               if(err == -EAGAIN){
-                       /* scan_flash() wants us to try once more. A flipping 
-                          bits sector was detect in the middle of the scan flash.
-                          Clean up old allocated memory before going in.
-                       */
-                       D1(printk("jffs_build_fs: Cleaning up all control structures,"
-                                 " reallocating them and trying mount again.\n"));
-                       jffs_cleanup_control(c);
-                       if (!(c = jffs_create_control(sb))) {
-                               return -ENOMEM;
-                       }
-                       c->building_fs = 1;
-                       c->sb = sb;
-
-                       if ((err = jffs_scan_flash(c)) < 0) {
-                               goto jffs_build_fs_fail;
-                       }                       
-               }else{
-                       goto jffs_build_fs_fail;
-               }
-       }
-
-       /* Add a virtual root node if no one exists.  */
-       if (!jffs_find_file(c, JFFS_MIN_INO)) {
-               if ((err = jffs_add_virtual_root(c)) < 0) {
-                       goto jffs_build_fs_fail;
-               }
-       }
-
-       while (c->delete_list) {
-               struct jffs_file *f;
-               struct jffs_delete_list *delete_list_element;
-
-               if ((f = jffs_find_file(c, c->delete_list->ino))) {
-                       f->deleted = 1;
-               }
-               delete_list_element = c->delete_list;
-               c->delete_list = c->delete_list->next;
-               kfree(delete_list_element);
-       }
-
-       /* Remove deleted nodes.  */
-       if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) {
-               printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n");
-               goto jffs_build_fs_fail;
-       }
-       /* Remove redundant nodes.  (We are not interested in the
-          return value in this case.)  */
-       jffs_foreach_file(c, jffs_remove_redundant_nodes);
-       /* Try to build a tree from all the nodes.  */
-       if ((err = jffs_foreach_file(c, jffs_insert_file_into_tree)) < 0) {
-               printk("JFFS: Failed to build tree.\n");
-               goto jffs_build_fs_fail;
-       }
-       /* Compute the sizes of all files in the filesystem.  Adjust if
-          necessary.  */
-       if ((err = jffs_foreach_file(c, jffs_build_file)) < 0) {
-               printk("JFFS: Failed to build file system.\n");
-               goto jffs_build_fs_fail;
-       }
-       sb->s_fs_info = (void *)c;
-       c->building_fs = 0;
-
-       D1(jffs_print_hash_table(c));
-       D1(jffs_print_tree(c->root, 0));
-
-       return 0;
-
-jffs_build_fs_fail:
-       jffs_cleanup_control(c);
-       return err;
-} /* jffs_build_fs()  */
-
-
-/*
-  This checks for sectors that were being erased in their previous 
-  lifetimes and for some reason or the other (power fail etc.), 
-  the erase cycles never completed.
-  As the flash array would have reverted back to read status, 
-  these sectors are detected by the symptom of the "flipping bits",
-  i.e. bits being read back differently from the same location in
-  flash if read multiple times.
-  The only solution to this is to re-erase the entire
-  sector.
-  Unfortunately detecting "flipping bits" is not a simple exercise
-  as a bit may be read back at 1 or 0 depending on the alignment 
-  of the stars in the universe.
-  The level of confidence is in direct proportion to the number of 
-  scans done. By power fail testing I (Vipin) have been able to 
-  proove that reading twice is not enough.
-  Maybe 4 times? Change NUM_REREADS to a higher number if you want
-  a (even) higher degree of confidence in your mount process. 
-  A higher number would of course slow down your mount.
-*/
-static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
-
-#define NUM_REREADS             4 /* see note above */
-#define READ_AHEAD_BYTES        4096 /* must be a multiple of 4, 
-                                       usually set to kernel page size */
-
-       __u8 *read_buf1;
-       __u8 *read_buf2;
-
-       int err = 0;
-       int retlen;
-       int i;
-       int cnt;
-       __u32 offset;
-       loff_t pos = 0;
-       loff_t end = fmc->flash_size;
-
-
-       /* Allocate read buffers */
-       read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
-       if (!read_buf1)
-               return -ENOMEM;
-
-       read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
-       if (!read_buf2) {
-               kfree(read_buf1);
-               return -ENOMEM;
-       }
-
- CHECK_NEXT:
-       while(pos < end){
-               
-               D1(printk("check_partly_erased_sector():checking sector which contains"
-                         " offset 0x%x for flipping bits..\n", (__u32)pos));
-               
-               retlen = flash_safe_read(fmc->mtd, pos,
-                                        &read_buf1[0], READ_AHEAD_BYTES);
-               retlen &= ~3;
-               
-               for(cnt = 0; cnt < NUM_REREADS; cnt++){
-                       (void)flash_safe_read(fmc->mtd, pos,
-                                             &read_buf2[0], READ_AHEAD_BYTES);
-                       
-                       for (i=0 ; i < retlen ; i+=4) {
-                               /* buffers MUST match, double word for word! */
-                               if(*((__u32 *) &read_buf1[i]) !=
-                                  *((__u32 *) &read_buf2[i])
-                                  ){
-                                       /* flipping bits detected, time to erase sector */
-                                       /* This will help us log some statistics etc. */
-                                       D1(printk("Flipping bits detected in re-read round:%i of %i\n",
-                                              cnt, NUM_REREADS));
-                                       D1(printk("check_partly_erased_sectors:flipping bits detected"
-                                                 " @offset:0x%x(0x%x!=0x%x)\n",
-                                                 (__u32)pos+i, *((__u32 *) &read_buf1[i]), 
-                                                 *((__u32 *) &read_buf2[i])));
-                                       
-                                       /* calculate start of present sector */
-                                       offset = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-                                       
-                                       D1(printk("check_partly_erased_sector():erasing sector starting 0x%x.\n",
-                                                 offset));
-                                       
-                                       if (flash_erase_region(fmc->mtd,
-                                                              offset, fmc->sector_size) < 0) {
-                                               printk(KERN_ERR "JFFS: Erase of flash failed. "
-                                                      "offset = %u, erase_size = %d\n",
-                                                      offset , fmc->sector_size);
-                                               
-                                               err = -EIO;
-                                               goto returnBack;
-
-                                       }else{
-                                               D1(printk("JFFS: Erase of flash sector @0x%x successful.\n",
-                                                      offset));
-                                               /* skip ahead to the next sector */
-                                               pos = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-                                               pos += fmc->sector_size;
-                                               goto CHECK_NEXT;
-                                       }
-                               }
-                       }
-               }
-               pos += READ_AHEAD_BYTES;
-       }
-
- returnBack:
-       kfree(read_buf1);
-       kfree(read_buf2);
-
-       D2(printk("check_partly_erased_sector():Done checking all sectors till offset 0x%x for flipping bits.\n",
-                 (__u32)pos));
-
-       return err;
-
-}/* end check_partly_erased_sectors() */
-
-
-
-/* Scan the whole flash memory in order to find all nodes in the
-   file systems.  */
-static int
-jffs_scan_flash(struct jffs_control *c)
-{
-       char name[JFFS_MAX_NAME_LEN + 2];
-       struct jffs_raw_inode raw_inode;
-       struct jffs_node *node = NULL;
-       struct jffs_fmcontrol *fmc = c->fmc;
-       __u32 checksum;
-       __u8 tmp_accurate;
-       __u16 tmp_chksum;
-       __u32 deleted_file;
-       loff_t pos = 0;
-       loff_t start;
-       loff_t test_start;
-       loff_t end = fmc->flash_size;
-       __u8 *read_buf;
-       int i, len, retlen;
-       __u32 offset;
-
-       __u32 free_chunk_size1;
-       __u32 free_chunk_size2;
-
-       
-#define NUMFREEALLOWED     2        /* 2 chunks of at least erase size space allowed */
-       int num_free_space = 0;       /* Flag err if more than TWO
-                                      free blocks found. This is NOT allowed
-                                      by the current jffs design.
-                                   */
-       int num_free_spc_not_accp = 0; /* For debugging purposed keep count 
-                                       of how much free space was rejected and
-                                       marked dirty
-                                    */
-
-       D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n",
-                 (long)pos, (long)end));
-
-       flash_safe_acquire(fmc->mtd);
-
-       /*
-         check and make sure that any sector does not suffer
-         from the "partly erased, bit flipping syndrome" (TM Vipin :)
-         If so, offending sectors will be erased.
-       */
-       if(check_partly_erased_sectors(fmc) < 0){
-
-               flash_safe_release(fmc->mtd);
-               return -EIO; /* bad, bad, bad error. Cannot continue.*/
-       }
-
-       /* Allocate read buffer */
-       read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
-       if (!read_buf) {
-               flash_safe_release(fmc->mtd);
-               return -ENOMEM;
-       }
-                             
-       /* Start the scan.  */
-       while (pos < end) {
-               deleted_file = 0;
-
-               /* Remember the position from where we started this scan.  */
-               start = pos;
-
-               switch (flash_read_u32(fmc->mtd, pos)) {
-               case JFFS_EMPTY_BITMASK:
-                       /* We have found 0xffffffff at this position.  We have to
-                          scan the rest of the flash till the end or till
-                          something else than 0xffffffff is found.
-                          Keep going till we do not find JFFS_EMPTY_BITMASK 
-                          anymore */
-
-                       D1(printk("jffs_scan_flash(): 0xffffffff at pos 0x%lx.\n",
-                                 (long)pos));
-
-                       while(pos < end){
-
-                             len = end - pos < 4096 ? end - pos : 4096;
-                             
-                             retlen = flash_safe_read(fmc->mtd, pos,
-                                                &read_buf[0], len);
-
-                             retlen &= ~3;
-                             
-                             for (i=0 ; i < retlen ; i+=4, pos += 4) {
-                                     if(*((__u32 *) &read_buf[i]) !=
-                                        JFFS_EMPTY_BITMASK)
-                                       break;
-                             }
-                             if (i == retlen)
-                                   continue;
-                             else
-                                   break;
-                       }
-
-                       D1(printk("jffs_scan_flash():0xffffffff ended at pos 0x%lx.\n",
-                                 (long)pos));
-                       
-                       /* If some free space ends in the middle of a sector,
-                          treat it as dirty rather than clean.
-                          This is to handle the case where one thread 
-                          allocated space for a node, but didn't get to
-                          actually _write_ it before power was lost, leaving
-                          a gap in the log. Shifting all node writes into
-                          a single kernel thread will fix the original problem.
-                       */
-                       if ((__u32) pos % fmc->sector_size) {
-                               /* If there was free space in previous 
-                                  sectors, don't mark that dirty too - 
-                                  only from the beginning of this sector
-                                  (or from start) 
-                               */
-
-                               test_start = pos & ~(fmc->sector_size-1); /* end of last sector */
-
-                               if (start < test_start) {
-
-                                       /* free space started in the previous sector! */
-
-                                       if((num_free_space < NUMFREEALLOWED) && 
-                                          ((unsigned int)(test_start - start) >= fmc->sector_size)){
-
-                                               /*
-                                                 Count it in if we are still under NUMFREEALLOWED *and* it is 
-                                                 at least 1 erase sector in length. This will keep us from 
-                                                 picking any little ole' space as "free".
-                                               */
-                                         
-                                               D1(printk("Reducing end of free space to 0x%x from 0x%x\n",
-                                                         (unsigned int)test_start, (unsigned int)pos));
-
-                                               D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
-                                                         (unsigned int) start,
-                                                         (unsigned int)(test_start - start)));
-
-                                               /* below, space from "start" to "pos" will be marked dirty. */
-                                               start = test_start; 
-                                               
-                                               /* Being in here means that we have found at least an entire 
-                                                  erase sector size of free space ending on a sector boundary.
-                                                  Keep track of free spaces accepted.
-                                               */
-                                               num_free_space++;
-                                       }else{
-                                               num_free_spc_not_accp++;
-                                               D1(printk("Free space (#%i) found but *Not* accepted: Starting"
-                                                         " 0x%x for 0x%x bytes\n",
-                                                         num_free_spc_not_accp, (unsigned int)start, 
-                                                         (unsigned int)((unsigned int)(pos & ~(fmc->sector_size-1)) - (unsigned int)start)));
-                                               
-                                       }
-                                       
-                               }
-                               if((((__u32)(pos - start)) != 0)){
-
-                                       D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
-                                                 (unsigned int) start, (unsigned int) (pos - start)));
-                                       jffs_fmalloced(fmc, (__u32) start,
-                                                      (__u32) (pos - start), NULL);
-                               }else{
-                                       /* "Flipping bits" detected. This means that our scan for them
-                                          did not catch this offset. See check_partly_erased_sectors() for
-                                          more info.
-                                       */
-                                       
-                                       D1(printk("jffs_scan_flash():wants to allocate dirty flash "
-                                                 "space for 0 bytes.\n"));
-                                       D1(printk("jffs_scan_flash(): Flipping bits! We will free "
-                                                 "all allocated memory, erase this sector and remount\n"));
-
-                                       /* calculate start of present sector */
-                                       offset = (((__u32)pos)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-                                       
-                                       D1(printk("jffs_scan_flash():erasing sector starting 0x%x.\n",
-                                                 offset));
-                                       
-                                       if (flash_erase_region(fmc->mtd,
-                                                              offset, fmc->sector_size) < 0) {
-                                               printk(KERN_ERR "JFFS: Erase of flash failed. "
-                                                      "offset = %u, erase_size = %d\n",
-                                                      offset , fmc->sector_size);
-
-                                               flash_safe_release(fmc->mtd);
-                                               kfree(read_buf);
-                                               return -1; /* bad, bad, bad! */
-
-                                       }
-                                       flash_safe_release(fmc->mtd);
-                                       kfree(read_buf);
-
-                                       return -EAGAIN; /* erased offending sector. Try mount one more time please. */
-                               }
-                       }else{
-                               /* Being in here means that we have found free space that ends on an erase sector
-                                  boundary.
-                                  Count it in if we are still under NUMFREEALLOWED *and* it is at least 1 erase 
-                                  sector in length. This will keep us from picking any little ole' space as "free".
-                                */
-                                if((num_free_space < NUMFREEALLOWED) && 
-                                   ((unsigned int)(pos - start) >= fmc->sector_size)){
-                                          /* We really don't do anything to mark space as free, except *not* 
-                                             mark it dirty and just advance the "pos" location pointer. 
-                                             It will automatically be picked up as free space.
-                                           */ 
-                                          num_free_space++;
-                                          D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
-                                                    (unsigned int) start, (unsigned int) (pos - start)));
-                                }else{
-                                        num_free_spc_not_accp++;
-                                        D1(printk("Free space (#%i) found but *Not* accepted: Starting "
-                                                  "0x%x for 0x%x bytes\n", num_free_spc_not_accp, 
-                                                  (unsigned int) start, 
-                                                  (unsigned int) (pos - start)));
-                                        
-                                        /* Mark this space as dirty. We already have our free space. */
-                                        D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
-                                                  (unsigned int) start, (unsigned int) (pos - start)));
-                                        jffs_fmalloced(fmc, (__u32) start,
-                                                       (__u32) (pos - start), NULL);                                      
-                                }
-                                
-                       }
-                       if(num_free_space > NUMFREEALLOWED){
-                                printk(KERN_WARNING "jffs_scan_flash(): Found free space "
-                                       "number %i. Only %i free space is allowed.\n",
-                                       num_free_space, NUMFREEALLOWED);                              
-                       }
-                       continue;
-
-               case JFFS_DIRTY_BITMASK:
-                       /* We have found 0x00000000 at this position.  Scan as far
-                          as possible to find out how much is dirty.  */
-                       D1(printk("jffs_scan_flash(): 0x00000000 at pos 0x%lx.\n",
-                                 (long)pos));
-                       for (; pos < end
-                              && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos);
-                            pos += 4);
-                       D1(printk("jffs_scan_flash(): 0x00 ended at "
-                                 "pos 0x%lx.\n", (long)pos));
-                       jffs_fmalloced(fmc, (__u32) start,
-                                      (__u32) (pos - start), NULL);
-                       continue;
-
-               case JFFS_MAGIC_BITMASK:
-                       /* We have probably found a new raw inode.  */
-                       break;
-
-               default:
-               bad_inode:
-                       /* We're f*cked.  This is not solved yet.  We have
-                          to scan for the magic pattern.  */
-                       D1(printk("*************** Dirty flash memory or "
-                                 "bad inode: "
-                                 "hexdump(pos = 0x%lx, len = 128):\n",
-                                 (long)pos));
-                       D1(jffs_hexdump(fmc->mtd, pos, 128));
-
-                       for (pos += 4; pos < end; pos += 4) {
-                               switch (flash_read_u32(fmc->mtd, pos)) {
-                               case JFFS_MAGIC_BITMASK:
-                               case JFFS_EMPTY_BITMASK:
-                                       /* handle these in the main switch() loop */
-                                       goto cont_scan;
-
-                               default:
-                                       break;
-                               }
-                       }
-
-                       cont_scan:
-                       /* First, mark as dirty the region
-                          which really does contain crap. */
-                       jffs_fmalloced(fmc, (__u32) start,
-                                      (__u32) (pos - start),
-                                      NULL);
-                       
-                       continue;
-               }/* switch */
-
-               /* We have found the beginning of an inode.  Create a
-                  node for it unless there already is one available.  */
-               if (!node) {
-                       if (!(node = jffs_alloc_node())) {
-                               /* Free read buffer */
-                               kfree(read_buf);
-
-                               /* Release the flash device */
-                               flash_safe_release(fmc->mtd);
-       
-                               return -ENOMEM;
-                       }
-                       DJM(no_jffs_node++);
-               }
-
-               /* Read the next raw inode.  */
-
-               flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode,
-                               sizeof(struct jffs_raw_inode));
-
-               /* When we compute the checksum for the inode, we never
-                  count the 'accurate' or the 'checksum' fields.  */
-               tmp_accurate = raw_inode.accurate;
-               tmp_chksum = raw_inode.chksum;
-               raw_inode.accurate = 0;
-               raw_inode.chksum = 0;
-               checksum = jffs_checksum(&raw_inode,
-                                        sizeof(struct jffs_raw_inode));
-               raw_inode.accurate = tmp_accurate;
-               raw_inode.chksum = tmp_chksum;
-
-               D3(printk("*** We have found this raw inode at pos 0x%lx "
-                         "on the flash:\n", (long)pos));
-               D3(jffs_print_raw_inode(&raw_inode));
-
-               if (checksum != raw_inode.chksum) {
-                       D1(printk("jffs_scan_flash(): Bad checksum: "
-                                 "checksum = %u, "
-                                 "raw_inode.chksum = %u\n",
-                                 checksum, raw_inode.chksum));
-                       pos += sizeof(struct jffs_raw_inode);
-                       jffs_fmalloced(fmc, (__u32) start,
-                                      (__u32) (pos - start), NULL);
-                       /* Reuse this unused struct jffs_node.  */
-                       continue;
-               }
-
-               /* Check the raw inode read so far.  Start with the
-                  maximum length of the filename.  */
-               if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
-                       printk(KERN_WARNING "jffs_scan_flash: Found a "
-                              "JFFS node with name too large\n");
-                       goto bad_inode;
-               }
-
-               if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) {
-                       printk(KERN_WARNING "jffs_scan_flash: Found a "
-                              "rename node with dsize %u.\n",
-                              raw_inode.dsize);
-                       jffs_print_raw_inode(&raw_inode);
-                       goto bad_inode;
-               }
-
-               /* The node's data segment should not exceed a
-                  certain length.  */
-               if (raw_inode.dsize > fmc->max_chunk_size) {
-                       printk(KERN_WARNING "jffs_scan_flash: Found a "
-                              "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n",
-                              raw_inode.dsize, fmc->max_chunk_size);
-                       goto bad_inode;
-               }
-
-               pos += sizeof(struct jffs_raw_inode);
-
-               /* This shouldn't be necessary because a node that
-                  violates the flash boundaries shouldn't be written
-                  in the first place. */
-               if (pos >= end) {
-                       goto check_node;
-               }
-
-               /* Read the name.  */
-               *name = 0;
-               if (raw_inode.nsize) {
-                       flash_safe_read(fmc->mtd, pos, name, raw_inode.nsize);
-                       name[raw_inode.nsize] = '\0';
-                       pos += raw_inode.nsize
-                              + JFFS_GET_PAD_BYTES(raw_inode.nsize);
-                       D3(printk("name == \"%s\"\n", name));
-                       checksum = jffs_checksum(name, raw_inode.nsize);
-                       if (checksum != raw_inode.nchksum) {
-                               D1(printk("jffs_scan_flash(): Bad checksum: "
-                                         "checksum = %u, "
-                                         "raw_inode.nchksum = %u\n",
-                                         checksum, raw_inode.nchksum));
-                               jffs_fmalloced(fmc, (__u32) start,
-                                              (__u32) (pos - start), NULL);
-                               /* Reuse this unused struct jffs_node.  */
-                               continue;
-                       }
-                       if (pos >= end) {
-                               goto check_node;
-                       }
-               }
-
-               /* Read the data, if it exists, in order to be sure it
-                  matches the checksum.  */
-               if (raw_inode.dsize) {
-                       if (raw_inode.rename) {
-                               deleted_file = flash_read_u32(fmc->mtd, pos);
-                       }
-                       if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) {
-                               printk("jffs_checksum_flash() failed to calculate a checksum\n");
-                               jffs_fmalloced(fmc, (__u32) start,
-                                              (__u32) (pos - start), NULL);
-                               /* Reuse this unused struct jffs_node.  */
-                               continue;
-                       }                               
-                       pos += raw_inode.dsize
-                              + JFFS_GET_PAD_BYTES(raw_inode.dsize);
-
-                       if (checksum != raw_inode.dchksum) {
-                               D1(printk("jffs_scan_flash(): Bad checksum: "
-                                         "checksum = %u, "
-                                         "raw_inode.dchksum = %u\n",
-                                         checksum, raw_inode.dchksum));
-                               jffs_fmalloced(fmc, (__u32) start,
-                                              (__u32) (pos - start), NULL);
-                               /* Reuse this unused struct jffs_node.  */
-                               continue;
-                       }
-               }
-
-               check_node:
-
-               /* Remember the highest inode number in the whole file
-                  system.  This information will be used when assigning
-                  new files new inode numbers.  */
-               if (c->next_ino <= raw_inode.ino) {
-                       c->next_ino = raw_inode.ino + 1;
-               }
-
-               if (raw_inode.accurate) {
-                       int err;
-                       node->data_offset = raw_inode.offset;
-                       node->data_size = raw_inode.dsize;
-                       node->removed_size = raw_inode.rsize;
-                       /* Compute the offset to the actual data in the
-                          on-flash node.  */
-                       node->fm_offset
-                       = sizeof(struct jffs_raw_inode)
-                         + raw_inode.nsize
-                         + JFFS_GET_PAD_BYTES(raw_inode.nsize);
-                       node->fm = jffs_fmalloced(fmc, (__u32) start,
-                                                 (__u32) (pos - start),
-                                                 node);
-                       if (!node->fm) {
-                               D(printk("jffs_scan_flash(): !node->fm\n"));
-                               jffs_free_node(node);
-                               DJM(no_jffs_node--);
-
-                               /* Free read buffer */
-                               kfree(read_buf);
-
-                               /* Release the flash device */
-                               flash_safe_release(fmc->mtd);
-
-                               return -ENOMEM;
-                       }
-                       if ((err = jffs_insert_node(c, NULL, &raw_inode,
-                                                   name, node)) < 0) {
-                               printk("JFFS: Failed to handle raw inode. "
-                                      "(err = %d)\n", err);
-                               break;
-                       }
-                       if (raw_inode.rename) {
-                               struct jffs_delete_list *dl
-                               = (struct jffs_delete_list *)
-                                 kmalloc(sizeof(struct jffs_delete_list),
-                                         GFP_KERNEL);
-                               if (!dl) {
-                                       D(printk("jffs_scan_flash: !dl\n"));
-                                       jffs_free_node(node);
-                                       DJM(no_jffs_node--);
-
-                                       /* Release the flash device */
-                                       flash_safe_release(fmc->flash_part);
-
-                                       /* Free read buffer */
-                                       kfree(read_buf);
-
-                                       return -ENOMEM;
-                               }
-                               dl->ino = deleted_file;
-                               dl->next = c->delete_list;
-                               c->delete_list = dl;
-                               node->data_size = 0;
-                       }
-                       D3(jffs_print_node(node));
-                       node = NULL; /* Don't free the node!  */
-               }
-               else {
-                       jffs_fmalloced(fmc, (__u32) start,
-                                      (__u32) (pos - start), NULL);
-                       D3(printk("jffs_scan_flash(): Just found an obsolete "
-                                 "raw_inode. Continuing the scan...\n"));
-                       /* Reuse this unused struct jffs_node.  */
-               }
-       }
-
-       if (node) {
-               jffs_free_node(node);
-               DJM(no_jffs_node--);
-       }
-       jffs_build_end(fmc);
-
-       /* Free read buffer */
-       kfree(read_buf);
-
-       if(!num_free_space){
-               printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single "
-                      "chunk of free space. This is BAD!\n");
-       }
-
-       /* Return happy */
-       D3(printk("jffs_scan_flash(): Leaving...\n"));
-       flash_safe_release(fmc->mtd);
-
-       /* This is to trap the "free size accounting screwed error. */
-       free_chunk_size1 = jffs_free_size1(fmc);
-       free_chunk_size2 = jffs_free_size2(fmc);
-
-       if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
-
-               printk(KERN_WARNING "jffs_scan_falsh():Free size accounting screwed\n");
-               printk(KERN_WARNING "jfffs_scan_flash():free_chunk_size1 == 0x%x, "
-                      "free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", 
-                      free_chunk_size1, free_chunk_size2, fmc->free_size);
-
-               return -1; /* Do NOT mount f/s so that we can inspect what happened.
-                             Mounting this  screwed up f/s will screw us up anyway.
-                           */
-       }       
-
-       return 0; /* as far as we are concerned, we are happy! */
-} /* jffs_scan_flash()  */
-
-
-/* Insert any kind of node into the file system.  Take care of data
-   insertions and deletions.  Also remove redundant information. The
-   memory allocated for the `name' is regarded as "given away" in the
-   caller's perspective.  */
-int
-jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
-                const struct jffs_raw_inode *raw_inode,
-                const char *name, struct jffs_node *node)
-{
-       int update_name = 0;
-       int insert_into_tree = 0;
-
-       D2(printk("jffs_insert_node(): ino = %u, version = %u, "
-                 "name = \"%s\", deleted = %d\n",
-                 raw_inode->ino, raw_inode->version,
-                 ((name && *name) ? name : ""), raw_inode->deleted));
-
-       /* If there doesn't exist an associated jffs_file, then
-          create, initialize and insert one into the file system.  */
-       if (!f && !(f = jffs_find_file(c, raw_inode->ino))) {
-               if (!(f = jffs_create_file(c, raw_inode))) {
-                       return -ENOMEM;
-               }
-               jffs_insert_file_into_hash(f);
-               insert_into_tree = 1;
-       }
-       node->ino = raw_inode->ino;
-       node->version = raw_inode->version;
-       node->data_size = raw_inode->dsize;
-       node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode->nsize
-                         + JFFS_GET_PAD_BYTES(raw_inode->nsize);
-       node->name_size = raw_inode->nsize;
-
-       /* Now insert the node at the correct position into the file's
-          version list.  */
-       if (!f->version_head) {
-               /* This is the first node.  */
-               f->version_head = node;
-               f->version_tail = node;
-               node->version_prev = NULL;
-               node->version_next = NULL;
-               f->highest_version = node->version;
-               update_name = 1;
-               f->mode = raw_inode->mode;
-               f->uid = raw_inode->uid;
-               f->gid = raw_inode->gid;
-               f->atime = raw_inode->atime;
-               f->mtime = raw_inode->mtime;
-               f->ctime = raw_inode->ctime;
-       }
-       else if ((f->highest_version < node->version)
-                || (node->version == 0)) {
-               /* Insert at the end of the list.  I.e. this node is the
-                  newest one so far.  */
-               node->version_prev = f->version_tail;
-               node->version_next = NULL;
-               f->version_tail->version_next = node;
-               f->version_tail = node;
-               f->highest_version = node->version;
-               update_name = 1;
-               f->pino = raw_inode->pino;
-               f->mode = raw_inode->mode;
-               f->uid = raw_inode->uid;
-               f->gid = raw_inode->gid;
-               f->atime = raw_inode->atime;
-               f->mtime = raw_inode->mtime;
-               f->ctime = raw_inode->ctime;
-       }
-       else if (f->version_head->version > node->version) {
-               /* Insert at the bottom of the list.  */
-               node->version_prev = NULL;
-               node->version_next = f->version_head;
-               f->version_head->version_prev = node;
-               f->version_head = node;
-               if (!f->name) {
-                       update_name = 1;
-               }
-       }
-       else {
-               struct jffs_node *n;
-               int newer_name = 0;
-               /* Search for the insertion position starting from
-                  the tail (newest node).  */
-               for (n = f->version_tail; n; n = n->version_prev) {
-                       if (n->version < node->version) {
-                               node->version_prev = n;
-                               node->version_next = n->version_next;
-                               node->version_next->version_prev = node;
-                               n->version_next = node;
-                               if (!newer_name) {
-                                       update_name = 1;
-                               }
-                               break;
-                       }
-                       if (n->name_size) {
-                               newer_name = 1;
-                       }
-               }
-       }
-
-       /* Deletion is irreversible. If any 'deleted' node is ever
-          written, the file is deleted */
-       if (raw_inode->deleted)
-               f->deleted = raw_inode->deleted;
-
-       /* Perhaps update the name.  */
-       if (raw_inode->nsize && update_name && name && *name && (name != f->name)) {
-               if (f->name) {
-                       kfree(f->name);
-                       DJM(no_name--);
-               }
-               if (!(f->name = kmalloc(raw_inode->nsize + 1,
-                                                GFP_KERNEL))) {
-                       return -ENOMEM;
-               }
-               DJM(no_name++);
-               memcpy(f->name, name, raw_inode->nsize);
-               f->name[raw_inode->nsize] = '\0';
-               f->nsize = raw_inode->nsize;
-               D3(printk("jffs_insert_node(): Updated the name of "
-                         "the file to \"%s\".\n", name));
-       }
-
-       if (!c->building_fs) {
-               D3(printk("jffs_insert_node(): ---------------------------"
-                         "------------------------------------------- 1\n"));
-               if (insert_into_tree) {
-                       jffs_insert_file_into_tree(f);
-               }
-               /* Once upon a time, we would call jffs_possibly_delete_file()
-                  here. That causes an oops if someone's still got the file
-                  open, so now we only do it in jffs_delete_inode()
-                  -- dwmw2
-               */
-               if (node->data_size || node->removed_size) {
-                       jffs_update_file(f, node);
-               }
-               jffs_remove_redundant_nodes(f);
-
-               jffs_garbage_collect_trigger(c);
-
-               D3(printk("jffs_insert_node(): ---------------------------"
-                         "------------------------------------------- 2\n"));
-       }
-
-       return 0;
-} /* jffs_insert_node()  */
-
-
-/* Unlink a jffs_node from the version list it is in.  */
-static inline void
-jffs_unlink_node_from_version_list(struct jffs_file *f,
-                                  struct jffs_node *node)
-{
-       if (node->version_prev) {
-               node->version_prev->version_next = node->version_next;
-       } else {
-               f->version_head = node->version_next;
-       }
-       if (node->version_next) {
-               node->version_next->version_prev = node->version_prev;
-       } else {
-               f->version_tail = node->version_prev;
-       }
-}
-
-
-/* Unlink a jffs_node from the range list it is in.  */
-static inline void
-jffs_unlink_node_from_range_list(struct jffs_file *f, struct jffs_node *node)
-{
-       if (node->range_prev) {
-               node->range_prev->range_next = node->range_next;
-       }
-       else {
-               f->range_head = node->range_next;
-       }
-       if (node->range_next) {
-               node->range_next->range_prev = node->range_prev;
-       }
-       else {
-               f->range_tail = node->range_prev;
-       }
-}
-
-
-/* Function used by jffs_remove_redundant_nodes() below.  This function
-   classifies what kind of information a node adds to a file.  */
-static inline __u8
-jffs_classify_node(struct jffs_node *node)
-{
-       __u8 mod_type = JFFS_MODIFY_INODE;
-
-       if (node->name_size) {
-               mod_type |= JFFS_MODIFY_NAME;
-       }
-       if (node->data_size || node->removed_size) {
-               mod_type |= JFFS_MODIFY_DATA;
-       }
-       return mod_type;
-}
-
-
-/* Remove redundant nodes from a file.  Mark the on-flash memory
-   as dirty.  */
-static int
-jffs_remove_redundant_nodes(struct jffs_file *f)
-{
-       struct jffs_node *newest_node;
-       struct jffs_node *cur;
-       struct jffs_node *prev;
-       __u8 newest_type;
-       __u8 mod_type;
-       __u8 node_with_name_later = 0;
-
-       if (!(newest_node = f->version_tail)) {
-               return 0;
-       }
-
-       /* What does the `newest_node' modify?  */
-       newest_type = jffs_classify_node(newest_node);
-       node_with_name_later = newest_type & JFFS_MODIFY_NAME;
-
-       D3(printk("jffs_remove_redundant_nodes(): ino: %u, name: \"%s\", "
-                 "newest_type: %u\n", f->ino, (f->name ? f->name : ""),
-                 newest_type));
-
-       /* Traverse the file's nodes and determine which of them that are
-          superfluous.  Yeah, this might look very complex at first
-          glance but it is actually very simple.  */
-       for (cur = newest_node->version_prev; cur; cur = prev) {
-               prev = cur->version_prev;
-               mod_type = jffs_classify_node(cur);
-               if ((mod_type <= JFFS_MODIFY_INODE)
-                   || ((newest_type & JFFS_MODIFY_NAME)
-                       && (mod_type
-                           <= (JFFS_MODIFY_INODE + JFFS_MODIFY_NAME)))
-                   || (cur->data_size == 0 && cur->removed_size
-                       && !cur->version_prev && node_with_name_later)) {
-                       /* Yes, this node is redundant. Remove it.  */
-                       D2(printk("jffs_remove_redundant_nodes(): "
-                                 "Removing node: ino: %u, version: %u, "
-                                 "mod_type: %u\n", cur->ino, cur->version,
-                                 mod_type));
-                       jffs_unlink_node_from_version_list(f, cur);
-                       jffs_fmfree(f->c->fmc, cur->fm, cur);
-                       jffs_free_node(cur);
-                       DJM(no_jffs_node--);
-               }
-               else {
-                       node_with_name_later |= (mod_type & JFFS_MODIFY_NAME);
-               }
-       }
-
-       return 0;
-}
-
-
-/* Insert a file into the hash table.  */
-static int
-jffs_insert_file_into_hash(struct jffs_file *f)
-{
-       int i = f->ino % f->c->hash_len;
-
-       D3(printk("jffs_insert_file_into_hash(): f->ino: %u\n", f->ino));
-
-       list_add(&f->hash, &f->c->hash[i]);
-       return 0;
-}
-
-
-/* Insert a file into the file system tree.  */
-int
-jffs_insert_file_into_tree(struct jffs_file *f)
-{
-       struct jffs_file *parent;
-
-       D3(printk("jffs_insert_file_into_tree(): name: \"%s\"\n",
-                 (f->name ? f->name : "")));
-
-       if (!(parent = jffs_find_file(f->c, f->pino))) {
-               if (f->pino == 0) {
-                       f->c->root = f;
-                       f->parent = NULL;
-                       f->sibling_prev = NULL;
-                       f->sibling_next = NULL;
-                       return 0;
-               }
-               else {
-                       D1(printk("jffs_insert_file_into_tree(): Found "
-                                 "inode with no parent and pino == %u\n",
-                                 f->pino));
-                       return -1;
-               }
-       }
-       f->parent = parent;
-       f->sibling_next = parent->children;
-       if (f->sibling_next) {
-               f->sibling_next->sibling_prev = f;
-       }
-       f->sibling_prev = NULL;
-       parent->children = f;
-       return 0;
-}
-
-
-/* Remove a file from the hash table.  */
-static int
-jffs_unlink_file_from_hash(struct jffs_file *f)
-{
-       D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, "
-                 "ino %u\n", f, f->ino));
-
-       list_del(&f->hash);
-       return 0;
-}
-
-
-/* Just remove the file from the parent's children.  Don't free
-   any memory.  */
-int
-jffs_unlink_file_from_tree(struct jffs_file *f)
-{
-       D3(printk("jffs_unlink_file_from_tree(): ino: %d, pino: %d, name: "
-                 "\"%s\"\n", f->ino, f->pino, (f->name ? f->name : "")));
-
-       if (f->sibling_prev) {
-               f->sibling_prev->sibling_next = f->sibling_next;
-       }
-       else if (f->parent) {
-               D3(printk("f->parent=%p\n", f->parent));
-               f->parent->children = f->sibling_next;
-       }
-       if (f->sibling_next) {
-               f->sibling_next->sibling_prev = f->sibling_prev;
-       }
-       return 0;
-}
-
-
-/* Find a file with its inode number.  */
-struct jffs_file *
-jffs_find_file(struct jffs_control *c, __u32 ino)
-{
-       struct jffs_file *f;
-       int i = ino % c->hash_len;
-
-       D3(printk("jffs_find_file(): ino: %u\n", ino));
-
-       list_for_each_entry(f, &c->hash[i], hash) {
-               if (ino != f->ino)
-                       continue;
-               D3(printk("jffs_find_file(): Found file with ino "
-                              "%u. (name: \"%s\")\n",
-                              ino, (f->name ? f->name : ""));
-               );
-               return f;
-       }
-       D3(printk("jffs_find_file(): Didn't find file "
-                        "with ino %u.\n", ino);
-       );
-       return NULL;
-}
-
-
-/* Find a file in a directory.  We are comparing the names.  */
-struct jffs_file *
-jffs_find_child(struct jffs_file *dir, const char *name, int len)
-{
-       struct jffs_file *f;
-
-       D3(printk("jffs_find_child()\n"));
-
-       for (f = dir->children; f; f = f->sibling_next) {
-               if (!f->deleted && f->name
-                   && !strncmp(f->name, name, len)
-                   && f->name[len] == '\0') {
-                       break;
-               }
-       }
-
-       D3(if (f) {
-               printk("jffs_find_child(): Found \"%s\".\n", f->name);
-       }
-       else {
-               char *copy = kmalloc(len + 1, GFP_KERNEL);
-               if (copy) {
-                       memcpy(copy, name, len);
-                       copy[len] = '\0';
-               }
-               printk("jffs_find_child(): Didn't find the file \"%s\".\n",
-                      (copy ? copy : ""));
-               kfree(copy);
-       });
-
-       return f;
-}
-
-
-/* Write a raw inode that takes up a certain amount of space in the flash
-   memory.  At the end of the flash device, there is often space that is
-   impossible to use.  At these times we want to mark this space as not
-   used.  In the cases when the amount of space is greater or equal than
-   a struct jffs_raw_inode, we write a "dummy node" that takes up this
-   space.  The space after the raw inode, if it exists, is left as it is.
-   Since this space after the raw inode contains JFFS_EMPTY_BITMASK bytes,
-   we can compute the checksum of it; we don't have to manipulate it any
-   further.
-
-   If the space left on the device is less than the size of a struct
-   jffs_raw_inode, this space is filled with JFFS_DIRTY_BITMASK bytes.
-   No raw inode is written this time.  */
-static int
-jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-       int err;
-
-       D1(printk("jffs_write_dummy_node(): dirty_fm->offset = 0x%08x, "
-                 "dirty_fm->size = %u\n",
-                 dirty_fm->offset, dirty_fm->size));
-
-       if (dirty_fm->size >= sizeof(struct jffs_raw_inode)) {
-               struct jffs_raw_inode raw_inode;
-               memset(&raw_inode, 0, sizeof(struct jffs_raw_inode));
-               raw_inode.magic = JFFS_MAGIC_BITMASK;
-               raw_inode.dsize = dirty_fm->size
-                                 - sizeof(struct jffs_raw_inode);
-               raw_inode.dchksum = raw_inode.dsize * 0xff;
-               raw_inode.chksum
-               = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode));
-
-               if ((err = flash_safe_write(fmc->mtd,
-                                           dirty_fm->offset,
-                                           (u_char *)&raw_inode,
-                                           sizeof(struct jffs_raw_inode)))
-                   < 0) {
-                       printk(KERN_ERR "JFFS: jffs_write_dummy_node: "
-                              "flash_safe_write failed!\n");
-                       return err;
-               }
-       }
-       else {
-               flash_safe_acquire(fmc->mtd);
-               flash_memset(fmc->mtd, dirty_fm->offset, 0, dirty_fm->size);
-               flash_safe_release(fmc->mtd);
-       }
-
-       D3(printk("jffs_write_dummy_node(): Leaving...\n"));
-       return 0;
-}
-
-
-/* Write a raw inode, possibly its name and possibly some data.  */
-int
-jffs_write_node(struct jffs_control *c, struct jffs_node *node,
-               struct jffs_raw_inode *raw_inode,
-               const char *name, const unsigned char *data,
-               int recoverable,
-               struct jffs_file *f)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-       struct jffs_fm *fm;
-       struct kvec node_iovec[4];
-       unsigned long iovec_cnt;
-
-       __u32 pos;
-       int err;
-       __u32 slack = 0;
-
-       __u32 total_name_size = raw_inode->nsize
-                               + JFFS_GET_PAD_BYTES(raw_inode->nsize);
-       __u32 total_data_size = raw_inode->dsize
-                               + JFFS_GET_PAD_BYTES(raw_inode->dsize);
-       __u32 total_size = sizeof(struct jffs_raw_inode)
-                          + total_name_size + total_data_size;
-       
-       /* If this node isn't something that will eventually let
-          GC free even more space, then don't allow it unless
-          there's at least max_chunk_size space still available
-       */
-       if (!recoverable)
-               slack = fmc->max_chunk_size;
-               
-
-       /* Fire the retrorockets and shoot the fruiton torpedoes, sir!  */
-
-       ASSERT(if (!node) {
-               printk("jffs_write_node(): node == NULL\n");
-               return -EINVAL;
-       });
-       ASSERT(if (raw_inode && raw_inode->nsize && !name) {
-               printk("*** jffs_write_node(): nsize = %u but name == NULL\n",
-                      raw_inode->nsize);
-               return -EINVAL;
-       });
-
-       D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, "
-                 "total_size = %u\n",
-                 (name ? name : ""), raw_inode->ino,
-                 total_size));
-
-       jffs_fm_write_lock(fmc);
-
-retry:
-       fm = NULL;
-       err = 0;
-       while (!fm) {
-
-               /* Deadlocks suck. */
-               while(fmc->free_size < fmc->min_free_size + total_size + slack) {
-                       jffs_fm_write_unlock(fmc);
-                       if (!JFFS_ENOUGH_SPACE(c, total_size + slack))
-                               return -ENOSPC;
-                       jffs_fm_write_lock(fmc);
-               }
-
-               /* First try to allocate some flash memory.  */
-               err = jffs_fmalloc(fmc, total_size, node, &fm);
-               
-               if (err == -ENOSPC) {
-                       /* Just out of space. GC and try again */
-                       if (fmc->dirty_size < fmc->sector_size) {
-                               D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
-                                        "failed, no dirty space to GC\n", fmc,
-                                        total_size));
-                               return err;
-                       }
-                       
-                       D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n"));
-                       jffs_fm_write_unlock(fmc);
-                       if ((err = jffs_garbage_collect_now(c))) {
-                               D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n"));
-                               return err;
-                       }
-                       jffs_fm_write_lock(fmc);
-                       continue;
-               } 
-
-               if (err < 0) {
-                       jffs_fm_write_unlock(fmc);
-
-                       D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
-                                "failed!\n", fmc, total_size));
-                       return err;
-               }
-
-               if (!fm->nodes) {
-                       /* The jffs_fm struct that we got is not good enough.
-                          Make that space dirty and try again  */
-                       if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-                               kfree(fm);
-                               DJM(no_jffs_fm--);
-                               jffs_fm_write_unlock(fmc);
-                               D(printk("jffs_write_node(): "
-                                        "jffs_write_dummy_node(): Failed!\n"));
-                               return err;
-                       }
-                       fm = NULL;
-               }
-       } /* while(!fm) */
-       node->fm = fm;
-
-       ASSERT(if (fm->nodes == 0) {
-               printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n");
-       });
-
-       pos = node->fm->offset;
-
-       /* Increment the version number here. We can't let the caller
-          set it beforehand, because we might have had to do GC on a node
-          of this file - and we'd end up reusing version numbers.
-       */
-       if (f) {
-               raw_inode->version = f->highest_version + 1;
-               D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version));
-
-               /* if the file was deleted, set the deleted bit in the raw inode */
-               if (f->deleted)
-                       raw_inode->deleted = 1;
-       }
-
-       /* Compute the checksum for the data and name chunks.  */
-       raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize);
-       raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize);
-
-       /* The checksum is calculated without the chksum and accurate
-          fields so set them to zero first.  */
-       raw_inode->accurate = 0;
-       raw_inode->chksum = 0;
-       raw_inode->chksum = jffs_checksum(raw_inode,
-                                         sizeof(struct jffs_raw_inode));
-       raw_inode->accurate = 0xff;
-
-       D3(printk("jffs_write_node(): About to write this raw inode to the "
-                 "flash at pos 0x%lx:\n", (long)pos));
-       D3(jffs_print_raw_inode(raw_inode));
-
-       /* The actual raw JFFS node */
-       node_iovec[0].iov_base = (void *) raw_inode;
-       node_iovec[0].iov_len = (size_t) sizeof(struct jffs_raw_inode);
-       iovec_cnt = 1;
-
-       /* Get name and size if there is one */
-       if (raw_inode->nsize) {
-               node_iovec[iovec_cnt].iov_base = (void *) name;
-               node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->nsize;
-               iovec_cnt++;
-
-               if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) {
-                       static unsigned char allff[3]={255,255,255};
-                       /* Add some extra padding if necessary */
-                       node_iovec[iovec_cnt].iov_base = allff;
-                       node_iovec[iovec_cnt].iov_len =
-                               JFFS_GET_PAD_BYTES(raw_inode->nsize);
-                       iovec_cnt++;
-               }
-       }
-
-       /* Get data and size if there is any */
-       if (raw_inode->dsize) {
-               node_iovec[iovec_cnt].iov_base = (void *) data;
-               node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->dsize;
-               iovec_cnt++;
-               /* No need to pad this because we're not actually putting
-                  anything after it.
-               */
-       }
-
-       if ((err = flash_safe_writev(fmc->mtd, node_iovec, iovec_cnt,
-                                   pos)) < 0) {
-               jffs_fmfree_partly(fmc, fm, 0);
-               jffs_fm_write_unlock(fmc);
-               printk(KERN_ERR "JFFS: jffs_write_node: Failed to write, "
-                      "requested %i, wrote %i\n", total_size, err);
-               goto retry;
-       }
-       if (raw_inode->deleted)
-               f->deleted = 1;
-
-       jffs_fm_write_unlock(fmc);
-       D3(printk("jffs_write_node(): Leaving...\n"));
-       return raw_inode->dsize;
-} /* jffs_write_node()  */
-
-
-/* Read data from the node and write it to the buffer.  'node_offset'
-   is how much we have read from this particular node before and which
-   shouldn't be read again.  'max_size' is how much space there is in
-   the buffer.  */
-static int
-jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, 
-                  unsigned char *buf,__u32 node_offset, __u32 max_size)
-{
-       struct jffs_fmcontrol *fmc = f->c->fmc;
-       __u32 pos = node->fm->offset + node->fm_offset + node_offset;
-       __u32 avail = node->data_size - node_offset;
-       __u32 r;
-
-       D2(printk("  jffs_get_node_data(): file: \"%s\", ino: %u, "
-                 "version: %u, node_offset: %u\n",
-                 f->name, node->ino, node->version, node_offset));
-
-       r = min(avail, max_size);
-       D3(printk(KERN_NOTICE "jffs_get_node_data\n"));
-       flash_safe_read(fmc->mtd, pos, buf, r);
-
-       D3(printk("  jffs_get_node_data(): Read %u byte%s.\n",
-                 r, (r == 1 ? "" : "s")));
-
-       return r;
-}
-
-
-/* Read data from the file's nodes.  Write the data to the buffer
-   'buf'.  'read_offset' tells how much data we should skip.  */
-int
-jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset,
-              __u32 size)
-{
-       struct jffs_node *node;
-       __u32 read_data = 0; /* Total amount of read data.  */
-       __u32 node_offset = 0;
-       __u32 pos = 0; /* Number of bytes traversed.  */
-
-       D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
-                 "size = %u\n",
-                 (f->name ? f->name : ""), read_offset, size));
-
-       if (read_offset >= f->size) {
-               D(printk("  f->size: %d\n", f->size));
-               return 0;
-       }
-
-       /* First find the node to read data from.  */
-       node = f->range_head;
-       while (pos <= read_offset) {
-               node_offset = read_offset - pos;
-               if (node_offset >= node->data_size) {
-                       pos += node->data_size;
-                       node = node->range_next;
-               }
-               else {
-                       break;
-               }
-       }
-
-       /* "Cats are living proof that not everything in nature
-          has to be useful."
-          - Garrison Keilor ('97)  */
-
-       /* Fill the buffer.  */
-       while (node && (read_data < size)) {
-               int r;
-               if (!node->fm) {
-                       /* This node does not refer to real data.  */
-                       r = min(size - read_data,
-                                    node->data_size - node_offset);
-                       memset(&buf[read_data], 0, r);
-               }
-               else if ((r = jffs_get_node_data(f, node, &buf[read_data],
-                                                node_offset,
-                                                size - read_data)) < 0) {
-                       return r;
-               }
-               read_data += r;
-               node_offset = 0;
-               node = node->range_next;
-       }
-       D3(printk("  jffs_read_data(): Read %u bytes.\n", read_data));
-       return read_data;
-}
-
-
-/* Used for traversing all nodes in the hash table.  */
-int
-jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
-{
-       int pos;
-       int r;
-       int result = 0;
-
-       for (pos = 0; pos < c->hash_len; pos++) {
-               struct jffs_file *f, *next;
-
-               /* We must do _safe, because 'func' might remove the
-                  current file 'f' from the list.  */
-               list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
-                       r = func(f);
-                       if (r < 0)
-                               return r;
-                       result += r;
-               }
-       }
-
-       return result;
-}
-
-
-/* Free all nodes associated with a file.  */
-static int
-jffs_free_node_list(struct jffs_file *f)
-{
-       struct jffs_node *node;
-       struct jffs_node *p;
-
-       D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n",
-                 f->ino, (f->name ? f->name : "")));
-       node = f->version_head;
-       while (node) {
-               p = node;
-               node = node->version_next;
-               jffs_free_node(p);
-               DJM(no_jffs_node--);
-       }
-       return 0;
-}
-
-
-/* Free a file and its name.  */
-static int
-jffs_free_file(struct jffs_file *f)
-{
-       D3(printk("jffs_free_file: f #%u, \"%s\"\n",
-                 f->ino, (f->name ? f->name : "")));
-
-       if (f->name) {
-               kfree(f->name);
-               DJM(no_name--);
-       }
-       kfree(f);
-       no_jffs_file--;
-       return 0;
-}
-
-static long
-jffs_get_file_count(void)
-{
-       return no_jffs_file;
-}
-
-/* See if a file is deleted. If so, mark that file's nodes as obsolete.  */
-int
-jffs_possibly_delete_file(struct jffs_file *f)
-{
-       struct jffs_node *n;
-
-       D3(printk("jffs_possibly_delete_file(): ino: %u\n",
-                 f->ino));
-
-       ASSERT(if (!f) {
-               printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n");
-               return -1;
-       });
-
-       if (f->deleted) {
-               /* First try to remove all older versions.  Commence with
-                  the oldest node.  */
-               for (n = f->version_head; n; n = n->version_next) {
-                       if (!n->fm) {
-                               continue;
-                       }
-                       if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) {
-                               break;
-                       }
-               }
-               /* Unlink the file from the filesystem.  */
-               if (!f->c->building_fs) {
-                       jffs_unlink_file_from_tree(f);
-               }
-               jffs_unlink_file_from_hash(f);
-               jffs_free_node_list(f);
-               jffs_free_file(f);
-       }
-       return 0;
-}
-
-
-/* Used in conjunction with jffs_foreach_file() to count the number
-   of files in the file system.  */
-int
-jffs_file_count(struct jffs_file *f)
-{
-       return 1;
-}
-
-
-/* Build up a file's range list from scratch by going through the
-   version list.  */
-static int
-jffs_build_file(struct jffs_file *f)
-{
-       struct jffs_node *n;
-
-       D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n",
-                 f->ino, (f->name ? f->name : "")));
-
-       for (n = f->version_head; n; n = n->version_next) {
-               jffs_update_file(f, n);
-       }
-       return 0;
-}
-
-
-/* Remove an amount of data from a file. If this amount of data is
-   zero, that could mean that a node should be split in two parts.
-   We remove or change the appropriate nodes in the lists.
-
-   Starting offset of area to be removed is node->data_offset,
-   and the length of the area is in node->removed_size.   */
-static int
-jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
-{
-       struct jffs_node *n;
-       __u32 offset = node->data_offset;
-       __u32 remove_size = node->removed_size;
-
-       D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n",
-                 offset, remove_size));
-
-       if (remove_size == 0
-           && f->range_tail
-           && f->range_tail->data_offset + f->range_tail->data_size
-              == offset) {
-               /* A simple append; nothing to remove or no node to split.  */
-               return 0;
-       }
-
-       /* Find the node where we should begin the removal.  */
-       for (n = f->range_head; n; n = n->range_next) {
-               if (n->data_offset + n->data_size > offset) {
-                       break;
-               }
-       }
-       if (!n) {
-               /* If there's no data in the file there's no data to
-                  remove either.  */
-               return 0;
-       }
-
-       if (n->data_offset > offset) {
-               /* XXX: Not implemented yet.  */
-               printk(KERN_WARNING "JFFS: An unexpected situation "
-                      "occurred in jffs_delete_data.\n");
-       }
-       else if (n->data_offset < offset) {
-               /* See if the node has to be split into two parts.  */
-               if (n->data_offset + n->data_size > offset + remove_size) {
-                       /* Do the split.  */
-                       struct jffs_node *new_node;
-                       D3(printk("jffs_delete_data(): Split node with "
-                                 "version number %u.\n", n->version));
-
-                       if (!(new_node = jffs_alloc_node())) {
-                               D(printk("jffs_delete_data(): -ENOMEM\n"));
-                               return -ENOMEM;
-                       }
-                       DJM(no_jffs_node++);
-
-                       new_node->ino = n->ino;
-                       new_node->version = n->version;
-                       new_node->data_offset = offset;
-                       new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset));
-                       new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset));
-                       new_node->name_size = n->name_size;
-                       new_node->fm = n->fm;
-                       new_node->version_prev = n;
-                       new_node->version_next = n->version_next;
-                       if (new_node->version_next) {
-                               new_node->version_next->version_prev
-                               = new_node;
-                       }
-                       else {
-                               f->version_tail = new_node;
-                       }
-                       n->version_next = new_node;
-                       new_node->range_prev = n;
-                       new_node->range_next = n->range_next;
-                       if (new_node->range_next) {
-                               new_node->range_next->range_prev = new_node;
-                       }
-                       else {
-                               f->range_tail = new_node;
-                       }
-                       /* A very interesting can of worms.  */
-                       n->range_next = new_node;
-                       n->data_size = offset - n->data_offset;
-                       if (new_node->fm)
-                               jffs_add_node(new_node);
-                       else {
-                               D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!"));
-                               D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n"));
-                       }
-                       n = new_node->range_next;
-                       remove_size = 0;
-               }
-               else {
-                       /* No.  No need to split the node.  Just remove
-                          the end of the node.  */
-                       int r = min(n->data_offset + n->data_size
-                                        - offset, remove_size);
-                       n->data_size -= r;
-                       remove_size -= r;
-                       n = n->range_next;
-               }
-       }
-
-       /* Remove as many nodes as necessary.  */
-       while (n && remove_size) {
-               if (n->data_size <= remove_size) {
-                       struct jffs_node *p = n;
-                       remove_size -= n->data_size;
-                       n = n->range_next;
-                       D3(printk("jffs_delete_data(): Removing node: "
-                                 "ino: %u, version: %u%s\n",
-                                 p->ino, p->version,
-                                 (p->fm ? "" : " (virtual)")));
-                       if (p->fm) {
-                               jffs_fmfree(f->c->fmc, p->fm, p);
-                       }
-                       jffs_unlink_node_from_range_list(f, p);
-                       jffs_unlink_node_from_version_list(f, p);
-                       jffs_free_node(p);
-                       DJM(no_jffs_node--);
-               }
-               else {
-                       n->data_size -= remove_size;
-                       n->fm_offset += remove_size;
-                       n->data_offset -= (node->removed_size - remove_size);
-                       n = n->range_next;
-                       break;
-               }
-       }
-
-       /* Adjust the following nodes' information about offsets etc.  */
-       while (n && node->removed_size) {
-               n->data_offset -= node->removed_size;
-               n = n->range_next;
-       }
-
-       if (node->removed_size > (f->size - node->data_offset)) {
-               /* It's possible that the removed_size is in fact
-                * greater than the amount of data we actually thought
-                * were present in the first place - some of the nodes 
-                * which this node originally obsoleted may already have
-                * been deleted from the flash by subsequent garbage 
-                * collection.
-                *
-                * If this is the case, don't let f->size go negative.
-                * Bad things would happen :)
-                */
-               f->size = node->data_offset;
-       } else {
-               f->size -= node->removed_size;
-       }
-       D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
-       return 0;
-} /* jffs_delete_data()  */
-
-
-/* Insert some data into a file.  Prior to the call to this function,
-   jffs_delete_data should be called.  */
-static int
-jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
-{
-       D3(printk("jffs_insert_data(): node->data_offset = %u, "
-                 "node->data_size = %u, f->size = %u\n",
-                 node->data_offset, node->data_size, f->size));
-
-       /* Find the position where we should insert data.  */
-       retry:
-       if (node->data_offset == f->size) {
-               /* A simple append.  This is the most common operation.  */
-               node->range_next = NULL;
-               node->range_prev = f->range_tail;
-               if (node->range_prev) {
-                       node->range_prev->range_next = node;
-               }
-               f->range_tail = node;
-               f->size += node->data_size;
-               if (!f->range_head) {
-                       f->range_head = node;
-               }
-       }
-       else if (node->data_offset < f->size) {
-               /* Trying to insert data into the middle of the file.  This
-                  means no problem because jffs_delete_data() has already
-                  prepared the range list for us.  */
-               struct jffs_node *n;
-
-               /* Find the correct place for the insertion and then insert
-                  the node.  */
-               for (n = f->range_head; n; n = n->range_next) {
-                       D2(printk("Cool stuff's happening!\n"));
-
-                       if (n->data_offset == node->data_offset) {
-                               node->range_prev = n->range_prev;
-                               if (node->range_prev) {
-                                       node->range_prev->range_next = node;
-                               }
-                               else {
-                                       f->range_head = node;
-                               }
-                               node->range_next = n;
-                               n->range_prev = node;
-                               break;
-                       }
-                       ASSERT(else if (n->data_offset + n->data_size >
-                                       node->data_offset) {
-                               printk(KERN_ERR "jffs_insert_data(): "
-                                      "Couldn't find a place to insert "
-                                      "the data!\n");
-                               return -1;
-                       });
-               }
-
-               /* Adjust later nodes' offsets etc.  */
-               n = node->range_next;
-               while (n) {
-                       n->data_offset += node->data_size;
-                       n = n->range_next;
-               }
-               f->size += node->data_size;
-       }
-       else if (node->data_offset > f->size) {
-               /* Okay.  This is tricky.  This means that we want to insert
-                  data at a place that is beyond the limits of the file as
-                  it is constructed right now.  This is actually a common
-                  event that for instance could occur during the mounting
-                  of the file system if a large file have been truncated,
-                  rewritten and then only partially garbage collected.  */
-
-               struct jffs_node *n;
-
-               /* We need a place holder for the data that is missing in
-                  front of this insertion.  This "virtual node" will not
-                  be associated with any space on the flash device.  */
-               struct jffs_node *virtual_node;
-               if (!(virtual_node = jffs_alloc_node())) {
-                       return -ENOMEM;
-               }
-
-               D(printk("jffs_insert_data: Inserting a virtual node.\n"));
-               D(printk("  node->data_offset = %u\n", node->data_offset));
-               D(printk("  f->size = %u\n", f->size));
-
-               virtual_node->ino = node->ino;
-               virtual_node->version = node->version;
-               virtual_node->removed_size = 0;
-               virtual_node->fm_offset = 0;
-               virtual_node->name_size = 0;
-               virtual_node->fm = NULL; /* This is a virtual data holder.  */
-               virtual_node->version_prev = NULL;
-               virtual_node->version_next = NULL;
-               virtual_node->range_next = NULL;
-
-               /* Are there any data at all in the file yet?  */
-               if (f->range_head) {
-                       virtual_node->data_offset
-                       = f->range_tail->data_offset
-                         + f->range_tail->data_size;
-                       virtual_node->data_size
-                       = node->data_offset - virtual_node->data_offset;
-                       virtual_node->range_prev = f->range_tail;
-                       f->range_tail->range_next = virtual_node;
-               }
-               else {
-                       virtual_node->data_offset = 0;
-                       virtual_node->data_size = node->data_offset;
-                       virtual_node->range_prev = NULL;
-                       f->range_head = virtual_node;
-               }
-
-               f->range_tail = virtual_node;
-               f->size += virtual_node->data_size;
-
-               /* Insert this virtual node in the version list as well.  */
-               for (n = f->version_head; n ; n = n->version_next) {
-                       if (n->version == virtual_node->version) {
-                               virtual_node->version_prev = n->version_prev;
-                               n->version_prev = virtual_node;
-                               if (virtual_node->version_prev) {
-                                       virtual_node->version_prev
-                                       ->version_next = virtual_node;
-                               }
-                               else {
-                                       f->version_head = virtual_node;
-                               }
-                               virtual_node->version_next = n;
-                               break;
-                       }
-               }
-
-               D(jffs_print_node(virtual_node));
-
-               /* Make a new try to insert the node.  */
-               goto retry;
-       }
-
-       D3(printk("jffs_insert_data(): f->size = %d\n", f->size));
-       return 0;
-}
-
-
-/* A new node (with data) has been added to the file and now the range
-   list has to be modified.  */
-static int
-jffs_update_file(struct jffs_file *f, struct jffs_node *node)
-{
-       int err;
-
-       D3(printk("jffs_update_file(): ino: %u, version: %u\n",
-                 f->ino, node->version));
-
-       if (node->data_size == 0) {
-               if (node->removed_size == 0) {
-                       /* data_offset == X  */
-                       /* data_size == 0  */
-                       /* remove_size == 0  */
-               }
-               else {
-                       /* data_offset == X  */
-                       /* data_size == 0  */
-                       /* remove_size != 0  */
-                       if ((err = jffs_delete_data(f, node)) < 0) {
-                               return err;
-                       }
-               }
-       }
-       else {
-               /* data_offset == X  */
-               /* data_size != 0  */
-               /* remove_size == Y  */
-               if ((err = jffs_delete_data(f, node)) < 0) {
-                       return err;
-               }
-               if ((err = jffs_insert_data(f, node)) < 0) {
-                       return err;
-               }
-       }
-       return 0;
-}
-
-/* Print the contents of a file.  */
-#if 0
-int
-jffs_print_file(struct jffs_file *f)
-{
-       D(int i);
-       D(printk("jffs_file: 0x%p\n", f));
-       D(printk("{\n"));
-       D(printk("        0x%08x, /* ino  */\n", f->ino));
-       D(printk("        0x%08x, /* pino  */\n", f->pino));
-       D(printk("        0x%08x, /* mode  */\n", f->mode));
-       D(printk("        0x%04x,     /* uid  */\n", f->uid));
-       D(printk("        0x%04x,     /* gid  */\n", f->gid));
-       D(printk("        0x%08x, /* atime  */\n", f->atime));
-       D(printk("        0x%08x, /* mtime  */\n", f->mtime));
-       D(printk("        0x%08x, /* ctime  */\n", f->ctime));
-       D(printk("        0x%02x,       /* nsize  */\n", f->nsize));
-       D(printk("        0x%02x,       /* nlink  */\n", f->nlink));
-       D(printk("        0x%02x,       /* deleted  */\n", f->deleted));
-       D(printk("        \"%s\", ", (f->name ? f->name : "")));
-       D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) {
-               printk(" ");
-       });
-       D(printk("/* name  */\n"));
-       D(printk("        0x%08x, /* size  */\n", f->size));
-       D(printk("        0x%08x, /* highest_version  */\n",
-                f->highest_version));
-       D(printk("        0x%p, /* c  */\n", f->c));
-       D(printk("        0x%p, /* parent  */\n", f->parent));
-       D(printk("        0x%p, /* children  */\n", f->children));
-       D(printk("        0x%p, /* sibling_prev  */\n", f->sibling_prev));
-       D(printk("        0x%p, /* sibling_next  */\n", f->sibling_next));
-       D(printk("        0x%p, /* hash_prev  */\n", f->hash.prev));
-       D(printk("        0x%p, /* hash_next  */\n", f->hash.next));
-       D(printk("        0x%p, /* range_head  */\n", f->range_head));
-       D(printk("        0x%p, /* range_tail  */\n", f->range_tail));
-       D(printk("        0x%p, /* version_head  */\n", f->version_head));
-       D(printk("        0x%p, /* version_tail  */\n", f->version_tail));
-       D(printk("}\n"));
-       return 0;
-}
-#endif  /*  0  */
-
-void
-jffs_print_hash_table(struct jffs_control *c)
-{
-       int i;
-
-       printk("JFFS: Dumping the file system's hash table...\n");
-       for (i = 0; i < c->hash_len; i++) {
-               struct jffs_file *f;
-               list_for_each_entry(f, &c->hash[i], hash) {
-                       printk("*** c->hash[%u]: \"%s\" "
-                              "(ino: %u, pino: %u)\n",
-                              i, (f->name ? f->name : ""),
-                              f->ino, f->pino);
-               }
-       }
-}
-
-
-void
-jffs_print_tree(struct jffs_file *first_file, int indent)
-{
-       struct jffs_file *f;
-       char *space;
-       int dir;
-
-       if (!first_file) {
-               return;
-       }
-
-       if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
-               printk("jffs_print_tree(): Out of memory!\n");
-               return;
-       }
-
-       memset(space, ' ', indent);
-       space[indent] = '\0';
-
-       for (f = first_file; f; f = f->sibling_next) {
-               dir = S_ISDIR(f->mode);
-               printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n",
-                      space, (f->name ? f->name : ""), (dir ? "/" : ""),
-                      f->ino, f->highest_version, f->size);
-               if (dir) {
-                       jffs_print_tree(f->children, indent + 2);
-               }
-       }
-
-       kfree(space);
-}
-
-
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-void
-jffs_print_memory_allocation_statistics(void)
-{
-       static long printout;
-       printk("________ Memory printout #%ld ________\n", ++printout);
-       printk("no_jffs_file = %ld\n", no_jffs_file);
-       printk("no_jffs_node = %ld\n", no_jffs_node);
-       printk("no_jffs_control = %ld\n", no_jffs_control);
-       printk("no_jffs_raw_inode = %ld\n", no_jffs_raw_inode);
-       printk("no_jffs_node_ref = %ld\n", no_jffs_node_ref);
-       printk("no_jffs_fm = %ld\n", no_jffs_fm);
-       printk("no_jffs_fmcontrol = %ld\n", no_jffs_fmcontrol);
-       printk("no_hash = %ld\n", no_hash);
-       printk("no_name = %ld\n", no_name);
-       printk("\n");
-}
-#endif
-
-
-/* Rewrite `size' bytes, and begin at `node'.  */
-static int
-jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size)
-{
-       struct jffs_control *c = f->c;
-       struct jffs_fmcontrol *fmc = c->fmc;
-       struct jffs_raw_inode raw_inode;
-       struct jffs_node *new_node;
-       struct jffs_fm *fm;
-       __u32 pos;
-       __u32 pos_dchksum;
-       __u32 total_name_size;
-       __u32 total_data_size;
-       __u32 total_size;
-       int err;
-
-       D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n",
-                 f->ino, (f->name ? f->name : "(null)"), size));
-
-       /* Create and initialize the new node.  */
-       if (!(new_node = jffs_alloc_node())) {
-               D(printk("jffs_rewrite_data(): "
-                        "Failed to allocate node.\n"));
-               return -ENOMEM;
-       }
-       DJM(no_jffs_node++);
-       new_node->data_offset = node->data_offset;
-       new_node->removed_size = size;
-       total_name_size = JFFS_PAD(f->nsize);
-       total_data_size = JFFS_PAD(size);
-       total_size = sizeof(struct jffs_raw_inode)
-                    + total_name_size + total_data_size;
-       new_node->fm_offset = sizeof(struct jffs_raw_inode)
-                             + total_name_size;
-
-retry:
-       jffs_fm_write_lock(fmc);
-       err = 0;
-
-       if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
-               DJM(no_jffs_node--);
-               jffs_fm_write_unlock(fmc);
-               D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
-               jffs_free_node(new_node);
-               return err;
-       }
-       else if (!fm->nodes) {
-               /* The jffs_fm struct that we got is not big enough.  */
-               /* This should never happen, because we deal with this case
-                  in jffs_garbage_collect_next().*/
-               printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size);
-               if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-                       D(printk("jffs_rewrite_data(): "
-                                "jffs_write_dummy_node() Failed!\n"));
-               } else {
-                       err = -ENOSPC;
-               }
-               DJM(no_jffs_fm--);
-               jffs_fm_write_unlock(fmc);
-               kfree(fm);
-               
-               return err;
-       }
-       new_node->fm = fm;
-
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = f->ino;
-       raw_inode.pino = f->pino;
-       raw_inode.version = f->highest_version + 1;
-       raw_inode.mode = f->mode;
-       raw_inode.uid = f->uid;
-       raw_inode.gid = f->gid;
-       raw_inode.atime = f->atime;
-       raw_inode.mtime = f->mtime;
-       raw_inode.ctime = f->ctime;
-       raw_inode.offset = node->data_offset;
-       raw_inode.dsize = size;
-       raw_inode.rsize = size;
-       raw_inode.nsize = f->nsize;
-       raw_inode.nlink = f->nlink;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = f->deleted;
-       raw_inode.accurate = 0xff;
-       raw_inode.dchksum = 0;
-       raw_inode.nchksum = 0;
-
-       pos = new_node->fm->offset;
-       pos_dchksum = pos +JFFS_RAW_INODE_DCHKSUM_OFFSET;
-
-       D3(printk("jffs_rewrite_data(): Writing this raw inode "
-                 "to pos 0x%ul.\n", pos));
-       D3(jffs_print_raw_inode(&raw_inode));
-
-       if ((err = flash_safe_write(fmc->mtd, pos,
-                                   (u_char *) &raw_inode,
-                                   sizeof(struct jffs_raw_inode)
-                                   - sizeof(__u32)
-                                   - sizeof(__u16) - sizeof(__u16))) < 0) {
-               jffs_fmfree_partly(fmc, fm,
-                                  total_name_size + total_data_size);
-               jffs_fm_write_unlock(fmc);
-               printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-                       "rewrite. (raw inode)\n");
-               printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
-                       "rewrite. (raw inode)\n");
-               goto retry;
-       }
-       pos += sizeof(struct jffs_raw_inode);
-
-       /* Write the name to the flash memory.  */
-       if (f->nsize) {
-               D3(printk("jffs_rewrite_data(): Writing name \"%s\" to "
-                         "pos 0x%ul.\n", f->name, (unsigned int) pos));
-               if ((err = flash_safe_write(fmc->mtd, pos,
-                                           (u_char *)f->name,
-                                           f->nsize)) < 0) {
-                       jffs_fmfree_partly(fmc, fm, total_data_size);
-                       jffs_fm_write_unlock(fmc);
-                       printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
-                               "error during rewrite. (name)\n");
-                       printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
-                               "rewrite. (name)\n");
-                       goto retry;
-               }
-               pos += total_name_size;
-               raw_inode.nchksum = jffs_checksum(f->name, f->nsize);
-       }
-
-       /* Write the data.  */
-       if (size) {
-               int r;
-               unsigned char *page;
-               __u32 offset = node->data_offset;
-
-               if (!(page = (unsigned char *)__get_free_page(GFP_KERNEL))) {
-                       jffs_fmfree_partly(fmc, fm, 0);
-                       return -1;
-               }
-
-               while (size) {
-                       __u32 s = min(size, (__u32)PAGE_SIZE);
-                       if ((r = jffs_read_data(f, (char *)page,
-                                               offset, s)) < s) {
-                               free_page((unsigned long)page);
-                               jffs_fmfree_partly(fmc, fm, 0);
-                               jffs_fm_write_unlock(fmc);
-                               printk(KERN_ERR "JFFS: jffs_rewrite_data: "
-                                        "jffs_read_data() "
-                                        "failed! (r = %d)\n", r);
-                               return -1;
-                       }
-                       if ((err = flash_safe_write(fmc->mtd,
-                                                   pos, page, r)) < 0) {
-                               free_page((unsigned long)page);
-                               jffs_fmfree_partly(fmc, fm, 0);
-                               jffs_fm_write_unlock(fmc);
-                               printk(KERN_ERR "JFFS: jffs_rewrite_data: "
-                                      "Write error during rewrite. "
-                                      "(data)\n");
-                               goto retry;
-                       }
-                       pos += r;
-                       size -= r;
-                       offset += r;
-                       raw_inode.dchksum += jffs_checksum(page, r);
-               }
-
-               free_page((unsigned long)page);
-       }
-
-       raw_inode.accurate = 0;
-       raw_inode.chksum = jffs_checksum(&raw_inode,
-                                        sizeof(struct jffs_raw_inode)
-                                        - sizeof(__u16));
-
-       /* Add the checksum.  */
-       if ((err
-            = flash_safe_write(fmc->mtd, pos_dchksum,
-                               &((u_char *)
-                               &raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
-                               sizeof(__u32) + sizeof(__u16)
-                               + sizeof(__u16))) < 0) {
-               jffs_fmfree_partly(fmc, fm, 0);
-               jffs_fm_write_unlock(fmc);
-               printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-                      "rewrite. (checksum)\n");
-               goto retry;
-       }
-
-       /* Now make the file system aware of the newly written node.  */
-       jffs_insert_node(c, f, &raw_inode, f->name, new_node);
-       jffs_fm_write_unlock(fmc);
-
-       D3(printk("jffs_rewrite_data(): Leaving...\n"));
-       return 0;
-} /* jffs_rewrite_data()  */
-
-
-/* jffs_garbage_collect_next implements one step in the garbage collect
-   process and is often called multiple times at each occasion of a
-   garbage collect.  */
-
-static int
-jffs_garbage_collect_next(struct jffs_control *c)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-       struct jffs_node *node;
-       struct jffs_file *f;
-       int err = 0;
-       __u32 size;
-       __u32 data_size;
-       __u32 total_name_size;
-       __u32 extra_available;
-       __u32 space_needed;
-       __u32 free_chunk_size1 = jffs_free_size1(fmc);
-       D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
-
-       /* Get the oldest node in the flash.  */
-       node = jffs_get_oldest_node(fmc);
-       ASSERT(if (!node) {
-               printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                      "No oldest node found!\n");
-                err = -1;
-                goto jffs_garbage_collect_next_end;
-               
-
-       });
-
-       /* Find its corresponding file too.  */
-       f = jffs_find_file(c, node->ino);
-
-       if (!f) {
-         printk (KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                  "No file to garbage collect! "
-                 "(ino = 0x%08x)\n", node->ino);
-          /* FIXME: Free the offending node and recover. */
-          err = -1;
-          goto jffs_garbage_collect_next_end;
-       }
-
-       /* We always write out the name. Theoretically, we don't need
-          to, but for now it's easier - because otherwise we'd have
-          to keep track of how many times the current name exists on
-          the flash and make sure it never reaches zero.
-
-          The current approach means that would be possible to cause
-          the GC to end up eating its tail by writing lots of nodes
-          with no name for it to garbage-collect. Hence the change in
-          inode.c to write names with _every_ node.
-
-          It sucks, but it _should_ work.
-       */
-       total_name_size = JFFS_PAD(f->nsize);
-
-       D1(printk("jffs_garbage_collect_next(): \"%s\", "
-                 "ino: %u, version: %u, location 0x%x, dsize %u\n",
-                 (f->name ? f->name : ""), node->ino, node->version, 
-                 node->fm->offset, node->data_size));
-
-       /* Compute how many data it's possible to rewrite at the moment.  */
-       data_size = f->size - node->data_offset;
-
-       /* And from that, the total size of the chunk we want to write */
-       size = sizeof(struct jffs_raw_inode) + total_name_size
-              + data_size + JFFS_GET_PAD_BYTES(data_size);
-
-       /* If that's more than max_chunk_size, reduce it accordingly */
-       if (size > fmc->max_chunk_size) {
-               size = fmc->max_chunk_size;
-               data_size = size - sizeof(struct jffs_raw_inode)
-                           - total_name_size;
-       }
-
-       /* If we're asking to take up more space than free_chunk_size1
-          but we _could_ fit in it, shrink accordingly.
-       */
-       if (size > free_chunk_size1) {
-
-               if (free_chunk_size1 <
-                   (sizeof(struct jffs_raw_inode) + total_name_size + BLOCK_SIZE)){
-                       /* The space left is too small to be of any
-                          use really.  */
-                       struct jffs_fm *dirty_fm
-                       = jffs_fmalloced(fmc,
-                                        fmc->tail->offset + fmc->tail->size,
-                                        free_chunk_size1, NULL);
-                       if (!dirty_fm) {
-                               printk(KERN_ERR "JFFS: "
-                                      "jffs_garbage_collect_next: "
-                                      "Failed to allocate `dirty' "
-                                      "flash memory!\n");
-                               err = -1;
-                                goto jffs_garbage_collect_next_end;
-                       }
-                       D1(printk("Dirtying end of flash - too small\n"));
-                       jffs_write_dummy_node(c, dirty_fm);
-                        err = 0;
-                       goto jffs_garbage_collect_next_end;
-               }
-               D1(printk("Reducing size of new node from %d to %d to avoid "
-                         " exceeding free_chunk_size1\n",
-                         size, free_chunk_size1));
-
-               size = free_chunk_size1;
-               data_size = size - sizeof(struct jffs_raw_inode)
-                           - total_name_size;
-       }
-
-
-       /* Calculate the amount of space needed to hold the nodes
-          which are remaining in the tail */
-       space_needed = fmc->min_free_size - (node->fm->offset % fmc->sector_size);
-
-       /* From that, calculate how much 'extra' space we can use to
-          increase the size of the node we're writing from the size
-          of the node we're obsoleting
-       */
-       if (space_needed > fmc->free_size) {
-               /* If we've gone below min_free_size for some reason,
-                  don't fuck up. This is why we have 
-                  min_free_size > sector_size. Whinge about it though,
-                  just so I can convince myself my maths is right.
-               */
-               D1(printk(KERN_WARNING "jffs_garbage_collect_next(): "
-                         "space_needed %d exceeded free_size %d\n",
-                         space_needed, fmc->free_size));
-               extra_available = 0;
-       } else {
-               extra_available = fmc->free_size - space_needed;
-       }
-
-       /* Check that we don't use up any more 'extra' space than
-          what's available */
-       if (size > JFFS_PAD(node->data_size) + total_name_size + 
-           sizeof(struct jffs_raw_inode) + extra_available) {
-               D1(printk("Reducing size of new node from %d to %ld to avoid "
-                      "catching our tail\n", size, 
-                         (long) (JFFS_PAD(node->data_size) + JFFS_PAD(node->name_size) + 
-                         sizeof(struct jffs_raw_inode) + extra_available)));
-               D1(printk("space_needed = %d, extra_available = %d\n", 
-                         space_needed, extra_available));
-
-               size = JFFS_PAD(node->data_size) + total_name_size + 
-                 sizeof(struct jffs_raw_inode) + extra_available;
-               data_size = size - sizeof(struct jffs_raw_inode)
-                       - total_name_size;
-       };
-
-       D2(printk("  total_name_size: %u\n", total_name_size));
-       D2(printk("  data_size: %u\n", data_size));
-       D2(printk("  size: %u\n", size));
-       D2(printk("  f->nsize: %u\n", f->nsize));
-       D2(printk("  f->size: %u\n", f->size));
-       D2(printk("  node->data_offset: %u\n", node->data_offset));
-       D2(printk("  free_chunk_size1: %u\n", free_chunk_size1));
-       D2(printk("  free_chunk_size2: %u\n", free_chunk_size2));
-       D2(printk("  node->fm->offset: 0x%08x\n", node->fm->offset));
-
-       if ((err = jffs_rewrite_data(f, node, data_size))) {
-               printk(KERN_WARNING "jffs_rewrite_data() failed: %d\n", err);
-               return err;
-       }
-         
-jffs_garbage_collect_next_end:
-       D3(printk("jffs_garbage_collect_next: Leaving...\n"));
-       return err;
-} /* jffs_garbage_collect_next */
-
-
-/* If an obsolete node is partly going to be erased due to garbage
-   collection, the part that isn't going to be erased must be filled
-   with zeroes so that the scan of the flash will work smoothly next
-   time.  (The data in the file could for instance be a JFFS image
-   which could cause enormous confusion during a scan of the flash
-   device if we didn't do this.)
-     There are two phases in this procedure: First, the clearing of
-   the name and data parts of the node. Second, possibly also clearing
-   a part of the raw inode as well.  If the box is power cycled during
-   the first phase, only the checksum of this node-to-be-cleared-at-
-   the-end will be wrong.  If the box is power cycled during, or after,
-   the clearing of the raw inode, the information like the length of
-   the name and data parts are zeroed.  The next time the box is
-   powered up, the scanning algorithm manages this faulty data too
-   because:
-
-   - The checksum is invalid and thus the raw inode must be discarded
-     in any case.
-   - If the lengths of the data part or the name part are zeroed, the
-     scanning just continues after the raw inode.  But after the inode
-     the scanning procedure just finds zeroes which is the same as
-     dirt.
-
-   So, in the end, this could never fail. :-)  Even if it does fail,
-   the scanning algorithm should manage that too.  */
-
-static int
-jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size)
-{
-       struct jffs_fm *fm;
-       struct jffs_fmcontrol *fmc = c->fmc;
-       __u32 zero_offset;
-       __u32 zero_size;
-       __u32 zero_offset_data;
-       __u32 zero_size_data;
-       __u32 cutting_raw_inode = 0;
-
-       if (!(fm = jffs_cut_node(fmc, erase_size))) {
-               D3(printk("jffs_clear_end_of_node(): fm == NULL\n"));
-               return 0;
-       }
-
-       /* Where and how much shall we clear?  */
-       zero_offset = fmc->head->offset + erase_size;
-       zero_size = fm->offset + fm->size - zero_offset;
-
-       /* Do we have to clear the raw_inode explicitly?  */
-       if (fm->size - zero_size < sizeof(struct jffs_raw_inode)) {
-               cutting_raw_inode = sizeof(struct jffs_raw_inode)
-                                   - (fm->size - zero_size);
-       }
-
-       /* First, clear the name and data fields.  */
-       zero_offset_data = zero_offset + cutting_raw_inode;
-       zero_size_data = zero_size - cutting_raw_inode;
-       flash_safe_acquire(fmc->mtd);
-       flash_memset(fmc->mtd, zero_offset_data, 0, zero_size_data);
-       flash_safe_release(fmc->mtd);
-
-       /* Should we clear a part of the raw inode?  */
-       if (cutting_raw_inode) {
-               /* I guess it is ok to clear the raw inode in this order.  */
-               flash_safe_acquire(fmc->mtd);
-               flash_memset(fmc->mtd, zero_offset, 0,
-                            cutting_raw_inode);
-               flash_safe_release(fmc->mtd);
-       }
-
-       return 0;
-} /* jffs_clear_end_of_node()  */
-
-/* Try to erase as much as possible of the dirt in the flash memory.  */
-static long
-jffs_try_to_erase(struct jffs_control *c)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-       long erase_size;
-       int err;
-       __u32 offset;
-
-       D3(printk("jffs_try_to_erase()\n"));
-
-       erase_size = jffs_erasable_size(fmc);
-
-       D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size));
-
-       if (erase_size == 0) {
-               return 0;
-       }
-       else if (erase_size < 0) {
-               printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-                      "jffs_erasable_size returned %ld.\n", erase_size);
-               return erase_size;
-       }
-
-       if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
-               printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-                      "Clearing of node failed.\n");
-               return err;
-       }
-
-       offset = fmc->head->offset;
-
-       /* Now, let's try to do the erase.  */
-       if ((err = flash_erase_region(fmc->mtd,
-                                     offset, erase_size)) < 0) {
-               printk(KERN_ERR "JFFS: Erase of flash failed. "
-                      "offset = %u, erase_size = %ld\n",
-                      offset, erase_size);
-               /* XXX: Here we should allocate this area as dirty
-                  with jffs_fmalloced or something similar.  Now
-                  we just report the error.  */
-               return err;
-       }
-
-#if 0
-       /* Check if the erased sectors really got erased.  */
-       {
-               __u32 pos;
-               __u32 end;
-
-               pos = (__u32)flash_get_direct_pointer(to_kdev_t(c->sb->s_dev), offset);
-               end = pos + erase_size;
-
-               D2(printk("JFFS: Checking erased sector(s)...\n"));
-
-               flash_safe_acquire(fmc->mtd);
-
-               for (; pos < end; pos += 4) {
-                       if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) {
-                               printk("JFFS: Erase failed! pos = 0x%lx\n",
-                                      (long)pos);
-                               jffs_hexdump(fmc->mtd, pos,
-                                            jffs_min(256, end - pos));
-                               err = -1;
-                               break;
-                       }
-               }
-
-               flash_safe_release(fmc->mtd);
-
-               if (!err) {
-                       D2(printk("JFFS: Erase succeeded.\n"));
-               }
-               else {
-                       /* XXX: Here we should allocate the memory
-                          with jffs_fmalloced() in order to prevent
-                          JFFS from using this area accidentally.  */
-                       return err;
-               }
-       }
-#endif
-
-       /* Update the flash memory data structures.  */
-       jffs_sync_erase(fmc, erase_size);
-
-       return erase_size;
-}
-
-
-/* There are different criteria that should trigger a garbage collect:
-
-   1. There is too much dirt in the memory.
-   2. The free space is becoming small.
-   3. There are many versions of a node.
-
-   The garbage collect should always be done in a manner that guarantees
-   that future garbage collects cannot be locked.  E.g. Rewritten chunks
-   should not be too large (span more than one sector in the flash memory
-   for exemple).  Of course there is a limit on how intelligent this garbage
-   collection can be.  */
-
-
-static int
-jffs_garbage_collect_now(struct jffs_control *c)
-{
-       struct jffs_fmcontrol *fmc = c->fmc;
-       long erased = 0;
-       int result = 0;
-       D1(int i = 1);
-       D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u, fmc->free_size = 0x%x\n, fcs1=0x%x, fcs2=0x%x",
-                 fmc->dirty_size, fmc->free_size, jffs_free_size1(fmc), jffs_free_size2(fmc)));
-       D2(jffs_print_fmcontrol(fmc));
-
-       //      down(&fmc->gclock);
-
-       /* If it is possible to garbage collect, do so.  */
-       
-       while (erased == 0) {
-               D1(printk("***jffs_garbage_collect_now(): round #%u, "
-                         "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
-               D2(jffs_print_fmcontrol(fmc));
-
-               if ((erased = jffs_try_to_erase(c)) < 0) {
-                       printk(KERN_WARNING "JFFS: Error in "
-                              "garbage collector.\n");
-                       result = erased;
-                       goto gc_end;
-               }
-               if (erased)
-                       break;
-               
-               if (fmc->free_size == 0) {
-                       /* Argh */
-                       printk(KERN_ERR "jffs_garbage_collect_now(): free_size == 0. This is BAD.\n");
-                       result = -ENOSPC;
-                       break;
-               }
-
-               if (fmc->dirty_size < fmc->sector_size) {
-                       /* Actually, we _may_ have been able to free some, 
-                        * if there are many overlapping nodes which aren't
-                        * actually marked dirty because they still have
-                        * some valid data in each.
-                        */
-                       result = -ENOSPC;
-                       break;
-               }
-
-               /* Let's dare to make a garbage collect.  */
-               if ((result = jffs_garbage_collect_next(c)) < 0) {
-                       printk(KERN_ERR "JFFS: Something "
-                              "has gone seriously wrong "
-                              "with a garbage collect.\n");
-                       goto gc_end;
-               }
-
-               D1(printk("   jffs_garbage_collect_now(): erased: %ld\n", erased));
-               DJM(jffs_print_memory_allocation_statistics());
-       }
-       
-gc_end:
-       //      up(&fmc->gclock);
-
-       D3(printk("   jffs_garbage_collect_now(): Leaving...\n"));
-       D1(if (erased) {
-               printk("jffs_g_c_now(): erased = %ld\n", erased);
-               jffs_print_fmcontrol(fmc);
-       });
-
-       if (!erased && !result)
-               return -ENOSPC;
-
-       return result;
-} /* jffs_garbage_collect_now() */
-
-
-/* Determine if it is reasonable to start garbage collection.
-   We start a gc pass if either:
-   - The number of free bytes < MIN_FREE_BYTES && at least one
-     block is dirty, OR
-   - The number of dirty bytes > MAX_DIRTY_BYTES
-*/
-static inline int thread_should_wake (struct jffs_control *c)
-{
-       D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n",
-                  c->fmc->free_size, c->fmc->dirty_size, c->fmc->sector_size));
-
-       /* If there's not enough dirty space to free a block, there's no point. */
-       if (c->fmc->dirty_size < c->fmc->sector_size) {
-               D2(printk(KERN_NOTICE "thread_should_wake(): Not waking. Insufficient dirty space\n"));
-               return 0;
-       }
-#if 1
-       /* If there is too much RAM used by the various structures, GC */
-       if (jffs_get_node_inuse() > (c->fmc->used_size/c->fmc->max_chunk_size * 5 + jffs_get_file_count() * 2 + 50)) {
-               /* FIXME: Provide proof that this test can be satisfied. We
-                  don't want a filesystem doing endless GC just because this
-                  condition cannot ever be false.
-               */
-               D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to number of nodes\n"));
-               return 1;
-       }
-#endif
-       /* If there are fewer free bytes than the threshold, GC */
-       if (c->fmc->free_size < c->gc_minfree_threshold) {
-               D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to insufficent free space\n"));
-               return 1;
-       }
-       /* If there are more dirty bytes than the threshold, GC */
-       if (c->fmc->dirty_size > c->gc_maxdirty_threshold) {
-               D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to excessive dirty space\n"));
-               return 1;
-       }       
-       /* FIXME: What about the "There are many versions of a node" condition? */
-
-       return 0;
-}
-
-
-void jffs_garbage_collect_trigger(struct jffs_control *c)
-{
-       /* NOTE: We rely on the fact that we have the BKL here.
-        * Otherwise, the gc_task could go away between the check
-        * and the wake_up_process()
-        */
-       if (c->gc_task && thread_should_wake(c))
-               send_sig(SIGHUP, c->gc_task, 1);
-}
-  
-
-/* Kernel threads  take (void *) as arguments.   Thus we pass
-   the jffs_control data as a (void *) and then cast it. */
-int
-jffs_garbage_collect_thread(void *ptr)
-{
-        struct jffs_control *c = (struct jffs_control *) ptr;
-       struct jffs_fmcontrol *fmc = c->fmc;
-       long erased;
-       int result = 0;
-       D1(int i = 1);
-
-       daemonize("jffs_gcd");
-
-       c->gc_task = current;
-
-       lock_kernel();
-       init_completion(&c->gc_thread_comp); /* barrier */ 
-       spin_lock_irq(&current->sighand->siglock);
-       siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
-
-       for (;;) {
-
-               /* See if we need to start gc.  If we don't, go to sleep.
-                  
-                  Current implementation is a BAD THING(tm).  If we try 
-                  to unmount the FS, the unmount operation will sleep waiting
-                  for this thread to exit.  We need to arrange to send it a
-                  sig before the umount process sleeps.
-               */
-
-               if (!thread_should_wake(c))
-                       set_current_state (TASK_INTERRUPTIBLE);
-               
-               schedule(); /* Yes, we do this even if we want to go
-                                      on immediately - we're a low priority 
-                                      background task. */
-
-               /* Put_super will send a SIGKILL and then wait on the sem. 
-                */
-               while (signal_pending(current)) {
-                       siginfo_t info;
-                       unsigned long signr = 0;
-
-                       if (try_to_freeze())
-                               continue;
-
-                       spin_lock_irq(&current->sighand->siglock);
-                       signr = dequeue_signal(current, &current->blocked, &info);
-                       spin_unlock_irq(&current->sighand->siglock);
-
-                       switch(signr) {
-                       case SIGSTOP:
-                               D1(printk("jffs_garbage_collect_thread(): SIGSTOP received.\n"));
-                               set_current_state(TASK_STOPPED);
-                               schedule();
-                               break;
-
-                       case SIGKILL:
-                               D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n"));
-                               c->gc_task = NULL;
-                               complete_and_exit(&c->gc_thread_comp, 0);
-                       }
-               }
-
-
-               D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
-
-               D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n"));
-               mutex_lock(&fmc->biglock);
-               
-               D1(printk("***jffs_garbage_collect_thread(): round #%u, "
-                         "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
-               D2(jffs_print_fmcontrol(fmc));
-
-               if ((erased = jffs_try_to_erase(c)) < 0) {
-                       printk(KERN_WARNING "JFFS: Error in "
-                              "garbage collector: %ld.\n", erased);
-               }
-
-               if (erased)
-                       goto gc_end;
-
-               if (fmc->free_size == 0) {
-                       /* Argh. Might as well commit suicide. */
-                       printk(KERN_ERR "jffs_garbage_collect_thread(): free_size == 0. This is BAD.\n");
-                       send_sig(SIGQUIT, c->gc_task, 1);
-                       // panic()
-                       goto gc_end;
-               }
-               
-               /* Let's dare to make a garbage collect.  */
-               if ((result = jffs_garbage_collect_next(c)) < 0) {
-                       printk(KERN_ERR "JFFS: Something "
-                              "has gone seriously wrong "
-                              "with a garbage collect: %d\n", result);
-               }
-               
-       gc_end:
-               D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n"));
-               mutex_unlock(&fmc->biglock);
-       } /* for (;;) */
-} /* jffs_garbage_collect_thread() */
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
deleted file mode 100644 (file)
index 5c7abe0..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: intrep.h,v 1.14 2001/09/23 23:28:37 dwmw2 Exp $
- *
- */
-
-#ifndef __LINUX_JFFS_INTREP_H__
-#define __LINUX_JFFS_INTREP_H__
-#include "jffs_fm.h"
-struct jffs_node *jffs_alloc_node(void);
-void jffs_free_node(struct jffs_node *n);
-int jffs_get_node_inuse(void);
-
-void jffs_cleanup_control(struct jffs_control *c);
-int jffs_build_fs(struct super_block *sb);
-
-int jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
-                    const struct jffs_raw_inode *raw_inode,
-                    const char *name, struct jffs_node *node);
-struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino);
-struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len);
-
-void jffs_free_node(struct jffs_node *node);
-
-int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
-int jffs_possibly_delete_file(struct jffs_file *f);
-int jffs_insert_file_into_tree(struct jffs_file *f);
-int jffs_unlink_file_from_tree(struct jffs_file *f);
-int jffs_file_count(struct jffs_file *f);
-
-int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
-                   struct jffs_raw_inode *raw_inode,
-                   const char *name, const unsigned char *buf,
-                   int recoverable, struct jffs_file *f);
-int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size);
-
-/* Garbage collection stuff.  */
-int jffs_garbage_collect_thread(void *c);
-void jffs_garbage_collect_trigger(struct jffs_control *c);
-
-/* For debugging purposes.  */
-#if 0
-int jffs_print_file(struct jffs_file *f);
-#endif  /*  0  */
-void jffs_print_hash_table(struct jffs_control *c);
-void jffs_print_tree(struct jffs_file *first_file, int indent);
-
-#endif /* __LINUX_JFFS_INTREP_H__  */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
deleted file mode 100644 (file)
index 5a95fbd..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/blkdev.h>
-#include <linux/jffs.h>
-#include "jffs_fm.h"
-#include "intrep.h"
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
-#endif
-
-static struct jffs_fm *jffs_alloc_fm(void);
-static void jffs_free_fm(struct jffs_fm *n);
-
-extern struct kmem_cache     *fm_cache;
-extern struct kmem_cache     *node_cache;
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void
-jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
-{
-       D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
-       D(printk("{\n"));
-       D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
-       D(printk("        %u, /* used_size  */\n", fmc->used_size));
-       D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
-       D(printk("        %u, /* free_size  */\n", fmc->free_size));
-       D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
-       D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
-       D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
-       D(printk("        0x%p, /* mtd  */\n", fmc->mtd));
-       D(printk("        0x%p, /* head  */    "
-                "(head->offset = 0x%08x)\n",
-                fmc->head, (fmc->head ? fmc->head->offset : 0)));
-       D(printk("        0x%p, /* tail  */    "
-                "(tail->offset + tail->size = 0x%08x)\n",
-                fmc->tail,
-                (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
-       D(printk("        0x%p, /* head_extra  */\n", fmc->head_extra));
-       D(printk("        0x%p, /* tail_extra  */\n", fmc->tail_extra));
-       D(printk("}\n"));
-}
-#endif  /*  CONFIG_JFFS_FS_VERBOSE > 0  */
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-static void
-jffs_print_fm(struct jffs_fm *fm)
-{
-       D(printk("struct jffs_fm: 0x%p\n", fm));
-       D(printk("{\n"));
-       D(printk("       0x%08x, /* offset  */\n", fm->offset));
-       D(printk("       %u, /* size  */\n", fm->size));
-       D(printk("       0x%p, /* prev  */\n", fm->prev));
-       D(printk("       0x%p, /* next  */\n", fm->next));
-       D(printk("       0x%p, /* nodes  */\n", fm->nodes));
-       D(printk("}\n"));
-}
-#endif  /*  CONFIG_JFFS_FS_VERBOSE > 2  */
-
-#if 0
-void
-jffs_print_node_ref(struct jffs_node_ref *ref)
-{
-       D(printk("struct jffs_node_ref: 0x%p\n", ref));
-       D(printk("{\n"));
-       D(printk("       0x%p, /* node  */\n", ref->node));
-       D(printk("       0x%p, /* next  */\n", ref->next));
-       D(printk("}\n"));
-}
-#endif  /*  0  */
-
-/* This function creates a new shiny flash memory control structure.  */
-struct jffs_fmcontrol *
-jffs_build_begin(struct jffs_control *c, int unit)
-{
-       struct jffs_fmcontrol *fmc;
-       struct mtd_info *mtd;
-       
-       D3(printk("jffs_build_begin()\n"));
-       fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
-       if (!fmc) {
-               D(printk("jffs_build_begin(): Allocation of "
-                        "struct jffs_fmcontrol failed!\n"));
-               return (struct jffs_fmcontrol *)0;
-       }
-       DJM(no_jffs_fmcontrol++);
-
-       mtd = get_mtd_device(NULL, unit);
-
-       if (IS_ERR(mtd)) {
-               kfree(fmc);
-               DJM(no_jffs_fmcontrol--);
-               return NULL;
-       }
-       
-       /* Retrieve the size of the flash memory.  */
-       fmc->flash_size = mtd->size;
-       D3(printk("  fmc->flash_size = %d bytes\n", fmc->flash_size));
-
-       fmc->used_size = 0;
-       fmc->dirty_size = 0;
-       fmc->free_size = mtd->size;
-       fmc->sector_size = mtd->erasesize;
-       fmc->max_chunk_size = fmc->sector_size >> 1;
-       /* min_free_size:
-          1 sector, obviously.
-          + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
-          + 1 x max_chunk_size again, which ought to be enough to handle 
-                  the case where a rename causes a name to grow, and GC has
-                  to write out larger nodes than the ones it's obsoleting.
-                  We should fix it so it doesn't have to write the name
-                  _every_ time. Later.
-          + another 2 sectors because people keep getting GC stuck and
-                  we don't know why. This scares me - I want formal proof
-                  of correctness of whatever number we put here. dwmw2.
-       */
-       fmc->min_free_size = fmc->sector_size << 2;
-       fmc->mtd = mtd;
-       fmc->c = c;
-       fmc->head = NULL;
-       fmc->tail = NULL;
-       fmc->head_extra = NULL;
-       fmc->tail_extra = NULL;
-       mutex_init(&fmc->biglock);
-       return fmc;
-}
-
-
-/* When the flash memory scan has completed, this function should be called
-   before use of the control structure.  */
-void
-jffs_build_end(struct jffs_fmcontrol *fmc)
-{
-       D3(printk("jffs_build_end()\n"));
-
-       if (!fmc->head) {
-               fmc->head = fmc->head_extra;
-               fmc->tail = fmc->tail_extra;
-       }
-       else if (fmc->head_extra) {
-               fmc->tail_extra->next = fmc->head;
-               fmc->head->prev = fmc->tail_extra;
-               fmc->head = fmc->head_extra;
-       }
-       fmc->head_extra = NULL; /* These two instructions should be omitted.  */
-       fmc->tail_extra = NULL;
-       D3(jffs_print_fmcontrol(fmc));
-}
-
-
-/* Call this function when the file system is unmounted.  This function
-   frees all memory used by this module.  */
-void
-jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
-{
-       if (fmc) {
-               struct jffs_fm *next = fmc->head;
-               while (next) {
-                       struct jffs_fm *cur = next;
-                       next = next->next;
-                       jffs_free_fm(cur);
-               }
-               put_mtd_device(fmc->mtd);
-               kfree(fmc);
-               DJM(no_jffs_fmcontrol--);
-       }
-}
-
-
-/* This function returns the size of the first chunk of free space on the
-   flash memory.  This function will return something nonzero if the flash
-   memory contains any free space.  */
-__u32
-jffs_free_size1(struct jffs_fmcontrol *fmc)
-{
-       __u32 head;
-       __u32 tail;
-       __u32 end = fmc->flash_size;
-
-       if (!fmc->head) {
-               /* There is nothing on the flash.  */
-               return fmc->flash_size;
-       }
-
-       /* Compute the beginning and ending of the contents of the flash.  */
-       head = fmc->head->offset;
-       tail = fmc->tail->offset + fmc->tail->size;
-       if (tail == end) {
-               tail = 0;
-       }
-       ASSERT(else if (tail > end) {
-               printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
-               tail = 0;
-       });
-
-       if (head <= tail) {
-               return end - tail;
-       }
-       else {
-               return head - tail;
-       }
-}
-
-/* This function will return something nonzero in case there are two free
-   areas on the flash.  Like this:
-
-     +----------------+------------------+----------------+
-     |     FREE 1     |   USED / DIRTY   |     FREE 2     |
-     +----------------+------------------+----------------+
-       fmc->head -----^
-       fmc->tail ------------------------^
-
-   The value returned, will be the size of the first empty area on the
-   flash, in this case marked "FREE 1".  */
-__u32
-jffs_free_size2(struct jffs_fmcontrol *fmc)
-{
-       if (fmc->head) {
-               __u32 head = fmc->head->offset;
-               __u32 tail = fmc->tail->offset + fmc->tail->size;
-               if (tail == fmc->flash_size) {
-                       tail = 0;
-               }
-
-               if (tail >= head) {
-                       return head;
-               }
-       }
-       return 0;
-}
-
-
-/* Allocate a chunk of flash memory.  If there is enough space on the
-   device, a reference to the associated node is stored in the jffs_fm
-   struct.  */
-int
-jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
-            struct jffs_fm **result)
-{
-       struct jffs_fm *fm;
-       __u32 free_chunk_size1;
-       __u32 free_chunk_size2;
-
-       D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
-                 "node = 0x%p\n", fmc, size, node));
-
-       *result = NULL;
-
-       if (!(fm = jffs_alloc_fm())) {
-               D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
-               return -ENOMEM;
-       }
-
-       free_chunk_size1 = jffs_free_size1(fmc);
-       free_chunk_size2 = jffs_free_size2(fmc);
-       if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
-               printk(KERN_WARNING "Free size accounting screwed\n");
-               printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
-       }
-
-       D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
-                 "free_chunk_size2 = %u\n",
-                 free_chunk_size1, free_chunk_size2));
-
-       if (size <= free_chunk_size1) {
-               if (!(fm->nodes = (struct jffs_node_ref *)
-                                 kmalloc(sizeof(struct jffs_node_ref),
-                                         GFP_KERNEL))) {
-                       D(printk("jffs_fmalloc(): kmalloc() failed! "
-                                "(node_ref)\n"));
-                       jffs_free_fm(fm);
-                       return -ENOMEM;
-               }
-               DJM(no_jffs_node_ref++);
-               fm->nodes->node = node;
-               fm->nodes->next = NULL;
-               if (fmc->tail) {
-                       fm->offset = fmc->tail->offset + fmc->tail->size;
-                       if (fm->offset == fmc->flash_size) {
-                               fm->offset = 0;
-                       }
-                       ASSERT(else if (fm->offset > fmc->flash_size) {
-                               printk(KERN_WARNING "jffs_fmalloc(): "
-                                      "offset > flash_end\n");
-                               fm->offset = 0;
-                       });
-               }
-               else {
-                       /* There don't have to be files in the file
-                          system yet.  */
-                       fm->offset = 0;
-               }
-               fm->size = size;
-               fmc->free_size -= size;
-               fmc->used_size += size;
-       }
-       else if (size > free_chunk_size2) {
-               printk(KERN_WARNING "JFFS: Tried to allocate a too "
-                      "large flash memory chunk. (size = %u)\n", size);
-               jffs_free_fm(fm);
-               return -ENOSPC;
-       }
-       else {
-               fm->offset = fmc->tail->offset + fmc->tail->size;
-               fm->size = free_chunk_size1;
-               fm->nodes = NULL;
-               fmc->free_size -= fm->size;
-               fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a 
-                                               bug that caused infinite garbage collection.
-                                               It previously set fmc->dirty_size to size (which is the
-                                               size of the requested chunk).
-                                            */
-       }
-
-       fm->next = NULL;
-       if (!fmc->head) {
-               fm->prev = NULL;
-               fmc->head = fm;
-               fmc->tail = fm;
-       }
-       else {
-               fm->prev = fmc->tail;
-               fmc->tail->next = fm;
-               fmc->tail = fm;
-       }
-
-       D3(jffs_print_fmcontrol(fmc));
-       D3(jffs_print_fm(fm));
-       *result = fm;
-       return 0;
-}
-
-
-/* The on-flash space is not needed anymore by the passed node.  Remove
-   the reference to the node from the node list.  If the data chunk in
-   the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
-   then mark that chunk as dirty.  */
-int
-jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
-{
-       struct jffs_node_ref *ref;
-       struct jffs_node_ref *prev;
-       ASSERT(int del = 0);
-
-       D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
-                node->ino, node->version));
-
-       ASSERT(if (!fmc || !fm || !fm->nodes) {
-               printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
-                      "fm->nodes: 0x%p\n",
-                      fmc, fm, (fm ? fm->nodes : NULL));
-               return -1;
-       });
-
-       /* Find the reference to the node that is going to be removed
-          and remove it.  */
-       for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) {
-               if (ref->node == node) {
-                       if (prev) {
-                               prev->next = ref->next;
-                       }
-                       else {
-                               fm->nodes = ref->next;
-                       }
-                       kfree(ref);
-                       DJM(no_jffs_node_ref--);
-                       ASSERT(del = 1);
-                       break;
-               }
-               prev = ref;
-       }
-
-       /* If the data chunk in the flash memory isn't used anymore
-          just mark it as obsolete.  */
-       if (!fm->nodes) {
-               /* No node uses this chunk so let's remove it.  */
-               fmc->used_size -= fm->size;
-               fmc->dirty_size += fm->size;
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-               if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
-                       D1(printk("jffs_fmfree(): Failed to mark an on-flash "
-                                 "node obsolete!\n"));
-                       return -1;
-               }
-#endif
-       }
-
-       ASSERT(if (!del) {
-               printk(KERN_WARNING "***jffs_fmfree(): "
-                      "Didn't delete any node reference!\n");
-       });
-
-       return 0;
-}
-
-
-/* This allocation function is used during the initialization of
-   the file system.  */
-struct jffs_fm *
-jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
-              struct jffs_node *node)
-{
-       struct jffs_fm *fm;
-
-       D3(printk("jffs_fmalloced()\n"));
-
-       if (!(fm = jffs_alloc_fm())) {
-               D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
-                        fmc, offset, size, node));
-               return NULL;
-       }
-       fm->offset = offset;
-       fm->size = size;
-       fm->prev = NULL;
-       fm->next = NULL;
-       fm->nodes = NULL;
-       if (node) {
-               /* `node' exists and it should be associated with the
-                   jffs_fm structure `fm'.  */
-               if (!(fm->nodes = (struct jffs_node_ref *)
-                                 kmalloc(sizeof(struct jffs_node_ref),
-                                         GFP_KERNEL))) {
-                       D(printk("jffs_fmalloced(): !fm->nodes\n"));
-                       jffs_free_fm(fm);
-                       return NULL;
-               }
-               DJM(no_jffs_node_ref++);
-               fm->nodes->node = node;
-               fm->nodes->next = NULL;
-               fmc->used_size += size;
-               fmc->free_size -= size;
-       }
-       else {
-               /* If there is no node, then this is just a chunk of dirt.  */
-               fmc->dirty_size += size;
-               fmc->free_size -= size;
-       }
-
-       if (fmc->head_extra) {
-               fm->prev = fmc->tail_extra;
-               fmc->tail_extra->next = fm;
-               fmc->tail_extra = fm;
-       }
-       else if (!fmc->head) {
-               fmc->head = fm;
-               fmc->tail = fm;
-       }
-       else if (fmc->tail->offset + fmc->tail->size < offset) {
-               fmc->head_extra = fm;
-               fmc->tail_extra = fm;
-       }
-       else {
-               fm->prev = fmc->tail;
-               fmc->tail->next = fm;
-               fmc->tail = fm;
-       }
-       D3(jffs_print_fmcontrol(fmc));
-       D3(jffs_print_fm(fm));
-       return fm;
-}
-
-
-/* Add a new node to an already existing jffs_fm struct.  */
-int
-jffs_add_node(struct jffs_node *node)
-{
-       struct jffs_node_ref *ref;
-
-       D3(printk("jffs_add_node(): ino = %u\n", node->ino));
-
-       ref = kmalloc(sizeof(*ref), GFP_KERNEL);
-       if (!ref)
-               return -ENOMEM;
-
-       DJM(no_jffs_node_ref++);
-       ref->node = node;
-       ref->next = node->fm->nodes;
-       node->fm->nodes = ref;
-       return 0;
-}
-
-
-/* Free a part of some allocated space.  */
-void
-jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
-{
-       D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
-                 "fm->nodes->node->ino = %u, size = %u\n",
-                 fm, (fm ? fm->nodes : 0),
-                 (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
-
-       if (fm->nodes) {
-               kfree(fm->nodes);
-               DJM(no_jffs_node_ref--);
-               fm->nodes = NULL;
-       }
-       fmc->used_size -= fm->size;
-       if (fm == fmc->tail) {
-               fm->size -= size;
-               fmc->free_size += size;
-       }
-       fmc->dirty_size += fm->size;
-}
-
-
-/* Find the jffs_fm struct that contains the end of the data chunk that
-   begins at the logical beginning of the flash memory and spans `size'
-   bytes.  If we want to erase a sector of the flash memory, we use this
-   function to find where the sector limit cuts a chunk of data.  */
-struct jffs_fm *
-jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
-{
-       struct jffs_fm *fm;
-       __u32 pos = 0;
-
-       if (size == 0) {
-               return NULL;
-       }
-
-       ASSERT(if (!fmc) {
-               printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
-               return NULL;
-       });
-
-       fm = fmc->head;
-
-       while (fm) {
-               pos += fm->size;
-               if (pos < size) {
-                       fm = fm->next;
-               }
-               else if (pos > size) {
-                       break;
-               }
-               else {
-                       fm = NULL;
-                       break;
-               }
-       }
-
-       return fm;
-}
-
-
-/* Move the head of the fmc structures and delete the obsolete parts.  */
-void
-jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
-{
-       struct jffs_fm *fm;
-       struct jffs_fm *del;
-
-       ASSERT(if (!fmc) {
-               printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
-               return;
-       });
-
-       fmc->dirty_size -= erased_size;
-       fmc->free_size += erased_size;
-
-       for (fm = fmc->head; fm && (erased_size > 0);) {
-               if (erased_size >= fm->size) {
-                       erased_size -= fm->size;
-                       del = fm;
-                       fm = fm->next;
-                       fm->prev = NULL;
-                       fmc->head = fm;
-                       jffs_free_fm(del);
-               }
-               else {
-                       fm->size -= erased_size;
-                       fm->offset += erased_size;
-                       break;
-               }
-       }
-}
-
-
-/* Return the oldest used node in the flash memory.  */
-struct jffs_node *
-jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
-{
-       struct jffs_fm *fm;
-       struct jffs_node_ref *nref;
-       struct jffs_node *node = NULL;
-
-       ASSERT(if (!fmc) {
-               printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
-               return NULL;
-       });
-
-       for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
-
-       if (!fm) {
-               return NULL;
-       }
-
-       /* The oldest node is the last one in the reference list.  This list
-          shouldn't be too long; just one or perhaps two elements.  */
-       for (nref = fm->nodes; nref; nref = nref->next) {
-               node = nref->node;
-       }
-
-       D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
-                 (node ? node->ino : 0), (node ? node->version : 0)));
-
-       return node;
-}
-
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-
-/* Mark an on-flash node as obsolete.
-
-   Note that this is just an optimization that isn't necessary for the
-   filesystem to work.  */
-
-static int
-jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
-{
-       /* The `accurate_pos' holds the position of the accurate byte
-          in the jffs_raw_inode structure that we are going to mark
-          as obsolete.  */
-       __u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
-       unsigned char zero = 0x00;
-       size_t len;
-
-       D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
-       ASSERT(if (!fmc) {
-               printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
-               return -1;
-       });
-
-       /* Write 0x00 to the raw inode's accurate member.  Don't care
-          about the return value.  */
-       MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
-       return 0;
-}
-
-#endif /* JFFS_MARK_OBSOLETE  */
-
-/* check if it's possible to erase the wanted range, and if not, return
- * the range that IS erasable, or a negative error code.
- */
-static long
-jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
-{
-         u_long ssize;
-
-       /* assume that sector size for a partition is constant even
-        * if it spans more than one chip (you usually put the same
-        * type of chips in a system)
-        */
-
-        ssize = mtd->erasesize;
-
-       if (offset % ssize) {
-               printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
-               /* The offset is not sector size aligned.  */
-               return -1;
-       }
-       else if (offset > mtd->size) {
-               printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
-               return -2;
-       }
-       else if (offset + size > mtd->size) {
-               printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
-               return -3;
-       }
-
-       return (size / ssize) * ssize;
-}
-
-
-/* How much dirty flash memory is possible to erase at the moment?  */
-long
-jffs_erasable_size(struct jffs_fmcontrol *fmc)
-{
-       struct jffs_fm *fm;
-       __u32 size = 0;
-       long ret;
-
-       ASSERT(if (!fmc) {
-               printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
-               return -1;
-       });
-
-       if (!fmc->head) {
-               /* The flash memory is totally empty. No nodes. No dirt.
-                  Just return.  */
-               return 0;
-       }
-
-       /* Calculate how much space that is dirty.  */
-       for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
-               if (size && fm->offset == 0) {
-                       /* We have reached the beginning of the flash.  */
-                       break;
-               }
-               size += fm->size;
-       }
-
-       /* Someone's signature contained this:
-          There's a fine line between fishing and just standing on
-          the shore like an idiot...  */
-       ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
-
-       ASSERT(if (ret < 0) {
-               printk("jffs_erasable_size: flash_erasable_size() "
-                      "returned something less than zero (%ld).\n", ret);
-               printk("jffs_erasable_size: offset = 0x%08x\n",
-                      fmc->head->offset);
-       });
-
-       /* If there is dirt on the flash (which is the reason to why
-          this function was called in the first place) but no space is
-          possible to erase right now, the initial part of the list of
-          jffs_fm structs, that hold place for dirty space, could perhaps
-          be shortened.  The list's initial "dirty" elements are merged
-          into just one large dirty jffs_fm struct.  This operation must
-          only be performed if nothing is possible to erase.  Otherwise,
-          jffs_clear_end_of_node() won't work as expected.  */
-       if (ret == 0) {
-               struct jffs_fm *head = fmc->head;
-               struct jffs_fm *del;
-               /* While there are two dirty nodes beside each other.*/
-               while (head->nodes == 0
-                      && head->next
-                      && head->next->nodes == 0) {
-                       del = head->next;
-                       head->size += del->size;
-                       head->next = del->next;
-                       if (del->next) {
-                               del->next->prev = head;
-                       }
-                       jffs_free_fm(del);
-               }
-       }
-
-       return (ret >= 0 ? ret : 0);
-}
-
-static struct jffs_fm *jffs_alloc_fm(void)
-{
-       struct jffs_fm *fm;
-
-       fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
-       DJM(if (fm) no_jffs_fm++;);
-       
-       return fm;
-}
-
-static void jffs_free_fm(struct jffs_fm *n)
-{
-       kmem_cache_free(fm_cache,n);
-       DJM(no_jffs_fm--);
-}
-
-
-
-struct jffs_node *jffs_alloc_node(void)
-{
-       struct jffs_node *n;
-
-       n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
-       if(n != NULL)
-               no_jffs_node++;
-       return n;
-}
-
-void jffs_free_node(struct jffs_node *n)
-{
-       kmem_cache_free(node_cache,n);
-       no_jffs_node--;
-}
-
-
-int jffs_get_node_inuse(void)
-{
-       return no_jffs_node;
-}
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
deleted file mode 100644 (file)
index 9ee6ad2..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_FM_H__
-#define __LINUX_JFFS_FM_H__
-
-#include <linux/types.h>
-#include <linux/jffs.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mutex.h>
-
-/* The alignment between two nodes in the flash memory.  */
-#define JFFS_ALIGN_SIZE 4
-
-/* Mark the on-flash space as obsolete when appropriate.  */
-#define JFFS_MARK_OBSOLETE 0
-
-#ifndef CONFIG_JFFS_FS_VERBOSE
-#define CONFIG_JFFS_FS_VERBOSE 1
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-#define D(x) x
-#define D1(x) D(x)
-#else
-#define D(x)
-#define D1(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 1
-#define D2(x) D(x)
-#else
-#define D2(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-#define D3(x) D(x)
-#else
-#define D3(x)
-#endif
-
-#define ASSERT(x) x
-
-/* How many padding bytes should be inserted between two chunks of data
-   on the flash?  */
-#define JFFS_GET_PAD_BYTES(size) ( (JFFS_ALIGN_SIZE-1) & -(__u32)(size) )
-#define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) )
-
-
-
-struct jffs_node_ref
-{
-       struct jffs_node *node;
-       struct jffs_node_ref *next;
-};
-
-
-/* The struct jffs_fm represents a chunk of data in the flash memory.  */
-struct jffs_fm
-{
-       __u32 offset;
-       __u32 size;
-       struct jffs_fm *prev;
-       struct jffs_fm *next;
-       struct jffs_node_ref *nodes; /* USED if != 0.  */
-};
-
-struct jffs_fmcontrol
-{
-       __u32 flash_size;
-       __u32 used_size;
-       __u32 dirty_size;
-       __u32 free_size;
-       __u32 sector_size;
-       __u32 min_free_size;  /* The minimum free space needed to be able
-                                to perform garbage collections.  */
-       __u32 max_chunk_size; /* The maximum size of a chunk of data.  */
-       struct mtd_info *mtd;
-       struct jffs_control *c;
-       struct jffs_fm *head;
-       struct jffs_fm *tail;
-       struct jffs_fm *head_extra;
-       struct jffs_fm *tail_extra;
-       struct mutex biglock;
-};
-
-/* Notice the two members head_extra and tail_extra in the jffs_control
-   structure above. Those are only used during the scanning of the flash
-   memory; while the file system is being built. If the data in the flash
-   memory is organized like
-
-      +----------------+------------------+----------------+
-      |  USED / DIRTY  |       FREE       |  USED / DIRTY  |
-      +----------------+------------------+----------------+
-
-   then the scan is split in two parts. The first scanned part of the
-   flash memory is organized through the members head and tail. The
-   second scanned part is organized with head_extra and tail_extra. When
-   the scan is completed, the two lists are merged together. The jffs_fm
-   struct that head_extra references is the logical beginning of the
-   flash memory so it will be referenced by the head member.  */
-
-
-
-struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, int unit);
-void jffs_build_end(struct jffs_fmcontrol *fmc);
-void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
-
-int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
-                struct jffs_node *node, struct jffs_fm **result);
-int jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
-               struct jffs_node *node);
-
-__u32 jffs_free_size1(struct jffs_fmcontrol *fmc);
-__u32 jffs_free_size2(struct jffs_fmcontrol *fmc);
-void jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size);
-struct jffs_fm *jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size);
-struct jffs_node *jffs_get_oldest_node(struct jffs_fmcontrol *fmc);
-long jffs_erasable_size(struct jffs_fmcontrol *fmc);
-struct jffs_fm *jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset,
-                              __u32 size, struct jffs_node *node);
-int jffs_add_node(struct jffs_node *node);
-void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
-                       __u32 size);
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
-#endif
-#if 0
-void jffs_print_node_ref(struct jffs_node_ref *ref);
-#endif  /*  0  */
-
-#endif /* __LINUX_JFFS_FM_H__  */
diff --git a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c
deleted file mode 100644 (file)
index 9bdd99a..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000  Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- *  Overview:
- *   This file defines JFFS partition entries in the proc file system.
- *
- *  TODO:
- *   Create some more proc files for different kinds of info, i.e. statistics
- *   about written and read bytes, number of calls to different routines,
- *   reports about failures.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/jffs.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include "jffs_fm.h"
-#include "jffs_proc.h"
-
-/*
- * Structure for a JFFS partition in the system
- */
-struct jffs_partition_dir {
-       struct jffs_control *c;
-       struct proc_dir_entry *part_root;
-       struct proc_dir_entry *part_info;
-       struct proc_dir_entry *part_layout;
-       struct jffs_partition_dir *next;
-};
-
-/*
- * Structure for top-level entry in '/proc/fs' directory
- */
-struct proc_dir_entry *jffs_proc_root;
-
-/*
- * Linked list of 'jffs_partition_dirs' to help us track
- * the mounted JFFS partitions in the system
- */
-static struct jffs_partition_dir *jffs_part_dirs;
-
-/*
- * Read functions for entries
- */
-static int jffs_proc_info_read(char *page, char **start, off_t off,
-               int count, int *eof, void *data);
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
-               int count, int *eof, void *data);
-
-
-/*
- * Register a JFFS partition directory (called upon mount)
- */
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c)
-{
-       struct jffs_partition_dir *part_dir;
-       struct proc_dir_entry *part_info = NULL;
-       struct proc_dir_entry *part_layout = NULL;
-       struct proc_dir_entry *part_root = NULL;
-       char name[10];
-
-       sprintf(name, "%d", mtd);
-       /* Allocate structure for local JFFS partition table */
-       part_dir = (struct jffs_partition_dir *)
-               kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL);
-       if (!part_dir)
-               goto out;
-
-       /* Create entry for this partition */
-       part_root = proc_mkdir(name, jffs_proc_root);
-       if (!part_root)
-               goto out1;
-
-       /* Create entry for 'info' file */
-       part_info = create_proc_entry ("info", 0, part_root);
-       if (!part_info)
-               goto out2;
-       part_info->read_proc = jffs_proc_info_read;
-       part_info->data = (void *) c;
-
-       /* Create entry for 'layout' file */
-       part_layout = create_proc_entry ("layout", 0, part_root);
-       if (!part_layout)
-               goto out3;
-       part_layout->read_proc = jffs_proc_layout_read;
-       part_layout->data = (void *) c;
-
-       /* Fill in structure for table and insert in the list */
-       part_dir->c = c;
-       part_dir->part_root = part_root;
-       part_dir->part_info = part_info;
-       part_dir->part_layout = part_layout;
-       part_dir->next = jffs_part_dirs;
-       jffs_part_dirs = part_dir;
-
-       /* Return happy */
-       return 0;
-
-out3:
-       remove_proc_entry("info", part_root);
-out2:
-       remove_proc_entry(name, jffs_proc_root);
-out1:
-       kfree(part_dir);
-out:
-       return -ENOMEM;
-}
-
-
-/*
- * Unregister a JFFS partition directory (called at umount)
- */
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
-{
-       struct jffs_partition_dir *part_dir = jffs_part_dirs;
-       struct jffs_partition_dir *prev_part_dir = NULL;
-
-       while (part_dir) {
-               if (part_dir->c == c) {
-                       /* Remove entries for partition */
-                       remove_proc_entry (part_dir->part_info->name,
-                               part_dir->part_root);
-                       remove_proc_entry (part_dir->part_layout->name,
-                               part_dir->part_root);
-                       remove_proc_entry (part_dir->part_root->name,
-                               jffs_proc_root);
-
-                       /* Remove entry from list */
-                       if (prev_part_dir)
-                               prev_part_dir->next = part_dir->next;
-                       else
-                               jffs_part_dirs = part_dir->next;
-
-                       /*
-                        * Check to see if this is the last one
-                        * and remove the entry from '/proc/fs'
-                        * if it is.
-                        */
-                       if (jffs_part_dirs == part_dir->next)
-                               remove_proc_entry ("jffs", proc_root_fs);
-
-                       /* Free memory for entry */
-                       kfree(part_dir);
-
-                       /* Return happy */
-                       return 0;
-               }
-
-               /* Move to next entry */
-               prev_part_dir = part_dir;
-               part_dir = part_dir->next;
-       }
-
-       /* Return unhappy */
-       return -1;
-}
-
-
-/*
- * Read a JFFS partition's `info' file
- */
-static int jffs_proc_info_read (char *page, char **start, off_t off,
-               int count, int *eof, void *data)
-{
-       struct jffs_control *c = (struct jffs_control *) data;
-       int len = 0;
-
-       /* Get information on the parition */
-       len += sprintf (page,
-               "partition size:     %08lX (%u)\n"
-               "sector size:        %08lX (%u)\n"
-               "used size:          %08lX (%u)\n"
-               "dirty size:         %08lX (%u)\n"
-               "free size:          %08lX (%u)\n\n",
-               (unsigned long) c->fmc->flash_size, c->fmc->flash_size,
-               (unsigned long) c->fmc->sector_size, c->fmc->sector_size,
-               (unsigned long) c->fmc->used_size, c->fmc->used_size,
-               (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
-               (unsigned long) (c->fmc->flash_size -
-                       (c->fmc->used_size + c->fmc->dirty_size)),
-               c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
-
-       /* We're done */
-       *eof = 1;
-
-       /* Return length */
-       return len;
-}
-
-
-/*
- * Read a JFFS partition's `layout' file
- */
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
-               int count, int *eof, void *data)
-{
-       struct jffs_control *c = (struct jffs_control *) data;
-       struct jffs_fm *fm = NULL;
-       struct jffs_fm *last_fm = NULL;
-       int len = 0;
-
-       /* Get the first item in the list */
-       fm = c->fmc->head;
-
-       /* Print free space */
-       if (fm && fm->offset) {
-               len += sprintf (page, "00000000 %08lX free\n",
-                       (unsigned long) fm->offset);
-       }
-
-       /* Loop through all of the flash control structures */
-       while (fm && (len < (off + count))) {
-               if (fm->nodes) {
-                       len += sprintf (page + len,
-                               "%08lX %08lX ino=%08lX, ver=%08lX\n",
-                               (unsigned long) fm->offset,
-                               (unsigned long) fm->size,
-                               (unsigned long) fm->nodes->node->ino,
-                               (unsigned long) fm->nodes->node->version);
-               }
-               else {
-                       len += sprintf (page + len,
-                               "%08lX %08lX dirty\n",
-                               (unsigned long) fm->offset,
-                               (unsigned long) fm->size);
-               }
-               last_fm = fm;
-               fm = fm->next;
-       }
-
-       /* Print free space */
-       if ((len < (off + count)) && last_fm
-           && (last_fm->offset < c->fmc->flash_size)) {
-               len += sprintf (page + len,
-                              "%08lX %08lX free\n",
-                              (unsigned long) last_fm->offset + 
-                               last_fm->size,
-                              (unsigned long) (c->fmc->flash_size -
-                                                   (last_fm->offset + last_fm->size)));
-       }
-
-       /* We're done */
-       *eof = 1;
-
-       /* Return length */
-       return len;
-}
diff --git a/fs/jffs/jffs_proc.h b/fs/jffs/jffs_proc.h
deleted file mode 100644 (file)
index 39a1c5d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000  Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: jffs_proc.h,v 1.2 2000/11/15 22:04:12 sjhill Exp $
- */
-
-/* jffs_proc.h defines a structure for inclusion in the proc-file system.  */
-#ifndef __LINUX_JFFS_PROC_H__
-#define __LINUX_JFFS_PROC_H__
-
-#include <linux/proc_fs.h>
-
-/* The proc_dir_entry for jffs (defined in jffs_proc.c).  */
-extern struct proc_dir_entry *jffs_proc_root;
-
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c);
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c);
-
-#endif /* __LINUX_JFFS_PROC_H__ */
index 02826967ab58918ac6fa6ec7723d5e81485c357e..07119c42a861ad2ddf6fa86ae7fc79753879aa0f 100644 (file)
@@ -348,23 +348,27 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
 
        ret = jffs2_sum_init(c);
        if (ret)
-               return ret;
+               goto out_free;
 
        if (jffs2_build_filesystem(c)) {
                dbg_fsbuild("build_fs failed\n");
                jffs2_free_ino_caches(c);
                jffs2_free_raw_node_refs(c);
-#ifndef __ECOS
-               if (jffs2_blocks_use_vmalloc(c))
-                       vfree(c->blocks);
-               else
-#endif
-                       kfree(c->blocks);
-
-               return -EIO;
+               ret = -EIO;
+               goto out_free;
        }
 
        jffs2_calc_trigger_levels(c);
 
        return 0;
+
+ out_free:
+#ifndef __ECOS
+       if (jffs2_blocks_use_vmalloc(c))
+               vfree(c->blocks);
+       else
+#endif
+               kfree(c->blocks);
+
+       return ret;
 }
index 3681d0728ac7901f2179534ebec0f4d9c88afcf8..0c1fc6e20b4321af24ecb92a22b4cdce926caaa6 100644 (file)
@@ -16,7 +16,6 @@
 #endif
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/zlib.h>
 #include <linux/zutil.h>
index cdbe2fe14e2d185fe4763d6afeebb3bfb9a3d2b3..9fa2e27f06413f7d490ecc552213d99dbe432f73 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
index b98594992eed530a7431a8db7c85f104ba734d73..ea88f69af13071dcfbb64953609a89678207b0cc 100644 (file)
@@ -98,20 +98,14 @@ struct jffs2_sb_info {
        uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-       /* Write-behind buffer for NAND flash */
-       unsigned char *wbuf;
-       unsigned char *oobbuf;
+       unsigned char *wbuf; /* Write-behind buffer for NAND flash */
        uint32_t wbuf_ofs;
        uint32_t wbuf_len;
        struct jffs2_inodirty *wbuf_inodes;
-
        struct rw_semaphore wbuf_sem;   /* Protects the write buffer */
 
-       /* Information about out-of-band area usage... */
-       struct nand_ecclayout *ecclayout;
-       uint32_t badblock_pos;
-       uint32_t fsdata_pos;
-       uint32_t fsdata_len;
+       unsigned char *oobbuf;
+       int oobavail; /* How many bytes are available for JFFS2 in OOB */
 #endif
 
        struct jffs2_summary *summary;          /* Summary information */
index 3af746eaff0ec124168e0baffa247de09253e68c..31c1475d922aa2d3f4eb5c75841838f1100a385b 100644 (file)
@@ -450,16 +450,20 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
        if (jffs2_cleanmarker_oob(c)) {
-               int ret = jffs2_check_nand_cleanmarker(c, jeb);
+               int ret;
+
+               if (c->mtd->block_isbad(c->mtd, jeb->offset))
+                       return BLK_STATE_BADBLOCK;
+
+               ret = jffs2_check_nand_cleanmarker(c, jeb);
                D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret));
+
                /* Even if it's not found, we still scan to see
                   if the block is empty. We use this information
                   to decide whether to erase it or not. */
                switch (ret) {
                case 0:         cleanmarkerfound = 1; break;
                case 1:         break;
-               case 2:         return BLK_STATE_BADBLOCK;
-               case 3:         return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */
                default:        return ret;
                }
        }
index 25265965bdc1f67254dc51463510e19af07ec7aa..30f888414ce77f1ce5534d9e23650a2ca8b4f0d3 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/pagemap.h>
index 9c99859f5eddb12f24386d1cab20f71dd52ef756..de718e3a169296c6c6dc526743f2498762205ee8 100644 (file)
@@ -957,43 +957,48 @@ exit:
        return ret;
 }
 
-#define NR_OOB_SCAN_PAGES      4
+#define NR_OOB_SCAN_PAGES 4
+
+/* For historical reasons we use only 12 bytes for OOB clean marker */
+#define OOB_CM_SIZE 12
+
+static const struct jffs2_unknown_node oob_cleanmarker =
+{
+       .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
+       .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+       .totlen = cpu_to_je32(8)
+};
 
 /*
- * Check, if the out of band area is empty
+ * Check, if the out of band area is empty. This function knows about the clean
+ * marker and if it is present in OOB, treats the OOB as empty anyway.
  */
 int jffs2_check_oob_empty(struct jffs2_sb_info *c,
                          struct jffs2_eraseblock *jeb, int mode)
 {
-       int i, page, ret;
-       int oobsize = c->mtd->oobsize;
+       int i, ret;
+       int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
        struct mtd_oob_ops ops;
 
-       ops.ooblen = NR_OOB_SCAN_PAGES * oobsize;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail;
        ops.oobbuf = c->oobbuf;
-       ops.ooboffs = 0;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
        ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
-       if (ret) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-                         "failed %d for block at %08x\n", ret, jeb->offset));
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
 
-       if (ops.oobretlen < ops.ooblen) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-                         "returned short read (%zd bytes not %d) for block "
-                         "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset));
-               return -EIO;
-       }
-
-       /* Special check for first page */
-       for(i = 0; i < oobsize ; i++) {
-               /* Yeah, we know about the cleanmarker. */
-               if (mode && i >= c->fsdata_pos &&
-                   i < c->fsdata_pos + c->fsdata_len)
+       for(i = 0; i < ops.ooblen; i++) {
+               if (mode && i < cmlen)
+                       /* Yeah, we know about the cleanmarker */
                        continue;
 
                if (ops.oobbuf[i] != 0xFF) {
@@ -1003,111 +1008,63 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
                }
        }
 
-       /* we know, we are aligned :) */
-       for (page = oobsize; page < ops.ooblen; page += sizeof(long)) {
-               long dat = *(long *)(&ops.oobbuf[page]);
-               if(dat != -1)
-                       return 1;
-       }
        return 0;
 }
 
 /*
- * Scan for a valid cleanmarker and for bad blocks
+ * Check for a valid cleanmarker.
+ * Returns: 0 if a valid cleanmarker was found
+ *          1 if no cleanmarker was found
+ *          negative error code if an error occurred
  */
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
-                                 struct jffs2_eraseblock *jeb)
+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
+                                struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_unknown_node n;
        struct mtd_oob_ops ops;
-       int oobsize = c->mtd->oobsize;
-       unsigned char *p,*b;
-       int i, ret;
-       size_t offset = jeb->offset;
-
-       /* Check first if the block is bad. */
-       if (c->mtd->block_isbad(c->mtd, offset)) {
-               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
-                          ": Bad block at %08x\n", jeb->offset));
-               return 2;
-       }
+       int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       ops.ooblen = oobsize;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = cmlen;
        ops.oobbuf = c->oobbuf;
-       ops.ooboffs = 0;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
-       ret = c->mtd->read_oob(c->mtd, offset, &ops);
-       if (ret) {
-               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                          "Read OOB failed %d for block at %08x\n",
-                          ret, jeb->offset));
+       ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
 
-       if (ops.oobretlen < ops.ooblen) {
-               D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                           "Read OOB return short read (%zd bytes not %d) "
-                           "for block at %08x\n", ops.oobretlen, ops.ooblen,
-                           jeb->offset));
-               return -EIO;
-       }
-
-       n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-       n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-       n.totlen = cpu_to_je32 (8);
-       p = (unsigned char *) &n;
-       b = c->oobbuf + c->fsdata_pos;
-
-       for (i = c->fsdata_len; i; i--) {
-               if (*b++ != *p++)
-                       ret = 1;
-       }
-
-       D1(if (ret == 1) {
-               printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                      "Cleanmarker node not detected in block at %08x\n",
-                      offset);
-               printk(KERN_WARNING "OOB at %08zx was ", offset);
-               for (i=0; i < oobsize; i++)
-                       printk("%02x ", c->oobbuf[i]);
-               printk("\n");
-       });
-       return ret;
+       return !!memcmp(&oob_cleanmarker, c->oobbuf, cmlen);
 }
 
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
                                 struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_unknown_node n;
-       int     ret;
+       int ret;
        struct mtd_oob_ops ops;
+       int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-       n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
-       n.totlen = cpu_to_je32(8);
-
-       ops.ooblen = c->fsdata_len;
-       ops.oobbuf = (uint8_t *)&n;
-       ops.ooboffs = c->fsdata_pos;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = cmlen;
+       ops.oobbuf = (uint8_t *)&oob_cleanmarker;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
        ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
-
-       if (ret) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-                         "Write failed for block at %08x: error %d\n",
-                         jeb->offset, ret));
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot write OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
-       if (ops.oobretlen != ops.ooblen) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-                         "Short write for block at %08x: %zd not %d\n",
-                         jeb->offset, ops.oobretlen, ops.ooblen));
-               return -EIO;
-       }
+
        return 0;
 }
 
@@ -1140,41 +1097,24 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
        return 1;
 }
 
-static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
+int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 {
        struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
-       /* Do this only, if we have an oob buffer */
        if (!c->mtd->oobsize)
                return 0;
 
        /* Cleanmarker is out-of-band, so inline size zero */
        c->cleanmarker_size = 0;
 
-       /* Should we use autoplacement ? */
-       if (!oinfo) {
-               D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+       if (!oinfo || oinfo->oobavail == 0) {
+               printk(KERN_ERR "inconsistent device description\n");
                return -EINVAL;
        }
 
-       D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-       /* Get the position of the free bytes */
-       if (!oinfo->oobfree[0].length) {
-               printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
-                       " Autoplacement selected and no empty space in oob\n");
-               return -ENOSPC;
-       }
-       c->fsdata_pos = oinfo->oobfree[0].offset;
-       c->fsdata_len = oinfo->oobfree[0].length;
-       if (c->fsdata_len > 8)
-               c->fsdata_len = 8;
+       D1(printk(KERN_DEBUG "JFFS2 using OOB on NAND\n"));
 
-       return 0;
-}
-
-int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
-{
-       int res;
+       c->oobavail = oinfo->oobavail;
 
        /* Initialise write buffer */
        init_rwsem(&c->wbuf_sem);
@@ -1185,22 +1125,13 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
        if (!c->wbuf)
                return -ENOMEM;
 
-       c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
-       if (!c->oobbuf)
-               return -ENOMEM;
-
-       res = jffs2_nand_set_oobinfo(c);
-
-#ifdef BREAKME
-       if (!brokenbuf)
-               brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!brokenbuf) {
+       c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL);
+       if (!c->oobbuf) {
                kfree(c->wbuf);
                return -ENOMEM;
        }
-       memset(brokenbuf, 0xdb, c->wbuf_pagesize);
-#endif
-       return res;
+
+       return 0;
 }
 
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
index 22d40320897362823803b0e3a0059d086f9cc1ab..ad21c0713efa705ad7aeb5a18f165a46a934453f 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
index 80fcacc1acf96f9e3cfb826979c9a75428f5687a..126b1bf02c0ec2d8b5c051eb1e29acf27d6a32b3 100644 (file)
@@ -440,7 +440,7 @@ static ctl_table nlm_sysctl_root[] = {
 };
 
 /*
- * Module (and driverfs) parameters.
+ * Module (and sysfs) parameters.
  */
 
 #define param_set_min_max(name, type, which_strtol, min, max)          \
@@ -512,7 +512,7 @@ module_param(nsm_use_hostnames, bool, 0644);
 
 static int __init init_nlm(void)
 {
-       nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0);
+       nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
        return nlm_sysctl_table ? 0 : -ENOMEM;
 }
 
index 161e2225c75702f1f2ba88e97a2d21d1155da1a3..ee60cc4d3453209723d6f70982e7083d7cb39477 100644 (file)
@@ -2688,10 +2688,11 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
-       int err = -ENOMEM;
+       int err;
        char *kaddr;
 
 retry:
+       err = -ENOMEM;
        page = find_or_create_page(mapping, 0, gfp_mask);
        if (!page)
                goto fail;
index 823298561c0a9a7904695ce554899165d26f7403..f5f4430fb2a4c0ba3d488878a9007f26397cae43 100644 (file)
@@ -43,7 +43,6 @@
  * child task framework of the RPC layer?
  */
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
index 3ea50ac648209dc28ad6ed1aa632f3a9f0df1ff9..fcdcafbb32939931c111d3fe75458d71f6f676ff 100644 (file)
@@ -75,7 +75,7 @@ static ctl_table nfs_cb_sysctl_root[] = {
 
 int nfs_register_sysctl(void)
 {
-       nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root, 0);
+       nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root);
        if (nfs_callback_sysctl_table == NULL)
                return -ENOMEM;
        return 0;
index 49c310b849239cecc236c9a039352ea40cffa728..6f24768272a1f05dcdd9657d3bb22755c06e9dce 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/unistd.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/in.h>
 #include <linux/seq_file.h>
@@ -190,18 +189,17 @@ static int expkey_show(struct seq_file *m,
                       struct cache_head *h)
 {
        struct svc_expkey *ek ;
+       int i;
 
        if (h ==NULL) {
                seq_puts(m, "#domain fsidtype fsid [path]\n");
                return 0;
        }
        ek = container_of(h, struct svc_expkey, h);
-       seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
-                  ek->ek_fsidtype, ek->ek_fsid[0]);
-       if (ek->ek_fsidtype != 1)
-               seq_printf(m, "%08x", ek->ek_fsid[1]);
-       if (ek->ek_fsidtype == 2)
-               seq_printf(m, "%08x", ek->ek_fsid[2]);
+       seq_printf(m, "%s %d 0x", ek->ek_client->name,
+                  ek->ek_fsidtype);
+       for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
+               seq_printf(m, "%08x", ek->ek_fsid[i]);
        if (test_bit(CACHE_VALID, &h->flags) && 
            !test_bit(CACHE_NEGATIVE, &h->flags)) {
                seq_printf(m, " ");
@@ -232,9 +230,8 @@ static inline void expkey_init(struct cache_head *cnew,
        kref_get(&item->ek_client->ref);
        new->ek_client = item->ek_client;
        new->ek_fsidtype = item->ek_fsidtype;
-       new->ek_fsid[0] = item->ek_fsid[0];
-       new->ek_fsid[1] = item->ek_fsid[1];
-       new->ek_fsid[2] = item->ek_fsid[2];
+
+       memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
 }
 
 static inline void expkey_update(struct cache_head *cnew,
@@ -363,7 +360,7 @@ static struct svc_export *svc_export_update(struct svc_export *new,
                                            struct svc_export *old);
 static struct svc_export *svc_export_lookup(struct svc_export *);
 
-static int check_export(struct inode *inode, int flags)
+static int check_export(struct inode *inode, int flags, unsigned char *uuid)
 {
 
        /* We currently export only dirs and regular files.
@@ -376,12 +373,13 @@ static int check_export(struct inode *inode, int flags)
        /* There are two requirements on a filesystem to be exportable.
         * 1:  We must be able to identify the filesystem from a number.
         *       either a device number (so FS_REQUIRES_DEV needed)
-        *       or an FSID number (so NFSEXP_FSID needed).
+        *       or an FSID number (so NFSEXP_FSID or ->uuid is needed).
         * 2:  We must be able to find an inode from a filehandle.
         *       This means that s_export_op must be set.
         */
        if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
-           !(flags & NFSEXP_FSID)) {
+           !(flags & NFSEXP_FSID) &&
+           uuid == NULL) {
                dprintk("exp_export: export of non-dev fs without fsid\n");
                return -EINVAL;
        }
@@ -406,10 +404,6 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
        int len;
        int migrated, i, err;
 
-       len = qword_get(mesg, buf, PAGE_SIZE);
-       if (len != 5 || memcmp(buf, "fsloc", 5))
-               return 0;
-
        /* listsize */
        err = get_int(mesg, &fsloc->locations_count);
        if (err)
@@ -520,6 +514,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
        exp.ex_fslocs.locations_count = 0;
        exp.ex_fslocs.migrated = 0;
 
+       exp.ex_uuid = NULL;
+
        /* flags */
        err = get_int(&mesg, &an_int);
        if (err == -ENOENT)
@@ -543,12 +539,33 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
                if (err) goto out;
                exp.ex_fsid = an_int;
 
-               err = check_export(nd.dentry->d_inode, exp.ex_flags);
-               if (err) goto out;
+               while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
+                       if (strcmp(buf, "fsloc") == 0)
+                               err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
+                       else if (strcmp(buf, "uuid") == 0) {
+                               /* expect a 16 byte uuid encoded as \xXXXX... */
+                               len = qword_get(&mesg, buf, PAGE_SIZE);
+                               if (len != 16)
+                                       err  = -EINVAL;
+                               else {
+                                       exp.ex_uuid =
+                                               kmemdup(buf, 16, GFP_KERNEL);
+                                       if (exp.ex_uuid == NULL)
+                                               err = -ENOMEM;
+                               }
+                       } else
+                               /* quietly ignore unknown words and anything
+                                * following. Newer user-space can try to set
+                                * new values, then see what the result was.
+                                */
+                               break;
+                       if (err)
+                               goto out;
+               }
 
-               err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
-               if (err)
-                       goto out;
+               err = check_export(nd.dentry->d_inode, exp.ex_flags,
+                                  exp.ex_uuid);
+               if (err) goto out;
        }
 
        expp = svc_export_lookup(&exp);
@@ -562,6 +579,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
        else
                exp_put(expp);
  out:
+       nfsd4_fslocs_free(&exp.ex_fslocs);
+       kfree(exp.ex_uuid);
        kfree(exp.ex_path);
        if (nd.dentry)
                path_release(&nd);
@@ -591,9 +610,19 @@ static int svc_export_show(struct seq_file *m,
        seq_escape(m, exp->ex_client->name, " \t\n\\");
        seq_putc(m, '(');
        if (test_bit(CACHE_VALID, &h->flags) && 
-           !test_bit(CACHE_NEGATIVE, &h->flags))
+           !test_bit(CACHE_NEGATIVE, &h->flags)) {
                exp_flags(m, exp->ex_flags, exp->ex_fsid,
                          exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
+               if (exp->ex_uuid) {
+                       int i;
+                       seq_puts(m, ",uuid=");
+                       for (i=0; i<16; i++) {
+                               if ((i&3) == 0 && i)
+                                       seq_putc(m, ':');
+                               seq_printf(m, "%02x", exp->ex_uuid[i]);
+                       }
+               }
+       }
        seq_puts(m, ")\n");
        return 0;
 }
@@ -630,6 +659,8 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
        new->ex_anon_uid = item->ex_anon_uid;
        new->ex_anon_gid = item->ex_anon_gid;
        new->ex_fsid = item->ex_fsid;
+       new->ex_uuid = item->ex_uuid;
+       item->ex_uuid = NULL;
        new->ex_path = item->ex_path;
        item->ex_path = NULL;
        new->ex_fslocs.locations = item->ex_fslocs.locations;
@@ -752,11 +783,11 @@ exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
        u32 fsidv[3];
        
        if (old_valid_dev(dev)) {
-               mk_fsid_v0(fsidv, dev, ino);
-               return exp_find_key(clp, 0, fsidv, NULL);
+               mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
+               return exp_find_key(clp, FSID_DEV, fsidv, NULL);
        }
-       mk_fsid_v3(fsidv, dev, ino);
-       return exp_find_key(clp, 3, fsidv, NULL);
+       mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
+       return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
 }
 
 /*
@@ -767,9 +798,9 @@ exp_get_fsid_key(svc_client *clp, int fsid)
 {
        u32 fsidv[2];
 
-       mk_fsid_v1(fsidv, fsid);
+       mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
 
-       return exp_find_key(clp, 1, fsidv, NULL);
+       return exp_find_key(clp, FSID_NUM, fsidv, NULL);
 }
 
 svc_export *
@@ -883,8 +914,8 @@ static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
        if ((exp->ex_flags & NFSEXP_FSID) == 0)
                return 0;
 
-       mk_fsid_v1(fsid, exp->ex_fsid);
-       return exp_set_key(clp, 1, fsid, exp);
+       mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
+       return exp_set_key(clp, FSID_NUM, fsid, exp);
 }
 
 static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
@@ -894,11 +925,11 @@ static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
        dev_t dev = inode->i_sb->s_dev;
 
        if (old_valid_dev(dev)) {
-               mk_fsid_v0(fsid, dev, inode->i_ino);
-               return exp_set_key(clp, 0, fsid, exp);
+               mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
+               return exp_set_key(clp, FSID_DEV, fsid, exp);
        }
-       mk_fsid_v3(fsid, dev, inode->i_ino);
-       return exp_set_key(clp, 3, fsid, exp);
+       mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
+       return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
 }
 
 static void exp_unhash(struct svc_export *exp)
@@ -977,7 +1008,7 @@ exp_export(struct nfsctl_export *nxp)
                goto finish;
        }
 
-       err = check_export(nd.dentry->d_inode, nxp->ex_flags);
+       err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL);
        if (err) goto finish;
 
        err = -ENOMEM;
@@ -1170,9 +1201,9 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
        __be32 rv;
        u32 fsidv[2];
 
-       mk_fsid_v1(fsidv, 0);
+       mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
 
-       exp = exp_find(clp, 1, fsidv, creq);
+       exp = exp_find(clp, FSID_NUM, fsidv, creq);
        if (IS_ERR(exp))
                return nfserrno(PTR_ERR(exp));
        if (exp == NULL)
index e695660921ec30adfd6f0ebb3546120ee536964e..6f677988c71d74c60edcda3002233ffba9d807ed 100644 (file)
@@ -149,6 +149,27 @@ decode_sattr3(__be32 *p, struct iattr *iap)
        return p;
 }
 
+static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
+{
+       u64 f;
+       switch(fsid_source(fhp)) {
+       default:
+       case FSIDSOURCE_DEV:
+               p = xdr_encode_hyper(p, (u64)huge_encode_dev
+                                    (fhp->fh_dentry->d_inode->i_sb->s_dev));
+               break;
+       case FSIDSOURCE_FSID:
+               p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
+               break;
+       case FSIDSOURCE_UUID:
+               f = ((u64*)fhp->fh_export->ex_uuid)[0];
+               f ^= ((u64*)fhp->fh_export->ex_uuid)[1];
+               p = xdr_encode_hyper(p, f);
+               break;
+       }
+       return p;
+}
+
 static __be32 *
 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
@@ -169,10 +190,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
        *p++ = htonl((u32) MAJOR(stat->rdev));
        *p++ = htonl((u32) MINOR(stat->rdev));
-       if (is_fsid(fhp, rqstp->rq_reffh))
-               p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
-       else
-               p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
+       p = encode_fsid(p, fhp);
        p = xdr_encode_hyper(p, (u64) stat->ino);
        p = encode_time3(p, &stat->atime);
        lease_get_mtime(dentry->d_inode, &time); 
@@ -203,10 +221,7 @@ encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
        p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
        *p++ = fhp->fh_post_rdev[0];
        *p++ = fhp->fh_post_rdev[1];
-       if (is_fsid(fhp, rqstp->rq_reffh))
-               p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
-       else
-               p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev));
+       p = encode_fsid(p, fhp);
        p = xdr_encode_hyper(p, (u64) inode->i_ino);
        p = encode_time3(p, &fhp->fh_post_atime);
        p = encode_time3(p, &fhp->fh_post_mtime);
index 5d94555cdc836a4f9ce2f0e998e2d5a734e1ca00..832673b14587da06496a34b35e8a4046439bc502 100644 (file)
 
 /* flags used to simulate posix default ACLs */
 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
-               | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
+               | NFS4_ACE_DIRECTORY_INHERIT_ACE)
 
-#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP)
+#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
+               | NFS4_ACE_INHERIT_ONLY_ACE \
+               | NFS4_ACE_IDENTIFIER_GROUP)
 
 #define MASK_EQUAL(mask1, mask2) \
        ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
@@ -87,12 +89,19 @@ mask_from_posix(unsigned short perm, unsigned int flags)
 }
 
 static u32
-deny_mask(u32 allow_mask, unsigned int flags)
+deny_mask_from_posix(unsigned short perm, u32 flags)
 {
-       u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
-       if (!(flags & NFS4_ACL_DIR))
-               ret &= ~NFS4_ACE_DELETE_CHILD;
-       return ret;
+       u32 mask = 0;
+
+       if (perm & ACL_READ)
+               mask |= NFS4_READ_MODE;
+       if (perm & ACL_WRITE)
+               mask |= NFS4_WRITE_MODE;
+       if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
+               mask |= NFS4_ACE_DELETE_CHILD;
+       if (perm & ACL_EXECUTE)
+               mask |= NFS4_EXECUTE_MODE;
+       return mask;
 }
 
 /* XXX: modify functions to return NFS errors; they're only ever
@@ -126,108 +135,151 @@ struct ace_container {
 };
 
 static short ace2type(struct nfs4_ace *);
-static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
-static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
-static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
+                               unsigned int);
+void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 
 struct nfs4_acl *
 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
                        unsigned int flags)
 {
        struct nfs4_acl *acl;
-       int error = -EINVAL;
+       int size = 0;
 
-       if ((pacl != NULL &&
-               (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
-           (dpacl != NULL &&
-               (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
-               goto out_err;
-
-       acl = nfs4_acl_new();
-       if (acl == NULL) {
-               error = -ENOMEM;
-               goto out_err;
+       if (pacl) {
+               if (posix_acl_valid(pacl) < 0)
+                       return ERR_PTR(-EINVAL);
+               size += 2*pacl->a_count;
        }
-
-       if (pacl != NULL) {
-               error = _posix_to_nfsv4_one(pacl, acl,
-                                               flags & ~NFS4_ACL_TYPE_DEFAULT);
-               if (error < 0)
-                       goto out_acl;
+       if (dpacl) {
+               if (posix_acl_valid(dpacl) < 0)
+                       return ERR_PTR(-EINVAL);
+               size += 2*dpacl->a_count;
        }
 
-       if (dpacl != NULL) {
-               error = _posix_to_nfsv4_one(dpacl, acl,
-                                               flags | NFS4_ACL_TYPE_DEFAULT);
-               if (error < 0)
-                       goto out_acl;
-       }
+       /* Allocate for worst case: one (deny, allow) pair each: */
+       acl = nfs4_acl_new(size);
+       if (acl == NULL)
+               return ERR_PTR(-ENOMEM);
 
-       return acl;
+       if (pacl)
+               _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 
-out_acl:
-       nfs4_acl_free(acl);
-out_err:
-       acl = ERR_PTR(error);
+       if (dpacl)
+               _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
 
        return acl;
 }
 
-static int
-nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
-               uid_t owner, unsigned int flags)
+struct posix_acl_summary {
+       unsigned short owner;
+       unsigned short users;
+       unsigned short group;
+       unsigned short groups;
+       unsigned short other;
+       unsigned short mask;
+};
+
+static void
+summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
 {
-       int error;
-
-       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-                                eflag, mask, whotype, owner);
-       if (error < 0)
-               return error;
-       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                               eflag, deny_mask(mask, flags), whotype, owner);
-       return error;
+       struct posix_acl_entry *pa, *pe;
+       pas->users = 0;
+       pas->groups = 0;
+       pas->mask = 07;
+
+       pe = acl->a_entries + acl->a_count;
+
+       FOREACH_ACL_ENTRY(pa, acl, pe) {
+               switch (pa->e_tag) {
+                       case ACL_USER_OBJ:
+                               pas->owner = pa->e_perm;
+                               break;
+                       case ACL_GROUP_OBJ:
+                               pas->group = pa->e_perm;
+                               break;
+                       case ACL_USER:
+                               pas->users |= pa->e_perm;
+                               break;
+                       case ACL_GROUP:
+                               pas->groups |= pa->e_perm;
+                               break;
+                       case ACL_OTHER:
+                               pas->other = pa->e_perm;
+                               break;
+                       case ACL_MASK:
+                               pas->mask = pa->e_perm;
+                               break;
+               }
+       }
+       /* We'll only care about effective permissions: */
+       pas->users &= pas->mask;
+       pas->group &= pas->mask;
+       pas->groups &= pas->mask;
 }
 
 /* We assume the acl has been verified with posix_acl_valid. */
-static int
+static void
 _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
                                                unsigned int flags)
 {
-       struct posix_acl_entry *pa, *pe, *group_owner_entry;
-       int error = -EINVAL;
-       u32 mask, mask_mask;
+       struct posix_acl_entry *pa, *group_owner_entry;
+       struct nfs4_ace *ace;
+       struct posix_acl_summary pas;
+       unsigned short deny;
        int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
                                        NFS4_INHERITANCE_FLAGS : 0);
 
        BUG_ON(pacl->a_count < 3);
-       pe = pacl->a_entries + pacl->a_count;
-       pa = pe - 2; /* if mask entry exists, it's second from the last. */
-       if (pa->e_tag == ACL_MASK)
-               mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
-       else
-               mask_mask = 0;
+       summarize_posix_acl(pacl, &pas);
 
        pa = pacl->a_entries;
-       BUG_ON(pa->e_tag != ACL_USER_OBJ);
-       mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
-       error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
-       if (error < 0)
-               goto out;
-       pa++;
+       ace = acl->aces + acl->naces;
 
-       while (pa->e_tag == ACL_USER) {
-               mask = mask_from_posix(pa->e_perm, flags);
-               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                               eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
-               if (error < 0)
-                       goto out;
+       /* We could deny everything not granted by the owner: */
+       deny = ~pas.owner;
+       /*
+        * but it is equivalent (and simpler) to deny only what is not
+        * granted by later entries:
+        */
+       deny &= pas.users | pas.group | pas.groups | pas.other;
+       if (deny) {
+               ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+               ace->flag = eflag;
+               ace->access_mask = deny_mask_from_posix(deny, flags);
+               ace->whotype = NFS4_ACL_WHO_OWNER;
+               ace++;
+               acl->naces++;
+       }
 
+       ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+       ace->flag = eflag;
+       ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+       ace->whotype = NFS4_ACL_WHO_OWNER;
+       ace++;
+       acl->naces++;
+       pa++;
 
-               error = nfs4_acl_add_pair(acl, eflag, mask,
-                               NFS4_ACL_WHO_NAMED, pa->e_id, flags);
-               if (error < 0)
-                       goto out;
+       while (pa->e_tag == ACL_USER) {
+               deny = ~(pa->e_perm & pas.mask);
+               deny &= pas.groups | pas.group | pas.other;
+               if (deny) {
+                       ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+                       ace->flag = eflag;
+                       ace->access_mask = deny_mask_from_posix(deny, flags);
+                       ace->whotype = NFS4_ACL_WHO_NAMED;
+                       ace->who = pa->e_id;
+                       ace++;
+                       acl->naces++;
+               }
+               ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+               ace->flag = eflag;
+               ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
+                                                  flags);
+               ace->whotype = NFS4_ACL_WHO_NAMED;
+               ace->who = pa->e_id;
+               ace++;
+               acl->naces++;
                pa++;
        }
 
@@ -236,67 +288,65 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
 
        /* allow ACEs */
 
-       if (pacl->a_count > 3) {
-               BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
-               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
-                               NFS4_ACL_WHO_GROUP, 0);
-               if (error < 0)
-                       goto out;
-       }
        group_owner_entry = pa;
-       mask = mask_from_posix(pa->e_perm, flags);
-       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-                       NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
-                       NFS4_ACL_WHO_GROUP, 0);
-       if (error < 0)
-               goto out;
+
+       ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+       ace->flag = eflag;
+       ace->access_mask = mask_from_posix(pas.group, flags);
+       ace->whotype = NFS4_ACL_WHO_GROUP;
+       ace++;
+       acl->naces++;
        pa++;
 
        while (pa->e_tag == ACL_GROUP) {
-               mask = mask_from_posix(pa->e_perm, flags);
-               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
-                               NFS4_ACL_WHO_NAMED, pa->e_id);
-               if (error < 0)
-                       goto out;
-
-               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
-                               NFS4_ACL_WHO_NAMED, pa->e_id);
-               if (error < 0)
-                       goto out;
+               ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+               ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+               ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
+                                                  flags);
+               ace->whotype = NFS4_ACL_WHO_NAMED;
+               ace->who = pa->e_id;
+               ace++;
+               acl->naces++;
                pa++;
        }
 
        /* deny ACEs */
 
        pa = group_owner_entry;
-       mask = mask_from_posix(pa->e_perm, flags);
-       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                       NFS4_ACE_IDENTIFIER_GROUP | eflag,
-                       deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
-       if (error < 0)
-               goto out;
+
+       deny = ~pas.group & pas.other;
+       if (deny) {
+               ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+               ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+               ace->access_mask = deny_mask_from_posix(deny, flags);
+               ace->whotype = NFS4_ACL_WHO_GROUP;
+               ace++;
+               acl->naces++;
+       }
        pa++;
+
        while (pa->e_tag == ACL_GROUP) {
-               mask = mask_from_posix(pa->e_perm, flags);
-               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-                               NFS4_ACE_IDENTIFIER_GROUP | eflag,
-                               deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
-               if (error < 0)
-                       goto out;
+               deny = ~(pa->e_perm & pas.mask);
+               deny &= pas.other;
+               if (deny) {
+                       ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+                       ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+                       ace->access_mask = mask_from_posix(deny, flags);
+                       ace->whotype = NFS4_ACL_WHO_NAMED;
+                       ace->who = pa->e_id;
+                       ace++;
+                       acl->naces++;
+               }
                pa++;
        }
 
        if (pa->e_tag == ACL_MASK)
                pa++;
-       BUG_ON(pa->e_tag != ACL_OTHER);
-       mask = mask_from_posix(pa->e_perm, flags);
-       error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
-
-out:
-       return error;
+       ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+       ace->flag = eflag;
+       ace->access_mask = mask_from_posix(pa->e_perm, flags);
+       ace->whotype = NFS4_ACL_WHO_EVERYONE;
+       acl->naces++;
 }
 
 static void
@@ -342,46 +392,6 @@ sort_pacl(struct posix_acl *pacl)
        return;
 }
 
-int
-nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
-               struct posix_acl **dpacl, unsigned int flags)
-{
-       struct nfs4_acl *dacl;
-       int error = -ENOMEM;
-
-       *pacl = NULL;
-       *dpacl = NULL;
-
-       dacl = nfs4_acl_new();
-       if (dacl == NULL)
-               goto out;
-
-       error = nfs4_acl_split(acl, dacl);
-       if (error)
-               goto out_acl;
-
-       *pacl = _nfsv4_to_posix_one(acl, flags);
-       if (IS_ERR(*pacl)) {
-               error = PTR_ERR(*pacl);
-               *pacl = NULL;
-               goto out_acl;
-       }
-
-       *dpacl = _nfsv4_to_posix_one(dacl, flags);
-       if (IS_ERR(*dpacl)) {
-               error = PTR_ERR(*dpacl);
-               *dpacl = NULL;
-       }
-out_acl:
-       if (error) {
-               posix_acl_release(*pacl);
-               *pacl = NULL;
-       }
-       nfs4_acl_free(dacl);
-out:
-       return error;
-}
-
 /*
  * While processing the NFSv4 ACE, this maintains bitmasks representing
  * which permission bits have been allowed and which denied to a given
@@ -406,6 +416,7 @@ struct posix_ace_state_array {
  * calculated so far: */
 
 struct posix_acl_state {
+       int empty;
        struct posix_ace_state owner;
        struct posix_ace_state group;
        struct posix_ace_state other;
@@ -421,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt)
        int alloc;
 
        memset(state, 0, sizeof(struct posix_acl_state));
+       state->empty = 1;
        /*
         * In the worst case, each individual acl could be for a distinct
         * named user or group, but we don't no which, so we allocate
@@ -488,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
        int nace;
        int i, error = 0;
 
+       /*
+        * ACLs with no ACEs are treated differently in the inheritable
+        * and effective cases: when there are no inheritable ACEs, we
+        * set a zero-length default posix acl:
+        */
+       if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
+               pacl = posix_acl_alloc(0, GFP_KERNEL);
+               return pacl ? pacl : ERR_PTR(-ENOMEM);
+       }
+       /*
+        * When there are no effective ACEs, the following will end
+        * up setting a 3-element effective posix ACL with all
+        * permissions zero.
+        */
        nace = 4 + state->users->n + state->groups->n;
        pacl = posix_acl_alloc(nace, GFP_KERNEL);
        if (!pacl)
@@ -603,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state,
        u32 mask = ace->access_mask;
        int i;
 
+       state->empty = 0;
+
        switch (ace2type(ace)) {
        case ACL_USER_OBJ:
                if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
@@ -666,75 +694,62 @@ static void process_one_v4_ace(struct posix_acl_state *state,
        }
 }
 
-static struct posix_acl *
-_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
+int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+                           struct posix_acl **dpacl, unsigned int flags)
 {
-       struct posix_acl_state state;
-       struct posix_acl *pacl;
+       struct posix_acl_state effective_acl_state, default_acl_state;
        struct nfs4_ace *ace;
        int ret;
 
-       ret = init_state(&state, n4acl->naces);
+       ret = init_state(&effective_acl_state, acl->naces);
        if (ret)
-               return ERR_PTR(ret);
-
-       list_for_each_entry(ace, &n4acl->ace_head, l_ace)
-               process_one_v4_ace(&state, ace);
-
-       pacl = posix_state_to_acl(&state, flags);
-
-       free_state(&state);
-
-       if (!IS_ERR(pacl))
-               sort_pacl(pacl);
-       return pacl;
-}
-
-static int
-nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
-{
-       struct list_head *h, *n;
-       struct nfs4_ace *ace;
-       int error = 0;
-
-       list_for_each_safe(h, n, &acl->ace_head) {
-               ace = list_entry(h, struct nfs4_ace, l_ace);
-
+               return ret;
+       ret = init_state(&default_acl_state, acl->naces);
+       if (ret)
+               goto out_estate;
+       ret = -EINVAL;
+       for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
                if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
                    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
-                       return -EINVAL;
-
+                       goto out_dstate;
                if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
-                       return -EINVAL;
-
-               switch (ace->flag & NFS4_INHERITANCE_FLAGS) {
-               case 0:
-                       /* Leave this ace in the effective acl: */
+                       goto out_dstate;
+               if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
+                       process_one_v4_ace(&effective_acl_state, ace);
                        continue;
-               case NFS4_INHERITANCE_FLAGS:
-                       /* Add this ace to the default acl and remove it
-                        * from the effective acl: */
-                       error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
-                               ace->access_mask, ace->whotype, ace->who);
-                       if (error)
-                               return error;
-                       list_del(h);
-                       kfree(ace);
-                       acl->naces--;
-                       break;
-               case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE:
-                       /* Add this ace to the default, but leave it in
-                        * the effective acl as well: */
-                       error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
-                               ace->access_mask, ace->whotype, ace->who);
-                       if (error)
-                               return error;
-                       break;
-               default:
-                       return -EINVAL;
                }
+               if (!(flags & NFS4_ACL_DIR))
+                       goto out_dstate;
+               /*
+                * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
+                * is set, we're effectively turning on the other.  That's OK,
+                * according to rfc 3530.
+                */
+               process_one_v4_ace(&default_acl_state, ace);
+
+               if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
+                       process_one_v4_ace(&effective_acl_state, ace);
        }
-       return 0;
+       *pacl = posix_state_to_acl(&effective_acl_state, flags);
+       if (IS_ERR(*pacl)) {
+               ret = PTR_ERR(*pacl);
+               goto out_dstate;
+       }
+       *dpacl = posix_state_to_acl(&default_acl_state,
+                                               flags | NFS4_ACL_TYPE_DEFAULT);
+       if (IS_ERR(*dpacl)) {
+               ret = PTR_ERR(*dpacl);
+               posix_acl_release(*pacl);
+               goto out_dstate;
+       }
+       sort_pacl(*pacl);
+       sort_pacl(*dpacl);
+       ret = 0;
+out_dstate:
+       free_state(&default_acl_state);
+out_estate:
+       free_state(&effective_acl_state);
+       return ret;
 }
 
 static short
@@ -759,48 +774,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
 EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
 
 struct nfs4_acl *
-nfs4_acl_new(void)
+nfs4_acl_new(int n)
 {
        struct nfs4_acl *acl;
 
-       if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
+       acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
+       if (acl == NULL)
                return NULL;
-
        acl->naces = 0;
-       INIT_LIST_HEAD(&acl->ace_head);
-
        return acl;
 }
 
 void
-nfs4_acl_free(struct nfs4_acl *acl)
-{
-       struct list_head *h;
-       struct nfs4_ace *ace;
-
-       if (!acl)
-               return;
-
-       while (!list_empty(&acl->ace_head)) {
-               h = acl->ace_head.next;
-               list_del(h);
-               ace = list_entry(h, struct nfs4_ace, l_ace);
-               kfree(ace);
-       }
-
-       kfree(acl);
-
-       return;
-}
-
-int
 nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
                int whotype, uid_t who)
 {
-       struct nfs4_ace *ace;
-
-       if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
-               return -ENOMEM;
+       struct nfs4_ace *ace = acl->aces + acl->naces;
 
        ace->type = type;
        ace->flag = flag;
@@ -808,10 +797,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
        ace->whotype = whotype;
        ace->who = who;
 
-       list_add_tail(&ace->l_ace, &acl->ace_head);
        acl->naces++;
-
-       return 0;
 }
 
 static struct {
@@ -865,7 +851,6 @@ nfs4_acl_write_who(int who, char *p)
 }
 
 EXPORT_SYMBOL(nfs4_acl_new);
-EXPORT_SYMBOL(nfs4_acl_free);
 EXPORT_SYMBOL(nfs4_acl_add_ace);
 EXPORT_SYMBOL(nfs4_acl_get_whotype);
 EXPORT_SYMBOL(nfs4_acl_write_who);
index f57655a7a2b66b9ae1b1567e9d5500b581a5c9ae..fb14d68eacab846db08f92bbcdca7a1aff56e43c 100644 (file)
@@ -387,7 +387,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
                .address        = (struct sockaddr *)&addr,
                .addrsize       = sizeof(addr),
                .timeout        = &timeparms,
-               .servername     = clp->cl_name.data,
                .program        = program,
                .version        = nfs_cb_version[1]->number,
                .authflavor     = RPC_AUTH_UNIX,        /* XXX: need AUTH_GSS... */
@@ -397,6 +396,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
                .rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
                .rpc_argp       = clp,
        };
+       char clientname[16];
        int status;
 
        if (atomic_read(&cb->cb_set))
@@ -419,6 +419,11 @@ nfsd4_probe_callback(struct nfs4_client *clp)
        memset(program->stats, 0, sizeof(cb->cb_stat));
        program->stats->program = program;
 
+       /* Just here to make some printk's more useful: */
+       snprintf(clientname, sizeof(clientname),
+               "%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
+       args.servername = clientname;
+
        /* Create RPC client */
        cb->cb_client = rpc_create(&args);
        if (IS_ERR(cb->cb_client)) {
index b1902ebaab4158d03cbe1482426d89de80f76fd7..e4a83d727afda0e2f85e293783dce44b2e351fd5 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/sunrpc/cache.h>
 #include <linux/nfsd_idmap.h>
 #include <linux/list.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/seq_file.h>
 #include <linux/sunrpc/svcauth.h>
index 18aa9440df14400eaf63f3d2d7cdedfff8b1952d..5d090f11f2bee92c3e371fbd0ae982df7d6a758d 100644 (file)
@@ -199,24 +199,22 @@ defer_free(struct nfsd4_compoundargs *argp,
 
 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 {
-       void *new = NULL;
        if (p == argp->tmp) {
-               new = kmalloc(nbytes, GFP_KERNEL);
-               if (!new) return NULL;
-               p = new;
+               p = kmalloc(nbytes, GFP_KERNEL);
+               if (!p)
+                       return NULL;
                memcpy(p, argp->tmp, nbytes);
        } else {
                BUG_ON(p != argp->tmpp);
                argp->tmpp = NULL;
        }
        if (defer_free(argp, kfree, p)) {
-               kfree(new);
+               kfree(p);
                return NULL;
        } else
                return (char *)p;
 }
 
-
 static __be32
 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 {
@@ -255,7 +253,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
                return status;
 
        /*
-        * According to spec, unsupported attributes return ERR_NOTSUPP;
+        * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
         * read-only attributes return ERR_INVAL.
         */
        if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
@@ -273,42 +271,42 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
                iattr->ia_valid |= ATTR_SIZE;
        }
        if (bmval[0] & FATTR4_WORD0_ACL) {
-               int nace, i;
-               struct nfs4_ace ace;
+               int nace;
+               struct nfs4_ace *ace;
 
                READ_BUF(4); len += 4;
                READ32(nace);
 
-               *acl = nfs4_acl_new();
+               if (nace > NFS4_ACL_MAX)
+                       return nfserr_resource;
+
+               *acl = nfs4_acl_new(nace);
                if (*acl == NULL) {
                        host_err = -ENOMEM;
                        goto out_nfserr;
                }
-               defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
+               defer_free(argp, kfree, *acl);
 
-               for (i = 0; i < nace; i++) {
+               (*acl)->naces = nace;
+               for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
                        READ_BUF(16); len += 16;
-                       READ32(ace.type);
-                       READ32(ace.flag);
-                       READ32(ace.access_mask);
+                       READ32(ace->type);
+                       READ32(ace->flag);
+                       READ32(ace->access_mask);
                        READ32(dummy32);
                        READ_BUF(dummy32);
                        len += XDR_QUADLEN(dummy32) << 2;
                        READMEM(buf, dummy32);
-                       ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
+                       ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
                        host_err = 0;
-                       if (ace.whotype != NFS4_ACL_WHO_NAMED)
-                               ace.who = 0;
-                       else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
+                       if (ace->whotype != NFS4_ACL_WHO_NAMED)
+                               ace->who = 0;
+                       else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
                                host_err = nfsd_map_name_to_gid(argp->rqstp,
-                                               buf, dummy32, &ace.who);
+                                               buf, dummy32, &ace->who);
                        else
                                host_err = nfsd_map_name_to_uid(argp->rqstp,
-                                               buf, dummy32, &ace.who);
-                       if (host_err)
-                               goto out_nfserr;
-                       host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
-                                ace.access_mask, ace.whotype, ace.who);
+                                               buf, dummy32, &ace->who);
                        if (host_err)
                                goto out_nfserr;
                }
@@ -1563,14 +1561,20 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                if (exp->ex_fslocs.migrated) {
                        WRITE64(NFS4_REFERRAL_FSID_MAJOR);
                        WRITE64(NFS4_REFERRAL_FSID_MINOR);
-               } else if (is_fsid(fhp, rqstp->rq_reffh)) {
+               } else switch(fsid_source(fhp)) {
+               case FSIDSOURCE_FSID:
                        WRITE64((u64)exp->ex_fsid);
                        WRITE64((u64)0);
-               } else {
+                       break;
+               case FSIDSOURCE_DEV:
                        WRITE32(0);
                        WRITE32(MAJOR(stat.dev));
                        WRITE32(0);
                        WRITE32(MINOR(stat.dev));
+                       break;
+               case FSIDSOURCE_UUID:
+                       WRITEMEM(exp->ex_uuid, 16);
+                       break;
                }
        }
        if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
@@ -1590,7 +1594,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
        }
        if (bmval0 & FATTR4_WORD0_ACL) {
                struct nfs4_ace *ace;
-               struct list_head *h;
 
                if (acl == NULL) {
                        if ((buflen -= 4) < 0)
@@ -1603,9 +1606,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                        goto out_resource;
                WRITE32(acl->naces);
 
-               list_for_each(h, &acl->ace_head) {
-                       ace = list_entry(h, struct nfs4_ace, l_ace);
-
+               for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
                        if ((buflen -= 4*3) < 0)
                                goto out_resource;
                        WRITE32(ace->type);
@@ -1815,7 +1816,7 @@ out_acl:
        status = nfs_ok;
 
 out:
-       nfs4_acl_free(acl);
+       kfree(acl);
        if (fhp == &tempfh)
                fh_put(&tempfh);
        return status;
index eedf2e3990a9a8f3d0bdad85faa119f4eef4ef97..71c686dc7257140f3c12c7cd0549d93af3f48816 100644 (file)
@@ -123,7 +123,7 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
                return PTR_ERR(data);
 
        rv =  write_op[ino](file, data, size);
-       if (rv>0) {
+       if (rv >= 0) {
                simple_transaction_set(file, rv);
                rv = size;
        }
index a0b4282cb2849579aa2b38f0e3c38705cb65dd87..c2660cbfcd96edac59b82419fd31c347c1b05f59 100644 (file)
@@ -9,7 +9,6 @@
  * ... and again Southern-Winter 2001 to support export_operations
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
@@ -119,9 +118,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 
        dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
-       /* keep this filehandle for possible reference  when encoding attributes */
-       rqstp->rq_reffh = fh;
-
        if (!fhp->fh_dentry) {
                __u32 *datap=NULL;
                __u32 tfh[3];           /* filehandle fragment for oldstyle filehandles */
@@ -146,10 +142,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                        }
                        len = key_len(fh->fh_fsid_type) / 4;
                        if (len == 0) goto out;
-                       if  (fh->fh_fsid_type == 2) {
+                       if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
                                /* deprecated, convert to type 3 */
-                               len = 3;
-                               fh->fh_fsid_type = 3;
+                               len = key_len(FSID_ENCODE_DEV)/4;
+                               fh->fh_fsid_type = FSID_ENCODE_DEV;
                                fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
                                fh->fh_fsid[1] = fh->fh_fsid[2];
                        }
@@ -164,8 +160,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                        /* assume old filehandle format */
                        xdev = old_decode_dev(fh->ofh_xdev);
                        xino = u32_to_ino_t(fh->ofh_xino);
-                       mk_fsid_v0(tfh, xdev, xino);
-                       exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
+                       mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+                       exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
+                                      &rqstp->rq_chandle);
                }
 
                if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
@@ -212,7 +209,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                                fileid_type = 2;
                } else
                        fileid_type = fh->fh_fileid_type;
-               
+
                if (fileid_type == 0)
                        dentry = dget(exp->ex_dentry);
                else {
@@ -292,7 +289,7 @@ static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
                             __u32 *datap, int *maxsize)
 {
        struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-       
+
        if (dentry == exp->ex_dentry) {
                *maxsize = 0;
                return 0;
@@ -317,7 +314,8 @@ static inline void _fh_update_old(struct dentry *dentry,
 }
 
 __be32
-fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
+fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+          struct svc_fh *ref_fh)
 {
        /* ref_fh is a reference file handle.
         * if it is non-null and for the same filesystem, then we should compose
@@ -327,12 +325,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
         *
         */
 
-       u8 ref_fh_version = 0;
-       u8 ref_fh_fsid_type = 0;
+       u8 version = 1;
+       u8 fsid_type = 0;
        struct inode * inode = dentry->d_inode;
        struct dentry *parent = dentry->d_parent;
        __u32 *datap;
        dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
+       int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root);
 
        dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
                MAJOR(ex_dev), MINOR(ex_dev),
@@ -340,57 +339,64 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
                parent->d_name.name, dentry->d_name.name,
                (inode ? inode->i_ino : 0));
 
+       /* Choose filehandle version and fsid type based on
+        * the reference filehandle (if it is in the same export)
+        * or the export options.
+        */
        if (ref_fh && ref_fh->fh_export == exp) {
-               ref_fh_version = ref_fh->fh_handle.fh_version;
-               if (ref_fh_version == 0xca)
-                       ref_fh_fsid_type = 0;
+               version = ref_fh->fh_handle.fh_version;
+               if (version == 0xca)
+                       fsid_type = FSID_DEV;
                else
-                       ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
-               if (ref_fh_fsid_type > 3)
-                       ref_fh_fsid_type = 0;
-
-               /* make sure ref_fh type works for given export */
-               if (ref_fh_fsid_type == 1 &&
-                   !(exp->ex_flags & NFSEXP_FSID)) {
-                       /* if we don't have an fsid, we cannot provide one... */
-                       ref_fh_fsid_type = 0;
+                       fsid_type = ref_fh->fh_handle.fh_fsid_type;
+               /* We know this version/type works for this export
+                * so there is no need for further checks.
+                */
+       } else if (exp->ex_uuid) {
+               if (fhp->fh_maxsize >= 64) {
+                       if (root_export)
+                               fsid_type = FSID_UUID16;
+                       else
+                               fsid_type = FSID_UUID16_INUM;
+               } else {
+                       if (root_export)
+                               fsid_type = FSID_UUID8;
+                       else
+                               fsid_type = FSID_UUID4_INUM;
                }
        } else if (exp->ex_flags & NFSEXP_FSID)
-               ref_fh_fsid_type = 1;
-
-       if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) {
+               fsid_type = FSID_NUM;
+       else if (!old_valid_dev(ex_dev))
                /* for newer device numbers, we must use a newer fsid format */
-               ref_fh_version = 1;
-               ref_fh_fsid_type = 3;
-       }
-       if (old_valid_dev(ex_dev) &&
-           (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3))
-               /* must use type1 for smaller device numbers */
-               ref_fh_fsid_type = 0;
+               fsid_type = FSID_ENCODE_DEV;
+       else
+               fsid_type = FSID_DEV;
 
        if (ref_fh == fhp)
                fh_put(ref_fh);
 
        if (fhp->fh_locked || fhp->fh_dentry) {
                printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
-                       parent->d_name.name, dentry->d_name.name);
+                      parent->d_name.name, dentry->d_name.name);
        }
        if (fhp->fh_maxsize < NFS_FHSIZE)
                printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
-                      fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
+                      fhp->fh_maxsize,
+                      parent->d_name.name, dentry->d_name.name);
 
        fhp->fh_dentry = dget(dentry); /* our internal copy */
        fhp->fh_export = exp;
        cache_get(&exp->h);
 
-       if (ref_fh_version == 0xca) {
+       if (version == 0xca) {
                /* old style filehandle please */
                memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
                fhp->fh_handle.fh_size = NFS_FHSIZE;
                fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
                fhp->fh_handle.ofh_dev =  old_encode_dev(ex_dev);
                fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
-               fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
+               fhp->fh_handle.ofh_xino =
+                       ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
                fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
                if (inode)
                        _fh_update_old(dentry, exp, &fhp->fh_handle);
@@ -399,38 +405,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
                fhp->fh_handle.fh_version = 1;
                fhp->fh_handle.fh_auth_type = 0;
                datap = fhp->fh_handle.fh_auth+0;
-               fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type;
-               switch (ref_fh_fsid_type) {
-                       case 0:
-                               /*
-                                * fsid_type 0:
-                                * 2byte major, 2byte minor, 4byte inode
-                                */
-                               mk_fsid_v0(datap, ex_dev,
-                                       exp->ex_dentry->d_inode->i_ino);
-                               break;
-                       case 1:
-                               /* fsid_type 1 == 4 bytes filesystem id */
-                               mk_fsid_v1(datap, exp->ex_fsid);
-                               break;
-                       case 2:
-                               /*
-                                * fsid_type 2:
-                                * 4byte major, 4byte minor, 4byte inode
-                                */
-                               mk_fsid_v2(datap, ex_dev,
-                                       exp->ex_dentry->d_inode->i_ino);
-                               break;
-                       case 3:
-                               /*
-                                * fsid_type 3:
-                                * 4byte devicenumber, 4byte inode
-                                */
-                               mk_fsid_v3(datap, ex_dev,
-                                       exp->ex_dentry->d_inode->i_ino);
-                               break;
-               }
-               len = key_len(ref_fh_fsid_type);
+               fhp->fh_handle.fh_fsid_type = fsid_type;
+               mk_fsid(fsid_type, datap, ex_dev,
+                       exp->ex_dentry->d_inode->i_ino,
+                       exp->ex_fsid, exp->ex_uuid);
+
+               len = key_len(fsid_type);
                datap += len/4;
                fhp->fh_handle.fh_size = 4 + len;
 
@@ -457,7 +437,7 @@ fh_update(struct svc_fh *fhp)
 {
        struct dentry *dentry;
        __u32 *datap;
-       
+
        if (!fhp->fh_dentry)
                goto out_bad;
 
@@ -534,3 +514,22 @@ char * SVCFH_fmt(struct svc_fh *fhp)
                fh->fh_base.fh_pad[5]);
        return buf;
 }
+
+enum fsid_source fsid_source(struct svc_fh *fhp)
+{
+       if (fhp->fh_handle.fh_version != 1)
+               return FSIDSOURCE_DEV;
+       switch(fhp->fh_handle.fh_fsid_type) {
+       case FSID_DEV:
+       case FSID_ENCODE_DEV:
+       case FSID_MAJOR_MINOR:
+               return FSIDSOURCE_DEV;
+       case FSID_NUM:
+               return FSIDSOURCE_FSID;
+       default:
+               if (fhp->fh_export->ex_flags & NFSEXP_FSID)
+                       return FSIDSOURCE_FSID;
+               else
+                       return FSIDSOURCE_UUID;
+       }
+}
index 6555c50d9006966f37f659f39e837c30a53c7c03..0c24b9e24fe866683a357f1a9e8b08bcb2fbe30c 100644 (file)
@@ -153,6 +153,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        struct dentry   *dentry = fhp->fh_dentry;
        int type;
        struct timespec time;
+       u32 f;
 
        type = (stat->mode & S_IFMT);
 
@@ -173,10 +174,22 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        else
                *p++ = htonl(0xffffffff);
        *p++ = htonl((u32) stat->blocks);
-       if (is_fsid(fhp, rqstp->rq_reffh))
-               *p++ = htonl((u32) fhp->fh_export->ex_fsid);
-       else
+       switch (fsid_source(fhp)) {
+       default:
+       case FSIDSOURCE_DEV:
                *p++ = htonl(new_encode_dev(stat->dev));
+               break;
+       case FSIDSOURCE_FSID:
+               *p++ = htonl((u32) fhp->fh_export->ex_fsid);
+               break;
+       case FSIDSOURCE_UUID:
+               f = ((u32*)fhp->fh_export->ex_uuid)[0];
+               f ^= ((u32*)fhp->fh_export->ex_uuid)[1];
+               f ^= ((u32*)fhp->fh_export->ex_uuid)[2];
+               f ^= ((u32*)fhp->fh_export->ex_uuid)[3];
+               *p++ = htonl(f);
+               break;
+       }
        *p++ = htonl((u32) stat->ino);
        *p++ = htonl((u32) stat->atime.tv_sec);
        *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
index 8283236c6a0f1f8034f5006ed484cf4b2bb758eb..7e6aa245b5d5f30b270c5336267eb77760be41ac 100644 (file)
@@ -466,7 +466,10 @@ out:
        posix_acl_release(dpacl);
        return (error);
 out_nfserr:
-       error = nfserrno(host_error);
+       if (host_error == -EOPNOTSUPP)
+               error = nfserr_attrnotsupp;
+       else
+               error = nfserrno(host_error);
        goto out;
 }
 
index 1c23138d00b340287664ee3587e6518e368a905a..4847fbfb0107af9a687dccdd4a77f9c3690bdf02 100644 (file)
 #include "sysctl.h"
 #include "debug.h"
 
-#define FS_NTFS        1
-
 /* Definition of the ntfs sysctl. */
 static ctl_table ntfs_sysctls[] = {
-       { FS_NTFS, "ntfs-debug",                /* Binary and text IDs. */
-         &debug_msgs,sizeof(debug_msgs),       /* Data pointer and size. */
-         0644, NULL, &proc_dointvec },         /* Mode, child, proc handler. */
-       { 0 }
+       {
+               .ctl_name       = CTL_UNNUMBERED,       /* Binary and text IDs. */
+               .procname       = "ntfs-debug",
+               .data           = &debug_msgs,          /* Data pointer and size. */
+               .maxlen         = sizeof(debug_msgs),
+               .mode           = 0644,                 /* Mode, proc handler. */
+               .proc_handler   = &proc_dointvec
+       },
+       {}
 };
 
 /* Define the parent directory /proc/sys/fs. */
 static ctl_table sysctls_root[] = {
-       { CTL_FS, "fs", NULL, 0, 0555, ntfs_sysctls },
-       { 0 }
+       {
+               .ctl_name       = CTL_FS,
+               .procname       = "fs",
+               .mode           = 0555,
+               .child          = ntfs_sysctls
+       },
+       {}
 };
 
 /* Storage for the sysctls header. */
@@ -62,17 +70,9 @@ int ntfs_sysctl(int add)
 {
        if (add) {
                BUG_ON(sysctls_root_table);
-               sysctls_root_table = register_sysctl_table(sysctls_root, 0);
+               sysctls_root_table = register_sysctl_table(sysctls_root);
                if (!sysctls_root_table)
                        return -ENOMEM;
-#ifdef CONFIG_PROC_FS
-               /*
-                * If the proc filesystem is in use and we are a module, need
-                * to set the owner of our proc entry to our module. In the
-                * non-modular case, THIS_MODULE is NULL, so this is ok.
-                */
-               ntfs_sysctls[0].de->owner = THIS_MODULE;
-#endif
        } else {
                BUG_ON(!sysctls_root_table);
                unregister_sysctl_table(sysctls_root_table);
index b17333a0606b55cf641ae90c3997918e7ef64992..9f5ad0f01ce0d885e787003d07c4fa0907139dc0 100644 (file)
@@ -55,7 +55,7 @@ static ctl_table ocfs2_nm_table[] = {
 
 static ctl_table ocfs2_mod_table[] = {
        {
-               .ctl_name       = KERN_OCFS2_NM,
+               .ctl_name       = FS_OCFS2_NM,
                .procname       = "nm",
                .data           = NULL,
                .maxlen         = 0,
@@ -67,7 +67,7 @@ static ctl_table ocfs2_mod_table[] = {
 
 static ctl_table ocfs2_kern_table[] = {
        {
-               .ctl_name       = KERN_OCFS2,
+               .ctl_name       = FS_OCFS2,
                .procname       = "ocfs2",
                .data           = NULL,
                .maxlen         = 0,
@@ -922,7 +922,7 @@ static int __init init_o2nm(void)
        o2hb_init();
        o2net_init();
 
-       ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0);
+       ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
        if (!ocfs2_table_header) {
                printk(KERN_ERR "nodemanager: unable to register sysctl\n");
                ret = -ENOMEM; /* or something. */
index 8fb23cacc2f5f15308b7288321a503eb5322fa0d..070522138ae26c1b10f0f50683a48b5c53f5bf8e 100644 (file)
@@ -33,8 +33,7 @@
 #include <linux/configfs.h>
 #include <linux/rbtree.h>
 
-#define KERN_OCFS2             988
-#define KERN_OCFS2_NM          1
+#define FS_OCFS2_NM            1
 
 const char *o2nm_get_hb_ctl_path(void);
 
index f7fa52bb3f6b66c2a94d5a1188946f028c1b8a97..28dd757ff67dfee2c480aa334f643f508318705f 100644 (file)
@@ -1098,7 +1098,7 @@ static int ocfs2_rename(struct inode *old_dir,
                        BUG();
        }
 
-       /* Assume a directory heirarchy thusly:
+       /* Assume a directory hierarchy thusly:
         * a/b/c
         * a/d
         * a,b,c, and d are all directories.
index ac32a2e8540c4fb2ac34c1c27286f1a0d624fbd1..22d38ffc9ef0b892c65e8c380f6f6682bacb398a 100644 (file)
@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part)
        p->ios[0] = p->ios[1] = 0;
        p->sectors[0] = p->sectors[1] = 0;
        sysfs_remove_link(&p->kobj, "subsystem");
-       if (p->holder_dir)
-               kobject_unregister(p->holder_dir);
+       kobject_unregister(p->holder_dir);
        kobject_uevent(&p->kobj, KOBJ_REMOVE);
        kobject_del(&p->kobj);
        kobject_put(&p->kobj);
@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk)
        disk->stamp = 0;
 
        kobject_uevent(&disk->kobj, KOBJ_REMOVE);
-       if (disk->holder_dir)
-               kobject_unregister(disk->holder_dir);
-       if (disk->slave_dir)
-               kobject_unregister(disk->slave_dir);
+       kobject_unregister(disk->holder_dir);
+       kobject_unregister(disk->slave_dir);
        if (disk->driverfs_dev) {
                char *disk_name = make_block_name(disk);
                sysfs_remove_link(&disk->kobj, "device");
index 68090e84f589305ebe80ee57e723c86494ca6143..ebafde7d6abab948f9fa3a23e71f39360c757c71 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -16,6 +16,7 @@
 #include <linux/uio.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -985,6 +986,10 @@ int do_pipe(int *fd)
                goto err_fdr;
        fdw = error;
 
+       error = audit_fd_pair(fdr, fdw);
+       if (error < 0)
+               goto err_fdw;
+
        fd_install(fdr, fr);
        fd_install(fdw, fw);
        fd[0] = fdr;
@@ -992,6 +997,8 @@ int do_pipe(int *fd)
 
        return 0;
 
+ err_fdw:
+       put_unused_fd(fdw);
  err_fdr:
        put_unused_fd(fdr);
  err_read_pipe:
index f6c7762725727b49af2e7b4afbdff56a2440f822..a6b3a8f878f0e2eb2aef668b7a3cec03c4402f5a 100644 (file)
@@ -8,7 +8,7 @@ proc-y                  := nommu.o task_nommu.o
 proc-$(CONFIG_MMU)     := mmu.o task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
-               proc_tty.o proc_misc.o
+               proc_tty.o proc_misc.o proc_sysctl.o
 
 proc-$(CONFIG_PROC_KCORE)      += kcore.o
 proc-$(CONFIG_PROC_VMCORE)     += vmcore.o
index 0cdc00d9d97e5feb9e9e5872029e067527c8dea7..775fb21294d821419ed6b7e0939d963dd6d00e87 100644 (file)
@@ -32,7 +32,7 @@ static loff_t proc_file_lseek(struct file *, loff_t, int);
 
 DEFINE_SPINLOCK(proc_subdir_lock);
 
-int proc_match(int len, const char *name, struct proc_dir_entry *de)
+static int proc_match(int len, const char *name, struct proc_dir_entry *de)
 {
        if (de->namelen != len)
                return 0;
index f6722be37ddeedd46ea72035de7e16427c78a090..c372eb151a3aa7a0198f6705159bb18b4471617f 100644 (file)
@@ -161,6 +161,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
        if (!inode)
                goto out_ino;
 
+       PROC_I(inode)->fd = 0;
        PROC_I(inode)->pde = de;
        if (de) {
                if (de->mode) {
index 277dcd66ebe20eab6d87d1f99ab2b21aab8ddcf9..c932aa65e19816e85ca78d95b2795e80513e0409 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <linux/proc_fs.h>
 
+extern int proc_sys_init(void);
+
 struct vmalloc_info {
        unsigned long   used;
        unsigned long   largest_chunk;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
new file mode 100644 (file)
index 0000000..20e8cbb
--- /dev/null
@@ -0,0 +1,479 @@
+/*
+ * /proc/sys support
+ */
+
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include "internal.h"
+
+static struct dentry_operations proc_sys_dentry_operations;
+static const struct file_operations proc_sys_file_operations;
+static struct inode_operations proc_sys_inode_operations;
+
+static void proc_sys_refresh_inode(struct inode *inode, struct ctl_table *table)
+{
+       /* Refresh the cached information bits in the inode */
+       if (table) {
+               inode->i_uid = 0;
+               inode->i_gid = 0;
+               inode->i_mode = table->mode;
+               if (table->proc_handler) {
+                       inode->i_mode |= S_IFREG;
+                       inode->i_nlink = 1;
+               } else {
+                       inode->i_mode |= S_IFDIR;
+                       inode->i_nlink = 0;     /* It is too hard to figure out */
+               }
+       }
+}
+
+static struct inode *proc_sys_make_inode(struct inode *dir, struct ctl_table *table)
+{
+       struct inode *inode;
+       struct proc_inode *dir_ei, *ei;
+       int depth;
+
+       inode = new_inode(dir->i_sb);
+       if (!inode)
+               goto out;
+
+       /* A directory is always one deeper than it's parent */
+       dir_ei = PROC_I(dir);
+       depth = dir_ei->fd + 1;
+
+       ei = PROC_I(inode);
+       ei->fd = depth;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+       inode->i_op = &proc_sys_inode_operations;
+       inode->i_fop = &proc_sys_file_operations;
+       inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
+       proc_sys_refresh_inode(inode, table);
+out:
+       return inode;
+}
+
+static struct dentry *proc_sys_ancestor(struct dentry *dentry, int depth)
+{
+       for (;;) {
+               struct proc_inode *ei;
+
+               ei = PROC_I(dentry->d_inode);
+               if (ei->fd == depth)
+                       break; /* found */
+
+               dentry = dentry->d_parent;
+       }
+       return dentry;
+}
+
+static struct ctl_table *proc_sys_lookup_table_one(struct ctl_table *table,
+                                                       struct qstr *name)
+{
+       int len;
+       for ( ; table->ctl_name || table->procname; table++) {
+
+               if (!table->procname)
+                       continue;
+
+               len = strlen(table->procname);
+               if (len != name->len)
+                       continue;
+
+               if (memcmp(table->procname, name->name, len) != 0)
+                       continue;
+
+               /* I have a match */
+               return table;
+       }
+       return NULL;
+}
+
+static struct ctl_table *proc_sys_lookup_table(struct dentry *dentry,
+                                               struct ctl_table *table)
+{
+       struct dentry *ancestor;
+       struct proc_inode *ei;
+       int depth, i;
+
+       ei = PROC_I(dentry->d_inode);
+       depth = ei->fd;
+
+       if (depth == 0)
+               return table;
+
+       for (i = 1; table && (i <= depth); i++) {
+               ancestor = proc_sys_ancestor(dentry, i);
+               table = proc_sys_lookup_table_one(table, &ancestor->d_name);
+               if (table)
+                       table = table->child;
+       }
+       return table;
+
+}
+static struct ctl_table *proc_sys_lookup_entry(struct dentry *dparent,
+                                               struct qstr *name,
+                                               struct ctl_table *table)
+{
+       table = proc_sys_lookup_table(dparent, table);
+       if (table)
+               table = proc_sys_lookup_table_one(table, name);
+       return table;
+}
+
+static struct ctl_table *do_proc_sys_lookup(struct dentry *parent,
+                                               struct qstr *name,
+                                               struct ctl_table_header **ptr)
+{
+       struct ctl_table_header *head;
+       struct ctl_table *table = NULL;
+
+       for (head = sysctl_head_next(NULL); head;
+                       head = sysctl_head_next(head)) {
+               table = proc_sys_lookup_entry(parent, name, head->ctl_table);
+               if (table)
+                       break;
+       }
+       *ptr = head;
+       return table;
+}
+
+static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
+                                       struct nameidata *nd)
+{
+       struct ctl_table_header *head;
+       struct inode *inode;
+       struct dentry *err;
+       struct ctl_table *table;
+
+       err = ERR_PTR(-ENOENT);
+       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+       if (!table)
+               goto out;
+
+       err = ERR_PTR(-ENOMEM);
+       inode = proc_sys_make_inode(dir, table);
+       if (!inode)
+               goto out;
+
+       err = NULL;
+       dentry->d_op = &proc_sys_dentry_operations;
+       d_add(dentry, inode);
+
+out:
+       sysctl_head_finish(head);
+       return err;
+}
+
+static ssize_t proc_sys_read(struct file *filp, char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       struct dentry *dentry = filp->f_dentry;
+       struct ctl_table_header *head;
+       struct ctl_table *table;
+       ssize_t error, res;
+
+       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+       /* Has the sysctl entry disappeared on us? */
+       error = -ENOENT;
+       if (!table)
+               goto out;
+
+       /* Has the sysctl entry been replaced by a directory? */
+       error = -EISDIR;
+       if (!table->proc_handler)
+               goto out;
+
+       /*
+        * At this point we know that the sysctl was not unregistered
+        * and won't be until we finish.
+        */
+       error = -EPERM;
+       if (sysctl_perm(table, MAY_READ))
+               goto out;
+
+       /* careful: calling conventions are nasty here */
+       res = count;
+       error = table->proc_handler(table, 0, filp, buf, &res, ppos);
+       if (!error)
+               error = res;
+out:
+       sysctl_head_finish(head);
+
+       return error;
+}
+
+static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       struct dentry *dentry = filp->f_dentry;
+       struct ctl_table_header *head;
+       struct ctl_table *table;
+       ssize_t error, res;
+
+       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+       /* Has the sysctl entry disappeared on us? */
+       error = -ENOENT;
+       if (!table)
+               goto out;
+
+       /* Has the sysctl entry been replaced by a directory? */
+       error = -EISDIR;
+       if (!table->proc_handler)
+               goto out;
+
+       /*
+        * At this point we know that the sysctl was not unregistered
+        * and won't be until we finish.
+        */
+       error = -EPERM;
+       if (sysctl_perm(table, MAY_WRITE))
+               goto out;
+
+       /* careful: calling conventions are nasty here */
+       res = count;
+       error = table->proc_handler(table, 1, filp, (char __user *)buf,
+                                   &res, ppos);
+       if (!error)
+               error = res;
+out:
+       sysctl_head_finish(head);
+
+       return error;
+}
+
+
+static int proc_sys_fill_cache(struct file *filp, void *dirent,
+                               filldir_t filldir, struct ctl_table *table)
+{
+       struct ctl_table_header *head;
+       struct ctl_table *child_table = NULL;
+       struct dentry *child, *dir = filp->f_path.dentry;
+       struct inode *inode;
+       struct qstr qname;
+       ino_t ino = 0;
+       unsigned type = DT_UNKNOWN;
+       int ret;
+
+       qname.name = table->procname;
+       qname.len  = strlen(table->procname);
+       qname.hash = full_name_hash(qname.name, qname.len);
+
+       /* Suppress duplicates.
+        * Only fill a directory entry if it is the value that
+        * an ordinary lookup of that name returns.  Hide all
+        * others.
+        *
+        * If we ever cache this translation in the dcache
+        * I should do a dcache lookup first.  But for now
+        * it is just simpler not to.
+        */
+       ret = 0;
+       child_table = do_proc_sys_lookup(dir, &qname, &head);
+       sysctl_head_finish(head);
+       if (child_table != table)
+               return 0;
+
+       child = d_lookup(dir, &qname);
+       if (!child) {
+               struct dentry *new;
+               new = d_alloc(dir, &qname);
+               if (new) {
+                       inode = proc_sys_make_inode(dir->d_inode, table);
+                       if (!inode)
+                               child = ERR_PTR(-ENOMEM);
+                       else {
+                               new->d_op = &proc_sys_dentry_operations;
+                               d_add(new, inode);
+                       }
+                       if (child)
+                               dput(new);
+                       else
+                               child = new;
+               }
+       }
+       if (!child || IS_ERR(child) || !child->d_inode)
+               goto end_instantiate;
+       inode = child->d_inode;
+       if (inode) {
+               ino  = inode->i_ino;
+               type = inode->i_mode >> 12;
+       }
+       dput(child);
+end_instantiate:
+       if (!ino)
+               ino= find_inode_number(dir, &qname);
+       if (!ino)
+               ino = 1;
+       return filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
+}
+
+static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct dentry *dentry = filp->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       struct ctl_table_header *head = NULL;
+       struct ctl_table *table;
+       unsigned long pos;
+       int ret;
+
+       ret = -ENOTDIR;
+       if (!S_ISDIR(inode->i_mode))
+               goto out;
+
+       ret = 0;
+       /* Avoid a switch here: arm builds fail with missing __cmpdi2 */
+       if (filp->f_pos == 0) {
+               if (filldir(dirent, ".", 1, filp->f_pos,
+                               inode->i_ino, DT_DIR) < 0)
+                       goto out;
+               filp->f_pos++;
+       }
+       if (filp->f_pos == 1) {
+               if (filldir(dirent, "..", 2, filp->f_pos,
+                               parent_ino(dentry), DT_DIR) < 0)
+                       goto out;
+               filp->f_pos++;
+       }
+       pos = 2;
+
+       /* - Find each instance of the directory
+        * - Read all entries in each instance
+        * - Before returning an entry to user space lookup the entry
+        *   by name and if I find a different entry don't return
+        *   this one because it means it is a buried dup.
+        * For sysctl this should only happen for directory entries.
+        */
+       for (head = sysctl_head_next(NULL); head; head = sysctl_head_next(head)) {
+               table = proc_sys_lookup_table(dentry, head->ctl_table);
+
+               if (!table)
+                       continue;
+
+               for (; table->ctl_name || table->procname; table++, pos++) {
+                       /* Can't do anything without a proc name */
+                       if (!table->procname)
+                               continue;
+
+                       if (pos < filp->f_pos)
+                               continue;
+
+                       if (proc_sys_fill_cache(filp, dirent, filldir, table) < 0)
+                               goto out;
+                       filp->f_pos = pos + 1;
+               }
+       }
+       ret = 1;
+out:
+       sysctl_head_finish(head);
+       return ret;
+}
+
+static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       /*
+        * sysctl entries that are not writeable,
+        * are _NOT_ writeable, capabilities or not.
+        */
+       struct ctl_table_header *head;
+       struct ctl_table *table;
+       struct dentry *dentry;
+       int mode;
+       int depth;
+       int error;
+
+       head = NULL;
+       depth = PROC_I(inode)->fd;
+
+       /* First check the cached permissions, in case we don't have
+        * enough information to lookup the sysctl table entry.
+        */
+       error = -EACCES;
+       mode = inode->i_mode;
+
+       if (current->euid == 0)
+               mode >>= 6;
+       else if (in_group_p(0))
+               mode >>= 3;
+
+       if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
+               error = 0;
+
+       /* If we can't get a sysctl table entry the permission
+        * checks on the cached mode will have to be enough.
+        */
+       if (!nd || !depth)
+               goto out;
+
+       dentry = nd->dentry;
+       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+
+       /* If the entry does not exist deny permission */
+       error = -EACCES;
+       if (!table)
+               goto out;
+
+       /* Use the permissions on the sysctl table entry */
+       error = sysctl_perm(table, mask);
+out:
+       sysctl_head_finish(head);
+       return error;
+}
+
+static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       struct inode *inode = dentry->d_inode;
+       int error;
+
+       if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
+               return -EPERM;
+
+       error = inode_change_ok(inode, attr);
+       if (!error) {
+               error = security_inode_setattr(dentry, attr);
+               if (!error)
+                       error = inode_setattr(inode, attr);
+       }
+
+       return error;
+}
+
+/* I'm lazy and don't distinguish between files and directories,
+ * until access time.
+ */
+static const struct file_operations proc_sys_file_operations = {
+       .read           = proc_sys_read,
+       .write          = proc_sys_write,
+       .readdir        = proc_sys_readdir,
+};
+
+static struct inode_operations proc_sys_inode_operations = {
+       .lookup         = proc_sys_lookup,
+       .permission     = proc_sys_permission,
+       .setattr        = proc_sys_setattr,
+};
+
+static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+       struct ctl_table_header *head;
+       struct ctl_table *table;
+       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+       proc_sys_refresh_inode(dentry->d_inode, table);
+       sysctl_head_finish(head);
+       return !!table;
+}
+
+static struct dentry_operations proc_sys_dentry_operations = {
+       .d_revalidate   = proc_sys_revalidate,
+};
+
+static struct proc_dir_entry *proc_sys_root;
+
+int proc_sys_init(void)
+{
+       proc_sys_root = proc_mkdir("sys", NULL);
+       proc_sys_root->proc_iops = &proc_sys_inode_operations;
+       proc_sys_root->proc_fops = &proc_sys_file_operations;
+       proc_sys_root->nlink = 0;
+       return 0;
+}
index af154458b540ccf6f4d89741b037523ef4f87f08..5834a744c2a96fec843290a83a38c090f34618d5 100644 (file)
 
 struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
 
-#ifdef CONFIG_SYSCTL
-struct proc_dir_entry *proc_sys_root;
-#endif
-
 static int proc_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
@@ -70,13 +66,6 @@ void __init proc_root_init(void)
 
 #ifdef CONFIG_SYSVIPC
        proc_mkdir("sysvipc", NULL);
-#endif
-#ifdef CONFIG_SYSCTL
-       proc_sys_root = proc_mkdir("sys", NULL);
-#endif
-#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
-       proc_mkdir("sys/fs", NULL);
-       proc_mkdir("sys/fs/binfmt_misc", NULL);
 #endif
        proc_root_fs = proc_mkdir("fs", NULL);
        proc_root_driver = proc_mkdir("driver", NULL);
@@ -90,6 +79,9 @@ void __init proc_root_init(void)
        proc_device_tree_init();
 #endif
        proc_bus = proc_mkdir("bus", NULL);
+#ifdef CONFIG_SYSCTL
+       proc_sys_init();
+#endif
 }
 
 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
index e4bf3456d07ed6443a2a382bf5bb31c2c95b8b41..fea20ceb8a5f8fab59f4afe7421614231274d0e8 100644 (file)
@@ -6,7 +6,6 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
index c0e117649a4dd4dd1bc06f47ebfa22941f9bf866..98b0910ad80c43795456d56bd061966499bf7fa7 100644 (file)
@@ -54,7 +54,7 @@ static struct sysfs_ops subsys_sysfs_ops = {
 /**
  *     add_to_collection - add buffer to a collection
  *     @buffer:        buffer to be added
- *     @node           inode of set to add to
+ *     @node:          inode of set to add to
  */
 
 static inline void
index 0e97a4f79c319ad7adfefca81629be2667170a42..bcc44084e0049fca554e28d87a02c12ec2ab8bc0 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 #include <asm/byteorder.h>
 
index a6c0ca9f48bff1ba6d087413a5accbdcaf1fa370..4890ddf1518e347a45ef00bc451b55891022ff10 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
 
 #include "swab.h"
 #include "util.h"
index 789a2559bd54a6da7a8166a60e27489e53d29938..c6ad7c7e3ee9eaa58c4a7994c316f4f4a24fd45a 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/posix_acl_xattr.h>
index 004baf6006110ae7cd8beee0f1e7f90f618c5550..ed2b16dff91434f2bd0b90d35dec3921c447cb27 100644 (file)
@@ -15,7 +15,6 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
index 5c46c35a97a5f69ceb32a39594d407a769885013..cd6eaa44aa2be069875dd56c5d1eb6847d291e8b 100644 (file)
@@ -251,7 +251,7 @@ static ctl_table xfs_root_table[] = {
 void
 xfs_sysctl_register(void)
 {
-       xfs_table_header = register_sysctl_table(xfs_root_table, 0);
+       xfs_table_header = register_sysctl_table(xfs_root_table);
 }
 
 void
index ce7c9d653910598c29cce2baa2dcbb28b8cbb83b..73967c8152d325012db1f690f9cd6744caec2f76 100644 (file)
@@ -253,7 +253,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
 void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+                         struct acpi_thread_state *thread);
 
 /*
  * exprep - ACPI AML execution - prep utilities
index 04e9735a674214fb49aab10f3b75d273e3f44e0d..5206d61d74a6039eac0852145eb956b842554d6a 100644 (file)
@@ -155,7 +155,7 @@ struct acpi_object_event {
 struct acpi_object_mutex {
        ACPI_OBJECT_COMMON_HEADER u8 sync_level;        /* 0-15, specified in Mutex() call */
        u16 acquisition_depth;  /* Allow multiple Acquires, same thread */
-       struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+       acpi_thread_id owner_thread_id; /* Current owner of the mutex */
        acpi_mutex os_mutex;    /* Actual OS synchronization object */
        union acpi_operand_object *prev;        /* Link for list of acquired mutexes */
        union acpi_operand_object *next;        /* Link for list of acquired mutexes */
index 4dc8a5043ef033fd35042be6ad0999233c8db0ad..f6275b0e66dd34bbd5e3fde2be186eeda43ebba4 100644 (file)
@@ -105,12 +105,6 @@ int acpi_ec_ecdt_probe(void);
 
 int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
 
-/* --------------------------------------------------------------------------
-                                    Hot Keys
-   -------------------------------------------------------------------------- */
-
-extern int acpi_specific_hotkey_enabled;
-
 /*--------------------------------------------------------------------------
                                   Dock Station
   -------------------------------------------------------------------------- */
@@ -122,10 +116,34 @@ extern int register_hotplug_dock_device(acpi_handle handle,
        acpi_notify_handler handler, void *context);
 extern void unregister_hotplug_dock_device(acpi_handle handle);
 #else
-#define is_dock_device(h)                      (0)
-#define register_dock_notifier(nb)             (-ENODEV)
-#define unregister_dock_notifier(nb)                   do { } while(0)
-#define register_hotplug_dock_device(h1, h2, c)        (-ENODEV)
-#define unregister_hotplug_dock_device(h)       do { } while(0)
+static inline int is_dock_device(acpi_handle handle)
+{
+       return 0;
+}
+static inline int register_dock_notifier(struct notifier_block *nb)
+{
+       return -ENODEV;
+}
+static inline void unregister_dock_notifier(struct notifier_block *nb)
+{
+}
+static inline int register_hotplug_dock_device(acpi_handle handle,
+                               acpi_notify_handler handler, void *context)
+{
+       return -ENODEV;
+}
+static inline void unregister_hotplug_dock_device(acpi_handle handle)
+{
+}
+#endif
+
+/*--------------------------------------------------------------------------
+                                  Suspend/Resume
+  -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_SLEEP
+extern int acpi_sleep_init(void);
+#else
+#define acpi_sleep_init() do {} while (0)
 #endif
+
 #endif /*__ACPI_DRIVERS_H__*/
index 781394b9efe0b630621e246450f4bc575f754b94..2785058c82ab0621991b54a243473e49ff3bc2a8 100644 (file)
@@ -240,12 +240,6 @@ acpi_status
 acpi_os_validate_address(u8 space_id,
                         acpi_physical_address address, acpi_size length);
 
-u8 acpi_os_readable(void *pointer, acpi_size length);
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *pointer, acpi_size length);
-#endif
-
 u64 acpi_os_get_timer(void);
 
 acpi_status acpi_os_signal(u32 function, void *info);
index 7798d2a9f793aaab8005c2a45d3362a35029ea5b..916c0102db5be85430791c1b5c575cbee888be98 100644 (file)
@@ -79,6 +79,7 @@ struct acpi_processor_power {
        u32 bm_activity;
        int count;
        struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
+       int timer_broadcast_on_state;
 };
 
 /* Performance Management */
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
new file mode 100644 (file)
index 0000000..e02c15d
--- /dev/null
@@ -0,0 +1,2 @@
+arch
+mach-types.h
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91_aic.h
rename to include/asm-arm/arch-at91/at91_aic.h
index 267e69812e26bbea403f110dad88f31c981e8d8d..df44c12a12d4dd53e5ed1780eb74dc0a551a9a37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_aic.h
+ * include/asm-arm/arch-at91/at91_aic.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 76%
rename from include/asm-arm/arch-at91rm9200/at91_dbgu.h
rename to include/asm-arm/arch-at91/at91_dbgu.h
index e4b8b27acfcaf7eff253909e1a6e096284a7a5d2..b0369e176f7bbd95a3fa333498a77a43b5f136dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_dbgu.h
+ * include/asm-arm/arch-at91/at91_dbgu.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
 #define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
 #define                AT91_CIDR_NVPSIZ2       (0xf  << 12)            /* Second Nonvolatile Program Memory Size */
 #define                AT91_CIDR_SRAMSIZ       (0xf  << 16)            /* Internal SRAM Size */
+#define                        AT91_CIDR_SRAMSIZ_1K    (1 << 16)
+#define                        AT91_CIDR_SRAMSIZ_2K    (2 << 16)
+#define                        AT91_CIDR_SRAMSIZ_112K  (4 << 16)
+#define                        AT91_CIDR_SRAMSIZ_4K    (5 << 16)
+#define                        AT91_CIDR_SRAMSIZ_80K   (6 << 16)
+#define                        AT91_CIDR_SRAMSIZ_160K  (7 << 16)
+#define                        AT91_CIDR_SRAMSIZ_8K    (8 << 16)
+#define                        AT91_CIDR_SRAMSIZ_16K   (9 << 16)
+#define                        AT91_CIDR_SRAMSIZ_32K   (10 << 16)
+#define                        AT91_CIDR_SRAMSIZ_64K   (11 << 16)
+#define                        AT91_CIDR_SRAMSIZ_128K  (12 << 16)
+#define                        AT91_CIDR_SRAMSIZ_256K  (13 << 16)
+#define                        AT91_CIDR_SRAMSIZ_96K   (14 << 16)
+#define                        AT91_CIDR_SRAMSIZ_512K  (15 << 16)
 #define                AT91_CIDR_ARCH          (0xff << 20)            /* Architecture Identifier */
 #define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
 #define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/at91_ecc.h
rename to include/asm-arm/arch-at91/at91_ecc.h
index 5c564ede5c5de0aae6b70818b1df325d43b1c538..ff93df516d6df11c419bf4767c3860aa941d392a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_ecc.h
+ * include/asm-arm/arch-at91/at91_ecc.h
  *
  * Error Corrected Code Controller (ECC) - System peripherals regsters.
  * Based on AT91SAM9260 datasheet revision B.
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91_lcdc.h
rename to include/asm-arm/arch-at91/at91_lcdc.h
index 9cbfcdd3c471c8032eea5c0231dc8004fcb0e7d9..ab040a40d37b47b01e46ca201d8ac56d0f44495a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_lcdc.h
+ * include/asm-arm/arch-at91/at91_lcdc.h
  *
  * LCD Controller (LCDC).
  * Based on AT91SAM9261 datasheet revision E.
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91_mci.h
rename to include/asm-arm/arch-at91/at91_mci.h
index 9a552cb743c0c763faec0050c49dc3b2088ced71..40a9876b661a1162aa11cbd401e7e872c611c390 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_mci.h
+ * include/asm-arm/arch-at91/at91_mci.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 97%
rename from include/asm-arm/arch-at91rm9200/at91_pio.h
rename to include/asm-arm/arch-at91/at91_pio.h
index 680eaa1f5915fc1576fbfa6476896bf9b3d9f47e..84c3866d309f84ce818042a6b0ecd3736d40f0ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_pio.h
+ * include/asm-arm/arch-at91/at91_pio.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 95%
rename from include/asm-arm/arch-at91rm9200/at91_pit.h
rename to include/asm-arm/arch-at91/at91_pit.h
index 4a30d009c588a77de85d6e7c778da6e2bcfd6028..5026325a5ae419b13cad93db555f2b1f79a74983 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_pit.h
+ * include/asm-arm/arch-at91/at91_pit.h
  *
  * Periodic Interval Timer (PIT) - System peripherals regsters.
  * Based on AT91SAM9261 datasheet revision D.
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91_pmc.h
rename to include/asm-arm/arch-at91/at91_pmc.h
index c3b489d09b6ca173654fd2a4e2b672603e8f4e8d..33ff5b6798ee4b46a60881efad670ac8b2645e7f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_pmc.h
+ * include/asm-arm/arch-at91/at91_pmc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 90%
rename from include/asm-arm/arch-at91rm9200/at91_rstc.h
rename to include/asm-arm/arch-at91/at91_rstc.h
index 237d3c40b318d9ac925af96ce5e270a71503d4eb..fb8d1618a231a40b2d23387344b53cd09a5828fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_rstc.h
+ * include/asm-arm/arch-at91/at91_rstc.h
  *
  * Reset Controller (RSTC) - System peripherals regsters.
  * Based on AT91SAM9261 datasheet revision D.
@@ -17,7 +17,7 @@
 #define                AT91_RSTC_PROCRST       (1 << 0)                /* Processor Reset */
 #define                AT91_RSTC_PERRST        (1 << 2)                /* Peripheral Reset */
 #define                AT91_RSTC_EXTRST        (1 << 3)                /* External Reset */
-#define                AT91_RSTC_KEY           (0xff << 24)            /* KEY Password */
+#define                AT91_RSTC_KEY           (0xa5 << 24)            /* KEY Password */
 
 #define AT91_RSTC_SR           (AT91_RSTC + 0x04)      /* Reset Controller Status Register */
 #define                AT91_RSTC_URSTS         (1 << 0)                /* User Reset Status */
@@ -34,6 +34,5 @@
 #define                AT91_RSTC_URSTEN        (1 << 0)                /* User Reset Enable */
 #define                AT91_RSTC_URSTIEN       (1 << 4)                /* User Reset Interrupt Enable */
 #define                AT91_RSTC_ERSTL         (0xf << 8)              /* External Reset Length */
-#define                AT91_RSTC_KEY           (0xff << 24)            /* KEY Password */
 
 #endif
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91_rtc.h
rename to include/asm-arm/arch-at91/at91_rtc.h
index 095fe08831026a4b593715378d348571ef623307..af9bd28174c05708cd3facfed783900deb8526c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_rtc.h
+ * include/asm-arm/arch-at91/at91_rtc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/at91_rtt.h
rename to include/asm-arm/arch-at91/at91_rtt.h
index c6751ba3cccccbf82721371587057f8116714704..bae1103fbbb29e0f1e0b0b5020da0246b213319b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_rtt.h
+ * include/asm-arm/arch-at91/at91_rtt.h
  *
  * Real-time Timer (RTT) - System peripherals regsters.
  * Based on AT91SAM9261 datasheet revision D.
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/at91_shdwc.h
rename to include/asm-arm/arch-at91/at91_shdwc.h
index 0439250553c96056bc6b5846dd1515ec34268028..795fcc266228b93f914a42b9a037fb4bb7046003 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_shdwc.h
+ * include/asm-arm/arch-at91/at91_shdwc.h
  *
  * Shutdown Controller (SHDWC) - System peripherals regsters.
  * Based on AT91SAM9261 datasheet revision D.
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91_spi.h
rename to include/asm-arm/arch-at91/at91_spi.h
index bec48ca89bbadd80500cfcfbceaa8547bcd1d30f..f9b9a84649974f532cb9be17ac98444811a9909c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_spi.h
+ * include/asm-arm/arch-at91/at91_spi.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91_ssc.h
rename to include/asm-arm/arch-at91/at91_ssc.h
index 694bcaa8f7c2016ef2e2b1429bd4f8453d1d974c..0ecc73460b5098145c707f8c0ff7500fa60cec08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_ssc.h
+ * include/asm-arm/arch-at91/at91_ssc.h
  *
  * Copyright (C) SAN People
  *
similarity index 97%
rename from include/asm-arm/arch-at91rm9200/at91_st.h
rename to include/asm-arm/arch-at91/at91_st.h
index 2432ddfc6c47a3a62b02aad798c948998b21e868..30446e2ea772266600489e4daf93d5b537ce217b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_st.h
+ * include/asm-arm/arch-at91/at91_st.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91_tc.h
rename to include/asm-arm/arch-at91/at91_tc.h
index 8d06eb078e1d1624e5faf737622530ea8de3ba70..b85d3faeef5ced996ae088cdc8b745adea0fbb98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_tc.h
+ * include/asm-arm/arch-at91/at91_tc.h
  *
  * Copyright (C) SAN People
  *
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91_twi.h
rename to include/asm-arm/arch-at91/at91_twi.h
index cda914f1e7402501482a090a1d88e29a01e3ceb0..ca9a90733456be5fba159820216bc4fd21f04187 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_twi.h
+ * include/asm-arm/arch-at91/at91_twi.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/at91_wdt.h
rename to include/asm-arm/arch-at91/at91_wdt.h
index ac63e775772c093e0c768a65e5070e9e817e02da..7251a344c740455a7e627a01e996e89c81b8e5e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91_wdt.h
+ * include/asm-arm/arch-at91/at91_wdt.h
  *
  * Watchdog Timer (WDT) - System peripherals regsters.
  * Based on AT91SAM9261 datasheet revision D.
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91rm9200.h
rename to include/asm-arm/arch-at91/at91rm9200.h
index c569b6a21a42a451496dfa1bb3aeea42e5b31771..a12ac8ab2ad081992349b924169c9c5148da1238 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200.h
+ * include/asm-arm/arch-at91/at91rm9200.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
rename to include/asm-arm/arch-at91/at91rm9200_emac.h
index fbc091e61e2fb6e20bcdcce95e2fd99f18369791..0c417af5fe7ff89c4bcc18783feb71eaf86270b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
+ * include/asm-arm/arch-at91/at91rm9200_emac.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
rename to include/asm-arm/arch-at91/at91rm9200_mc.h
index 0c0d81480b3a40e9e45cf4f7e8fb168f73a03e50..24d012939cc4921c9900f30e1d30cbf08889d765 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
+ * include/asm-arm/arch-at91/at91rm9200_mc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/at91sam9260.h
rename to include/asm-arm/arch-at91/at91sam9260.h
index 46f4dd65c0353fe1c384bd4f10581be2ae047ece..2cadebc36af70fc233fa35c143c52167df5d86ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91sam9260.h
+ * include/asm-arm/arch-at91/at91sam9260.h
  *
  * (C) 2006 Andrew Victor
  *
 
 #define AT91SAM9260_UHP_BASE   0x00500000      /* USB Host controller */
 
+#define AT91SAM9XE_FLASH_BASE  0x00200000      /* Internal FLASH base address */
+#define AT91SAM9XE_SRAM_BASE   0x00300000      /* Internal SRAM base address */
+
+
 #if 0
 /*
  * PIO pin definitions (peripheral A/B multiplexing).
similarity index 97%
rename from include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
rename to include/asm-arm/arch-at91/at91sam9260_matrix.h
index 78f6b4917b8b7e5bcfa1fd49f02d126f0ad1a769..aacb1e9764220d484be05a0db74a3251d0ad1f76 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+ * include/asm-arm/arch-at91/at91sam9260_matrix.h
  *
  * Memory Controllers (MATRIX, EBI) - System peripherals registers.
  * Based on AT91SAM9260 datasheet revision B.
@@ -18,7 +18,7 @@
 #define AT91_MATRIX_MCFG2      (AT91_MATRIX + 0x08)    /* Master Configuration Register 2 */
 #define AT91_MATRIX_MCFG3      (AT91_MATRIX + 0x0C)    /* Master Configuration Register 3 */
 #define AT91_MATRIX_MCFG4      (AT91_MATRIX + 0x10)    /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5      (AT91_MATRIX + 0x04)    /* Master Configuration Register 5 */
+#define AT91_MATRIX_MCFG5      (AT91_MATRIX + 0x14)    /* Master Configuration Register 5 */
 #define                AT91_MATRIX_ULBT                (7 << 0)        /* Undefined Length Burst Type */
 #define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
 #define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
similarity index 99%
rename from include/asm-arm/arch-at91rm9200/at91sam9261.h
rename to include/asm-arm/arch-at91/at91sam9261.h
index 8d39672d5b8272df3ea1fa22a44480ad065e3102..01b58ffe2e27c2c86c2502e0bcef41abd95f1516 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91sam9261.h
+ * include/asm-arm/arch-at91/at91sam9261.h
  *
  * Copyright (C) SAN People
  *
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
rename to include/asm-arm/arch-at91/at91sam9261_matrix.h
index ec88efabbe6c9370efcf4d61a8299fd0050757ca..6f072421be5b9b36cf7b683e21d3da8419dbf7b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+ * include/asm-arm/arch-at91/at91sam9261_matrix.h
  *
  * Memory Controllers (MATRIX, EBI) - System peripherals registers.
  * Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h
new file mode 100644 (file)
index 0000000..f4af68a
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263.h
+ *
+ * (C) 2007 Atmel Corporation.
+ *
+ * Common definitions.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91SAM9263_H
+#define AT91SAM9263_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ            0       /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS            1       /* System Peripherals */
+#define AT91SAM9263_ID_PIOA    2       /* Parallel IO Controller A */
+#define AT91SAM9263_ID_PIOB    3       /* Parallel IO Controller B */
+#define AT91SAM9263_ID_PIOCDE  4       /* Parallel IO Controller C, D and E */
+#define AT91SAM9263_ID_US0     7       /* USART 0 */
+#define AT91SAM9263_ID_US1     8       /* USART 1 */
+#define AT91SAM9263_ID_US2     9       /* USART 2 */
+#define AT91SAM9263_ID_MCI0    10      /* Multimedia Card Interface 0 */
+#define AT91SAM9263_ID_MCI1    11      /* Multimedia Card Interface 1 */
+#define AT91SAM9263_ID_CAN     12      /* CAN */
+#define AT91SAM9263_ID_TWI     13      /* Two-Wire Interface */
+#define AT91SAM9263_ID_SPI0    14      /* Serial Peripheral Interface 0 */
+#define AT91SAM9263_ID_SPI1    15      /* Serial Peripheral Interface 1 */
+#define AT91SAM9263_ID_SSC0    16      /* Serial Synchronous Controller 0 */
+#define AT91SAM9263_ID_SSC1    17      /* Serial Synchronous Controller 1 */
+#define AT91SAM9263_ID_AC97C   18      /* AC97 Controller */
+#define AT91SAM9263_ID_TCB     19      /* Timer Counter 0, 1 and 2 */
+#define AT91SAM9263_ID_PWMC    20      /* Pulse Width Modulation Controller */
+#define AT91SAM9263_ID_EMAC    21      /* Ethernet */
+#define AT91SAM9263_ID_2DGE    23      /* 2D Graphic Engine */
+#define AT91SAM9263_ID_UDP     24      /* USB Device Port */
+#define AT91SAM9263_ID_ISI     25      /* Image Sensor Interface */
+#define AT91SAM9263_ID_LCDC    26      /* LCD Controller */
+#define AT91SAM9263_ID_DMA     27      /* DMA Controller */
+#define AT91SAM9263_ID_UHP     29      /* USB Host port */
+#define AT91SAM9263_ID_IRQ0    30      /* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9263_ID_IRQ1    31      /* Advanced Interrupt Controller (IRQ1) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9263_BASE_UDP           0xfff78000
+#define AT91SAM9263_BASE_TCB0          0xfff7c000
+#define AT91SAM9263_BASE_TC0           0xfff7c000
+#define AT91SAM9263_BASE_TC1           0xfff7c040
+#define AT91SAM9263_BASE_TC2           0xfff7c080
+#define AT91SAM9263_BASE_MCI0          0xfff80000
+#define AT91SAM9263_BASE_MCI1          0xfff84000
+#define AT91SAM9263_BASE_TWI           0xfff88000
+#define AT91SAM9263_BASE_US0           0xfff8c000
+#define AT91SAM9263_BASE_US1           0xfff90000
+#define AT91SAM9263_BASE_US2           0xfff94000
+#define AT91SAM9263_BASE_SSC0          0xfff98000
+#define AT91SAM9263_BASE_SSC1          0xfff9c000
+#define AT91SAM9263_BASE_AC97C         0xfffa0000
+#define AT91SAM9263_BASE_SPI0          0xfffa4000
+#define AT91SAM9263_BASE_SPI1          0xfffa8000
+#define AT91SAM9263_BASE_CAN           0xfffac000
+#define AT91SAM9263_BASE_PWMC          0xfffb8000
+#define AT91SAM9263_BASE_EMAC          0xfffbc000
+#define AT91SAM9263_BASE_ISI           0xfffc4000
+#define AT91SAM9263_BASE_2DGE          0xfffc8000
+#define AT91_BASE_SYS                  0xffffe000
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_ECC0      (0xffffe000 - AT91_BASE_SYS)
+#define AT91_SDRAMC0   (0xffffe200 - AT91_BASE_SYS)
+#define AT91_SMC0      (0xffffe400 - AT91_BASE_SYS)
+#define AT91_ECC1      (0xffffe600 - AT91_BASE_SYS)
+#define AT91_SDRAMC1   (0xffffe800 - AT91_BASE_SYS)
+#define AT91_SMC1      (0xffffea00 - AT91_BASE_SYS)
+#define AT91_MATRIX    (0xffffec00 - AT91_BASE_SYS)
+#define AT91_CCFG      (0xffffed10 - AT91_BASE_SYS)
+#define AT91_DBGU      (0xffffee00 - AT91_BASE_SYS)
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)
+#define AT91_PIOA      (0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOB      (0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOC      (0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOD      (0xfffff800 - AT91_BASE_SYS)
+#define AT91_PIOE      (0xfffffa00 - AT91_BASE_SYS)
+#define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC     (0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT0      (0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT       (0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT       (0xfffffd40 - AT91_BASE_SYS)
+#define AT91_RTT1      (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_GPBR      (0xfffffd60 - AT91_BASE_SYS)
+
+#define AT91_SMC       AT91_SMC0
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9263_SRAM0_BASE 0x00300000      /* Internal SRAM 0 base address */
+#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K)    /* Internal SRAM 0 size (80Kb) */
+
+#define AT91SAM9263_ROM_BASE   0x00400000      /* Internal ROM base address */
+#define AT91SAM9263_ROM_SIZE   SZ_128K         /* Internal ROM size (128Kb) */
+
+#define AT91SAM9263_SRAM1_BASE 0x00500000      /* Internal SRAM 1 base address */
+#define AT91SAM9263_SRAM1_SIZE SZ_16K          /* Internal SRAM 1 size (16Kb) */
+
+#define AT91SAM9263_LCDC_BASE  0x00700000      /* LCD Controller */
+#define AT91SAM9263_DMAC_BASE  0x00800000      /* DMA Controller */
+#define AT91SAM9263_UHP_BASE   0x00a00000      /* USB Host controller */
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+
+// TODO: Add
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h
new file mode 100644 (file)
index 0000000..6fc6e4b
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263_matrix.h
+ *
+ *  Copyright (C) 2006 Atmel Corporation.
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91SAM9263_MATRIX_H
+#define AT91SAM9263_MATRIX_H
+
+#define AT91_MATRIX_MCFG0      (AT91_MATRIX + 0x00)    /* Master Configuration Register 0 */
+#define AT91_MATRIX_MCFG1      (AT91_MATRIX + 0x04)    /* Master Configuration Register 1 */
+#define AT91_MATRIX_MCFG2      (AT91_MATRIX + 0x08)    /* Master Configuration Register 2 */
+#define AT91_MATRIX_MCFG3      (AT91_MATRIX + 0x0C)    /* Master Configuration Register 3 */
+#define AT91_MATRIX_MCFG4      (AT91_MATRIX + 0x10)    /* Master Configuration Register 4 */
+#define AT91_MATRIX_MCFG5      (AT91_MATRIX + 0x14)    /* Master Configuration Register 5 */
+#define AT91_MATRIX_MCFG6      (AT91_MATRIX + 0x18)    /* Master Configuration Register 6 */
+#define AT91_MATRIX_MCFG7      (AT91_MATRIX + 0x1C)    /* Master Configuration Register 7 */
+#define AT91_MATRIX_MCFG8      (AT91_MATRIX + 0x20)    /* Master Configuration Register 8 */
+#define                AT91_MATRIX_ULBT        (7 << 0)        /* Undefined Length Burst Type */
+#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
+#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
+#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
+#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
+#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
+
+#define AT91_MATRIX_SCFG0      (AT91_MATRIX + 0x40)    /* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1      (AT91_MATRIX + 0x44)    /* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2      (AT91_MATRIX + 0x48)    /* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3      (AT91_MATRIX + 0x4C)    /* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4      (AT91_MATRIX + 0x50)    /* Slave Configuration Register 4 */
+#define AT91_MATRIX_SCFG5      (AT91_MATRIX + 0x54)    /* Slave Configuration Register 5 */
+#define AT91_MATRIX_SCFG6      (AT91_MATRIX + 0x58)    /* Slave Configuration Register 6 */
+#define AT91_MATRIX_SCFG7      (AT91_MATRIX + 0x5C)    /* Slave Configuration Register 7 */
+#define                AT91_MATRIX_SLOT_CYCLE          (0xff << 0)     /* Maximum Number of Allowed Cycles for a Burst */
+#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
+#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
+#define                AT91_MATRIX_FIXED_DEFMSTR       (7    << 18)    /* Fixed Index of Default Master */
+#define                AT91_MATRIX_ARBT                (3    << 24)    /* Arbitration Type */
+#define                        AT91_MATRIX_ARBT_ROUND_ROBIN    (0 << 24)
+#define                        AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
+
+#define AT91_MATRIX_PRAS0      (AT91_MATRIX + 0x80)    /* Priority Register A for Slave 0 */
+#define AT91_MATRIX_PRBS0      (AT91_MATRIX + 0x84)    /* Priority Register B for Slave 0 */
+#define AT91_MATRIX_PRAS1      (AT91_MATRIX + 0x88)    /* Priority Register A for Slave 1 */
+#define AT91_MATRIX_PRBS1      (AT91_MATRIX + 0x8C)    /* Priority Register B for Slave 1 */
+#define AT91_MATRIX_PRAS2      (AT91_MATRIX + 0x90)    /* Priority Register A for Slave 2 */
+#define AT91_MATRIX_PRBS2      (AT91_MATRIX + 0x94)    /* Priority Register B for Slave 2 */
+#define AT91_MATRIX_PRAS3      (AT91_MATRIX + 0x98)    /* Priority Register A for Slave 3 */
+#define AT91_MATRIX_PRBS3      (AT91_MATRIX + 0x9C)    /* Priority Register B for Slave 3 */
+#define AT91_MATRIX_PRAS4      (AT91_MATRIX + 0xA0)    /* Priority Register A for Slave 4 */
+#define AT91_MATRIX_PRBS4      (AT91_MATRIX + 0xA4)    /* Priority Register B for Slave 4 */
+#define AT91_MATRIX_PRAS5      (AT91_MATRIX + 0xA8)    /* Priority Register A for Slave 5 */
+#define AT91_MATRIX_PRBS5      (AT91_MATRIX + 0xAC)    /* Priority Register B for Slave 5 */
+#define AT91_MATRIX_PRAS6      (AT91_MATRIX + 0xB0)    /* Priority Register A for Slave 6 */
+#define AT91_MATRIX_PRBS6      (AT91_MATRIX + 0xB4)    /* Priority Register B for Slave 6 */
+#define AT91_MATRIX_PRAS7      (AT91_MATRIX + 0xB8)    /* Priority Register A for Slave 7 */
+#define AT91_MATRIX_PRBS7      (AT91_MATRIX + 0xBC)    /* Priority Register B for Slave 7 */
+#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
+#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
+#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
+#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
+#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
+#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
+#define                AT91_MATRIX_M6PR                (3 << 24)       /* Master 6 Priority */
+#define                AT91_MATRIX_M7PR                (3 << 28)       /* Master 7 Priority */
+#define                AT91_MATRIX_M8PR                (3 << 0)        /* Master 8 Priority (in Register B) */
+
+#define AT91_MATRIX_MRCR       (AT91_MATRIX + 0x100)   /* Master Remap Control Register */
+#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+#define                AT91_MATRIX_RCB2                (1 << 2)
+#define                AT91_MATRIX_RCB3                (1 << 3)
+#define                AT91_MATRIX_RCB4                (1 << 4)
+#define                AT91_MATRIX_RCB5                (1 << 5)
+#define                AT91_MATRIX_RCB6                (1 << 6)
+#define                AT91_MATRIX_RCB7                (1 << 7)
+#define                AT91_MATRIX_RCB8                (1 << 8)
+
+#define AT91_MATRIX_TCMR       (AT91_MATRIX + 0x114)   /* TCM Configuration Register */
+#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
+#define                        AT91_MATRIX_ITCM_0              (0 << 0)
+#define                        AT91_MATRIX_ITCM_16             (5 << 0)
+#define                        AT91_MATRIX_ITCM_32             (6 << 0)
+#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
+#define                        AT91_MATRIX_DTCM_0              (0 << 4)
+#define                        AT91_MATRIX_DTCM_16             (5 << 4)
+#define                        AT91_MATRIX_DTCM_32             (6 << 4)
+
+#define AT91_MATRIX_EBI0CSA    (AT91_MATRIX + 0x120)   /* EBI0 Chip Select Assignment Register */
+#define                AT91_MATRIX_EBI0_CS1A           (1 << 1)        /* Chip Select 1 Assignment */
+#define                        AT91_MATRIX_EBI0_CS1A_SMC               (0 << 1)
+#define                        AT91_MATRIX_EBI0_CS1A_SDRAMC            (1 << 1)
+#define                AT91_MATRIX_EBI0_CS3A           (1 << 3)        /* Chip Select 3 Assignment */
+#define                        AT91_MATRIX_EBI0_CS3A_SMC               (0 << 3)
+#define                        AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA    (1 << 3)
+#define                AT91_MATRIX_EBI0_CS4A           (1 << 4)        /* Chip Select 4 Assignment */
+#define                        AT91_MATRIX_EBI0_CS4A_SMC               (0 << 4)
+#define                        AT91_MATRIX_EBI0_CS4A_SMC_CF1           (1 << 4)
+#define                AT91_MATRIX_EBI0_CS5A           (1 << 5)        /* Chip Select 5 Assignment */
+#define                        AT91_MATRIX_EBI0_CS5A_SMC               (0 << 5)
+#define                        AT91_MATRIX_EBI0_CS5A_SMC_CF2           (1 << 5)
+#define                AT91_MATRIX_EBI0_DBPUC          (1 << 8)        /* Data Bus Pull-up Configuration */
+#define                AT91_MATRIX_EBI0_VDDIOMSEL      (1 << 16)       /* Memory voltage selection */
+#define                        AT91_MATRIX_EBI0_VDDIOMSEL_1_8V         (0 << 16)
+#define                        AT91_MATRIX_EBI0_VDDIOMSEL_3_3V         (1 << 16)
+
+#define AT91_MATRIX_EBI1CSA    (AT91_MATRIX + 0x124)   /* EBI1 Chip Select Assignment Register */
+#define                AT91_MATRIX_EBI1_CS1A           (1 << 1)        /* Chip Select 1 Assignment */
+#define                        AT91_MATRIX_EBI1_CS1A_SMC               (0 << 1)
+#define                        AT91_MATRIX_EBI1_CS1A_SDRAMC            (1 << 1)
+#define                AT91_MATRIX_EBI1_CS2A           (1 << 3)        /* Chip Select 3 Assignment */
+#define                        AT91_MATRIX_EBI1_CS2A_SMC               (0 << 3)
+#define                        AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA    (1 << 3)
+#define                AT91_MATRIX_EBI1_DBPUC          (1 << 8)        /* Data Bus Pull-up Configuration */
+#define                AT91_MATRIX_EBI1_VDDIOMSEL      (1 << 16)       /* Memory voltage selection */
+#define                        AT91_MATRIX_EBI1_VDDIOMSEL_1_8V         (0 << 16)
+#define                        AT91_MATRIX_EBI1_VDDIOMSEL_3_3V         (1 << 16)
+
+#endif
similarity index 92%
rename from include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
rename to include/asm-arm/arch-at91/at91sam926x_mc.h
index 972e7531c7f4c70c546b544259732db13d34502b..d82631c251f1b14af7eb2638be5b3652aec12188 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+ * include/asm-arm/arch-at91/at91sam926x_mc.h
  *
  * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
  * Based on AT91SAM9261 datasheet revision D.
 #define                        AT91_SMC_PS_16                  (2 << 28)
 #define                        AT91_SMC_PS_32                  (3 << 28)
 
+#if defined(AT91_SMC1)         /* The AT91SAM9263 has 2 Static Memory contollers */
+#define AT91_SMC1_SETUP(n)     (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
+#define AT91_SMC1_PULSE(n)     (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
+#define AT91_SMC1_CYCLE(n)     (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
+#define AT91_SMC1_MODE(n)      (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
+#endif
+
 #endif
similarity index 92%
rename from include/asm-arm/arch-at91rm9200/board.h
rename to include/asm-arm/arch-at91/board.h
index 768e0fc6aa2f2d6b08250ec67f3346f5b5d5a4d6..7b9903c2c447219a5a7642ea00165f46611c7710 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/board.h
+ * include/asm-arm/arch-at91/board.h
  *
  *  Copyright (C) 2005 HP Labs
  *
@@ -60,7 +60,7 @@ struct at91_mmc_data {
        u8              wp_pin;         /* (SD) writeprotect detect */
        u8              vcc_pin;        /* power switching (high == on) */
 };
-extern void __init at91_add_device_mmc(struct at91_mmc_data *data);
+extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
 
  /* Ethernet */
 struct at91_eth_data {
@@ -69,9 +69,14 @@ struct at91_eth_data {
 };
 extern void __init at91_add_device_eth(struct at91_eth_data *data);
 
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263)
+#define eth_platform_data      at91_eth_data
+#endif
+
  /* USB Host */
 struct at91_usbh_data {
        u8              ports;          /* number of ports on root hub */
+       u8              vbus_pin[];     /* port power-control pin */
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 
similarity index 56%
rename from include/asm-arm/arch-at91rm9200/cpu.h
rename to include/asm-arm/arch-at91/cpu.h
index 6f8d09b08692d545021f186ddac5411181f70867..d464ca58cdbc07e427180d235f590953c13a2fc1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/cpu.h
+ * include/asm-arm/arch-at91/cpu.h
  *
  *  Copyright (C) 2006 SAN People
  *
 #define ARCH_ID_AT91RM9200     0x09290780
 #define ARCH_ID_AT91SAM9260    0x019803a0
 #define ARCH_ID_AT91SAM9261    0x019703a0
+#define ARCH_ID_AT91SAM9263    0x019607a0
 
+#define ARCH_ID_AT91SAM9XE128  0x329973a0
+#define ARCH_ID_AT91SAM9XE256  0x329a93a0
+#define ARCH_ID_AT91SAM9XE512  0x329aa3a0
 
 static inline unsigned long at91_cpu_identify(void)
 {
@@ -28,6 +32,16 @@ static inline unsigned long at91_cpu_identify(void)
 }
 
 
+#define ARCH_FAMILY_AT91X92    0x09200000
+#define ARCH_FAMILY_AT91SAM9   0x01900000
+#define ARCH_FAMILY_AT91SAM9XE 0x02900000
+
+static inline unsigned long at91_arch_identify(void)
+{
+       return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH);
+}
+
+
 #ifdef CONFIG_ARCH_AT91RM9200
 #define cpu_is_at91rm9200()    (at91_cpu_identify() == ARCH_ID_AT91RM9200)
 #else
@@ -35,8 +49,10 @@ static inline unsigned long at91_cpu_identify(void)
 #endif
 
 #ifdef CONFIG_ARCH_AT91SAM9260
-#define cpu_is_at91sam9260()   (at91_cpu_identify() == ARCH_ID_AT91SAM9260)
+#define cpu_is_at91sam9xe()    (at91_arch_identify() == ARCH_FAMILY_AT91SAM9XE)
+#define cpu_is_at91sam9260()   ((at91_cpu_identify() == ARCH_ID_AT91SAM9260) || cpu_is_at91sam9xe())
 #else
+#define cpu_is_at91sam9xe()    (0)
 #define cpu_is_at91sam9260()   (0)
 #endif
 
@@ -46,4 +62,10 @@ static inline unsigned long at91_cpu_identify(void)
 #define cpu_is_at91sam9261()   (0)
 #endif
 
+#ifdef CONFIG_ARCH_AT91SAM9263
+#define cpu_is_at91sam9263()   (at91_cpu_identify() == ARCH_ID_AT91SAM9263)
+#else
+#define cpu_is_at91sam9263()   (0)
+#endif
+
 #endif
diff --git a/include/asm-arm/arch-at91/debug-macro.S b/include/asm-arm/arch-at91/debug-macro.S
new file mode 100644 (file)
index 0000000..13e9f5e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-at91/debug-macro.S
+ *
+ *  Copyright (C) 2003-2005 SAN People
+ *
+ * Debugging macro include header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+       .macro  addruart,rx
+       mrc     p15, 0, \rx, c1, c0
+       tst     \rx, #1                                         @ MMU enabled?
+       ldreq   \rx, =(AT91_BASE_SYS + AT91_DBGU)               @ System peripherals (phys address)
+       ldrne   \rx, =(AT91_VA_BASE_SYS + AT91_DBGU)            @ System peripherals (virt address)
+       .endm
+
+       .macro  senduart,rd,rx
+       strb    \rd, [\rx, #(AT91_DBGU_THR - AT91_DBGU)]        @ Write to Transmitter Holding Register
+       .endm
+
+       .macro  waituart,rd,rx
+1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]         @ Read Status Register
+       tst     \rd, #AT91_DBGU_TXRDY                           @ DBGU_TXRDY = 1 when ready to transmit
+       beq     1001b
+       .endm
+
+       .macro  busyuart,rd,rx
+1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]         @ Read Status Register
+       tst     \rd, #AT91_DBGU_TXEMPTY                         @ DBGU_TXEMPTY = 1 when transmission complete
+       beq     1001b
+       .endm
+
similarity index 94%
rename from include/asm-arm/arch-at91rm9200/dma.h
rename to include/asm-arm/arch-at91/dma.h
index 22c1dfdd8da34ce28c4f3e0edef000cb9533f729..774565412beb55ded758e6c27a2731d8ce7a0ce3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/dma.h
+ * include/asm-arm/arch-at91/dma.h
  *
  *  Copyright (C) 2003 SAN People
  *
diff --git a/include/asm-arm/arch-at91/entry-macro.S b/include/asm-arm/arch-at91/entry-macro.S
new file mode 100644 (file)
index 0000000..76c8ccc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-at91/entry-macro.S
+ *
+ *  Copyright (C) 2003-2005 SAN People
+ *
+ * Low-level IRQ helper macros for AT91RM9200 platforms
+ *
+ * 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 <asm/hardware.h>
+#include <asm/arch/at91_aic.h>
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       ldr     \base, =(AT91_VA_BASE_SYS + AT91_AIC)           @ base virtual address of AIC peripheral
+       ldr     \irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)]     @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
+       ldr     \irqstat, [\base, #(AT91_AIC_ISR - AT91_AIC)]   @ read interrupt source number
+       teq     \irqstat, #0                                    @ ISR is 0 when no current interrupt, or spurious interrupt
+       streq   \tmp, [\base, #(AT91_AIC_EOICR - AT91_AIC)]     @ not going to be handled further, then ACK it now.
+       .endm
+
similarity index 84%
rename from include/asm-arm/arch-at91rm9200/gpio.h
rename to include/asm-arm/arch-at91/gpio.h
index e09d6528fadf85497a0839206d67321bbc511852..98ad2114f43a2bbae4c68c19225dd25270d7a533 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/gpio.h
+ * include/asm-arm/arch-at91/gpio.h
  *
  *  Copyright (C) 2005 HP Labs
  *
@@ -17,7 +17,7 @@
 
 #define PIN_BASE               NR_AIC_IRQS
 
-#define MAX_GPIO_BANKS         4
+#define MAX_GPIO_BANKS         5
 
 /* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
 
 #define        AT91_PIN_PA2    (PIN_BASE + 0x00 + 2)
 #define        AT91_PIN_PA3    (PIN_BASE + 0x00 + 3)
 #define        AT91_PIN_PA4    (PIN_BASE + 0x00 + 4)
-
 #define        AT91_PIN_PA5    (PIN_BASE + 0x00 + 5)
 #define        AT91_PIN_PA6    (PIN_BASE + 0x00 + 6)
 #define        AT91_PIN_PA7    (PIN_BASE + 0x00 + 7)
 #define        AT91_PIN_PA8    (PIN_BASE + 0x00 + 8)
 #define        AT91_PIN_PA9    (PIN_BASE + 0x00 + 9)
-
 #define        AT91_PIN_PA10   (PIN_BASE + 0x00 + 10)
 #define        AT91_PIN_PA11   (PIN_BASE + 0x00 + 11)
 #define        AT91_PIN_PA12   (PIN_BASE + 0x00 + 12)
 #define        AT91_PIN_PA13   (PIN_BASE + 0x00 + 13)
 #define        AT91_PIN_PA14   (PIN_BASE + 0x00 + 14)
-
 #define        AT91_PIN_PA15   (PIN_BASE + 0x00 + 15)
 #define        AT91_PIN_PA16   (PIN_BASE + 0x00 + 16)
 #define        AT91_PIN_PA17   (PIN_BASE + 0x00 + 17)
 #define        AT91_PIN_PA18   (PIN_BASE + 0x00 + 18)
 #define        AT91_PIN_PA19   (PIN_BASE + 0x00 + 19)
-
 #define        AT91_PIN_PA20   (PIN_BASE + 0x00 + 20)
 #define        AT91_PIN_PA21   (PIN_BASE + 0x00 + 21)
 #define        AT91_PIN_PA22   (PIN_BASE + 0x00 + 22)
 #define        AT91_PIN_PA23   (PIN_BASE + 0x00 + 23)
 #define        AT91_PIN_PA24   (PIN_BASE + 0x00 + 24)
-
 #define        AT91_PIN_PA25   (PIN_BASE + 0x00 + 25)
 #define        AT91_PIN_PA26   (PIN_BASE + 0x00 + 26)
 #define        AT91_PIN_PA27   (PIN_BASE + 0x00 + 27)
 #define        AT91_PIN_PA28   (PIN_BASE + 0x00 + 28)
 #define        AT91_PIN_PA29   (PIN_BASE + 0x00 + 29)
-
 #define        AT91_PIN_PA30   (PIN_BASE + 0x00 + 30)
 #define        AT91_PIN_PA31   (PIN_BASE + 0x00 + 31)
 
 #define        AT91_PIN_PB2    (PIN_BASE + 0x20 + 2)
 #define        AT91_PIN_PB3    (PIN_BASE + 0x20 + 3)
 #define        AT91_PIN_PB4    (PIN_BASE + 0x20 + 4)
-
 #define        AT91_PIN_PB5    (PIN_BASE + 0x20 + 5)
 #define        AT91_PIN_PB6    (PIN_BASE + 0x20 + 6)
 #define        AT91_PIN_PB7    (PIN_BASE + 0x20 + 7)
 #define        AT91_PIN_PB8    (PIN_BASE + 0x20 + 8)
 #define        AT91_PIN_PB9    (PIN_BASE + 0x20 + 9)
-
 #define        AT91_PIN_PB10   (PIN_BASE + 0x20 + 10)
 #define        AT91_PIN_PB11   (PIN_BASE + 0x20 + 11)
 #define        AT91_PIN_PB12   (PIN_BASE + 0x20 + 12)
 #define        AT91_PIN_PB13   (PIN_BASE + 0x20 + 13)
 #define        AT91_PIN_PB14   (PIN_BASE + 0x20 + 14)
-
 #define        AT91_PIN_PB15   (PIN_BASE + 0x20 + 15)
 #define        AT91_PIN_PB16   (PIN_BASE + 0x20 + 16)
 #define        AT91_PIN_PB17   (PIN_BASE + 0x20 + 17)
 #define        AT91_PIN_PB18   (PIN_BASE + 0x20 + 18)
 #define        AT91_PIN_PB19   (PIN_BASE + 0x20 + 19)
-
 #define        AT91_PIN_PB20   (PIN_BASE + 0x20 + 20)
 #define        AT91_PIN_PB21   (PIN_BASE + 0x20 + 21)
 #define        AT91_PIN_PB22   (PIN_BASE + 0x20 + 22)
 #define        AT91_PIN_PB23   (PIN_BASE + 0x20 + 23)
 #define        AT91_PIN_PB24   (PIN_BASE + 0x20 + 24)
-
 #define        AT91_PIN_PB25   (PIN_BASE + 0x20 + 25)
 #define        AT91_PIN_PB26   (PIN_BASE + 0x20 + 26)
 #define        AT91_PIN_PB27   (PIN_BASE + 0x20 + 27)
 #define        AT91_PIN_PB28   (PIN_BASE + 0x20 + 28)
 #define        AT91_PIN_PB29   (PIN_BASE + 0x20 + 29)
-
 #define        AT91_PIN_PB30   (PIN_BASE + 0x20 + 30)
 #define        AT91_PIN_PB31   (PIN_BASE + 0x20 + 31)
 
 #define        AT91_PIN_PC2    (PIN_BASE + 0x40 + 2)
 #define        AT91_PIN_PC3    (PIN_BASE + 0x40 + 3)
 #define        AT91_PIN_PC4    (PIN_BASE + 0x40 + 4)
-
 #define        AT91_PIN_PC5    (PIN_BASE + 0x40 + 5)
 #define        AT91_PIN_PC6    (PIN_BASE + 0x40 + 6)
 #define        AT91_PIN_PC7    (PIN_BASE + 0x40 + 7)
 #define        AT91_PIN_PC8    (PIN_BASE + 0x40 + 8)
 #define        AT91_PIN_PC9    (PIN_BASE + 0x40 + 9)
-
 #define        AT91_PIN_PC10   (PIN_BASE + 0x40 + 10)
 #define        AT91_PIN_PC11   (PIN_BASE + 0x40 + 11)
 #define        AT91_PIN_PC12   (PIN_BASE + 0x40 + 12)
 #define        AT91_PIN_PC13   (PIN_BASE + 0x40 + 13)
 #define        AT91_PIN_PC14   (PIN_BASE + 0x40 + 14)
-
 #define        AT91_PIN_PC15   (PIN_BASE + 0x40 + 15)
 #define        AT91_PIN_PC16   (PIN_BASE + 0x40 + 16)
 #define        AT91_PIN_PC17   (PIN_BASE + 0x40 + 17)
 #define        AT91_PIN_PC18   (PIN_BASE + 0x40 + 18)
 #define        AT91_PIN_PC19   (PIN_BASE + 0x40 + 19)
-
 #define        AT91_PIN_PC20   (PIN_BASE + 0x40 + 20)
 #define        AT91_PIN_PC21   (PIN_BASE + 0x40 + 21)
 #define        AT91_PIN_PC22   (PIN_BASE + 0x40 + 22)
 #define        AT91_PIN_PC23   (PIN_BASE + 0x40 + 23)
 #define        AT91_PIN_PC24   (PIN_BASE + 0x40 + 24)
-
 #define        AT91_PIN_PC25   (PIN_BASE + 0x40 + 25)
 #define        AT91_PIN_PC26   (PIN_BASE + 0x40 + 26)
 #define        AT91_PIN_PC27   (PIN_BASE + 0x40 + 27)
 #define        AT91_PIN_PC28   (PIN_BASE + 0x40 + 28)
 #define        AT91_PIN_PC29   (PIN_BASE + 0x40 + 29)
-
 #define        AT91_PIN_PC30   (PIN_BASE + 0x40 + 30)
 #define        AT91_PIN_PC31   (PIN_BASE + 0x40 + 31)
 
 #define        AT91_PIN_PD2    (PIN_BASE + 0x60 + 2)
 #define        AT91_PIN_PD3    (PIN_BASE + 0x60 + 3)
 #define        AT91_PIN_PD4    (PIN_BASE + 0x60 + 4)
-
 #define        AT91_PIN_PD5    (PIN_BASE + 0x60 + 5)
 #define        AT91_PIN_PD6    (PIN_BASE + 0x60 + 6)
 #define        AT91_PIN_PD7    (PIN_BASE + 0x60 + 7)
 #define        AT91_PIN_PD8    (PIN_BASE + 0x60 + 8)
 #define        AT91_PIN_PD9    (PIN_BASE + 0x60 + 9)
-
 #define        AT91_PIN_PD10   (PIN_BASE + 0x60 + 10)
 #define        AT91_PIN_PD11   (PIN_BASE + 0x60 + 11)
 #define        AT91_PIN_PD12   (PIN_BASE + 0x60 + 12)
 #define        AT91_PIN_PD13   (PIN_BASE + 0x60 + 13)
 #define        AT91_PIN_PD14   (PIN_BASE + 0x60 + 14)
-
 #define        AT91_PIN_PD15   (PIN_BASE + 0x60 + 15)
 #define        AT91_PIN_PD16   (PIN_BASE + 0x60 + 16)
 #define        AT91_PIN_PD17   (PIN_BASE + 0x60 + 17)
 #define        AT91_PIN_PD18   (PIN_BASE + 0x60 + 18)
 #define        AT91_PIN_PD19   (PIN_BASE + 0x60 + 19)
-
 #define        AT91_PIN_PD20   (PIN_BASE + 0x60 + 20)
 #define        AT91_PIN_PD21   (PIN_BASE + 0x60 + 21)
 #define        AT91_PIN_PD22   (PIN_BASE + 0x60 + 22)
 #define        AT91_PIN_PD23   (PIN_BASE + 0x60 + 23)
 #define        AT91_PIN_PD24   (PIN_BASE + 0x60 + 24)
-
 #define        AT91_PIN_PD25   (PIN_BASE + 0x60 + 25)
 #define        AT91_PIN_PD26   (PIN_BASE + 0x60 + 26)
 #define        AT91_PIN_PD27   (PIN_BASE + 0x60 + 27)
 #define        AT91_PIN_PD28   (PIN_BASE + 0x60 + 28)
 #define        AT91_PIN_PD29   (PIN_BASE + 0x60 + 29)
-
 #define        AT91_PIN_PD30   (PIN_BASE + 0x60 + 30)
 #define        AT91_PIN_PD31   (PIN_BASE + 0x60 + 31)
 
+#define        AT91_PIN_PE0    (PIN_BASE + 0x80 + 0)
+#define        AT91_PIN_PE1    (PIN_BASE + 0x80 + 1)
+#define        AT91_PIN_PE2    (PIN_BASE + 0x80 + 2)
+#define        AT91_PIN_PE3    (PIN_BASE + 0x80 + 3)
+#define        AT91_PIN_PE4    (PIN_BASE + 0x80 + 4)
+#define        AT91_PIN_PE5    (PIN_BASE + 0x80 + 5)
+#define        AT91_PIN_PE6    (PIN_BASE + 0x80 + 6)
+#define        AT91_PIN_PE7    (PIN_BASE + 0x80 + 7)
+#define        AT91_PIN_PE8    (PIN_BASE + 0x80 + 8)
+#define        AT91_PIN_PE9    (PIN_BASE + 0x80 + 9)
+#define        AT91_PIN_PE10   (PIN_BASE + 0x80 + 10)
+#define        AT91_PIN_PE11   (PIN_BASE + 0x80 + 11)
+#define        AT91_PIN_PE12   (PIN_BASE + 0x80 + 12)
+#define        AT91_PIN_PE13   (PIN_BASE + 0x80 + 13)
+#define        AT91_PIN_PE14   (PIN_BASE + 0x80 + 14)
+#define        AT91_PIN_PE15   (PIN_BASE + 0x80 + 15)
+#define        AT91_PIN_PE16   (PIN_BASE + 0x80 + 16)
+#define        AT91_PIN_PE17   (PIN_BASE + 0x80 + 17)
+#define        AT91_PIN_PE18   (PIN_BASE + 0x80 + 18)
+#define        AT91_PIN_PE19   (PIN_BASE + 0x80 + 19)
+#define        AT91_PIN_PE20   (PIN_BASE + 0x80 + 20)
+#define        AT91_PIN_PE21   (PIN_BASE + 0x80 + 21)
+#define        AT91_PIN_PE22   (PIN_BASE + 0x80 + 22)
+#define        AT91_PIN_PE23   (PIN_BASE + 0x80 + 23)
+#define        AT91_PIN_PE24   (PIN_BASE + 0x80 + 24)
+#define        AT91_PIN_PE25   (PIN_BASE + 0x80 + 25)
+#define        AT91_PIN_PE26   (PIN_BASE + 0x80 + 26)
+#define        AT91_PIN_PE27   (PIN_BASE + 0x80 + 27)
+#define        AT91_PIN_PE28   (PIN_BASE + 0x80 + 28)
+#define        AT91_PIN_PE29   (PIN_BASE + 0x80 + 29)
+#define        AT91_PIN_PE30   (PIN_BASE + 0x80 + 30)
+#define        AT91_PIN_PE31   (PIN_BASE + 0x80 + 31)
+
 #ifndef __ASSEMBLY__
 /* setup setup routines, called from board init or driver probe() */
 extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup);
similarity index 86%
rename from include/asm-arm/arch-at91rm9200/hardware.h
rename to include/asm-arm/arch-at91/hardware.h
index 9ea5bfe06320ad908cc6b4e46023ddcbe1263146..eaaf1c12b75330c9d1fbf52a46df61e71e8ac069 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/hardware.h
+ * include/asm-arm/arch-at91/hardware.h
  *
  *  Copyright (C) 2003 SAN People
  *  Copyright (C) 2003 ATMEL
 #include <asm/arch/at91sam9260.h>
 #elif defined(CONFIG_ARCH_AT91SAM9261)
 #include <asm/arch/at91sam9261.h>
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+#include <asm/arch/at91sam9263.h>
 #else
 #error "Unsupported AT91 processor"
 #endif
 
 
 /*
- * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF
- * to 0xFEFA0000 .. 0xFF000000.  (384Kb)
+ * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
+ * to 0xFEF78000 .. 0xFF000000.  (5444Kb)
  */
-#define AT91_IO_PHYS_BASE      0xFFFA0000
+#define AT91_IO_PHYS_BASE      0xFFF78000
 #define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 #define AT91_IO_VIRT_BASE      (0xFF000000 - AT91_IO_SIZE)
 
  /* Convert a physical IO address to virtual IO address */
-#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
+#define AT91_IO_P2V(x)         ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
 
 /*
  * Virtual to Physical Address mapping for IO devices.
similarity index 95%
rename from include/asm-arm/arch-at91rm9200/io.h
rename to include/asm-arm/arch-at91/io.h
index 88fd1bebcef3c86f692c828acacf5ae8bf86bfc7..401f327ec0475ed901c024b0efec6570e03a41df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/io.h
+ * include/asm-arm/arch-at91/io.h
  *
  *  Copyright (C) 2003 SAN People
  *
similarity index 90%
rename from include/asm-arm/arch-at91rm9200/irqs.h
rename to include/asm-arm/arch-at91/irqs.h
index c0679eaefaf2587013d2a280565dcce13754d7ae..1ffa3bb9a9c17c058d826a0d7f63674bf507b7c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/irqs.h
+ * include/asm-arm/arch-at91/irqs.h
  *
  *  Copyright (C) 2004 SAN People
  *
@@ -37,8 +37,8 @@
  * IRQ interrupt symbols are the AT91xxx_ID_* symbols
  * for IRQs handled directly through the AIC, or else the AT91_PIN_*
  * symbols in gpio.h for ones handled indirectly as GPIOs.
- * We make provision for 4 banks of GPIO.
+ * We make provision for 5 banks of GPIO.
  */
-#define        NR_IRQS         (NR_AIC_IRQS + (4 * 32))
+#define        NR_IRQS         (NR_AIC_IRQS + (5 * 32))
 
 #endif
similarity index 96%
rename from include/asm-arm/arch-at91rm9200/memory.h
rename to include/asm-arm/arch-at91/memory.h
index f985069e6d011dd41784e83e65f6e6729fe49fff..4835d6784509debe4db74627b73caea6d4f15175 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/memory.h
+ * include/asm-arm/arch-at91/memory.h
  *
  *  Copyright (C) 2004 SAN People
  *
similarity index 97%
rename from include/asm-arm/arch-at91rm9200/system.h
rename to include/asm-arm/arch-at91/system.h
index 9c67130603b2896195649648f4869a749d5c5b0b..6bf846098ea973c20cdfd4d83372eb9fad48362c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/system.h
+ * include/asm-arm/arch-at91/system.h
  *
  *  Copyright (C) 2003 SAN People
  *
similarity index 86%
rename from include/asm-arm/arch-at91rm9200/timex.h
rename to include/asm-arm/arch-at91/timex.h
index faeca45a8d446f999badcb3a9fac7c95e4b9dfb4..f41636d607a25001d4bb6692fd51b463e5e10fff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/timex.h
+ * include/asm-arm/arch-at91/timex.h
  *
  *  Copyright (C) 2003 SAN People
  *
 #define AT91SAM9_MASTER_CLOCK  99300000
 #define CLOCK_TICK_RATE                (AT91SAM9_MASTER_CLOCK/16)
 
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+
+#define AT91SAM9_MASTER_CLOCK  99959500
+#define CLOCK_TICK_RATE                (AT91SAM9_MASTER_CLOCK/16)
+
 #endif
 
 #endif
similarity index 97%
rename from include/asm-arm/arch-at91rm9200/uncompress.h
rename to include/asm-arm/arch-at91/uncompress.h
index 34b4b93fa01523ad088fa9fbf699b80b7117cce0..a193d28304b630252cea573493942044670f06a5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/uncompress.h
+ * include/asm-arm/arch-at91/uncompress.h
  *
  *  Copyright (C) 2003 SAN People
  *
similarity index 95%
rename from include/asm-arm/arch-at91rm9200/vmalloc.h
rename to include/asm-arm/arch-at91/vmalloc.h
index 0a23b8c562b94f6033bef6c864bce85154e9b21b..bb05e70e932aabe7cf236dced09946bcbbc2711a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/vmalloc.h
+ * include/asm-arm/arch-at91/vmalloc.h
  *
  *  Copyright (C) 2003 SAN People
  *
diff --git a/include/asm-arm/arch-at91rm9200/at91_pdc.h b/include/asm-arm/arch-at91rm9200/at91_pdc.h
deleted file mode 100644 (file)
index 79d6e02..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR           0x100   /* Receive Pointer Register */
-#define AT91_PDC_RCR           0x104   /* Receive Counter Register */
-#define AT91_PDC_TPR           0x108   /* Transmit Pointer Register */
-#define AT91_PDC_TCR           0x10c   /* Transmit Counter Register */
-#define AT91_PDC_RNPR          0x110   /* Receive Next Pointer Register */
-#define AT91_PDC_RNCR          0x114   /* Receive Next Counter Register */
-#define AT91_PDC_TNPR          0x118   /* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR          0x11c   /* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR          0x120   /* Transfer Control Register */
-#define                AT91_PDC_RXTEN          (1 << 0)        /* Receiver Transfer Enable */
-#define                AT91_PDC_RXTDIS         (1 << 1)        /* Receiver Transfer Disable */
-#define                AT91_PDC_TXTEN          (1 << 8)        /* Transmitter Transfer Enable */
-#define                AT91_PDC_TXTDIS         (1 << 9)        /* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR          0x124   /* Transfer Status Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S
deleted file mode 100644 (file)
index 85cdadf..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/debug-macro.S
- *
- *  Copyright (C) 2003-2005 SAN People
- *
- * Debugging macro include header
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_dbgu.h>
-
-       .macro  addruart,rx
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                         @ MMU enabled?
-       ldreq   \rx, =AT91_BASE_SYS             @ System peripherals (phys address)
-       ldrne   \rx, =AT91_VA_BASE_SYS          @ System peripherals (virt address)
-       .endm
-
-       .macro  senduart,rd,rx
-       strb    \rd, [\rx, #AT91_DBGU_THR]      @ Write to Transmitter Holding Register
-       .endm
-
-       .macro  waituart,rd,rx
-1001:  ldr     \rd, [\rx, #AT91_DBGU_SR]       @ Read Status Register
-       tst     \rd, #AT91_DBGU_TXRDY           @ DBGU_TXRDY = 1 when ready to transmit
-       beq     1001b
-       .endm
-
-       .macro  busyuart,rd,rx
-1001:  ldr     \rd, [\rx, #AT91_DBGU_SR]       @ Read Status Register
-       tst     \rd, #AT91_DBGU_TXEMPTY         @ DBGU_TXEMPTY = 1 when transmission complete
-       beq     1001b
-       .endm
-
diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S
deleted file mode 100644 (file)
index 57248a7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/entry-macro.S
- *
- *  Copyright (C) 2003-2005 SAN People
- *
- * Low-level IRQ helper macros for AT91RM9200 platforms
- *
- * 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 <asm/hardware.h>
-#include <asm/arch/at91_aic.h>
-
-       .macro  disable_fiq
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \base, =(AT91_VA_BASE_SYS)              @ base virtual address of SYS peripherals
-       ldr     \irqnr, [\base, #AT91_AIC_IVR]          @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
-       ldr     \irqstat, [\base, #AT91_AIC_ISR]        @ read interrupt source number
-       teq     \irqstat, #0                            @ ISR is 0 when no current interrupt, or spurious interrupt
-       streq   \tmp, [\base, #AT91_AIC_EOICR]          @ not going to be handled further, then ACK it now.
-       .endm
-
index 593f562f85c35ab08cede727f564f51f3622b813..625c6f0abc030c50b5fab0f1014dae6deaeebd3b 100644 (file)
 
 #define EP93XX_GPIO_BASE               (EP93XX_APB_VIRT_BASE + 0x00040000)
 #define EP93XX_GPIO_REG(x)             (EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_TYPE1                EP93XX_GPIO_REG(0x4c)
+#define EP93XX_GPIO_F_INT_TYPE2                EP93XX_GPIO_REG(0x50)
+#define EP93XX_GPIO_F_INT_ACK          EP93XX_GPIO_REG(0x54)
+#define EP93XX_GPIO_F_INT_ENABLE       EP93XX_GPIO_REG(0x58)
+#define EP93XX_GPIO_F_INT_STATUS       EP93XX_GPIO_REG(0x5c)
 #define EP93XX_GPIO_A_INT_TYPE1                EP93XX_GPIO_REG(0x90)
 #define EP93XX_GPIO_A_INT_TYPE2                EP93XX_GPIO_REG(0x94)
 #define EP93XX_GPIO_A_INT_ACK          EP93XX_GPIO_REG(0x98)
index ae532e304bf1f2b182e1e1430c350c57c7089e2d..2a8c63638c5e824cd30aa2a612d185263ba28f05 100644 (file)
 #define IRQ_EP93XX_SAI                 60
 #define EP93XX_VIC2_VALID_IRQ_MASK     0x1fffffff
 
-#define IRQ_EP93XX_GPIO(x)             (64 + (x))
+/*
+ * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
+ * F0..F7 to 80..87.
+ */
+#define IRQ_EP93XX_GPIO(x)             (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
 
-#define NR_EP93XX_IRQS                 IRQ_EP93XX_GPIO(16)
+#define NR_EP93XX_IRQS                 (64 + 24)
 
 #define EP93XX_BOARD_IRQ(x)            (NR_EP93XX_IRQS + (x))
 #define EP93XX_BOARD_IRQS              32
index b4a8deb8bdef8c4aae9c08c50ca29702d2ea15eb..44eccec2cba45d36f69a6ac11e097feb250ca307 100644 (file)
@@ -8,7 +8,6 @@ void ep93xx_map_io(void);
 void ep93xx_init_irq(void);
 void ep93xx_init_time(unsigned long);
 void ep93xx_init_devices(void);
-void ep93xx_clock_init(void);
 extern struct sys_timer ep93xx_timer;
 
 struct ep93xx_eth_data
index 3b9ef69146275a68929602e67f773b238f676348..61bb0bdc1b1651744c0b888a5ffd73a8461dd50c 100644 (file)
                .endm
 #define AITC_NIVECSR   0x40
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \irqstat, =IO_ADDRESS(IMX_AITC_BASE)
+               ldr     \base, =IO_ADDRESS(IMX_AITC_BASE)
                @ Load offset & priority of the highest priority
                @ interrupt pending.
-               ldr     \irqnr, [\irqstat, #AITC_NIVECSR]
+               ldr     \irqstat, [\base, #AITC_NIVECSR]
                @ Shift off the priority leaving the offset or
-               @ "interrupt number"
-               mov     \irqnr, \irqnr, lsr #16
-               ldr     \irqstat, =1    @ dummy compare
-               ldr     \base, =0xFFFF          // invalid interrupt
-               cmp     \irqnr, \base
-               bne     1001f
-               ldr     \irqstat, =0
-1001:
-               tst     \irqstat, #1    @ to make the condition code = TRUE
+               @ "interrupt number", use arithmetic shift to
+               @ transform illegal source (0xffff) as -1
+               mov     \irqnr, \irqstat, asr #16
+               adds    \tmp, \irqnr, #1
                .endm
-
index 12d9ee02cde31c26c8421c38a70c140f97ac14a7..5f570a598a376919ba839da1750a7fe3f6bbe2ec 100644 (file)
 
 #include <asm/hardware.h>
 
-#define IO_SPACE_LIMIT         0xffffffff
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
 
-#define __io(p)                        ((void __iomem *)(p))
+#define IO_SPACE_LIMIT         0xffffffff
+#define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)       __iop3xx_iounmap(a)
 
 #endif
index c017402bab965d52fcdc88f10aadd233e27f3004..1bb5071e1fa8b98b4c1549a6797aa1083cc21905 100644 (file)
 
 #include <asm/hardware.h>
 
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
+
 #define IO_SPACE_LIMIT         0xffffffff
-#define __io(p)                        ((void __iomem *)(p))
+#define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)       __iop3xx_iounmap(a)
 
 #endif
diff --git a/include/asm-arm/arch-ixp4xx/avila.h b/include/asm-arm/arch-ixp4xx/avila.h
new file mode 100644 (file)
index 0000000..0dfea0c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-ixp4xx/avila.h
+ *
+ * Gateworks Avila platform specific definitions
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp425.h
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista, Software, 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define        AVILA_SDA_PIN           7
+#define        AVILA_SCL_PIN           6
+
+/*
+ * AVILA PCI IRQs
+ */
+#define AVILA_PCI_MAX_DEV      4
+#define LOFT_PCI_MAX_DEV    6
+#define AVILA_PCI_IRQ_LINES    4
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define AVILA_PCI_INTA_PIN     11
+#define AVILA_PCI_INTB_PIN     10
+#define AVILA_PCI_INTC_PIN     9
+#define AVILA_PCI_INTD_PIN     8
+
+
index 6acb69c95ef9cfebf262034fc7a0c1998a410420..88fd0877dcc13928ca5808a696dc8ca52f474e9b 100644 (file)
@@ -42,6 +42,7 @@ extern unsigned int processor_id;
 
 /* Platform specific details */
 #include "ixdp425.h"
+#include "avila.h"
 #include "coyote.h"
 #include "prpmc1100.h"
 #include "nslu2.h"
index f24b763ca18e406cf698d7096534ddb1f0282137..e44a563d00ffcf48c569031aac44975540544e05 100644 (file)
 #define        IRQ_IXDP425_PCI_INTC    IRQ_IXP4XX_GPIO9
 #define        IRQ_IXDP425_PCI_INTD    IRQ_IXP4XX_GPIO8
 
+/*
+ * Gateworks Avila board IRQs
+ */
+#define        IRQ_AVILA_PCI_INTA      IRQ_IXP4XX_GPIO11
+#define        IRQ_AVILA_PCI_INTB      IRQ_IXP4XX_GPIO10
+#define        IRQ_AVILA_PCI_INTC      IRQ_IXP4XX_GPIO9
+#define        IRQ_AVILA_PCI_INTD      IRQ_IXP4XX_GPIO8
+
+
 /*
  * PrPMC1100 Board IRQs
  */
index dbdec36ff0d1bc7642dd64c662ea17262a52a13a..79b850a3be475cdb96422c85be26d3170d8e8307 100644 (file)
@@ -6,3 +6,25 @@
 
 extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+       return 0;
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+       return 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+}
+
diff --git a/include/asm-arm/arch-ns9xxx/board.h b/include/asm-arm/arch-ns9xxx/board.h
new file mode 100644 (file)
index 0000000..91dc8fb
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/board.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <asm/mach-types.h>
+
+#define board_is_a9m9750dev()  (machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_BOARD_H */
diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
new file mode 100644 (file)
index 0000000..4371a48
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-ns9xxx/clock.h
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H
+
+static inline u32 ns9xxx_systemclock(void)
+{
+       /*
+        * This should be a multiple of HZ * TIMERCLOCKSELECT (in time.c)
+        */
+       return 353894400;
+}
+
+static inline const u32 ns9xxx_cpuclock(void)
+{
+       return ns9xxx_systemclock() / 2;
+}
+
+static inline const u32 ns9xxx_ahbclock(void)
+{
+       return ns9xxx_systemclock() / 4;
+}
+
+static inline const u32 ns9xxx_bbusclock(void)
+{
+       return ns9xxx_systemclock() / 8;
+}
+
+#endif /* ifndef __ASM_ARCH_CLOCK_H */
diff --git a/include/asm-arm/arch-ns9xxx/debug-macro.S b/include/asm-arm/arch-ns9xxx/debug-macro.S
new file mode 100644 (file)
index 0000000..b21b93e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/debug-macro.S
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+               .macro  addruart,rx
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1
+               ldreq   \rx, =NS9XXX_CSxSTAT_PHYS(0)
+               ldrne   \rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+               .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ns9xxx/dma.h b/include/asm-arm/arch-ns9xxx/dma.h
new file mode 100644 (file)
index 0000000..a67cbbe
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * include/asm-arm/arch-ns9xxx/dma.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#endif /* ifndef __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ns9xxx/entry-macro.S b/include/asm-arm/arch-ns9xxx/entry-macro.S
new file mode 100644 (file)
index 0000000..467a198
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/entry-macro.S
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               ldr     \base, =SYS_ISRADDR
+               ldr     \irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
+               cmp     \irqstat, #0
+               ldrne   \irqnr, [\base]
+               .endm
+
+               .macro  disable_fiq
+               .endm
diff --git a/include/asm-arm/arch-ns9xxx/hardware.h b/include/asm-arm/arch-ns9xxx/hardware.h
new file mode 100644 (file)
index 0000000..6819da7
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * include/asm-arm/arch-ns9xxx/hardware.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/memory.h>
+
+/*
+ * NetSilicon NS9xxx internal mapping:
+ *
+ * physical                <--> virtual
+ * 0x90000000 - 0x906fffff <--> 0xf9000000 - 0xf96fffff
+ * 0xa0100000 - 0xa0afffff <--> 0xfa100000 - 0xfaafffff
+ */
+#define io_p2v(x)      (0xf0000000 \
+                        + (((x) & 0xf0000000) >> 4) \
+                        + ((x) & 0x00ffffff))
+
+#define io_v2p(x)      ((((x) & 0x0f000000) << 4) \
+                        + ((x) & 0x00ffffff))
+
+#define __REGBIT(bit)          ((u32)1 << (bit))
+#define __REGBITS(hbit, lbit)  ((((u32)1 << ((hbit) - (lbit) + 1)) - 1) << (lbit))
+#define __REGVAL(mask, value)  (((value) * ((mask) & (-(mask))) & (mask)))
+
+#ifndef __ASSEMBLY__
+
+#  define __REG(x)     (*((volatile u32 *)io_p2v((x))))
+#  define __REG2(x, y) (*((volatile u32 *)io_p2v((x)) + (y)))
+
+#  define __REGB(x)    (*((volatile u8 *)io_p2v((x))))
+#  define __REGB2(x)   (*((volatile u8 *)io_p2v((x)) + (y)))
+
+#  define REGSET(var, reg, field, value)                               \
+       ((var) = (((var)                                                \
+                  & ~(reg ## _ ## field &                              \
+                      ~ reg ## _ ## field ## _ ## value))              \
+                 | (reg ## _ ## field ## _ ## value)))
+
+#  define REGSETIM(var, reg, field, value)                             \
+       ((var) = (((var)                                                \
+                  & ~(reg ## _ ## field &                              \
+                      ~(__REGVAL(reg ## _ ## field, value))))          \
+                 | (__REGVAL(reg ## _ ## field, value))))
+
+#  define REGGET(reg, field)                                           \
+       ((reg & (reg ## _ ## field)) / (field & (-field)))
+
+#else
+
+#  define __REG(x)     io_p2v(x)
+#  define __REG2(x, y) io_p2v((x) + (y))
+
+#  define __REGB(x)    __REG((x))
+#  define __REGB2(x, y)        __REG2((x), (y))
+
+#endif
+
+#endif /* ifndef __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ns9xxx/io.h b/include/asm-arm/arch-ns9xxx/io.h
new file mode 100644 (file)
index 0000000..6f82d28
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/io.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT  0xffffffff /* XXX */
+
+#define __io(a)         ((void __iomem *)(a))
+#define __mem_pci(a)    (a)
+#define __mem_isa(a)    (IO_BASE + (a))
+
+#endif /* ifndef __ASM_ARCH_IO_H */
diff --git a/include/asm-arm/arch-ns9xxx/irqs.h b/include/asm-arm/arch-ns9xxx/irqs.h
new file mode 100644 (file)
index 0000000..25d8d28
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * include/asm-arm/arch-ns9xxx/irqs.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_WATCHDOG   0
+#define IRQ_AHBBUSERR  1
+#define IRQ_BBUSAGG    2
+/* irq 3 is reserved for NS9360 */
+#define IRQ_ETHRX      4
+#define IRQ_ETHTX      5
+#define IRQ_ETHPHY     6
+#define IRQ_LCD                7
+#define IRQ_SERBRX     8
+#define IRQ_SERBTX     9
+#define IRQ_SERARX     10
+#define IRQ_SERATX     11
+#define IRQ_SERCRX     12
+#define IRQ_SERCTX     13
+#define IRQ_I2C                14
+#define IRQ_BBUSDMA    15
+#define IRQ_TIMER0     16
+#define IRQ_TIMER1     17
+#define IRQ_TIMER2     18
+#define IRQ_TIMER3     19
+#define IRQ_TIMER4     20
+#define IRQ_TIMER5     21
+#define IRQ_TIMER6     22
+#define IRQ_TIMER7     23
+#define IRQ_RTC                24
+#define IRQ_USBHOST    25
+#define IRQ_USBDEVICE  26
+#define IRQ_IEEE1284   27
+#define IRQ_EXT0       28
+#define IRQ_EXT1       29
+#define IRQ_EXT2       30
+#define IRQ_EXT3       31
+
+#define BBUS_IRQ(irq)  (32 + irq)
+
+#define IRQ_BBUS_DMA           BBUS_IRQ(0)
+#define IRQ_BBUS_SERBRX                BBUS_IRQ(2)
+#define IRQ_BBUS_SERBTX                BBUS_IRQ(3)
+#define IRQ_BBUS_SERARX                BBUS_IRQ(4)
+#define IRQ_BBUS_SERATX                BBUS_IRQ(5)
+#define IRQ_BBUS_SERCRX                BBUS_IRQ(6)
+#define IRQ_BBUS_SERCTX                BBUS_IRQ(7)
+#define IRQ_BBUS_SERDRX                BBUS_IRQ(8)
+#define IRQ_BBUS_SERDTX                BBUS_IRQ(9)
+#define IRQ_BBUS_I2C           BBUS_IRQ(10)
+#define IRQ_BBUS_1284          BBUS_IRQ(11)
+#define IRQ_BBUS_UTIL          BBUS_IRQ(12)
+#define IRQ_BBUS_RTC           BBUS_IRQ(13)
+#define IRQ_BBUS_USBHST                BBUS_IRQ(14)
+#define IRQ_BBUS_USBDEV                BBUS_IRQ(15)
+#define IRQ_BBUS_AHBDMA1       BBUS_IRQ(24)
+#define IRQ_BBUS_AHBDMA2       BBUS_IRQ(25)
+
+/*
+ * these Interrupts are specific for the a9m9750dev board.
+ * They are generated by an FPGA that interrupts the CPU on
+ * IRQ_EXT2
+ */
+#define FPGA_IRQ(irq)  (64 + irq)
+
+#define IRQ_FPGA_UARTA         FPGA_IRQ(0)
+#define IRQ_FPGA_UARTB         FPGA_IRQ(1)
+#define IRQ_FPGA_UARTC         FPGA_IRQ(2)
+#define IRQ_FPGA_UARTD         FPGA_IRQ(3)
+#define IRQ_FPGA_TOUCH         FPGA_IRQ(4)
+#define IRQ_FPGA_CF            FPGA_IRQ(5)
+#define IRQ_FPGA_CAN0          FPGA_IRQ(6)
+#define IRQ_FPGA_CAN1          FPGA_IRQ(7)
+
+#define NR_IRQS        72
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-ns9xxx/memory.h b/include/asm-arm/arch-ns9xxx/memory.h
new file mode 100644 (file)
index 0000000..ce1343e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-ns9xxx/memory.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+*/
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/* x in [0..3] */
+#define NS9XXX_CSxSTAT_PHYS(x) UL(((x) + 4) << 28)
+
+#define NS9XXX_CS0STAT_LENGTH  UL(0x1000)
+#define NS9XXX_CS1STAT_LENGTH  UL(0x1000)
+#define NS9XXX_CS2STAT_LENGTH  UL(0x1000)
+#define NS9XXX_CS3STAT_LENGTH  UL(0x1000)
+
+#define PHYS_OFFSET    UL(0x00000000)
+
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff --git a/include/asm-arm/arch-ns9xxx/processor.h b/include/asm-arm/arch-ns9xxx/processor.h
new file mode 100644 (file)
index 0000000..716c106
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/processor.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+#include <asm/mach-types.h>
+
+#define processor_is_ns9360()  (machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_PROCESSOR_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-bbu.h b/include/asm-arm/arch-ns9xxx/regs-bbu.h
new file mode 100644 (file)
index 0000000..e262695
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-bbu.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBBU_H
+#define __ASM_ARCH_REGSBBU_H
+
+#include <asm/hardware.h>
+
+/* BBus Utility */
+
+/* GPIO Configuration Register */
+#define BBU_GC(x)      __REG2(0x9060000c, (x))
+
+#endif /* ifndef __ASM_ARCH_REGSBBU_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
new file mode 100644 (file)
index 0000000..c3dc532
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBOARDA9M9750_H
+#define __ASM_ARCH_REGSBOARDA9M9750_H
+
+#include <asm/hardware.h>
+
+#define FPGA_UARTA_BASE        io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+#define FPGA_UARTB_BASE        io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x08)
+#define FPGA_UARTC_BASE        io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x10)
+#define FPGA_UARTD_BASE        io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x18)
+
+#define FPGA_IER       __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x50)
+#define FPGA_ISR       __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x60)
+
+#endif /* ifndef __ASM_ARCH_REGSBOARDA9M9750_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-mem.h b/include/asm-arm/arch-ns9xxx/regs-mem.h
new file mode 100644 (file)
index 0000000..8ed8448
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-mem.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSMEM_H
+#define __ASM_ARCH_REGSMEM_H
+
+#include <asm/hardware.h>
+
+/* Memory Module */
+
+/* Control register */
+#define MEM_CTRL       __REG(0xa0700000)
+
+/* Status register */
+#define MEM_STAT       __REG(0xa0700004)
+
+/* Configuration register */
+#define MEM_CONF       __REG(0xa0700008)
+
+/* Dynamic Memory Control register */
+#define MEM_DMCTRL     __REG(0xa0700020)
+
+/* Dynamic Memory Refresh Timer */
+#define MEM_DMRT       __REG(0xa0700024)
+
+/* Dynamic Memory Read Configuration register */
+#define MEM_DMRC       __REG(0xa0700028)
+
+/* Dynamic Memory Precharge Command Period (tRP) */
+#define MEM_DMPCP      __REG(0xa0700030)
+
+/* Dynamic Memory Active to Precharge Command Period (tRAS) */
+#define MEM_DMAPCP     __REG(0xa0700034)
+
+/* Dynamic Memory Self-Refresh Exit Time (tSREX) */
+#define MEM_DMSRET     __REG(0xa0700038)
+
+/* Dynamic Memory Last Data Out to Active Time (tAPR) */
+#define MEM_DMLDOAT    __REG(0xa070003c)
+
+/* Dynamic Memory Data-in to Active Command Time (tDAL or TAPW) */
+#define MEM_DMDIACT    __REG(0xa0700040)
+
+/* Dynamic Memory Write Recovery Time (tWR, tDPL, tRWL, tRDL) */
+#define MEM_DMWRT      __REG(0xa0700044)
+
+/* Dynamic Memory Active to Active Command Period (tRC) */
+#define MEM_DMAACP     __REG(0xa0700048)
+
+/* Dynamic Memory Auto Refresh Period, and Auto Refresh to Active Command Period (tRFC) */
+#define MEM_DMARP      __REG(0xa070004c)
+
+/* Dynamic Memory Exit Self-Refresh to Active Command (tXSR) */
+#define MEM_DMESRAC    __REG(0xa0700050)
+
+/* Dynamic Memory Active Bank A to Active B Time (tRRD) */
+#define MEM_DMABAABT   __REG(0xa0700054)
+
+/* Dynamic Memory Load Mode register to Active Command Time (tMRD) */
+#define MEM_DMLMACT    __REG(0xa0700058)
+
+/* Static Memory Extended Wait */
+#define MEM_SMEW       __REG(0xa0700080)
+
+/* Dynamic Memory Configuration Register x */
+#define MEM_DMCONF(x)  __REG2(0xa0700100, (x) << 3)
+
+/* Dynamic Memory RAS and CAS Delay x */
+#define MEM_DMRCD(x)   __REG2(0xa0700104, (x) << 3)
+
+/* Static Memory Configuration Register x */
+#define MEM_SMC(x)     __REG2(0xa0700200, (x) << 3)
+
+/* Static Memory Configuration Register x: Write protect */
+#define MEM_SMC_WSMC           __REGBIT(20)
+#define MEM_SMC_WSMC_OFF               __REGVAL(MEM_SMC_WSMC, 0)
+#define MEM_SMC_WSMC_ON                        __REGVAL(MEM_SMC_WSMC, 1)
+
+/* Static Memory Configuration Register x: Buffer enable */
+#define MEM_SMC_BSMC           __REGBIT(19)
+#define MEM_SMC_BSMC_OFF               __REGVAL(MEM_SMC_BSMC, 0)
+#define MEM_SMC_BSMC_ON                        __REGVAL(MEM_SMC_BSMC, 1)
+
+/* Static Memory Configuration Register x: Extended Wait */
+#define MEM_SMC_EW             __REGBIT(8)
+#define MEM_SMC_EW_OFF                 __REGVAL(MEM_SMC_EW, 0)
+#define MEM_SMC_EW_ON                  __REGVAL(MEM_SMC_EW, 1)
+
+/* Static Memory Configuration Register x: Byte lane state */
+#define MEM_SMC_PB             __REGBIT(7)
+#define MEM_SMC_PB_0                   __REGVAL(MEM_SMC_PB, 0)
+#define MEM_SMC_PB_1                   __REGVAL(MEM_SMC_PB, 1)
+
+/* Static Memory Configuration Register x: Chip select polarity */
+#define MEM_SMC_PC             __REGBIT(6)
+#define MEM_SMC_PC_AL                  __REGVAL(MEM_SMC_PC, 0)
+#define MEM_SMC_PC_AH                  __REGVAL(MEM_SMC_PC, 1)
+
+/* static memory configuration register x: page mode*/
+#define MEM_SMC_PM             __REGBIT(3)
+#define MEM_SMC_PM_DIS                 __REGVAL(MEM_SMC_PM, 0)
+#define MEM_SMC_PM_ASYNC               __REGVAL(MEM_SMC_PM, 1)
+
+/* static memory configuration register x: Memory width */
+#define MEM_SMC_MW             __REGBITS(1, 0)
+#define MEM_SMC_MW_8                   __REGVAL(MEM_SMC_MW, 0)
+#define MEM_SMC_MW_16                  __REGVAL(MEM_SMC_MW, 1)
+#define MEM_SMC_MW_32                  __REGVAL(MEM_SMC_MW, 2)
+
+/* Static Memory Write Enable Delay x */
+#define MEM_SMWED(x)   __REG2(0xa0700204, (x) << 3)
+
+/* Static Memory Output Enable Delay x */
+#define MEM_SMOED(x)   __REG2(0xa0700208, (x) << 3)
+
+/* Static Memory Read Delay x */
+#define MEM_SMRD(x)    __REG2(0xa070020c, (x) << 3)
+
+/* Static Memory Page Mode Read Delay 0 */
+#define MEM_SMPMRD(x)  __REG2(0xa0700210, (x) << 3)
+
+/* Static Memory Write Delay */
+#define MEM_SMWD(x)    __REG2(0xa0700214, (x) << 3)
+
+/* Static Memory Turn Round Delay x */
+#define MEM_SWT(x)     __REG2(0xa0700218, (x) << 3)
+
+#endif /* ifndef __ASM_ARCH_REGSMEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-sys.h b/include/asm-arm/arch-ns9xxx/regs-sys.h
new file mode 100644 (file)
index 0000000..8162a50
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-sys.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSSYS_H
+#define __ASM_ARCH_REGSSYS_H
+
+#include <asm/hardware.h>
+
+/* System Control Module */
+
+/* AHB Arbiter Gen Configuration */
+#define SYS_AHBAGENCONF        __REG(0xa0900000)
+
+/* BRC */
+#define SYS_BRC(x)     __REG2(0xa0900004, (x))
+
+/* Timer x Reload Count register */
+#define SYS_TRC(x)     __REG2(0xa0900044, (x))
+
+/* Timer x Read register */
+#define SYS_TR(x)      __REG2(0xa0900084, (x))
+
+/* Interrupt Vector Address Register Level x */
+#define SYS_IVA(x)     __REG2(0xa09000c4, (x))
+
+/* Interrupt Configuration registers */
+#define SYS_IC(x)      __REG2(0xa0900144, (x))
+
+/* ISRADDR */
+#define SYS_ISRADDR    __REG(0xa0900164)
+
+/* Interrupt Status Active */
+#define SYS_ISA                __REG(0xa0900168)
+
+/* Interrupt Status Raw */
+#define SYS_ISR                __REG(0xa090016c)
+
+/* Timer Interrupt Status register */
+#define SYS_TIS                __REG(0xa0900170)
+
+/* PLL Configuration register */
+#define SYS_PLL                __REG(0xa0900188)
+
+/* PLL Configuration register: PLL SW change */
+#define SYS_PLL_SWC            __REGBIT(15)
+#define SYS_PLL_SWC_NO                 __REGVAL(SYS_PLL_SWC, 0)
+#define SYS_PLL_SWC_YES                        __REGVAL(SYS_PLL_SWC, 1)
+
+/* Timer x Control register */
+#define SYS_TC(x)      __REG2(0xa0900190, (x))
+
+/* Timer x Control register: Timer enable */
+#define SYS_TCx_TEN            __REGBIT(15)
+#define SYS_TCx_TEN_DIS                        __REGVAL(SYS_TCx_TEN, 1)
+#define SYS_TCx_TEN_EN                 __REGVAL(SYS_TCx_TEN, 1)
+
+/* Timer x Control register: CPU debug mode */
+#define SYS_TCx_TDBG           __REGBIT(10)
+#define SYS_TCx_TDBG_CONT              __REGVAL(SYS_TCx_TDBG, 0)
+#define SYS_TCx_TDBG_STOP              __REGVAL(SYS_TCx_TDBG, 1)
+
+/* Timer x Control register: Interrupt clear */
+#define SYS_TCx_INTC           __REGBIT(9)
+#define SYS_TCx_INTC_UNSET             __REGVAL(SYS_TCx_INTC, 0)
+#define SYS_TCx_INTC_SET               __REGVAL(SYS_TCx_INTC, 1)
+
+/* Timer x Control register: Timer clock select */
+#define SYS_TCx_TLCS           __REGBITS(8, 6)
+#define SYS_TCx_TLCS_CPU               __REGVAL(SYS_TCx_TLCS, 0)       /* CPU clock */
+#define SYS_TCx_TLCS_DIV2              __REGVAL(SYS_TCx_TLCS, 1)       /* CPU clock / 2 */
+#define SYS_TCx_TLCS_DIV4              __REGVAL(SYS_TCx_TLCS, 2)       /* CPU clock / 4 */
+#define SYS_TCx_TLCS_DIV8              __REGVAL(SYS_TCx_TLCS, 3)       /* CPU clock / 8 */
+#define SYS_TCx_TLCS_DIV16             __REGVAL(SYS_TCx_TLCS, 4)       /* CPU clock / 16 */
+#define SYS_TCx_TLCS_DIV32             __REGVAL(SYS_TCx_TLCS, 5)       /* CPU clock / 32 */
+#define SYS_TCx_TLCS_DIV64             __REGVAL(SYS_TCx_TLCS, 6)       /* CPU clock / 64 */
+#define SYS_TCx_TLCS_EXT               __REGVAL(SYS_TCx_TLCS, 7)
+
+/* Timer x Control register: Timer mode */
+#define SYS_TCx_TM             __REGBITS(5, 4)
+#define SYS_TCx_TM_IEE                 __REGVAL(SYS_TCx_TM, 0)         /* Internal timer or external event */
+#define SYS_TCx_TM_ELL                 __REGVAL(SYS_TCx_TM, 1)         /* External low-level, gated timer */
+#define SYS_TCx_TM_EHL                 __REGVAL(SYS_TCx_TM, 2)         /* External high-level, gated timer */
+#define SYS_TCx_TM_CONCAT              __REGVAL(SYS_TCx_TM, 3)         /* Concatenate the lower timer. */
+
+/* Timer x Control register: Interrupt select */
+#define SYS_TCx_INTS           __REGBIT(3)
+#define SYS_TCx_INTS_DIS               __REGVAL(SYS_TCx_INTS, 0)
+#define SYS_TCx_INTS_EN                        __REGVAL(SYS_TCx_INTS, 1)
+
+/* Timer x Control register: Up/down select */
+#define SYS_TCx_UDS            __REGBIT(2)
+#define SYS_TCx_UDS_UP                 __REGVAL(SYS_TCx_UDS, 0)
+#define SYS_TCx_UDS_DOWN               __REGVAL(SYS_TCx_UDS, 1)
+
+/* Timer x Control register: 32- or 16-bit timer */
+#define SYS_TCx_TSZ            __REGBIT(1)
+#define SYS_TCx_TSZ_16                 __REGVAL(SYS_TCx_TSZ, 0)
+#define SYS_TCx_TSZ_32                 __REGVAL(SYS_TCx_TSZ, 1)
+
+/* Timer x Control register: Reload enable */
+#define SYS_TCx_REN            __REGBIT(0)
+#define SYS_TCx_REN_DIS                        __REGVAL(SYS_TCx_REN, 0)
+#define SYS_TCx_REN_EN                 __REGVAL(SYS_TCx_REN, 1)
+
+/* System Memory Chip Select x Dynamic Memory Base */
+#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
+
+/* System Memory Chip Select x Dynamic Memory Mask */
+#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base */
+#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base: Chip select x base */
+#define SYS_SMCSSMB_CSxB       __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask */
+#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+#define SYS_SMCSSMM_CSxM       __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+#define SYS_SMCSSMM_CSEx       __REGBIT(0)
+#define SYS_SMCSSMM_CSEx_DIS           __REGVAL(SYS_SMCSSMM_CSEx, 0)
+#define SYS_SMCSSMM_CSEx_EN            __REGVAL(SYS_SMCSSMM_CSEx, 1)
+
+/* General purpose, user-defined ID register */
+#define SYS_GENID      __REG(0xa0900210)
+
+/* External Interrupt x Control register */
+#define SYS_EIC(x)     __REG2(0xa0900214, (x))
+
+/* External Interrupt x Control register: Status */
+#define SYS_EIC_STS            __REGBIT(3)
+
+/* External Interrupt x Control register: Clear */
+#define SYS_EIC_CLR            __REGBIT(2)
+
+/* External Interrupt x Control register: Polarity */
+#define SYS_EIC_PLTY           __REGBIT(1)
+#define SYS_EIC_PLTY_AH                        __REGVAL(SYS_EIC_PLTY, 0)
+#define SYS_EIC_PLTY_AL                        __REGVAL(SYS_EIC_PLTY, 1)
+
+/* External Interrupt x Control register: Level edge */
+#define SYS_EIC_LVEDG          __REGBIT(0)
+#define SYS_EIC_LVEDG_LEVEL            __REGVAL(SYS_EIC_LVEDG, 0)
+#define SYS_EIC_LVEDG_EDGE             __REGVAL(SYS_EIC_LVEDG, 1)
+
+#endif /* ifndef __ASM_ARCH_REGSSYS_H */
diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
new file mode 100644 (file)
index 0000000..e3cd4d3
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-ns9xxx/system.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/proc-fns.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       u32 reg;
+
+       reg = SYS_PLL >> 16;
+       REGSET(reg, SYS_PLL, SWC, YES);
+       SYS_PLL = reg;
+
+       BUG();
+}
+
+#endif /* ifndef __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/timex.h b/include/asm-arm/arch-ns9xxx/timex.h
new file mode 100644 (file)
index 0000000..f776cbd
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/timex.h
+ *
+ * Copyright (C) 2005-2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/*
+ * value for CLOCK_TICK_RATE stolen from include/asm-arm/arch-s3c2410/timex.h.
+ * See there for an explanation.
+ */
+#define CLOCK_TICK_RATE         12000000
+
+#endif /* ifndef __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-ns9xxx/uncompress.h b/include/asm-arm/arch-ns9xxx/uncompress.h
new file mode 100644 (file)
index 0000000..961ca7d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * include/asm-arm/arch-ns9xxx/uncompress.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+static void putc(char c)
+{
+       volatile u8 *base = (volatile u8 *)0x40000000;
+       int t = 0x10000;
+
+       do {
+               if (base[5] & 0x20) {
+                       base[0] = c;
+                       break;
+               }
+       } while (--t);
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+static void flush(void)
+{
+       /* nothing */
+}
+
+#endif /* ifndef __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-ns9xxx/vmalloc.h b/include/asm-arm/arch-ns9xxx/vmalloc.h
new file mode 100644 (file)
index 0000000..2f3cb6f
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-ns9xxx/vmalloc.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END     (0xf0000000)
+
+#endif /* ifndef __ASM_ARCH_VMALLOC_H */
index e24f6b6c79ae763f97bd9806d01e55628357c531..aec835b6f057e52bc1edd16cafeb8494dbb7d37f 100644 (file)
  * Serial Audio Controller
  */
 
-/* FIXME: This clash with SA1111 defines */
-#ifndef _ASM_ARCH_SA1111
-
 #define SACR0          __REG(0x40400000)  /* Global Control Register */
 #define SACR1          __REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
 #define SASR0          __REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
 #define SADIV          __REG(0x40400060)  /* Audio Clock Divider Register. */
 #define SADR           __REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
 
-#define SACR0_RFTH(x)  (x << 12)       /* Rx FIFO Interrupt or DMA Trigger Threshold */
-#define SACR0_TFTH(x)  (x << 8)        /* Tx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_RFTH(x)  ((x) << 12)     /* Rx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_TFTH(x)  ((x) << 8)      /* Tx FIFO Interrupt or DMA Trigger Threshold */
 #define SACR0_STRF     (1 << 5)        /* FIFO Select for EFWR Special Function */
 #define SACR0_EFWR     (1 << 4)        /* Enable EFWR Function  */
 #define SACR0_RST      (1 << 3)        /* FIFO, i2s Register Reset */
 #define SAIMR_RFS      (1 << 4)        /* Enable Rx FIFO Service Interrupt */
 #define SAIMR_TFS      (1 << 3)        /* Enable Tx FIFO Service Interrupt */
 
-#endif
-
 /*
  * AC97 Controller registers
  */
 #define SSSR_PINT              (1 << 18)       /* Peripheral Trailing Byte Interrupt */
 
 #define SSPSP_FSRT             (1 << 25)       /* Frame Sync Relative Timing */
-#define SSPSP_DMYSTOP(x)       (x << 23)       /* Dummy Stop */
-#define SSPSP_SFRMWDTH(x)      (x << 16)       /* Serial Frame Width */
-#define SSPSP_SFRMDLY(x)       (x << 9)        /* Serial Frame Delay */
-#define SSPSP_DMYSTRT(x)       (x << 7)        /* Dummy Start */
-#define SSPSP_STRTDLY(x)       (x << 4)        /* Start Delay */
+#define SSPSP_DMYSTOP(x)       ((x) << 23)     /* Dummy Stop */
+#define SSPSP_SFRMWDTH(x)      ((x) << 16)     /* Serial Frame Width */
+#define SSPSP_SFRMDLY(x)       ((x) << 9)      /* Serial Frame Delay */
+#define SSPSP_DMYSTRT(x)       ((x) << 7)      /* Dummy Start */
+#define SSPSP_STRTDLY(x)       ((x) << 4)      /* Start Delay */
 #define SSPSP_ETDS                     (1 << 3)        /* End of Transfer data State */
 #define SSPSP_SFRMP                    (1 << 2)        /* Serial Frame Polarity */
-#define SSPSP_SCMODE(x)                (x << 0)        /* Serial Bit Rate Clock Mode */
+#define SSPSP_SCMODE(x)                ((x) << 0)      /* Serial Bit Rate Clock Mode */
 
+#define SSACD_SCDB             (1 << 3)        /* SSPSYSCLK Divider Bypass */
+#define SSACD_ACPS(x)          ((x) << 4)      /* Audio clock PLL select */
+#define SSACD_ACDS(x)          ((x) << 0)      /* Audio clock divider select */
 
 #define SSCR0_P1       __REG(0x41000000)  /* SSP Port 1 Control Register 0 */
 #define SSCR1_P1       __REG(0x41000004)  /* SSP Port 1 Control Register 1 */
index 646480d37256a067146db1a6202c734f06ad60d7..8bc6f9c3e3ea2c130b271b46359e7b0a34f7d3bc 100644 (file)
@@ -9,3 +9,33 @@
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+       return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+       pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+       pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+       return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+       int mask = GPIO_bit(gpio);
+
+       if (is_on)
+               GPSR(gpio) = mask;
+       else
+               GPCR(gpio) = mask;
+}
+
index 9ca76dc3a7af8ef39fbb6af750a3882ada9e5231..aa78fe087ab2a39cf9ed841aac5e97f42e318ab1 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/arch/platform.h>
 
 /* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x)          (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+#define IO_ADDRESS(x)          ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
 #define __io_address(n)                __io(IO_ADDRESS(n))
 
 #endif
index c16223c9588d88bf4f96d2ab5d7670d85df9e3d1..5a5db56f86b8cd9a712dc31fc8b630c4cf075e4f 100644 (file)
 #define IRQ_AACI               (IRQ_GIC_START + INT_AACI)
 #define IRQ_ETH                        (IRQ_GIC_START + INT_ETH)
 #define IRQ_USB                        (IRQ_GIC_START + INT_USB)
+#define IRQ_PMU_CPU0           (IRQ_GIC_START + INT_PMU_CPU0)
+#define IRQ_PMU_CPU1           (IRQ_GIC_START + INT_PMU_CPU1)
+#define IRQ_PMU_CPU2           (IRQ_GIC_START + INT_PMU_CPU2)
+#define IRQ_PMU_CPU3           (IRQ_GIC_START + INT_PMU_CPU3)
+#define IRQ_PMU_SCU0           (IRQ_GIC_START + INT_PMU_SCU0)
+#define IRQ_PMU_SCU1           (IRQ_GIC_START + INT_PMU_SCU1)
+#define IRQ_PMU_SCU2           (IRQ_GIC_START + INT_PMU_SCU2)
+#define IRQ_PMU_SCU3           (IRQ_GIC_START + INT_PMU_SCU3)
+#define IRQ_PMU_SCU4           (IRQ_GIC_START + INT_PMU_SCU4)
+#define IRQ_PMU_SCU5           (IRQ_GIC_START + INT_PMU_SCU5)
+#define IRQ_PMU_SCU6           (IRQ_GIC_START + INT_PMU_SCU6)
+#define IRQ_PMU_SCU7           (IRQ_GIC_START + INT_PMU_SCU7)
+
+#define IRQ_EB_IRQ1            (IRQ_GIC_START + INT_EB_IRQ1)
+#define IRQ_EB_IRQ2            (IRQ_GIC_START + INT_EB_IRQ2)
 
 #define IRQMASK_WDOGINT                INTMASK_WDOGINT
 #define IRQMASK_SOFTINT                INTMASK_SOFTINT
 #define IRQMASK_ETH            INTMASK_ETH
 #define IRQMASK_USB            INTMASK_USB
 
-#define NR_IRQS                        (IRQ_GIC_START + 64)
+#define NR_IRQS                        (IRQ_GIC_START + 96)
index 18d7c18b738c7941501063283de1061c31a33959..6e0eab95a3a2ed3b8de1a0ae9044e5bc78c193c9 100644 (file)
 #define REALVIEW_GIC_CPU_BASE         0x10040000       /* Generic interrupt controller CPU interface */
 #define REALVIEW_GIC_DIST_BASE        0x10041000       /* Generic interrupt controller distributor */
 #else
+#ifdef CONFIG_REALVIEW_MPCORE_REVB
 #define REALVIEW_MPCORE_SCU_BASE       0x10100000      /*  SCU registers */
 #define REALVIEW_GIC_CPU_BASE          0x10100100      /* Generic interrupt controller CPU interface */
 #define REALVIEW_TWD_BASE              0x10100700
 #define REALVIEW_TWD_SIZE              0x00000100
 #define REALVIEW_GIC_DIST_BASE         0x10101000      /* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE      0x10102000      /* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8             /*  Register offset for MPCore sysctl */
+#else
+#define REALVIEW_MPCORE_SCU_BASE      0x1F000000       /*  SCU registers */
+#define REALVIEW_GIC_CPU_BASE         0x1F000100       /* Generic interrupt controller CPU interface */
+#define REALVIEW_TWD_BASE             0x1F000700
+#define REALVIEW_TWD_SIZE             0x00000100
+#define REALVIEW_GIC_DIST_BASE        0x1F001000       /* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE     0x1F002000       /* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74             /*  Register offset for MPCore sysctl */
+#endif
+#define REALVIEW_GIC1_CPU_BASE        0x10040000       /* Generic interrupt controller CPU interface */
+#define REALVIEW_GIC1_DIST_BASE       0x10041000       /* Generic interrupt controller distributor */
 #endif
 #define REALVIEW_SMC_BASE             0x10080000       /* SMC */
        /* Reserved 0x10090000 - 0x100EFFFF */
 #define INT_USB                                29      /* USB controller */
 #define INT_TSPENINT                   30      /* Touchscreen pen */
 #define INT_TSKPADINT                  31      /* Touchscreen keypad */
+
 #else
+
+#define MAX_GIC_NR                     2
+
 #define INT_AACI                       0
 #define INT_TIMERINT0_1                        1
 #define INT_TIMERINT2_3                        2
diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
new file mode 100644 (file)
index 0000000..cc29364
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ASMARM_ARCH_SCU_H
+#define __ASMARM_ARCH_SCU_H
+
+#include <asm/arch/platform.h>
+
+#define SCU_BASE       REALVIEW_MPCORE_SCU_BASE
+
+#endif
index 58ffa7ba3c88dc68728794225220f14f297cd7e7..c6e8d8f64938e4e3aa0af3fb6119ec47ae8202ee 100644 (file)
@@ -51,13 +51,19 @@ enum dma_ch {
        DMACH_UART0_SRC2,       /* s3c2412 second uart sources */
        DMACH_UART1_SRC2,
        DMACH_UART2_SRC2,
+       DMACH_UART3,            /* s3c2443 has extra uart */
+       DMACH_UART3_SRC2,
        DMACH_MAX,              /* the end entry */
 };
 
 #define DMACH_LOW_LEVEL        (1<<28) /* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS        (4)
+#ifndef CONFIG_CPU_S3C2443
+#define S3C2410_DMA_CHANNELS           (4)
+#else
+#define S3C2410_DMA_CHANNELS           (6)
+#endif
 
 /* types */
 
@@ -321,6 +327,7 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 #define S3C2410_DMA_DCDST       (0x1C)
 #define S3C2410_DMA_DMASKTRIG   (0x20)
 #define S3C2412_DMA_DMAREQSEL  (0x24)
+#define S3C2443_DMA_DMAREQSEL  (0x24)
 
 #define S3C2410_DISRCC_INC     (1<<0)
 #define S3C2410_DISRCC_APB     (1<<1)
@@ -415,4 +422,31 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 #define S3C2412_DMAREQSEL_UART2_1      S3C2412_DMAREQSEL_SRC(24)
 
 #endif
+
+#define S3C2443_DMAREQSEL_SRC(x)       ((x)<<1)
+
+#define S3C2443_DMAREQSEL_HW           (1)
+
+#define S3C2443_DMAREQSEL_SPI0TX       S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX       S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX       S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX       S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX                S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX                S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER                S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI          S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0       S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1       S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0      S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1      S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0      S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1      S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0      S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1      S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0      S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1      S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT       S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN        S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN                S3C2443_DMAREQSEL_SRC(29)
+
 #endif /* __ASM_ARCH_DMA_H */
index 4b7cff456c4e04f935acfb3b07f87554101d62b1..c79cb18199138e18f20f33b86041e06c4a1390ff 100644 (file)
 #define IRQ_EINT4t7    S3C2410_IRQ(4)      /* 20 */
 #define IRQ_EINT8t23   S3C2410_IRQ(5)
 #define IRQ_RESERVED6  S3C2410_IRQ(6)      /* for s3c2410 */
-#define IRQ_CAM        S3C2410_IRQ(6)      /* for s3c2440 */
+#define IRQ_CAM        S3C2410_IRQ(6)      /* for s3c2440,s3c2443 */
 #define IRQ_BATT_FLT   S3C2410_IRQ(7)
 #define IRQ_TICK       S3C2410_IRQ(8)      /* 24 */
-#define IRQ_WDT               S3C2410_IRQ(9)
+#define IRQ_WDT               S3C2410_IRQ(9)       /* WDT/AC97 for s3c2443 */
 #define IRQ_TIMER0     S3C2410_IRQ(10)
 #define IRQ_TIMER1     S3C2410_IRQ(11)
 #define IRQ_TIMER2     S3C2410_IRQ(12)
@@ -45,7 +45,7 @@
 #define IRQ_TIMER4     S3C2410_IRQ(14)
 #define IRQ_UART2      S3C2410_IRQ(15)
 #define IRQ_LCD               S3C2410_IRQ(16)      /* 32 */
-#define IRQ_DMA0       S3C2410_IRQ(17)
+#define IRQ_DMA0       S3C2410_IRQ(17)     /* IRQ_DMA for s3c2443 */
 #define IRQ_DMA1       S3C2410_IRQ(18)
 #define IRQ_DMA2       S3C2410_IRQ(19)
 #define IRQ_DMA3       S3C2410_IRQ(20)
  * these need to be ordered in number of appearance in the
  * SUBSRC mask register
 */
-#define IRQ_S3CUART_RX0  S3C2410_IRQ(54)   /* 70 */
-#define IRQ_S3CUART_TX0  S3C2410_IRQ(55)   /* 71 */
-#define IRQ_S3CUART_ERR0 S3C2410_IRQ(56)
 
-#define IRQ_S3CUART_RX1  S3C2410_IRQ(57)
-#define IRQ_S3CUART_TX1  S3C2410_IRQ(58)
-#define IRQ_S3CUART_ERR1 S3C2410_IRQ(59)
+#define S3C2410_IRQSUB(x)      S3C2410_IRQ((x)+54)
 
-#define IRQ_S3CUART_RX2  S3C2410_IRQ(60)
-#define IRQ_S3CUART_TX2  S3C2410_IRQ(61)
-#define IRQ_S3CUART_ERR2 S3C2410_IRQ(62)
+#define IRQ_S3CUART_RX0                S3C2410_IRQSUB(0)       /* 70 */
+#define IRQ_S3CUART_TX0                S3C2410_IRQSUB(1)
+#define IRQ_S3CUART_ERR0       S3C2410_IRQSUB(2)
 
-#define IRQ_TC          S3C2410_IRQ(63)
-#define IRQ_ADC                 S3C2410_IRQ(64)
+#define IRQ_S3CUART_RX1                S3C2410_IRQSUB(3)       /* 73 */
+#define IRQ_S3CUART_TX1                S3C2410_IRQSUB(4)
+#define IRQ_S3CUART_ERR1       S3C2410_IRQSUB(5)
 
-/* extra irqs for s3c2440 */
+#define IRQ_S3CUART_RX2                S3C2410_IRQSUB(6)       /* 76 */
+#define IRQ_S3CUART_TX2                S3C2410_IRQSUB(7)
+#define IRQ_S3CUART_ERR2       S3C2410_IRQSUB(8)
 
-#define IRQ_S3C2440_CAM_C      S3C2410_IRQ(65)
-#define IRQ_S3C2440_CAM_P      S3C2410_IRQ(66)
-#define IRQ_S3C2440_WDT                S3C2410_IRQ(67)
-#define IRQ_S3C2440_AC97       S3C2410_IRQ(68)
+#define IRQ_TC                 S3C2410_IRQSUB(9)
+#define IRQ_ADC                        S3C2410_IRQSUB(10)
 
-#define NR_IRQS (IRQ_S3C2440_AC97+1)
+/* extra irqs for s3c2440 */
 
+#define IRQ_S3C2440_CAM_C      S3C2410_IRQSUB(11)      /* S3C2443 too */
+#define IRQ_S3C2440_CAM_P      S3C2410_IRQSUB(12)      /* S3C2443 too */
+#define IRQ_S3C2440_WDT                S3C2410_IRQSUB(13)
+#define IRQ_S3C2440_AC97       S3C2410_IRQSUB(14)
+
+/* irqs for s3c2443 */
+
+#define IRQ_S3C2443_DMA                S3C2410_IRQ(17)         /* IRQ_DMA1 */
+#define IRQ_S3C2443_UART3      S3C2410_IRQ(18)         /* IRQ_DMA2 */
+#define IRQ_S3C2443_CFCON      S3C2410_IRQ(19)         /* IRQ_DMA3 */
+#define IRQ_S3C2443_SDI1       S3C2410_IRQ(20)         /* IRQ_SDI */
+#define IRQ_S3C2443_NAND       S3C2410_IRQ(24)         /* reserved */
+
+#define IRQ_S3C2443_LCD1       S3C2410_IRQSUB(14)
+#define IRQ_S3C2443_LCD2       S3C2410_IRQSUB(15)
+#define IRQ_S3C2443_LCD3       S3C2410_IRQSUB(16)
+#define IRQ_S3C2443_LCD4       S3C2410_IRQSUB(17)
+
+#define IRQ_S3C2443_DMA0       S3C2410_IRQSUB(18)
+#define IRQ_S3C2443_DMA1       S3C2410_IRQSUB(19)
+#define IRQ_S3C2443_DMA2       S3C2410_IRQSUB(20)
+#define IRQ_S3C2443_DMA3       S3C2410_IRQSUB(21)
+#define IRQ_S3C2443_DMA4       S3C2410_IRQSUB(22)
+#define IRQ_S3C2443_DMA5       S3C2410_IRQSUB(23)
+
+/* UART3 */
+#define IRQ_S3C2443_RX3                S3C2410_IRQSUB(24)
+#define IRQ_S3C2443_TX3                S3C2410_IRQSUB(25)
+#define IRQ_S3C2443_ERR3       S3C2410_IRQSUB(26)
+
+#define IRQ_S3C2443_WDT                S3C2410_IRQSUB(27)
+#define IRQ_S3C2443_AC97       S3C2410_IRQSUB(28)
+
+#ifdef CONFIG_CPU_S3C2443
+#define NR_IRQS (IRQ_S3C2443_AC97+1)
+#else
+#define NR_IRQS (IRQ_S3C2440_AC97+1)
+#endif
 
 #endif /* __ASM_ARCH_IRQ_H */
index 3196a2849e8ae508061339b45ff4e2426d84698a..c7f231963e7607b30a108bb5526d1d7885ef5ccf 100644 (file)
@@ -41,7 +41,7 @@
 #define S3C2410_ADCTSC_XP_SEN          (1<<4)
 #define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
 #define S3C2410_ADCTSC_AUTO_PST                (1<<2)
-#define S3C2410_ADCTSC_XY_PST          (0x3<<0)
+#define S3C2410_ADCTSC_XY_PST(x)       (((x)&0x3)<<0)
 
 /* ADCDAT0 Bits */
 #define S3C2410_ADCDAT0_UPDOWN         (1<<15)
index eae91694edcdf61939eacbdd99225d440572e7bd..dea578b8f7f66e1b035bc07b03baa3764e8c2d7e 100644 (file)
 #define S3C2400_GPBDAT    S3C2410_GPIOREG(0x0C)
 #define S3C2400_GPBUP     S3C2410_GPIOREG(0x10)
 
-/* no i/o pin in port b can have value 3! */
+/* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
 
 #define S3C2410_GPB0         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
 #define S3C2410_GPB0_INP     (0x00 << 0)
 #define S3C2410_GPB5_INP     (0x00 << 10)
 #define S3C2410_GPB5_OUTP    (0x01 << 10)
 #define S3C2410_GPB5_nXBACK  (0x02 << 10)
+#define S3C2443_GPB5_XBACK   (0x03 << 10)
 #define S3C2400_GPB5_DATA21  (0x02 << 10)
 #define S3C2400_GPB5_nCTS1   (0x03 << 10)
 
 #define S3C2410_GPB6_INP     (0x00 << 12)
 #define S3C2410_GPB6_OUTP    (0x01 << 12)
 #define S3C2410_GPB6_nXBREQ  (0x02 << 12)
+#define S3C2443_GPB6_XBREQ   (0x03 << 12)
 #define S3C2400_GPB6_DATA22  (0x02 << 12)
 #define S3C2400_GPB6_nRTS1   (0x03 << 12)
 
 #define S3C2410_GPB7_INP     (0x00 << 14)
 #define S3C2410_GPB7_OUTP    (0x01 << 14)
 #define S3C2410_GPB7_nXDACK1 (0x02 << 14)
+#define S3C2443_GPB7_XDACK1  (0x03 << 14)
 #define S3C2400_GPB7_DATA23  (0x02 << 14)
 
 #define S3C2410_GPB8         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
 #define S3C2410_GPB9_INP     (0x00 << 18)
 #define S3C2410_GPB9_OUTP    (0x01 << 18)
 #define S3C2410_GPB9_nXDACK0 (0x02 << 18)
+#define S3C2443_GPB9_XDACK0  (0x03 << 18)
 #define S3C2400_GPB9_DATA25  (0x02 << 18)
 #define S3C2400_GPB9_I2SSDI  (0x03 << 18)
 
 #define S3C2410_GPB10_INP    (0x00 << 20)
 #define S3C2410_GPB10_OUTP   (0x01 << 20)
 #define S3C2410_GPB10_nXDRE0 (0x02 << 20)
+#define S3C2443_GPB10_XDREQ0 (0x03 << 20)
 #define S3C2400_GPB10_DATA26 (0x02 << 20)
 #define S3C2400_GPB10_nSS    (0x03 << 20)
 
 #define S3C2410_GPE0_INP       (0x00 << 0)
 #define S3C2410_GPE0_OUTP      (0x01 << 0)
 #define S3C2410_GPE0_I2SLRCK   (0x02 << 0)
+#define S3C2443_GPE0_AC_nRESET (0x03 << 0)
 #define S3C2400_GPE0_EINT0     (0x02 << 0)
 #define S3C2410_GPE0_MASK      (0x03 << 0)
 
 #define S3C2410_GPE1_INP       (0x00 << 2)
 #define S3C2410_GPE1_OUTP      (0x01 << 2)
 #define S3C2410_GPE1_I2SSCLK   (0x02 << 2)
+#define S3C2443_GPE1_AC_SYNC   (0x03 << 2)
 #define S3C2400_GPE1_EINT1     (0x02 << 2)
 #define S3C2400_GPE1_nSS       (0x03 << 2)
 #define S3C2410_GPE1_MASK      (0x03 << 2)
 #define S3C2410_GPE2_INP       (0x00 << 4)
 #define S3C2410_GPE2_OUTP      (0x01 << 4)
 #define S3C2410_GPE2_CDCLK     (0x02 << 4)
+#define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
 #define S3C2400_GPE2_EINT2     (0x02 << 4)
 #define S3C2400_GPE2_I2SSDI    (0x03 << 4)
 
 #define S3C2410_GPE3_INP       (0x00 << 6)
 #define S3C2410_GPE3_OUTP      (0x01 << 6)
 #define S3C2410_GPE3_I2SSDI    (0x02 << 6)
+#define S3C2443_GPE3_AC_SDI    (0x03 << 6)
 #define S3C2400_GPE3_EINT3     (0x02 << 6)
 #define S3C2400_GPE3_nCTS1     (0x03 << 6)
 #define S3C2410_GPE3_nSS0      (0x03 << 6)
 #define S3C2410_GPE4_INP       (0x00 << 8)
 #define S3C2410_GPE4_OUTP      (0x01 << 8)
 #define S3C2410_GPE4_I2SSDO    (0x02 << 8)
+#define S3C2443_GPE4_AC_SDO    (0x03 << 8)
 #define S3C2400_GPE4_EINT4     (0x02 << 8)
 #define S3C2400_GPE4_nRTS1     (0x03 << 8)
 #define S3C2410_GPE4_I2SSDI    (0x03 << 8)
 #define S3C2410_GPE5_INP       (0x00 << 10)
 #define S3C2410_GPE5_OUTP      (0x01 << 10)
 #define S3C2410_GPE5_SDCLK     (0x02 << 10)
+#define S3C2443_GPE5_SD1_CLK   (0x02 << 10)
 #define S3C2400_GPE5_EINT5     (0x02 << 10)
 #define S3C2400_GPE5_TCLK1     (0x03 << 10)
 
 #define S3C2410_GPE6_INP       (0x00 << 12)
 #define S3C2410_GPE6_OUTP      (0x01 << 12)
 #define S3C2410_GPE6_SDCMD     (0x02 << 12)
+#define S3C2443_GPE6_SD1_CMD   (0x02 << 12)
+#define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
 #define S3C2400_GPE6_EINT6     (0x02 << 12)
 
 #define S3C2410_GPE7           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7)
 #define S3C2410_GPE7_INP       (0x00 << 14)
 #define S3C2410_GPE7_OUTP      (0x01 << 14)
 #define S3C2410_GPE7_SDDAT0    (0x02 << 14)
+#define S3C2443_GPE5_SD1_DAT0  (0x02 << 14)
+#define S3C2443_GPE7_AC_SDI    (0x03 << 14)
 #define S3C2400_GPE7_EINT7     (0x02 << 14)
 
 #define S3C2410_GPE8           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8)
 #define S3C2410_GPE8_INP       (0x00 << 16)
 #define S3C2410_GPE8_OUTP      (0x01 << 16)
 #define S3C2410_GPE8_SDDAT1    (0x02 << 16)
+#define S3C2443_GPE8_SD1_DAT1  (0x02 << 16)
+#define S3C2443_GPE8_AC_SDO    (0x03 << 16)
 #define S3C2400_GPE8_nXDACK0   (0x02 << 16)
 
 #define S3C2410_GPE9           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9)
 #define S3C2410_GPE9_INP       (0x00 << 18)
 #define S3C2410_GPE9_OUTP      (0x01 << 18)
 #define S3C2410_GPE9_SDDAT2    (0x02 << 18)
+#define S3C2443_GPE9_SD1_DAT2  (0x02 << 18)
+#define S3C2443_GPE9_AC_SYNC   (0x03 << 18)
 #define S3C2400_GPE9_nXDACK1   (0x02 << 18)
 #define S3C2400_GPE9_nXBACK    (0x03 << 18)
 
 #define S3C2410_GPE10_INP      (0x00 << 20)
 #define S3C2410_GPE10_OUTP     (0x01 << 20)
 #define S3C2410_GPE10_SDDAT3   (0x02 << 20)
+#define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
+#define S3C2443_GPE10_AC_nRESET (0x03 << 20)
 #define S3C2400_GPE10_nXDREQ0  (0x02 << 20)
 
 #define S3C2410_GPE11          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11)
 #define S3C2400_GPG4_MMCCLK   (0x02 << 8)
 #define S3C2400_GPG4_I2SSDI   (0x03 << 8)
 #define S3C2410_GPG4_LCDPWREN (0x03 << 8)
+#define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
 
 #define S3C2410_GPG5          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5)
 #define S3C2410_GPG5_INP      (0x00 << 10)
 #define S3C2410_GPG5_EINT13   (0x02 << 10)
 #define S3C2400_GPG5_MMCCMD   (0x02 << 10)
 #define S3C2400_GPG5_IICSDA   (0x03 << 10)
-#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
+#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)     /* not s3c2443 */
 
 #define S3C2410_GPG6          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6)
 #define S3C2410_GPG6_INP      (0x00 << 12)
 #define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
+#define S3C2443_GPG11_CF_nIREQ (0x03 << 22)
 
 #define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
 #define S3C2410_GPG12_INP     (0x00 << 24)
 #define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 #define S3C2442_GPG12_nSPICS0 (0x03 << 24)
+#define S3C2443_GPG12_nINPACK (0x03 << 24)
 
 #define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPG13_OUTP    (0x01 << 26)
 #define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
+#define S3C2443_GPG13_CF_nREG (0x03 << 26)
 
 #define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
 #define S3C2410_GPG14_INP     (0x00 << 28)
 #define S3C2410_GPG14_OUTP    (0x01 << 28)
 #define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
+#define S3C2443_GPG14_CF_RESET (0x03 << 28)
 
 #define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
 #define S3C2410_GPG15_INP     (0x00 << 30)
 #define S3C2410_GPG15_OUTP    (0x01 << 30)
 #define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
-
+#define S3C2443_GPG15_CF_PWR  (0x03 << 30)
 
 #define S3C2410_GPG_PUPDIS(x)  (1<<(x))
 
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
new file mode 100644 (file)
index 0000000..ff0536d
--- /dev/null
@@ -0,0 +1,194 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-clock.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2443 clock register definitions
+*/
+
+#ifndef __ASM_ARM_REGS_S3C2443_CLOCK
+#define __ASM_ARM_REGS_S3C2443_CLOCK
+
+#define S3C2443_CLKREG(x)              ((x) + S3C24XX_VA_CLKPWR)
+
+#define S3C2443_PLLCON_MDIVSHIFT       16
+#define S3C2443_PLLCON_PDIVSHIFT       8
+#define S3C2443_PLLCON_SDIVSHIFT       0
+#define S3C2443_PLLCON_MDIVMASK                ((1<<(1+(23-16)))-1)
+#define S3C2443_PLLCON_PDIVMASK                ((1<<(1+(9-8)))-1)
+#define S3C2443_PLLCON_SDIVMASK                (3)
+
+#define S3C2443_MPLLCON                        S3C2443_CLKREG(0x10)
+#define S3C2443_EPLLCON                        S3C2443_CLKREG(0x18)
+#define S3C2443_CLKSRC                 S3C2443_CLKREG(0x20)
+#define S3C2443_CLKDIV0                        S3C2443_CLKREG(0x24)
+#define S3C2443_CLKDIV1                        S3C2443_CLKREG(0x28)
+#define S3C2443_HCLKCON                        S3C2443_CLKREG(0x30)
+#define S3C2443_PCLKCON                        S3C2443_CLKREG(0x34)
+#define S3C2443_SCLKCON                        S3C2443_CLKREG(0x38)
+#define S3C2443_PWRMODE                        S3C2443_CLKREG(0x40)
+#define S3C2443_SWRST                  S3C2443_CLKREG(0x44)
+#define S3C2443_BUSPRI0                        S3C2443_CLKREG(0x50)
+#define S3C2443_SYSID                  S3C2443_CLKREG(0x5C)
+#define S3C2443_PWRCFG                 S3C2443_CLKREG(0x60)
+#define S3C2443_RSTCON                 S3C2443_CLKREG(0x64)
+
+#define S3C2443_SWRST_RESET            (0x533c2443)
+
+#define S3C2443_PLLCON_OFF             (1<<24)
+
+#define S3C2443_CLKSRC_I2S_EXT         (1<<14)
+#define S3C2443_CLKSRC_I2S_EPLLDIV     (0<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF     (2<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF3    (3<<14)
+#define S3C2443_CLKSRC_I2S_MASK                (3<<14)
+
+#define S3C2443_CLKSRC_EPLLREF_XTAL    (2<<8)
+#define S3C2443_CLKSRC_EPLLREF_EXTCLK  (3<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF2        (1<<8)
+#define S3C2443_CLKSRC_EPLLREF_MASK    (3<<8)
+
+#define S3C2443_CLKSRC_ESYSCLK_EPLL    (1<<6)
+#define S3C2443_CLKSRC_MSYSCLK_MPLL    (1<<4)
+#define S3C2443_CLKSRC_EXTCLK_DIV      (1<<3)
+
+#define S3C2443_CLKDIV0_DVS            (1<<13)
+#define S3C2443_CLKDIV0_HALF_HCLK      (1<<3)
+#define S3C2443_CLKDIV0_HALF_PCLK      (1<<2)
+
+#define S3C2443_CLKDIV0_HCLKDIV_MASK   (3<<0)
+
+#define S3C2443_CLKDIV0_EXTDIV_MASK    (3<<6)
+#define S3C2443_CLKDIV0_EXTDIV_SHIFT   (6)
+
+#define S3C2443_CLKDIV0_PREDIV_MASK    (3<<4)
+#define S3C2443_CLKDIV0_PREDIV_SHIFT   (4)
+
+#define S3C2443_CLKDIV0_ARMDIV_MASK    (15<<9)
+#define S3C2443_CLKDIV0_ARMDIV_SHIFT   (9)
+#define S3C2443_CLKDIV0_ARMDIV_1       (0<<9)
+#define S3C2443_CLKDIV0_ARMDIV_2       (8<<9)
+#define S3C2443_CLKDIV0_ARMDIV_3       (2<<9)
+#define S3C2443_CLKDIV0_ARMDIV_4       (9<<9)
+#define S3C2443_CLKDIV0_ARMDIV_6       (10<<9)
+#define S3C2443_CLKDIV0_ARMDIV_8       (11<<9)
+#define S3C2443_CLKDIV0_ARMDIV_12      (13<<9)
+#define S3C2443_CLKDIV0_ARMDIV_16      (15<<9)
+
+/* S3C2443_CLKDIV1 */
+
+#define S3C2443_CLKDIV1_CAMDIV_MASK    (15<<26)
+#define S3C2443_CLKDIV1_CAMDIV_SHIFT   (26)
+
+#define S3C2443_CLKDIV1_HSSPIDIV_MASK  (3<<24)
+#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT (24)
+
+#define S3C2443_CLKDIV1_DISPDIV_MASK   (0xff<<16)
+#define S3C2443_CLKDIV1_DISPDIV_SHIFT  (16)
+
+#define S3C2443_CLKDIV1_I2SDIV_MASK    (15<<12)
+#define S3C2443_CLKDIV1_I2SDIV_SHIFT   (12)
+
+#define S3C2443_CLKDIV1_UARTDIV_MASK   (15<<8)
+#define S3C2443_CLKDIV1_UARTDIV_SHIFT  (8)
+
+#define S3C2443_CLKDIV1_HSMMCDIV_MASK  (3<<6)
+#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT (6)
+
+#define S3C2443_CLKDIV1_USBHOSTDIV_MASK        (3<<4)
+#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
+
+#define S3C2443_CLKCON_NAND
+
+#define S3C2443_HCLKCON_DMA0           (1<<0)
+#define S3C2443_HCLKCON_DMA1           (1<<1)
+#define S3C2443_HCLKCON_DMA2           (1<<2)
+#define S3C2443_HCLKCON_DMA3           (1<<3)
+#define S3C2443_HCLKCON_DMA4           (1<<4)
+#define S3C2443_HCLKCON_DMA5           (1<<5)
+#define S3C2443_HCLKCON_CAMIF          (1<<8)
+#define S3C2443_HCLKCON_DISP           (1<<9)
+#define S3C2443_HCLKCON_LCDC           (1<<10)
+#define S3C2443_HCLKCON_USBH           (1<<11)
+#define S3C2443_HCLKCON_USBD           (1<<12)
+#define S3C2443_HCLKCON_HSMMC          (1<<16)
+#define S3C2443_HCLKCON_CFC            (1<<17)
+#define S3C2443_HCLKCON_SSMC           (1<<18)
+#define S3C2443_HCLKCON_DRAMC          (1<<19)
+
+#define S3C2443_PCLKCON_UART0          (1<<0)
+#define S3C2443_PCLKCON_UART1          (1<<1)
+#define S3C2443_PCLKCON_UART2          (1<<2)
+#define S3C2443_PCLKCON_UART3          (1<<3)
+#define S3C2443_PCLKCON_IIC            (1<<4)
+#define S3C2443_PCLKCON_SDI            (1<<5)
+#define S3C2443_PCLKCON_ADC            (1<<7)
+#define S3C2443_PCLKCON_IIS            (1<<9)
+#define S3C2443_PCLKCON_PWMT           (1<<10)
+#define S3C2443_PCLKCON_WDT            (1<<11)
+#define S3C2443_PCLKCON_RTC            (1<<12)
+#define S3C2443_PCLKCON_GPIO           (1<<13)
+#define S3C2443_PCLKCON_SPI0           (1<<14)
+#define S3C2443_PCLKCON_SPI1           (1<<15)
+
+#define S3C2443_SCLKCON_DDRCLK         (1<<16)
+#define S3C2443_SCLKCON_SSMCCLK                (1<<15)
+#define S3C2443_SCLKCON_HSSPICLK       (1<<14)
+#define S3C2443_SCLKCON_HSMMCCLK_EXT   (1<<13)
+#define S3C2443_SCLKCON_HSMMCCLK_EPLL  (1<<12)
+#define S3C2443_SCLKCON_CAMCLK         (1<<11)
+#define S3C2443_SCLKCON_DISPCLK                (1<<10)
+#define S3C2443_SCLKCON_I2SCLK         (1<<9)
+#define S3C2443_SCLKCON_UARTCLK                (1<<8)
+#define S3C2443_SCLKCON_USBHOST                (1<<1)
+
+#include <asm/div64.h>
+
+static inline unsigned int
+s3c2443_get_mpll(unsigned int pllval, unsigned int baseclk)
+{
+       unsigned int mdiv, pdiv, sdiv;
+       uint64_t fvco;
+
+       mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+       pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+       sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+       mdiv &= S3C2443_PLLCON_MDIVMASK;
+       pdiv &= S3C2443_PLLCON_PDIVMASK;
+       sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+       fvco = (uint64_t)baseclk * (2 * (mdiv + 8));
+       do_div(fvco, pdiv << sdiv);
+
+       return (unsigned int)fvco;
+}
+
+static inline unsigned int
+s3c2443_get_epll(unsigned int pllval, unsigned int baseclk)
+{
+       unsigned int mdiv, pdiv, sdiv;
+       uint64_t fvco;
+
+       mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+       pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+       sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+       mdiv &= S3C2443_PLLCON_MDIVMASK;
+       pdiv &= S3C2443_PLLCON_PDIVMASK;
+       sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+       fvco = (uint64_t)baseclk * (mdiv + 8);
+       do_div(fvco, (pdiv + 2) << sdiv);
+
+       return (unsigned int)fvco;
+}
+
+#endif /*  __ASM_ARM_REGS_S3C2443_CLOCK */
+
index 46f52401d132f9e2baacd635d12bd475e4a51701..8946702a87f506f7f3c7066fa18b049a69e991c9 100644 (file)
 #define S3C24XX_VA_UART0      (S3C24XX_VA_UART)
 #define S3C24XX_VA_UART1      (S3C24XX_VA_UART + 0x4000 )
 #define S3C24XX_VA_UART2      (S3C24XX_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3      (S3C24XX_VA_UART + 0xC000 )
 
 #define S3C2410_PA_UART0      (S3C24XX_PA_UART)
 #define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
 #define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
 
 #define S3C2410_URXH     (0x24)
 #define S3C2410_UTXH     (0x20)
@@ -73,6 +75,8 @@
 #define S3C2440_UCON_UCLK        (1<<10)
 #define S3C2440_UCON_PCLK2       (2<<10)
 #define S3C2440_UCON_FCLK        (3<<10)
+#define S3C2443_UCON_EPLL        (3<<10)
+
 #define S3C2440_UCON2_FCLK_EN    (1<<15)
 #define S3C2440_UCON0_DIVMASK    (15 << 12)
 #define S3C2440_UCON1_DIVMASK    (15 << 12)
@@ -93,6 +97,8 @@
 #define S3C2410_UCON_TXIRQMODE   (1<<2)
 #define S3C2410_UCON_RXIRQMODE   (1<<0)
 #define S3C2410_UCON_RXFIFO_TOI          (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
+#define S3C2443_UCON_LOOPBACK    (1<<5)
 
 #define S3C2410_UCON_DEFAULT     (S3C2410_UCON_TXILEVEL  | \
                                   S3C2410_UCON_RXILEVEL  | \
 #define        S3C2410_UMCOM_AFC         (1<<4)
 #define        S3C2410_UMCOM_RTS_LOW     (1<<0)
 
-#define S3C2412_UMCON_AFC_63   (0<<5)
+#define S3C2412_UMCON_AFC_63   (0<<5)          /* same as s3c2443 */
 #define S3C2412_UMCON_AFC_56   (1<<5)
 #define S3C2412_UMCON_AFC_48   (2<<5)
 #define S3C2412_UMCON_AFC_40   (3<<5)
 #define S3C2410_UFSTAT_RXMASK    (15<<0)
 #define S3C2410_UFSTAT_RXSHIFT   (0)
 
+/* UFSTAT S3C2443 same as S3C2440 */
 #define S3C2440_UFSTAT_TXFULL    (1<<14)
 #define S3C2440_UFSTAT_RXFULL    (1<<6)
 #define S3C2440_UFSTAT_TXSHIFT   (8)
 #define S3C2410_UERSTAT_OVERRUN          (1<<0)
 #define S3C2410_UERSTAT_FRAME    (1<<2)
 #define S3C2410_UERSTAT_BREAK    (1<<3)
+#define S3C2443_UERSTAT_PARITY   (1<<1)
+
 #define S3C2410_UERSTAT_ANY      (S3C2410_UERSTAT_OVERRUN | \
                                   S3C2410_UERSTAT_FRAME | \
                                   S3C2410_UERSTAT_BREAK)
 #define S3C2410_UMSTAT_CTS       (1<<0)
 #define S3C2410_UMSTAT_DeltaCTS          (1<<2)
 
+#define S3C2443_DIVSLOT                  (0x2C)
+
 #ifndef __ASSEMBLY__
 
 /* struct s3c24xx_uart_clksrc
diff --git a/include/asm-arm/arch-s3c2410/reset.h b/include/asm-arm/arch-s3c2410/reset.h
new file mode 100644 (file)
index 0000000..4f866cd
--- /dev/null
@@ -0,0 +1,22 @@
+/* linux/include/asm-arm/arch-s3c2410/reset.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2410 CPU reset controls
+*/
+
+#ifndef __ASM_ARCH_RESET_H
+#define __ASM_ARCH_RESET_H __FILE__
+
+/* This allows the over-ride of the default reset code
+*/
+
+extern void (*s3c24xx_reset_hook)(void);
+
+#endif /* __ASM_ARCH_RESET_H */
index ecf250db45fbc613dd892f1595e39850a2c898e0..1c74ef17da3363eda55e8dcf8fee51c84d502148 100644 (file)
 
 #include <asm/arch/map.h>
 #include <asm/arch/idle.h>
+#include <asm/arch/reset.h>
 
 #include <asm/arch/regs-watchdog.h>
 #include <asm/arch/regs-clock.h>
 
 void (*s3c24xx_idle)(void);
+void (*s3c24xx_reset_hook)(void);
 
 void s3c24xx_default_idle(void)
 {
-       void __iomem *reg = S3C2410_CLKCON;
        unsigned long tmp;
        int i;
 
@@ -33,16 +34,18 @@ void s3c24xx_default_idle(void)
 
        /* Warning: going into idle state upsets jtag scanning */
 
-       __raw_writel(__raw_readl(reg) | (1<<2), reg);
+       __raw_writel(__raw_readl(S3C2410_CLKCON) | S3C2410_CLKCON_IDLE,
+                    S3C2410_CLKCON);
 
        /* the samsung port seems to do a loop and then unset idle.. */
        for (i = 0; i < 50; i++) {
-               tmp += __raw_readl(reg); /* ensure loop not optimised out */
+               tmp += __raw_readl(S3C2410_CLKCON); /* ensure loop not optimised out */
        }
 
        /* this bit is not cleared on re-start... */
 
-       __raw_writel(__raw_readl(reg) & ~(1<<2), reg);
+       __raw_writel(__raw_readl(S3C2410_CLKCON) & ~S3C2410_CLKCON_IDLE,
+                    S3C2410_CLKCON);
 }
 
 static void arch_idle(void)
@@ -53,7 +56,6 @@ static void arch_idle(void)
                s3c24xx_default_idle();
 }
 
-
 static void
 arch_reset(char mode)
 {
@@ -61,6 +63,9 @@ arch_reset(char mode)
                cpu_reset(0);
        }
 
+       if (s3c24xx_reset_hook)
+               s3c24xx_reset_hook();
+
        printk("arch_reset: attempting watchdog reset\n");
 
        __raw_writel(0, S3C2410_WTCON);   /* disable watchdog, to be safe  */
diff --git a/include/asm-arm/arch-s3c2410/udc.h b/include/asm-arm/arch-s3c2410/udc.h
new file mode 100644 (file)
index 0000000..e59ec33
--- /dev/null
@@ -0,0 +1,36 @@
+/* linux/include/asm/arch-s3c2410/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
+ *
+ *
+ *  Changelog:
+ *     14-Mar-2005     RTP     Created file
+ *     02-Aug-2005     RTP     File rename
+ *     07-Sep-2005     BJD     Minor cleanups, changed cmd to enum
+ *     18-Jan-2007     HMW     Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+       S3C2410_UDC_P_ENABLE    = 1,    /* Pull-up enable        */
+       S3C2410_UDC_P_DISABLE   = 2,    /* Pull-up disable       */
+       S3C2410_UDC_P_RESET     = 3,    /* UDC reset, in case of */
+};
+
+struct s3c2410_udc_mach_info {
+       void    (*udc_command)(enum s3c2410_udc_cmd_e);
+       void    (*vbus_draw)(unsigned int ma);
+       unsigned int vbus_pin;
+       unsigned char vbus_pin_inverted;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
index 5f531ea03059d003bab3e86643ed2580a36133cf..afad32c76e6c964df908c6493441139ccb328977 100644 (file)
@@ -185,9 +185,15 @@ struct cpu_cache_fns {
        void (*coherent_user_range)(unsigned long, unsigned long);
        void (*flush_kern_dcache_page)(void *);
 
-       void (*dma_inv_range)(unsigned long, unsigned long);
-       void (*dma_clean_range)(unsigned long, unsigned long);
-       void (*dma_flush_range)(unsigned long, unsigned long);
+       void (*dma_inv_range)(const void *, const void *);
+       void (*dma_clean_range)(const void *, const void *);
+       void (*dma_flush_range)(const void *, const void *);
+};
+
+struct outer_cache_fns {
+       void (*inv_range)(unsigned long, unsigned long);
+       void (*clean_range)(unsigned long, unsigned long);
+       void (*flush_range)(unsigned long, unsigned long);
 };
 
 /*
@@ -240,9 +246,40 @@ extern void __cpuc_flush_dcache_page(void *);
 #define dmac_clean_range               __glue(_CACHE,_dma_clean_range)
 #define dmac_flush_range               __glue(_CACHE,_dma_flush_range)
 
-extern void dmac_inv_range(unsigned long, unsigned long);
-extern void dmac_clean_range(unsigned long, unsigned long);
-extern void dmac_flush_range(unsigned long, unsigned long);
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
+extern void dmac_flush_range(const void *, const void *);
+
+#endif
+
+#ifdef CONFIG_OUTER_CACHE
+
+extern struct outer_cache_fns outer_cache;
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{
+       if (outer_cache.inv_range)
+               outer_cache.inv_range(start, end);
+}
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{
+       if (outer_cache.clean_range)
+               outer_cache.clean_range(start, end);
+}
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{
+       if (outer_cache.flush_range)
+               outer_cache.flush_range(start, end);
+}
+
+#else
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{ }
 
 #endif
 
index 8c0bb5bb14ee610df1db55f28714fa18aced21db..eaa0efd8d0d47e39ce6b5087a9eb60d1bc61811b 100644 (file)
@@ -39,6 +39,19 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
 __wsum
 csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
 
+/*
+ *     Fold a partial checksum without adding pseudo headers
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+       __asm__(
+       "add    %0, %1, %1, ror #16     @ csum_fold"
+       : "=r" (sum)
+       : "r" (sum)
+       : "cc");
+       return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
 /*
  *     This is a version of ip_compute_csum() optimized for IP headers,
  *     which always checksum on 4 octet boundaries.
@@ -46,7 +59,8 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum s
 static inline __sum16
 ip_fast_csum(const void *iph, unsigned int ihl)
 {
-       unsigned int sum, tmp1;
+       unsigned int tmp1;
+       __wsum sum;
 
        __asm__ __volatile__(
        "ldr    %0, [%1], #4            @ ip_fast_csum          \n\
@@ -62,29 +76,11 @@ ip_fast_csum(const void *iph, unsigned int ihl)
        subne   %2, %2, #1              @ without destroying    \n\
        bne     1b                      @ the carry flag        \n\
        adcs    %0, %0, %3                                      \n\
-       adc     %0, %0, #0                                      \n\
-       adds    %0, %0, %0, lsl #16                             \n\
-       addcs   %0, %0, #0x10000                                \n\
-       mvn     %0, %0                                          \n\
-       mov     %0, %0, lsr #16"
+       adc     %0, %0, #0"
        : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
        : "1" (iph), "2" (ihl)
        : "cc", "memory");
-       return (__force __sum16)sum;
-}
-
-/*
- *     Fold a partial checksum without adding pseudo headers
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-       __asm__(
-       "adds   %0, %1, %1, lsl #16     @ csum_fold             \n\
-       addcs   %0, %0, #0x10000"
-       : "=r" (sum)
-       : "r" (sum)
-       : "cc");
-       return (__force __sum16)(~(__force u32)sum >> 16);
+       return csum_fold(sum);
 }
 
 static inline __wsum
@@ -114,23 +110,7 @@ static inline __sum16
 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
                  unsigned short proto, __wsum sum)
 {
-       __asm__(
-       "adds   %0, %1, %2              @ csum_tcpudp_magic     \n\
-       adcs    %0, %0, %3                                      \n"
-#ifdef __ARMEB__
-       "adcs   %0, %0, %4                                      \n"
-#else
-       "adcs   %0, %0, %4, lsl #8                              \n"
-#endif
-       "adcs   %0, %0, %5                                      \n\
-       adc     %0, %0, #0                                      \n\
-       adds    %0, %0, %0, lsl #16                             \n\
-       addcs   %0, %0, #0x10000                                \n\
-       mvn     %0, %0"
-       : "=&r"(sum)
-       : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
-       : "cc");
-       return (__force __sum16)((__force u32)sum >> 16);
+       return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
 
 
index d8f9872b0e2dc3587a9e658adc957f093b7906fb..c61642b406033659db06494a75fcb4c8d8914477 100644 (file)
@@ -3,5 +3,13 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+#ifndef ASMARM_DEVICE_H
+#define ASMARM_DEVICE_H
 
+struct dev_archdata {
+#ifdef CONFIG_DMABOUNCE
+       struct dmabounce_device_info *dmabounce;
+#endif
+};
+
+#endif
index 9bc46b486afba7a5970e93b5c938a3be33c4684e..abfb75b654c7df7f8795b1f0db4ea4aa173fd0e8 100644 (file)
@@ -17,7 +17,7 @@
  * platforms with CONFIG_DMABOUNCE.
  * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
  */
-extern void consistent_sync(void *kaddr, size_t size, int rw);
+extern void consistent_sync(const void *kaddr, size_t size, int rw);
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -61,6 +61,22 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
        return dma_addr == ~0;
 }
 
+/*
+ * Dummy noncoherent implementation.  We don't provide a dma_cache_sync
+ * function so drivers using this API are highlighted with build warnings.
+ */
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+       return NULL;
+}
+
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+                    dma_addr_t handle)
+{
+}
+
 /**
  * dma_alloc_coherent - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
index 4c2885abbe6c950f04d06c6345bb6358f591421b..3c12a7625304d24d19bcb9e469c5b5bbcca8faef 100644 (file)
@@ -57,6 +57,7 @@
        __asm__ __volatile__(                           \
        "mcr    p15, 0, %0, c3, c0      @ set domain"   \
          : : "r" (x));                                 \
+       isb();                                          \
        } while (0)
 
 #define modify_domain(dom,type)                                        \
index 9903f60c84b713fdde431f61e33c87ba8f683be4..7d28eb5a17587ed0b4dbc3219d75e50fd52c5a4f 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef ASMARM_HARDWARE_ARM_SCU_H
 #define ASMARM_HARDWARE_ARM_SCU_H
 
+#include <asm/arch/scu.h>
+
 /*
  * SCU registers
  */
diff --git a/include/asm-arm/hardware/cache-l2x0.h b/include/asm-arm/hardware/cache-l2x0.h
new file mode 100644 (file)
index 0000000..54029a7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * include/asm-arm/hardware/cache-l2x0.h
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARM_HARDWARE_L2X0_H
+#define __ASM_ARM_HARDWARE_L2X0_H
+
+#define L2X0_CACHE_ID                  0x000
+#define L2X0_CACHE_TYPE                        0x004
+#define L2X0_CTRL                      0x100
+#define L2X0_AUX_CTRL                  0x104
+#define L2X0_EVENT_CNT_CTRL            0x200
+#define L2X0_EVENT_CNT1_CFG            0x204
+#define L2X0_EVENT_CNT0_CFG            0x208
+#define L2X0_EVENT_CNT1_VAL            0x20C
+#define L2X0_EVENT_CNT0_VAL            0x210
+#define L2X0_INTR_MASK                 0x214
+#define L2X0_MASKED_INTR_STAT          0x218
+#define L2X0_RAW_INTR_STAT             0x21C
+#define L2X0_INTR_CLEAR                        0x220
+#define L2X0_CACHE_SYNC                        0x730
+#define L2X0_INV_LINE_PA               0x770
+#define L2X0_INV_WAY                   0x77C
+#define L2X0_CLEAN_LINE_PA             0x7B0
+#define L2X0_CLEAN_LINE_IDX            0x7B8
+#define L2X0_CLEAN_WAY                 0x7BC
+#define L2X0_CLEAN_INV_LINE_PA         0x7F0
+#define L2X0_CLEAN_INV_LINE_IDX                0x7F8
+#define L2X0_CLEAN_INV_WAY             0x7FC
+#define L2X0_LOCKDOWN_WAY_D            0x900
+#define L2X0_LOCKDOWN_WAY_I            0x904
+#define L2X0_TEST_OPERATION            0xF00
+#define L2X0_LINE_DATA                 0xF10
+#define L2X0_LINE_TAG                  0xF30
+#define L2X0_DEBUG_CTRL                        0xF40
+
+#ifndef __ASSEMBLY__
+extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#endif
+
+#endif
index 3fa5eb70f64ed7926f0a41584a338e9279045289..966e428ad32c858aec9870a9cb72491effa7b3f3 100644 (file)
@@ -33,8 +33,9 @@
 #define GIC_DIST_SOFTINT               0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(void __iomem *base);
-void gic_cpu_init(void __iomem *base);
+void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
+void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
 #endif
 
index 13ac8a4cd01f6ba7fc070d88a6aa9023ac442f4f..c91b546e20ef8040419fbd86cb9170192581d915 100644 (file)
@@ -37,6 +37,13 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_PERIPHERAL_PHYS_BASE    0xffffe000
 #define IOP3XX_PERIPHERAL_VIRT_BASE    0xfeffe000
 #define IOP3XX_PERIPHERAL_SIZE         0x00002000
+#define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
+                                       IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PERIPHERAL_UPPER_VA (IOP3XX_PERIPHERAL_VIRT_BASE +\
+                                       IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+                                       (IOP3XX_PERIPHERAL_PHYS_BASE\
+                                       - IOP3XX_PERIPHERAL_VIRT_BASE))
 #define IOP3XX_REG_ADDR(reg)           (IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
 
 /* Address Translation Unit  */
@@ -258,12 +265,20 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_PCI_LOWER_IO_PA         0x90000000
 #define IOP3XX_PCI_LOWER_IO_VA         0xfe000000
 #define IOP3XX_PCI_LOWER_IO_BA         (*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_UPPER_IO_PA         (IOP3XX_PCI_LOWER_IO_PA +\
+                                       IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_UPPER_IO_VA         (IOP3XX_PCI_LOWER_IO_VA +\
+                                       IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\
+                                       IOP3XX_PCI_LOWER_IO_PA) +\
+                                       IOP3XX_PCI_LOWER_IO_VA)
 
 
 #ifndef __ASSEMBLY__
 void iop3xx_map_io(void);
 void iop3xx_init_time(unsigned long);
 unsigned long iop3xx_gettimeoffset(void);
+void iop_init_cp6_handler(void);
 
 extern struct platform_device iop3xx_i2c0_device;
 extern struct platform_device iop3xx_i2c1_device;
index 6aa0a5b75b69dc9bc5f72266f8df5763f9c561eb..61b1d05c7df74772f95cd581cd06c05ee81cbdf8 100644 (file)
@@ -29,6 +29,9 @@
 #define _SA1111(x)     ((x) + sa1111->resource.start)
 #endif
 
+#define sa1111_writel(val,addr)        __raw_writel(val, addr)
+#define sa1111_readl(addr)     __raw_readl(addr)
+
 /*
  * 26 bits of the SA-1110 address bus are available to the SA-1111.
  * Use these when feeding target addresses to the DMA engines.
 
 #define SA1111_SAC_DMA_MIN_XFER        (0x800)
 
-/*
- * SA1111 register definitions.
- */
-#define __CCREG(x)     __REGP(SA1111_VBASE + (x))
-
-#define sa1111_writel(val,addr)        __raw_writel(val, addr)
-#define sa1111_readl(addr)     __raw_readl(addr)
-
 /*
  * System Bus Interface (SBI)
  *
  *    SADR              Serial Audio Data Register (16 x 32-bit)
  */
 
-#define _SACR0          _SA1111( 0x0600 )
-#define _SACR1          _SA1111( 0x0604 )
-#define _SACR2          _SA1111( 0x0608 )
-#define _SASR0          _SA1111( 0x060c )
-#define _SASR1          _SA1111( 0x0610 )
-#define _SASCR          _SA1111( 0x0618 )
-#define _L3_CAR         _SA1111( 0x061c )
-#define _L3_CDR         _SA1111( 0x0620 )
-#define _ACCAR          _SA1111( 0x0624 )
-#define _ACCDR          _SA1111( 0x0628 )
-#define _ACSAR          _SA1111( 0x062c )
-#define _ACSDR          _SA1111( 0x0630 )
-#define _SADTCS         _SA1111( 0x0634 )
-#define _SADTSA         _SA1111( 0x0638 )
-#define _SADTCA         _SA1111( 0x063c )
-#define _SADTSB         _SA1111( 0x0640 )
-#define _SADTCB         _SA1111( 0x0644 )
-#define _SADRCS         _SA1111( 0x0648 )
-#define _SADRSA         _SA1111( 0x064c )
-#define _SADRCA         _SA1111( 0x0650 )
-#define _SADRSB         _SA1111( 0x0654 )
-#define _SADRCB         _SA1111( 0x0658 )
-#define _SAITR          _SA1111( 0x065c )
-#define _SADR           _SA1111( 0x0680 )
-
-#define SACR0          __CCREG(0x0600)
-#define SACR1          __CCREG(0x0604)
-#define SACR2          __CCREG(0x0608)
-#define SASR0          __CCREG(0x060c)
-#define SASR1          __CCREG(0x0610)
-#define SASCR          __CCREG(0x0618)
-#define L3_CAR         __CCREG(0x061c)
-#define L3_CDR         __CCREG(0x0620)
-#define ACCAR          __CCREG(0x0624)
-#define ACCDR          __CCREG(0x0628)
-#define ACSAR          __CCREG(0x062c)
-#define ACSDR          __CCREG(0x0630)
-#define SADTCS         __CCREG(0x0634)
-#define SADTSA         __CCREG(0x0638)
-#define SADTCA         __CCREG(0x063c)
-#define SADTSB         __CCREG(0x0640)
-#define SADTCB         __CCREG(0x0644)
-#define SADRCS         __CCREG(0x0648)
-#define SADRSA         __CCREG(0x064c)
-#define SADRCA         __CCREG(0x0650)
-#define SADRSB         __CCREG(0x0654)
-#define SADRCB         __CCREG(0x0658)
-#define SAITR          __CCREG(0x065c)
-#define SADR           __CCREG(0x0680)
+#define SA1111_SERAUDIO                0x0600
+
+/*
+ * These are offsets from the above base.
+ */
+#define SA1111_SACR0           0x00
+#define SA1111_SACR1           0x04
+#define SA1111_SACR2           0x08
+#define SA1111_SASR0           0x0c
+#define SA1111_SASR1           0x10
+#define SA1111_SASCR           0x18
+#define SA1111_L3_CAR          0x1c
+#define SA1111_L3_CDR          0x20
+#define SA1111_ACCAR           0x24
+#define SA1111_ACCDR           0x28
+#define SA1111_ACSAR           0x2c
+#define SA1111_ACSDR           0x30
+#define SA1111_SADTCS          0x34
+#define SA1111_SADTSA          0x38
+#define SA1111_SADTCA          0x3c
+#define SA1111_SADTSB          0x40
+#define SA1111_SADTCB          0x44
+#define SA1111_SADRCS          0x48
+#define SA1111_SADRSA          0x4c
+#define SA1111_SADRCA          0x50
+#define SA1111_SADRSB          0x54
+#define SA1111_SADRCB          0x58
+#define SA1111_SAITR           0x5c
+#define SA1111_SADR            0x80
+
+#ifndef CONFIG_ARCH_PXA
 
 #define SACR0_ENB      (1<<0)
 #define SACR0_BCKD     (1<<2)
 #define SAITR_RDBDA    (1<<10)
 #define SAITR_RDBDB    (1<<11)
 
+#endif  /* !CONFIG_ARCH_PXA */
+
 /*
  * General-Purpose I/O Interface
  *
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
new file mode 100644 (file)
index 0000000..8c1c616
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _ARM_KEXEC_H
+#define _ARM_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE        4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM
+
+#ifndef __ASSEMBLY__
+
+#define MAX_NOTE_BYTES 1024
+
+struct kimage;
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                        struct pt_regs *oldregs) { }
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ARM_KEXEC_H */
index b8cf2d5ec3041c7e3c5ff32a46078bca6b10e4aa..7b2bafce21a254924cdedcd17dfaf4e0e721e7f9 100644 (file)
@@ -175,19 +175,29 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #ifndef __ASSEMBLY__
 
 /*
- * The following macros handle the cache and bufferable bits...
+ * The pgprot_* and protection_map entries will be fixed up in runtime
+ * to include the cachable and bufferable bits based on memory policy,
+ * as well as any architecture dependent bits like global/ASID and SMP
+ * shared mapping bits.
  */
 #define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
 #define _L_PTE_READ    L_PTE_USER | L_PTE_EXEC
 
+extern pgprot_t                pgprot_user;
 extern pgprot_t                pgprot_kernel;
 
-#define PAGE_NONE       __pgprot(_L_PTE_DEFAULT)
-#define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
-#define PAGE_SHARED     __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
-#define PAGE_READONLY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_NONE      pgprot_user
+#define PAGE_COPY      __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
+#define PAGE_SHARED    __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ | \
+                                L_PTE_WRITE)
+#define PAGE_READONLY  __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
 #define PAGE_KERNEL    pgprot_kernel
 
+#define __PAGE_NONE    __pgprot(_L_PTE_DEFAULT)
+#define __PAGE_COPY    __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define __PAGE_SHARED  __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
+#define __PAGE_READONLY        __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+
 #endif /* __ASSEMBLY__ */
 
 /*
@@ -198,23 +208,23 @@ extern pgprot_t           pgprot_kernel;
  *  2) If we could do execute protection, then read is implied
  *  3) write implies read permissions
  */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
+#define __P000  __PAGE_NONE
+#define __P001  __PAGE_READONLY
+#define __P010  __PAGE_COPY
+#define __P011  __PAGE_COPY
+#define __P100  __PAGE_READONLY
+#define __P101  __PAGE_READONLY
+#define __P110  __PAGE_COPY
+#define __P111  __PAGE_COPY
+
+#define __S000  __PAGE_NONE
+#define __S001  __PAGE_READONLY
+#define __S010  __PAGE_SHARED
+#define __S011  __PAGE_SHARED
+#define __S100  __PAGE_READONLY
+#define __S101  __PAGE_READONLY
+#define __S110  __PAGE_SHARED
+#define __S111  __PAGE_SHARED
 
 #ifndef __ASSEMBLY__
 /*
similarity index 97%
rename from arch/arm/mach-s3c2410/clock.h
rename to include/asm-arm/plat-s3c24xx/clock.h
index 7f0ea03e1d49398df37f5e843982b769635dd583..f6135dbb9fa9601db1358979b1b0c6bc5033ec78 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* linux/include/asm-arm/plat-s3c24xx/clock.h
  * linux/arch/arm/mach-s3c2410/clock.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
similarity index 88%
rename from arch/arm/mach-s3c2410/common-smdk.h
rename to include/asm-arm/plat-s3c24xx/common-smdk.h
index 0e3a3be330a3455f001d426d99be021cfd21e575..58d9094c935c05b7ab71f5d74a507b7d241ca739 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.h
+/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 95%
rename from arch/arm/mach-s3c2410/cpu.h
rename to include/asm-arm/plat-s3c24xx/cpu.h
index be42e4032a6d670f3004ae550b88ac923400d284..15dd18810905c6f499af7f0e37cec0e0610e13b7 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/cpu.h
+/* linux/include/asm-arm/plat-s3c24xx/cpu.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -67,3 +67,4 @@ extern struct sysdev_class s3c2410_sysclass;
 extern struct sysdev_class s3c2412_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
 extern struct sysdev_class s3c2442_sysclass;
+extern struct sysdev_class s3c2443_sysclass;
similarity index 97%
rename from arch/arm/mach-s3c2410/devs.h
rename to include/asm-arm/plat-s3c24xx/devs.h
index 14fb0bade7165c68057eeb1cda6b03a353d2a176..dddf485fc0670fe4833b7fc5e57f282fb7df4223 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/devs.h
+/* linux/include/asm-arm/plat-s3c24xx/devs.h
  *
  * Copyright (c) 2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
similarity index 53%
rename from arch/arm/mach-s3c2410/dma.h
rename to include/asm-arm/plat-s3c24xx/dma.h
index 0ebfe0aab80be885bd256e6677793c19ce12be0b..2c59406435e56f1cc244c9258a60bc38c075cb14 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/dma.h
+/* linux/include/asm-arm/plat-s3c24xx/dma.h
  *
  * Copyright (C) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -14,6 +14,7 @@ extern struct sysdev_class dma_sysclass;
 extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
 
 #define DMA_CH_VALID           (1<<31)
+#define DMA_CH_NEVER           (1<<30)
 
 struct s3c24xx_dma_addr {
        unsigned long           from;
@@ -43,3 +44,34 @@ struct s3c24xx_dma_selection {
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+       unsigned int    list[S3C2410_DMA_CHANNELS];     /* list of channels */
+       unsigned int    flags;                          /* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+       struct s3c24xx_dma_order_ch     channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+                           unsigned int stride);
similarity index 98%
rename from arch/arm/mach-s3c2410/irq.h
rename to include/asm-arm/plat-s3c24xx/irq.h
index e5913da3b919bb3ffbffbbf48a94c129b6e8d243..8af6d9579b31c975bd86ca6e2e6c1c2ed62ab4f9 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/irq.h
+/* linux/include/asm-arm/plat-s3c24xx/irq.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 97%
rename from arch/arm/mach-s3c2410/pm.h
rename to include/asm-arm/plat-s3c24xx/pm.h
index ffe197a119fb096b2e3c1d9c6788094946011fcc..cc623667e48a4585a11145a50ec40e1207239a42 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm.h
+/* linux/include/asm-arm/plat-s3c24xx/pm.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Written by Ben Dooks, <ben@simtec.co.uk>
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c2400.h
rename to include/asm-arm/plat-s3c24xx/s3c2400.h
index 8b2394e1ed4088c3b8d38e87e58bde2f38152bf7..3a5a16821af8e5de6cbdcd3c3719847ff39d072a 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2400.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2410.h
rename to include/asm-arm/plat-s3c24xx/s3c2410.h
index fbed084f26d049116f58673383507583f815b5a7..36de0b8358737794c0fdcc2e53c58cab7cb56718 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2410.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2412.h
rename to include/asm-arm/plat-s3c24xx/s3c2412.h
index c6e56032a6e7177336ce06de58cce2d71b0967e3..3ec97685e7819029c342b0571a541db22c470cd1 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2412.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2440.h
rename to include/asm-arm/plat-s3c24xx/s3c2440.h
index dcd316076c595e3c1c014d7d64a59f95dd20669c..107853bf94813f14a72402ce2789176c1600d66d 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2440.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2442.h
rename to include/asm-arm/plat-s3c24xx/s3c2442.h
index 0ae37d24866cd4f9393cdca4e77faa4e36ad4bf8..451a23a2092aa98fb8d582f47b3141621f760eaf 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2442.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
diff --git a/include/asm-arm/plat-s3c24xx/s3c2443.h b/include/asm-arm/plat-s3c24xx/s3c2443.h
new file mode 100644 (file)
index 0000000..11d83b5
--- /dev/null
@@ -0,0 +1,32 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2443_init(void);
+
+extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern  int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
index aa223fc546afdee10d5b0d74bae41014122a07fe..f4386906b200002d6d6a3612f4037382a9ba9cef 100644 (file)
@@ -140,6 +140,40 @@ static inline int cpu_is_xsc3(void)
 #define        cpu_is_xscale() 1
 #endif
 
+#define UDBG_UNDEFINED (1 << 0)
+#define UDBG_SYSCALL   (1 << 1)
+#define UDBG_BADABORT  (1 << 2)
+#define UDBG_SEGV      (1 << 3)
+#define UDBG_BUS       (1 << 4)
+
+extern unsigned int user_debug;
+
+#if __LINUX_ARM_ARCH__ >= 4
+#define vectors_high() (cr_alignment & CR_V)
+#else
+#define vectors_high() (0)
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+                                   : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory")
+#else
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+#define mb() dmb()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
 extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
 extern unsigned long cr_alignment;     /* defined in entry-armv.S */
 
@@ -154,6 +188,7 @@ static inline void set_cr(unsigned int val)
 {
        asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
          : : "r" (val) : "cc");
+       isb();
 }
 
 #ifndef CONFIG_SMP
@@ -176,34 +211,9 @@ static inline void set_copro_access(unsigned int val)
 {
        asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
          : : "r" (val) : "cc");
+       isb();
 }
 
-#define UDBG_UNDEFINED (1 << 0)
-#define UDBG_SYSCALL   (1 << 1)
-#define UDBG_BADABORT  (1 << 2)
-#define UDBG_SEGV      (1 << 3)
-#define UDBG_BUS       (1 << 4)
-
-extern unsigned int user_debug;
-
-#if __LINUX_ARM_ARCH__ >= 4
-#define vectors_high() (cr_alignment & CR_V)
-#else
-#define vectors_high() (0)
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 6
-#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
-                                   : : "r" (0) : "memory")
-#else
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#endif
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
 /*
  * switch_mm() may do a full cache flush over the context switch,
  * so enable interrupts over the context switch to avoid high
index cd10a0b5f8ae77510234c15c9295f80944f59f4a..08c6991dc9c9925a36e5057047fdf3956639078f 100644 (file)
@@ -247,7 +247,7 @@ static inline void local_flush_tlb_all(void)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+               dsb();
 
        if (tlb_flag(TLB_V3_FULL))
                asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
@@ -257,6 +257,15 @@ static inline void local_flush_tlb_all(void)
                asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
        if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
                asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+
+       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+                    TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+               /* flush the branch target cache */
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+               isb();
+       }
 }
 
 static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,7 +275,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+               dsb();
 
        if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
                if (tlb_flag(TLB_V3_FULL))
@@ -285,6 +294,14 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
                asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
        if (tlb_flag(TLB_V6_I_ASID))
                asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
+
+       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+                    TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+               /* flush the branch target cache */
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+       }
 }
 
 static inline void
@@ -296,7 +313,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
 
        if (tlb_flag(TLB_WB))
-               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               dsb();
 
        if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
                if (tlb_flag(TLB_V3_PAGE))
@@ -317,6 +334,14 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
                asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
        if (tlb_flag(TLB_V6_I_PAGE))
                asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+
+       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+                    TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+               /* flush the branch target cache */
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+       }
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,7 +352,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        kaddr &= PAGE_MASK;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+               dsb();
 
        if (tlb_flag(TLB_V3_PAGE))
                asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
@@ -347,11 +372,14 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        if (tlb_flag(TLB_V6_I_PAGE))
                asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 
-       /* The ARM ARM states that the completion of a TLB maintenance
-        * operation is only guaranteed by a DSB instruction
-        */
-       if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+                    TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+               /* flush the branch target cache */
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+               isb();
+       }
 }
 
 /*
@@ -369,15 +397,13 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
  */
 static inline void flush_pmd_entry(pmd_t *pmd)
 {
-       const unsigned int zero = 0;
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_DCLEAN))
                asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
                        : : "r" (pmd) : "cc");
        if (tlb_flag(TLB_WB))
-               asm("mcr        p15, 0, %0, c7, c10, 4  @ flush_pmd"
-                       : : "r" (zero) : "cc");
+               dsb();
 }
 
 static inline void clean_pmd_entry(pmd_t *pmd)
index c92df958802e304dd60fb92a8a92bbb1facf142b..4c1a3fa9f2596cac7243e7d932252deb56817c0f 100644 (file)
@@ -109,7 +109,7 @@ extern int __get_user_4(void *);
 
 #define get_user(x,p)                                                  \
        ({                                                              \
-               const register typeof(*(p)) __user *__p asm("r0") = (p);\
+               register const typeof(*(p)) __user *__p asm("r0") = (p);\
                register unsigned long __r2 asm("r2");                  \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
@@ -143,8 +143,8 @@ extern int __put_user_8(void *, unsigned long long);
 
 #define put_user(x,p)                                                  \
        ({                                                              \
-               const register typeof(*(p)) __r2 asm("r2") = (x);       \
-               const register typeof(*(p)) __user *__p asm("r0") = (p);\
+               register const typeof(*(p)) __r2 asm("r2") = (x);       \
+               register const typeof(*(p)) __user *__p asm("r0") = (p);\
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
index 97e7060000cf9170fe376bf689681ef2c1f303f7..0991b7bc3f78dc0acac510de92668d818e6cc897 100644 (file)
 #define __NR_move_pages                        (__NR_SYSCALL_BASE+344)
 #define __NR_getcpu                    (__NR_SYSCALL_BASE+345)
                                        /* 346 for epoll_pwait */
+#define __NR_sys_kexec_load            (__NR_SYSCALL_BASE+347)
 
 /*
  * The following SWIs are ARM private.
index 3f2dd1093e58b6a233c20f223043f7efaa8afc13..d64ed84cb2d3eecb1068f5b70094c684a49fe99d 100644 (file)
@@ -74,7 +74,7 @@ extern int __get_user_bad(void);
 
 #define get_user(x,p)                                                  \
        ({                                                              \
-               const register typeof(*(p)) *__p asm("r0") = (p);       \
+               register const typeof(*(p)) *__p asm("r0") = (p);       \
                register typeof(*(p)) __r1 asm("r1");                   \
                register int __e asm("r0");                             \
                switch (sizeof(*(p))) {                                 \
@@ -139,8 +139,8 @@ extern int __put_user_bad(void);
 
 #define put_user(x,p)                                                   \
         ({                                                              \
-                const register typeof(*(p)) __r1 asm("r1") = (x);       \
-                const register typeof(*(p)) *__p asm("r0") = (p);       \
+                register const typeof(*(p)) __r1 asm("r1") = (x);       \
+                register const typeof(*(p)) *__p asm("r0") = (p);       \
                 register int __e asm("r0");                             \
                 switch (sizeof(*(__p))) {                               \
                 case 1:                                                 \
@@ -170,8 +170,8 @@ extern int __put_user_bad(void);
 
 #define put_user(x,p)                                                  \
        ({                                                              \
-               const register typeof(*(p)) __r1 asm("r1") = (x);       \
-               const register typeof(*(p)) *__p asm("r0") = (p);       \
+               register const typeof(*(p)) __r1 asm("r1") = (x);       \
+               register const typeof(*(p)) *__p asm("r0") = (p);       \
                register int __e asm("r0");                             \
                switch (sizeof(*(p))) {                                 \
                case 1:                                                 \
diff --git a/include/asm-avr32/arch-at32ap/at91_pdc.h b/include/asm-avr32/arch-at32ap/at91_pdc.h
deleted file mode 100644 (file)
index 79d6e02..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR           0x100   /* Receive Pointer Register */
-#define AT91_PDC_RCR           0x104   /* Receive Counter Register */
-#define AT91_PDC_TPR           0x108   /* Transmit Pointer Register */
-#define AT91_PDC_TCR           0x10c   /* Transmit Counter Register */
-#define AT91_PDC_RNPR          0x110   /* Receive Next Pointer Register */
-#define AT91_PDC_RNCR          0x114   /* Receive Next Counter Register */
-#define AT91_PDC_TNPR          0x118   /* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR          0x11c   /* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR          0x120   /* Transfer Control Register */
-#define                AT91_PDC_RXTEN          (1 << 0)        /* Receiver Transfer Enable */
-#define                AT91_PDC_RXTDIS         (1 << 1)        /* Receiver Transfer Disable */
-#define                AT91_PDC_TXTEN          (1 << 8)        /* Transmitter Transfer Enable */
-#define                AT91_PDC_TXTDIS         (1 << 9)        /* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR          0x124   /* Transfer Status Register */
-
-#endif
index b120ee030c867b97a46d1d314fe376d0f5fbd2e7..1a7b07d436ffe4cde3a3f9f65e4614eed96f5449 100644 (file)
@@ -26,7 +26,9 @@ struct eth_platform_data {
 struct platform_device *
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
 
-struct platform_device *at32_add_device_spi(unsigned int id);
+struct spi_board_info;
+struct platform_device *
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
 
 struct lcdc_platform_data {
        unsigned long fbmem_start;
index eec47500fa66e2d5514628b5950f014fc4a54d6d..c08e810483936534ba6da061cde31a6050dfb904 100644 (file)
@@ -28,13 +28,13 @@ static __inline__ void * phys_to_virt(unsigned long address)
  * Generic IO read/write.  These perform native-endian accesses.  Note
  * that some architectures will want to re-define __raw_{read,write}w.
  */
-extern void __raw_writesb(unsigned int addr, const void *data, int bytelen);
-extern void __raw_writesw(unsigned int addr, const void *data, int wordlen);
-extern void __raw_writesl(unsigned int addr, const void *data, int longlen);
+extern void __raw_writesb(void __iomem *addr, const void *data, int bytelen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int longlen);
 
-extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
-extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
-extern void __raw_readsl(unsigned int addr, void *data, int longlen);
+extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
 static inline void writeb(unsigned char b, volatile void __iomem *addr)
 {
@@ -252,6 +252,9 @@ extern void __iounmap(void __iomem *addr);
 #define ioremap(offset, size)                  \
        __ioremap((offset), (size), 0)
 
+#define ioremap_nocache(offset, size)          \
+       __ioremap((offset), (size), 0)
+
 #define iounmap(addr)                          \
        __iounmap(addr)
 
@@ -263,6 +266,14 @@ extern void __iounmap(void __iomem *addr);
 #define page_to_bus page_to_phys
 #define bus_to_page phys_to_page
 
+/*
+ * Create a virtual mapping cookie for an IO port range.  There exists
+ * no such thing as port-based I/O on AVR32, so a regular ioremap()
+ * should do what we need.
+ */
+#define ioport_map(port, nr)   ioremap(port, nr)
+#define ioport_unmap(port)     iounmap(port)
+
 #define dma_cache_wback_inv(_start, _size)     \
        flush_dcache_region(_start, _size)
 #define dma_cache_inv(_start, _size)           \
index 56ed1f9d348a55f1ad3e534310a63359ec66dc58..8f51204718193751bc131cc4f9ce772c2405a36b 100644 (file)
 #define __NR_getitimer         105
 #define __NR_swapoff           106
 #define __NR_sysinfo           107
-#define __NR_ipc               108
+/* 108 was __NR_ipc for a little while */
 #define __NR_sendfile          109
 #define __NR_setdomainname     110
 #define __NR_uname             111
 #define __NR_vmsplice          264
 #define __NR_epoll_pwait       265
 
+#define __NR_msgget            266
+#define __NR_msgsnd            267
+#define __NR_msgrcv            268
+#define __NR_msgctl            269
+#define __NR_semget            270
+#define __NR_semop             271
+#define __NR_semctl            272
+#define __NR_semtimedop                273
+#define __NR_shmat             274
+#define __NR_shmget            275
+#define __NR_shmdt             276
+#define __NR_shmctl            277
+
 #ifdef __KERNEL__
-#define NR_syscalls            266
+#define NR_syscalls            278
 
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
index 9d774d07d95b4a3a53d5fb75fac15b076d892a02..00c23433b39f2ad868aefc6f414d2e728398bd15 100644 (file)
@@ -182,6 +182,19 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #define arch_leave_lazy_mmu_mode()     do {} while (0)
 #endif
 
+/*
+ * A facility to provide batching of the reload of page tables with the
+ * actual context switch code for paravirtualized guests.  By convention,
+ * only one of the lazy modes (CPU, MMU) should be active at any given
+ * time, entry should never be nested, and entry and exits should always
+ * be paired.  This is for sanity of maintaining and reasoning about the
+ * kernel code.
+ */
+#ifndef __HAVE_ARCH_ENTER_LAZY_CPU_MODE
+#define arch_enter_lazy_cpu_mode()     do {} while (0)
+#define arch_leave_lazy_cpu_mode()     do {} while (0)
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
index 5e657eb8946c953bc0b58846344653cc9d1eaa9c..449f3f272e070753c25877e5b23445ffbd75ac4f 100644 (file)
@@ -127,6 +127,7 @@ extern int acpi_irq_balance_set(char *str);
 #define acpi_ioapic 0
 static inline void acpi_noirq_set(void) { }
 static inline void acpi_disable_pci(void) { }
+static inline void disable_acpi(void) { }
 
 #endif /* !CONFIG_ACPI */
 
index 41a44319905fa884d58f53384d00376c60d51fb8..cc6b1652249aed9ed4251166b1b9c47a8cd27338 100644 (file)
@@ -43,6 +43,8 @@ extern void generic_apic_probe(void);
 #define apic_write native_apic_write
 #define apic_write_atomic native_apic_write_atomic
 #define apic_read native_apic_read
+#define setup_boot_clock setup_boot_APIC_clock
+#define setup_secondary_clock setup_secondary_APIC_clock
 #endif
 
 static __inline fastcall void native_apic_write(unsigned long reg,
@@ -93,9 +95,7 @@ static inline void ack_APIC_irq(void)
        apic_write_around(APIC_EOI, 0);
 }
 
-extern void (*wait_timer_tick)(void);
-
-extern int get_maxlvt(void);
+extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC (void);
 extern void disconnect_bsp_APIC (int virt_wire_setup);
@@ -111,14 +111,9 @@ extern void smp_local_timer_interrupt (void);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
-extern void disable_APIC_timer(void);
-extern void enable_APIC_timer(void);
 
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-void smp_send_timer_broadcast_ipi(void);
-void switch_APIC_timer_to_ipi(void *cpumask);
-void switch_ipi_to_APIC_timer(void *cpumask);
 #define ARCH_APICTIMER_STOPS_ON_C3     1
 
 extern int timer_over_8254;
index 38f1aebbbdb5f5587df51976e13fd1f352fd36eb..c90c7c499302059524699649bf3d428d44bca408 100644 (file)
@@ -160,7 +160,7 @@ static void __init check_config(void)
  * If we configured ourselves for a TSC, we'd better have one!
  */
 #ifdef CONFIG_X86_TSC
-       if (!cpu_has_tsc)
+       if (!cpu_has_tsc && !tsc_disable)
                panic("Kernel compiled for Pentium+, requires TSC feature!");
 #endif
 
index f398cc456448187bff38c53ad81a314d2d063212..050831f34f71ce8f2001872c41b982c61262043e 100644 (file)
@@ -22,7 +22,7 @@ struct Xgt_desc_struct {
 
 extern struct Xgt_desc_struct idt_descr;
 DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-
+extern struct Xgt_desc_struct early_gdt_descr;
 
 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
 {
index 369035dfe4b6516c8b8b965729fc092500c41a65..8d33c9bb7c1c208681421a322ba37899f54098f4 100644 (file)
@@ -90,8 +90,8 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
        pr_reg[6] = regs->eax;                          \
        pr_reg[7] = regs->xds;                          \
        pr_reg[8] = regs->xes;                          \
-       savesegment(fs,pr_reg[9]);                      \
-       pr_reg[10] = regs->xgs;                         \
+       pr_reg[9] = regs->xfs;                          \
+       savesegment(gs,pr_reg[10]);                     \
        pr_reg[11] = regs->orig_eax;                    \
        pr_reg[12] = regs->eip;                         \
        pr_reg[13] = regs->xcs;                         \
index e47be9a56cc23aa8455e842af5eca1b8e4c58ff4..fc03cf9de5c48fa77238af44ca8feeb78541ba95 100644 (file)
 #define HPET_MIN_PERIOD (100000UL)
 #define HPET_TICK_RATE  (HZ * 100000UL)
 
-extern unsigned long hpet_tick;        /* hpet clks count per tick */
 extern unsigned long hpet_address;     /* hpet memory map physical address */
-extern int hpet_use_timer;
+extern int is_hpet_enabled(void);
 
+#ifdef CONFIG_X86_64
+extern unsigned long hpet_tick;        /* hpet clks count per tick */
+extern int hpet_use_timer;
 extern int hpet_rtc_timer_init(void);
 extern int hpet_enable(void);
-extern int hpet_reenable(void);
-extern int is_hpet_enabled(void);
 extern int is_hpet_capable(void);
 extern int hpet_readl(unsigned long a);
+#else
+extern int hpet_enable(void);
+#endif
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
@@ -110,5 +113,10 @@ extern int hpet_rtc_dropped_irq(void);
 extern int hpet_rtc_timer_init(void);
 extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif /* CONFIG_HPET_EMULATE_RTC */
+
+#else
+
+static inline int hpet_enable(void) { return 0; }
+
 #endif /* CONFIG_HPET_TIMER */
 #endif /* _I386_HPET_H */
index 015d8df076908038658aebce6f34d84581642793..6cb0dd4dcddef8c1e89791fe78c64aa8185befad 100644 (file)
@@ -1,6 +1,21 @@
 #ifndef __ASM_I8253_H__
 #define __ASM_I8253_H__
 
+#include <linux/clockchips.h>
+
 extern spinlock_t i8253_lock;
 
+extern struct clock_event_device *global_clock_event;
+
+/**
+ * pit_interrupt_hook - hook into timer tick
+ * @regs:      standard registers from interrupt
+ *
+ * Call the global clock event handler.
+ **/
+static inline void pit_interrupt_hook(void)
+{
+       global_clock_event->event_handler(global_clock_event);
+}
+
 #endif /* __ASM_I8253_H__ */
diff --git a/include/asm-i386/idle.h b/include/asm-i386/idle.h
new file mode 100644 (file)
index 0000000..87ab939
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_I386_IDLE_H
+#define _ASM_I386_IDLE_H 1
+
+#define IDLE_START 1
+#define IDLE_END 2
+
+struct notifier_block;
+void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
+
+void exit_idle(void);
+void enter_idle(void);
+
+#endif
index 7d606e3364aec30d667c9b21c6c5368671c40ca0..56e5689863aece4257d00395b66d6fa8ae8a489e 100644 (file)
@@ -1,86 +1,16 @@
 /* defines for inline arch setup functions */
+#include <linux/clockchips.h>
 
-#include <asm/apic.h>
 #include <asm/i8259.h>
+#include <asm/i8253.h>
 
 /**
  * do_timer_interrupt_hook - hook into timer tick
- * @regs:      standard registers from interrupt
  *
- * Description:
- *     This hook is called immediately after the timer interrupt is ack'd.
- *     It's primary purpose is to allow architectures that don't possess
- *     individual per CPU clocks (like the CPU APICs supply) to broadcast the
- *     timer interrupt as a means of triggering reschedules etc.
+ * Call the pit clock event handler. see asm/i8253.h
  **/
 
 static inline void do_timer_interrupt_hook(void)
 {
-       do_timer(1);
-#ifndef CONFIG_SMP
-       update_process_times(user_mode_vm(get_irq_regs()));
-#endif
-/*
- * In the SMP case we use the local APIC timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifndef CONFIG_X86_LOCAL_APIC
-       profile_tick(CPU_PROFILING);
-#else
-       if (!using_apic_timer)
-               smp_local_timer_interrupt();
-#endif
-}
-
-
-/* you can safely undefine this if you don't have the Neptune chipset */
-
-#define BUGGY_NEPTUN_TIMER
-
-/**
- * do_timer_overflow - process a detected timer overflow condition
- * @count:     hardware timer interrupt count on overflow
- *
- * Description:
- *     This call is invoked when the jiffies count has not incremented but
- *     the hardware timer interrupt has.  It means that a timer tick interrupt
- *     came along while the previous one was pending, thus a tick was missed
- **/
-static inline int do_timer_overflow(int count)
-{
-       int i;
-
-       spin_lock(&i8259A_lock);
-       /*
-        * This is tricky when I/O APICs are used;
-        * see do_timer_interrupt().
-        */
-       i = inb(0x20);
-       spin_unlock(&i8259A_lock);
-       
-       /* assumption about timer being IRQ0 */
-       if (i & 0x01) {
-               /*
-                * We cannot detect lost timer interrupts ... 
-                * well, that's why we call them lost, don't we? :)
-                * [hmm, on the Pentium and Alpha we can ... sort of]
-                */
-               count -= LATCH;
-       } else {
-#ifdef BUGGY_NEPTUN_TIMER
-               /*
-                * for the Neptun bug we know that the 'latch'
-                * command doesn't latch the high and low value
-                * of the counter atomically. Thus we have to 
-                * substract 256 from the counter 
-                * ... funny, isnt it? :)
-                */
-               
-               count -= 256;
-#else
-               printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-#endif
-       }
-       return count;
+       pit_interrupt_hook();
 }
index 04e69c104a74616fa18b3e926a31682a520b9cf2..60f9dcc15d5427c64ca4a0edd7d4a3adab6ddee8 100644 (file)
@@ -1,25 +1,18 @@
 /* defines for inline arch setup functions */
+#include <linux/clockchips.h>
+
 #include <asm/voyager.h>
+#include <asm/i8253.h>
 
+/**
+ * do_timer_interrupt_hook - hook into timer tick
+ * @regs:     standard registers from interrupt
+ *
+ * Call the pit clock event handler. see asm/i8253.h
+ **/
 static inline void do_timer_interrupt_hook(void)
 {
-       do_timer(1);
-#ifndef CONFIG_SMP
-       update_process_times(user_mode_vm(irq_regs));
-#endif
-
+       pit_interrupt_hook();
        voyager_timer_interrupt();
 }
 
-static inline int do_timer_overflow(int count)
-{
-       /* can't read the ISR, just assume 1 tick
-          overflow */
-       if(count > LATCH || count < 0) {
-               printk(KERN_ERR "VOYAGER PROBLEM: count is %d, latch is %d\n", count, LATCH);
-               count = LATCH;
-       }
-       count -= LATCH;
-
-       return count;
-}
index 7cc1a973bf00f283c1324f65938a7d9505a78319..b0a02ee34ffd74720747c295077720e86604933c 100644 (file)
@@ -3,3 +3,5 @@ extern void mcheck_init(struct cpuinfo_x86 *c);
 #else
 #define mcheck_init(c) do {} while(0)
 #endif
+
+extern int mce_disabled;
index 68ff102d6f5e9e19a92641ce43e40caff64a3e92..e6aa30f8de5b6d47666894711d39492b2774eaed 100644 (file)
@@ -63,7 +63,7 @@ static inline void switch_mm(struct mm_struct *prev,
 }
 
 #define deactivate_mm(tsk, mm)                 \
-       asm("movl %0,%%fs": :"r" (0));
+       asm("movl %0,%%gs": :"r" (0));
 
 #define activate_mm(prev, next) \
        switch_mm((prev),(next),NULL)
index 770bf6da8c3dd019aca47ca2251195db8e057564..f21349399d142e7c7368ddfb803ec2ad758a0714 100644 (file)
@@ -23,7 +23,6 @@ extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
 extern int mpc_default_type;
 extern unsigned long mp_lapic_addr;
 extern int pic_mode;
-extern int using_apic_timer;
 
 #ifdef CONFIG_ACPI
 extern void mp_register_lapic (u8 id, u8 enabled);
index 609a3899475c5546c1886e0af21e37ab36596f08..6db40d0583f1083e4b4c2c684e1637abdc9126a2 100644 (file)
@@ -307,4 +307,7 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
 #define MSR_CORE_PERF_GLOBAL_CTRL      0x38f
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x390
 
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0         0x1900
+
 #endif /* __ASM_MSR_H */
index 9f06265065f4ae564e508aa7851091bd81630f1c..6317e0a4d73565f9a61dcf0cba131782cc8ce3ba 100644 (file)
@@ -59,90 +59,102 @@ struct paravirt_ops
           convention.  This makes it easier to implement inline
           assembler replacements. */
 
-       void (fastcall *cpuid)(unsigned int *eax, unsigned int *ebx,
+       void (*cpuid)(unsigned int *eax, unsigned int *ebx,
                      unsigned int *ecx, unsigned int *edx);
 
-       unsigned long (fastcall *get_debugreg)(int regno);
-       void (fastcall *set_debugreg)(int regno, unsigned long value);
+       unsigned long (*get_debugreg)(int regno);
+       void (*set_debugreg)(int regno, unsigned long value);
 
-       void (fastcall *clts)(void);
+       void (*clts)(void);
 
-       unsigned long (fastcall *read_cr0)(void);
-       void (fastcall *write_cr0)(unsigned long);
+       unsigned long (*read_cr0)(void);
+       void (*write_cr0)(unsigned long);
 
-       unsigned long (fastcall *read_cr2)(void);
-       void (fastcall *write_cr2)(unsigned long);
+       unsigned long (*read_cr2)(void);
+       void (*write_cr2)(unsigned long);
 
-       unsigned long (fastcall *read_cr3)(void);
-       void (fastcall *write_cr3)(unsigned long);
+       unsigned long (*read_cr3)(void);
+       void (*write_cr3)(unsigned long);
 
-       unsigned long (fastcall *read_cr4_safe)(void);
-       unsigned long (fastcall *read_cr4)(void);
-       void (fastcall *write_cr4)(unsigned long);
+       unsigned long (*read_cr4_safe)(void);
+       unsigned long (*read_cr4)(void);
+       void (*write_cr4)(unsigned long);
 
-       unsigned long (fastcall *save_fl)(void);
-       void (fastcall *restore_fl)(unsigned long);
-       void (fastcall *irq_disable)(void);
-       void (fastcall *irq_enable)(void);
-       void (fastcall *safe_halt)(void);
-       void (fastcall *halt)(void);
-       void (fastcall *wbinvd)(void);
+       unsigned long (*save_fl)(void);
+       void (*restore_fl)(unsigned long);
+       void (*irq_disable)(void);
+       void (*irq_enable)(void);
+       void (*safe_halt)(void);
+       void (*halt)(void);
+       void (*wbinvd)(void);
 
        /* err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
-       u64 (fastcall *read_msr)(unsigned int msr, int *err);
-       int (fastcall *write_msr)(unsigned int msr, u64 val);
-
-       u64 (fastcall *read_tsc)(void);
-       u64 (fastcall *read_pmc)(void);
-
-       void (fastcall *load_tr_desc)(void);
-       void (fastcall *load_gdt)(const struct Xgt_desc_struct *);
-       void (fastcall *load_idt)(const struct Xgt_desc_struct *);
-       void (fastcall *store_gdt)(struct Xgt_desc_struct *);
-       void (fastcall *store_idt)(struct Xgt_desc_struct *);
-       void (fastcall *set_ldt)(const void *desc, unsigned entries);
-       unsigned long (fastcall *store_tr)(void);
-       void (fastcall *load_tls)(struct thread_struct *t, unsigned int cpu);
-       void (fastcall *write_ldt_entry)(void *dt, int entrynum,
+       u64 (*read_msr)(unsigned int msr, int *err);
+       int (*write_msr)(unsigned int msr, u64 val);
+
+       u64 (*read_tsc)(void);
+       u64 (*read_pmc)(void);
+
+       void (*load_tr_desc)(void);
+       void (*load_gdt)(const struct Xgt_desc_struct *);
+       void (*load_idt)(const struct Xgt_desc_struct *);
+       void (*store_gdt)(struct Xgt_desc_struct *);
+       void (*store_idt)(struct Xgt_desc_struct *);
+       void (*set_ldt)(const void *desc, unsigned entries);
+       unsigned long (*store_tr)(void);
+       void (*load_tls)(struct thread_struct *t, unsigned int cpu);
+       void (*write_ldt_entry)(void *dt, int entrynum,
                                         u32 low, u32 high);
-       void (fastcall *write_gdt_entry)(void *dt, int entrynum,
+       void (*write_gdt_entry)(void *dt, int entrynum,
                                         u32 low, u32 high);
-       void (fastcall *write_idt_entry)(void *dt, int entrynum,
+       void (*write_idt_entry)(void *dt, int entrynum,
                                         u32 low, u32 high);
-       void (fastcall *load_esp0)(struct tss_struct *tss,
+       void (*load_esp0)(struct tss_struct *tss,
                                   struct thread_struct *thread);
 
-       void (fastcall *set_iopl_mask)(unsigned mask);
+       void (*set_iopl_mask)(unsigned mask);
 
-       void (fastcall *io_delay)(void);
+       void (*io_delay)(void);
        void (*const_udelay)(unsigned long loops);
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       void (fastcall *apic_write)(unsigned long reg, unsigned long v);
-       void (fastcall *apic_write_atomic)(unsigned long reg, unsigned long v);
-       unsigned long (fastcall *apic_read)(unsigned long reg);
+       void (*apic_write)(unsigned long reg, unsigned long v);
+       void (*apic_write_atomic)(unsigned long reg, unsigned long v);
+       unsigned long (*apic_read)(unsigned long reg);
+       void (*setup_boot_clock)(void);
+       void (*setup_secondary_clock)(void);
 #endif
 
-       void (fastcall *flush_tlb_user)(void);
-       void (fastcall *flush_tlb_kernel)(void);
-       void (fastcall *flush_tlb_single)(u32 addr);
-
-       void (fastcall *set_pte)(pte_t *ptep, pte_t pteval);
-       void (fastcall *set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
-       void (fastcall *set_pmd)(pmd_t *pmdp, pmd_t pmdval);
-       void (fastcall *pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
-       void (fastcall *pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+       void (*flush_tlb_user)(void);
+       void (*flush_tlb_kernel)(void);
+       void (*flush_tlb_single)(u32 addr);
+
+       void (*alloc_pt)(u32 pfn);
+       void (*alloc_pd)(u32 pfn);
+       void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
+       void (*release_pt)(u32 pfn);
+       void (*release_pd)(u32 pfn);
+
+       void (*set_pte)(pte_t *ptep, pte_t pteval);
+       void (*set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
+       void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+       void (*pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+       void (*pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
 #ifdef CONFIG_X86_PAE
-       void (fastcall *set_pte_atomic)(pte_t *ptep, pte_t pteval);
-       void (fastcall *set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
-       void (fastcall *set_pud)(pud_t *pudp, pud_t pudval);
-       void (fastcall *pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-       void (fastcall *pmd_clear)(pmd_t *pmdp);
+       void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
+       void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
+       void (*set_pud)(pud_t *pudp, pud_t pudval);
+       void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+       void (*pmd_clear)(pmd_t *pmdp);
 #endif
 
+       void (*set_lazy_mode)(int mode);
+
        /* These two are jmp to, not actually called. */
-       void (fastcall *irq_enable_sysexit)(void);
-       void (fastcall *iret)(void);
+       void (*irq_enable_sysexit)(void);
+       void (*iret)(void);
+
+       void (*startup_ipi_hook)(int phys_apicid, unsigned long start_eip, unsigned long start_esp);
 };
 
 /* Mark a paravirt probe function. */
@@ -313,13 +325,38 @@ static inline unsigned long apic_read(unsigned long reg)
 {
        return paravirt_ops.apic_read(reg);
 }
+
+static inline void setup_boot_clock(void)
+{
+       paravirt_ops.setup_boot_clock();
+}
+
+static inline void setup_secondary_clock(void)
+{
+       paravirt_ops.setup_secondary_clock();
+}
 #endif
 
+#ifdef CONFIG_SMP
+static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
+                                   unsigned long start_esp)
+{
+       return paravirt_ops.startup_ipi_hook(phys_apicid, start_eip, start_esp);
+}
+#endif
 
 #define __flush_tlb() paravirt_ops.flush_tlb_user()
 #define __flush_tlb_global() paravirt_ops.flush_tlb_kernel()
 #define __flush_tlb_single(addr) paravirt_ops.flush_tlb_single(addr)
 
+#define paravirt_alloc_pt(pfn) paravirt_ops.alloc_pt(pfn)
+#define paravirt_release_pt(pfn) paravirt_ops.release_pt(pfn)
+
+#define paravirt_alloc_pd(pfn) paravirt_ops.alloc_pd(pfn)
+#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) \
+       paravirt_ops.alloc_pd_clone(pfn, clonepfn, start, count)
+#define paravirt_release_pd(pfn) paravirt_ops.release_pd(pfn)
+
 static inline void set_pte(pte_t *ptep, pte_t pteval)
 {
        paravirt_ops.set_pte(ptep, pteval);
@@ -372,6 +409,19 @@ static inline void pmd_clear(pmd_t *pmdp)
 }
 #endif
 
+/* Lazy mode for batching updates / context switch */
+#define PARAVIRT_LAZY_NONE 0
+#define PARAVIRT_LAZY_MMU  1
+#define PARAVIRT_LAZY_CPU  2
+
+#define  __HAVE_ARCH_ENTER_LAZY_CPU_MODE
+#define arch_enter_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_CPU)
+#define arch_leave_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
+
+#define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+#define arch_enter_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_MMU)
+#define arch_leave_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
+
 /* These all sit in the .parainstructions section to tell us what to patch. */
 struct paravirt_patch {
        u8 *instr;              /* original instructions */
index 2ba2736aa109833ef0cc4ae4819cbb4065ccbe95..b12d59a318b7cc46d581e347713e1964a4503ba7 100644 (file)
@@ -39,19 +39,19 @@ extern struct i386_pda _proxy_pda;
                if (0) { T__ tmp__; tmp__ = (val); }                    \
                switch (sizeof(_proxy_pda.field)) {                     \
                case 1:                                                 \
-                       asm(op "b %1,%%gs:%c2"                          \
+                       asm(op "b %1,%%fs:%c2"                          \
                            : "+m" (_proxy_pda.field)                   \
                            :"ri" ((T__)val),                           \
                             "i"(pda_offset(field)));                   \
                        break;                                          \
                case 2:                                                 \
-                       asm(op "w %1,%%gs:%c2"                          \
+                       asm(op "w %1,%%fs:%c2"                          \
                            : "+m" (_proxy_pda.field)                   \
                            :"ri" ((T__)val),                           \
                             "i"(pda_offset(field)));                   \
                        break;                                          \
                case 4:                                                 \
-                       asm(op "l %1,%%gs:%c2"                          \
+                       asm(op "l %1,%%fs:%c2"                          \
                            : "+m" (_proxy_pda.field)                   \
                            :"ri" ((T__)val),                           \
                             "i"(pda_offset(field)));                   \
@@ -65,19 +65,19 @@ extern struct i386_pda _proxy_pda;
                typeof(_proxy_pda.field) ret__;                         \
                switch (sizeof(_proxy_pda.field)) {                     \
                case 1:                                                 \
-                       asm(op "b %%gs:%c1,%0"                          \
+                       asm(op "b %%fs:%c1,%0"                          \
                            : "=r" (ret__)                              \
                            : "i" (pda_offset(field)),                  \
                              "m" (_proxy_pda.field));                  \
                        break;                                          \
                case 2:                                                 \
-                       asm(op "w %%gs:%c1,%0"                          \
+                       asm(op "w %%fs:%c1,%0"                          \
                            : "=r" (ret__)                              \
                            : "i" (pda_offset(field)),                  \
                              "m" (_proxy_pda.field));                  \
                        break;                                          \
                case 4:                                                 \
-                       asm(op "l %%gs:%c1,%0"                          \
+                       asm(op "l %%fs:%c1,%0"                          \
                            : "=r" (ret__)                              \
                            : "i" (pda_offset(field)),                  \
                              "m" (_proxy_pda.field));                  \
index 4b1e61359f89923428a5bb2368374c8d7b44ceb8..c8dc2d0141a71f5bdd1e3bfa7e19bfc9e868e917 100644 (file)
@@ -5,13 +5,31 @@
 #include <linux/threads.h>
 #include <linux/mm.h>          /* for struct page */
 
-#define pmd_populate_kernel(mm, pmd, pte) \
-               set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define paravirt_alloc_pt(pfn) do { } while (0)
+#define paravirt_alloc_pd(pfn) do { } while (0)
+#define paravirt_alloc_pd(pfn) do { } while (0)
+#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+#define paravirt_release_pt(pfn) do { } while (0)
+#define paravirt_release_pd(pfn) do { } while (0)
+#endif
+
+#define pmd_populate_kernel(mm, pmd, pte)                      \
+do {                                                           \
+       paravirt_alloc_pt(__pa(pte) >> PAGE_SHIFT);             \
+       set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));           \
+} while (0)
 
 #define pmd_populate(mm, pmd, pte)                             \
+do {                                                           \
+       paravirt_alloc_pt(page_to_pfn(pte));                    \
        set_pmd(pmd, __pmd(_PAGE_TABLE +                        \
                ((unsigned long long)page_to_pfn(pte) <<        \
-                       (unsigned long long) PAGE_SHIFT)))
+                       (unsigned long long) PAGE_SHIFT)));     \
+} while (0)
+
 /*
  * Allocate and free page tables.
  */
@@ -32,7 +50,11 @@ static inline void pte_free(struct page *pte)
 }
 
 
-#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
+#define __pte_free_tlb(tlb,pte)                                        \
+do {                                                                   \
+       paravirt_release_pt(page_to_pfn(pte));                          \
+       tlb_remove_page((tlb),(pte));                                   \
+} while (0)
 
 #ifdef CONFIG_X86_PAE
 /*
index 359f10b54f59ba7c99297dac910b73e4c0406796..edfbe46a5e13c8042a1b589ee23f2f2c45918a73 100644 (file)
@@ -257,6 +257,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
                : :"a" (eax), "c" (ecx));
 }
 
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+       /* "mwait %eax,%ecx;" */
+       asm volatile(
+               "sti; .byte 0x0f,0x01,0xc9;"
+               : :"a" (eax), "c" (ecx));
+}
+
 extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
 
 /* from system description table in BIOS.  Mostly for MCA use, but
@@ -424,7 +432,7 @@ struct thread_struct {
        .vm86_info = NULL,                                              \
        .sysenter_cs = __KERNEL_CS,                                     \
        .io_bitmap_ptr = NULL,                                          \
-       .gs = __KERNEL_PDA,                                             \
+       .fs = __KERNEL_PDA,                                             \
 }
 
 /*
@@ -442,8 +450,8 @@ struct thread_struct {
 }
 
 #define start_thread(regs, new_eip, new_esp) do {              \
-       __asm__("movl %0,%%fs": :"r" (0));                      \
-       regs->xgs = 0;                                          \
+       __asm__("movl %0,%%gs": :"r" (0));                      \
+       regs->xfs = 0;                                          \
        set_fs(USER_DS);                                        \
        regs->xds = __USER_DS;                                  \
        regs->xes = __USER_DS;                                  \
index bdbc894339b470b55fa6ed7848602bd8e5f4a071..6002597b9e12212b8e0986f9b7070d2d0b5ba041 100644 (file)
@@ -16,8 +16,8 @@ struct pt_regs {
        long eax;
        int  xds;
        int  xes;
-       /* int  xfs; */
-       int  xgs;
+       int  xfs;
+       /* int  xgs; */
        long orig_eax;
        long eip;
        int  xcs;
@@ -49,6 +49,10 @@ static inline int user_mode_vm(struct pt_regs *regs)
 {
        return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
 }
+static inline int v8086_mode(struct pt_regs *regs)
+{
+       return (regs->eflags & VM_MASK);
+}
 
 #define instruction_pointer(regs) ((regs)->eip)
 #define regs_return_value(regs) ((regs)->eax)
index 3c796af337762629038d39bc4ecc2031c7fff2a6..065f10bfa487c5a1938a5b0785b553e5586c0d3d 100644 (file)
  * The GDT has 32 entries
  */
 #define GDT_ENTRIES 32
-
 #define GDT_SIZE (GDT_ENTRIES * 8)
 
-/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
-#define SEGMENT_IS_FLAT_CODE(x)  (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
-/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
-#define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
-
 /* Simple and small GDT entries for booting only */
 
 #define GDT_ENTRY_BOOT_CS              2
 #ifndef CONFIG_PARAVIRT
 #define get_kernel_rpl()  0
 #endif
+/*
+ * Matching rules for certain types of segments.
+ */
+
+/* Matches only __KERNEL_CS, ignoring PnP / USER / APM segments */
+#define SEGMENT_IS_KERNEL_CODE(x) (((x) & 0xfc) == GDT_ENTRY_KERNEL_CS * 8)
+
+/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
+#define SEGMENT_IS_FLAT_CODE(x)  (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
+
+/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
+#define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
+
 #endif
index 76316275d6f9ac370ea445509e75eeced198803f..0e8077cbfdac7da388789be548d599c0839b8fbf 100644 (file)
@@ -77,6 +77,8 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
 void __init add_memory_region(unsigned long long start,
                              unsigned long long size, int type);
 
+extern unsigned long init_pg_tables_end;
+
 #endif /* __ASSEMBLY__ */
 
 #endif  /*  __KERNEL__  */
index 64fe624c02caa5ed80838428a5366aa385924888..6bf0033a301cee618101682b53e0677d7ce36ac0 100644 (file)
@@ -52,6 +52,11 @@ extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
 #endif
 
+#ifndef CONFIG_PARAVIRT
+#define startup_ipi_hook(phys_apicid, start_eip, start_esp)            \
+do { } while (0)
+#endif
+
 /*
  * This function is needed by all SMP systems. It must _always_ be valid
  * from the initial startup. We map APIC_BASE very early in page_setup(),
index ea8065af825a998654e23a92ffc18e60f34885ec..571b4294dc2e84d4029120fd05853a5fa62153ac 100644 (file)
@@ -30,6 +30,7 @@ static inline int native_set_wallclock(unsigned long nowtime)
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
+extern unsigned long long native_sched_clock(void);
 #else /* !CONFIG_PARAVIRT */
 
 #define get_wallclock() native_get_wallclock()
index d0ebd05f85169e5711a666d309522077a26986ea..4752c3a6a7089580eaf6b18333f26eadc94e18c8 100644 (file)
@@ -8,6 +8,9 @@ void setup_pit_timer(void);
 /* Modifiers for buggy PIT handling */
 extern int pit_latch_buggy;
 extern int timer_ack;
+extern int no_timer_check;
+extern unsigned long long (*custom_sched_clock)(void);
+extern int no_sync_cmos_clock;
 extern int recalibrate_cpu_khz(void);
 
 #endif
index c13933185c1cc20f1a0b0cfbc01d67f92bee26dc..e997891cc7cc8bfdedf6b9447996e291e5b0a9b1 100644 (file)
@@ -1,48 +1 @@
-/*
- * linux/include/asm-i386/tsc.h
- *
- * i386 TSC related functions
- */
-#ifndef _ASM_i386_TSC_H
-#define _ASM_i386_TSC_H
-
-#include <asm/processor.h>
-
-/*
- * Standard way to access the cycle counter on i586+ CPUs.
- * Currently only used on SMP.
- *
- * If you really have a SMP machine with i486 chips or older,
- * compile for that, and this will just always return zero.
- * That's ok, it just means that the nicer scheduling heuristics
- * won't work for you.
- *
- * We only use the low 32 bits, and we'd simply better make sure
- * that we reschedule before that wraps. Scheduling at least every
- * four billion cycles just basically sounds like a good idea,
- * regardless of how fast the machine is.
- */
-typedef unsigned long long cycles_t;
-
-extern unsigned int cpu_khz;
-extern unsigned int tsc_khz;
-
-static inline cycles_t get_cycles(void)
-{
-       unsigned long long ret = 0;
-
-#ifndef CONFIG_X86_TSC
-       if (!cpu_has_tsc)
-               return 0;
-#endif
-
-#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
-       rdtscll(ret);
-#endif
-       return ret;
-}
-
-extern void tsc_init(void);
-extern void mark_tsc_unstable(void);
-
-#endif
+#include <asm-x86_64/tsc.h>
diff --git a/include/asm-i386/vmi.h b/include/asm-i386/vmi.h
new file mode 100644 (file)
index 0000000..43c8933
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * VMI interface definition
+ *
+ * Copyright (C) 2005, VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Maintained by: Zachary Amsden zach@vmware.com
+ *
+ */
+#include <linux/types.h>
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  VMI Option ROM API
+ *
+ *---------------------------------------------------------------------
+ */
+#define VMI_SIGNATURE 0x696d5663   /* "cVmi" */
+
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
+
+/*
+ * We use two version numbers for compatibility, with the major
+ * number signifying interface breakages, and the minor number
+ * interface extensions.
+ */
+#define VMI_API_REV_MAJOR       3
+#define VMI_API_REV_MINOR       0
+
+#define VMI_CALL_CPUID                 0
+#define VMI_CALL_WRMSR                 1
+#define VMI_CALL_RDMSR                 2
+#define VMI_CALL_SetGDT                        3
+#define VMI_CALL_SetLDT                        4
+#define VMI_CALL_SetIDT                        5
+#define VMI_CALL_SetTR                 6
+#define VMI_CALL_GetGDT                        7
+#define VMI_CALL_GetLDT                        8
+#define VMI_CALL_GetIDT                        9
+#define VMI_CALL_GetTR                 10
+#define VMI_CALL_WriteGDTEntry         11
+#define VMI_CALL_WriteLDTEntry         12
+#define VMI_CALL_WriteIDTEntry         13
+#define VMI_CALL_UpdateKernelStack     14
+#define VMI_CALL_SetCR0                        15
+#define VMI_CALL_SetCR2                        16
+#define VMI_CALL_SetCR3                        17
+#define VMI_CALL_SetCR4                        18
+#define VMI_CALL_GetCR0                        19
+#define VMI_CALL_GetCR2                        20
+#define VMI_CALL_GetCR3                        21
+#define VMI_CALL_GetCR4                        22
+#define VMI_CALL_WBINVD                        23
+#define VMI_CALL_SetDR                 24
+#define VMI_CALL_GetDR                 25
+#define VMI_CALL_RDPMC                 26
+#define VMI_CALL_RDTSC                 27
+#define VMI_CALL_CLTS                  28
+#define VMI_CALL_EnableInterrupts      29
+#define VMI_CALL_DisableInterrupts     30
+#define VMI_CALL_GetInterruptMask      31
+#define VMI_CALL_SetInterruptMask      32
+#define VMI_CALL_IRET                  33
+#define VMI_CALL_SYSEXIT               34
+#define VMI_CALL_Halt                  35
+#define VMI_CALL_Reboot                        36
+#define VMI_CALL_Shutdown              37
+#define VMI_CALL_SetPxE                        38
+#define VMI_CALL_SetPxELong            39
+#define VMI_CALL_UpdatePxE             40
+#define VMI_CALL_UpdatePxELong         41
+#define VMI_CALL_MachineToPhysical     42
+#define VMI_CALL_PhysicalToMachine     43
+#define VMI_CALL_AllocatePage          44
+#define VMI_CALL_ReleasePage           45
+#define VMI_CALL_InvalPage             46
+#define VMI_CALL_FlushTLB              47
+#define VMI_CALL_SetLinearMapping      48
+
+#define VMI_CALL_SetIOPLMask           61
+#define VMI_CALL_SetInitialAPState     62
+#define VMI_CALL_APICWrite             63
+#define VMI_CALL_APICRead              64
+#define VMI_CALL_SetLazyMode           73
+
+/*
+ *---------------------------------------------------------------------
+ *
+ * MMU operation flags
+ *
+ *---------------------------------------------------------------------
+ */
+
+/* Flags used by VMI_{Allocate|Release}Page call */
+#define VMI_PAGE_PAE             0x10  /* Allocate PAE shadow */
+#define VMI_PAGE_CLONE           0x20  /* Clone from another shadow */
+#define VMI_PAGE_ZEROED          0x40  /* Page is pre-zeroed */
+
+
+/* Flags shared by Allocate|Release Page and PTE updates */
+#define VMI_PAGE_PT              0x01
+#define VMI_PAGE_PD              0x02
+#define VMI_PAGE_PDP             0x04
+#define VMI_PAGE_PML4            0x08
+
+#define VMI_PAGE_NORMAL          0x00 /* for debugging */
+
+/* Flags used by PTE updates */
+#define VMI_PAGE_CURRENT_AS      0x10 /* implies VMI_PAGE_VA_MASK is valid */
+#define VMI_PAGE_DEFER           0x20 /* may queue update until TLB inval */
+#define VMI_PAGE_VA_MASK         0xfffff000
+
+#ifdef CONFIG_X86_PAE
+#define VMI_PAGE_L1            (VMI_PAGE_PT | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
+#define VMI_PAGE_L2            (VMI_PAGE_PD | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
+#else
+#define VMI_PAGE_L1            (VMI_PAGE_PT | VMI_PAGE_ZEROED)
+#define VMI_PAGE_L2            (VMI_PAGE_PD | VMI_PAGE_ZEROED)
+#endif
+
+/* Flags used by VMI_FlushTLB call */
+#define VMI_FLUSH_TLB            0x01
+#define VMI_FLUSH_GLOBAL         0x02
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  VMI relocation definitions for ROM call get_reloc
+ *
+ *---------------------------------------------------------------------
+ */
+
+/* VMI Relocation types */
+#define VMI_RELOCATION_NONE     0
+#define VMI_RELOCATION_CALL_REL 1
+#define VMI_RELOCATION_JUMP_REL 2
+#define VMI_RELOCATION_NOP     3
+
+#ifndef __ASSEMBLY__
+struct vmi_relocation_info {
+        unsigned char           *eip;
+        unsigned char           type;
+        unsigned char           reserved[3];
+};
+#endif
+
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  Generic ROM structures and definitions
+ *
+ *---------------------------------------------------------------------
+ */
+
+#ifndef __ASSEMBLY__
+
+struct vrom_header {
+       u16     rom_signature;  // option ROM signature
+       u8      rom_length;     // ROM length in 512 byte chunks
+       u8      rom_entry[4];   // 16-bit code entry point
+       u8      rom_pad0;       // 4-byte align pad
+       u32     vrom_signature; // VROM identification signature
+       u8      api_version_min;// Minor version of API
+       u8      api_version_maj;// Major version of API
+       u8      jump_slots;     // Number of jump slots
+       u8      reserved1;      // Reserved for expansion
+       u32     virtual_top;    // Hypervisor virtual address start
+       u16     reserved2;      // Reserved for expansion
+       u16     license_offs;   // Offset to License string
+       u16     pci_header_offs;// Offset to PCI OPROM header
+       u16     pnp_header_offs;// Offset to PnP OPROM header
+       u32     rom_pad3;       // PnP reserverd / VMI reserved
+       u8      reserved[96];   // Reserved for headers
+       char    vmi_init[8];    // VMI_Init jump point
+       char    get_reloc[8];   // VMI_GetRelocationInfo jump point
+} __attribute__((packed));
+
+struct pnp_header {
+        char sig[4];
+        char rev;
+        char size;
+        short next;
+        short res;
+        long devID;
+        unsigned short manufacturer_offset;
+        unsigned short product_offset;
+} __attribute__((packed));
+
+struct pci_header {
+        char sig[4];
+        short vendorID;
+        short deviceID;
+        short vpdData;
+        short size;
+        char rev;
+        char class;
+        char subclass;
+        char interface;
+        short chunks;
+        char rom_version_min;
+        char rom_version_maj;
+        char codetype;
+        char lastRom;
+        short reserved;
+} __attribute__((packed));
+
+/* Function prototypes for bootstrapping */
+extern void vmi_init(void);
+extern void vmi_bringup(void);
+extern void vmi_apply_boot_page_allocations(void);
+
+/* State needed to start an application processor in an SMP system. */
+struct vmi_ap_state {
+       u32 cr0;
+       u32 cr2;
+       u32 cr3;
+       u32 cr4;
+
+       u64 efer;
+
+       u32 eip;
+       u32 eflags;
+       u32 eax;
+       u32 ebx;
+       u32 ecx;
+       u32 edx;
+       u32 esp;
+       u32 ebp;
+       u32 esi;
+       u32 edi;
+       u16 cs;
+       u16 ss;
+       u16 ds;
+       u16 es;
+       u16 fs;
+       u16 gs;
+       u16 ldtr;
+
+       u16 gdtr_limit;
+       u32 gdtr_base;
+       u32 idtr_base;
+       u16 idtr_limit;
+};
+
+#endif
diff --git a/include/asm-i386/vmi_time.h b/include/asm-i386/vmi_time.h
new file mode 100644 (file)
index 0000000..c129312
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * VMI Time wrappers
+ *
+ * Copyright (C) 2006, VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to dhecht@vmware.com
+ *
+ */
+
+#ifndef __VMI_TIME_H
+#define __VMI_TIME_H
+
+/*
+ * Raw VMI call indices for timer functions
+ */
+#define VMI_CALL_GetCycleFrequency     66
+#define VMI_CALL_GetCycleCounter       67
+#define VMI_CALL_SetAlarm              68
+#define VMI_CALL_CancelAlarm           69
+#define VMI_CALL_GetWallclockTime      70
+#define VMI_CALL_WallclockUpdated      71
+
+/* Cached VMI timer operations */
+extern struct vmi_timer_ops {
+       u64 (*get_cycle_frequency)(void);
+       u64 (*get_cycle_counter)(int);
+       u64 (*get_wallclock)(void);
+       int (*wallclock_updated)(void);
+       void (*set_alarm)(u32 flags, u64 expiry, u64 period);
+       void (*cancel_alarm)(u32 flags);
+} vmi_timer_ops;
+
+/* Prototypes */
+extern void __init vmi_time_init(void);
+extern unsigned long vmi_get_wallclock(void);
+extern int vmi_set_wallclock(unsigned long now);
+extern unsigned long long vmi_sched_clock(void);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+extern void __init vmi_timer_setup_boot_alarm(void);
+extern void __init vmi_timer_setup_secondary_alarm(void);
+extern void apic_vmi_timer_interrupt(void);
+#endif
+
+#ifdef CONFIG_NO_IDLE_HZ
+extern int vmi_stop_hz_timer(void);
+extern void vmi_account_time_restart_hz_timer(void);
+#endif
+
+/*
+ * When run under a hypervisor, a vcpu is always in one of three states:
+ * running, halted, or ready.  The vcpu is in the 'running' state if it
+ * is executing.  When the vcpu executes the halt interface, the vcpu
+ * enters the 'halted' state and remains halted until there is some work
+ * pending for the vcpu (e.g. an alarm expires, host I/O completes on
+ * behalf of virtual I/O).  At this point, the vcpu enters the 'ready'
+ * state (waiting for the hypervisor to reschedule it).  Finally, at any
+ * time when the vcpu is not in the 'running' state nor the 'halted'
+ * state, it is in the 'ready' state.
+ *
+ * Real time is advances while the vcpu is 'running', 'ready', or
+ * 'halted'.  Stolen time is the time in which the vcpu is in the
+ * 'ready' state.  Available time is the remaining time -- the vcpu is
+ * either 'running' or 'halted'.
+ *
+ * All three views of time are accessible through the VMI cycle
+ * counters.
+ */
+
+/* The cycle counters. */
+#define VMI_CYCLES_REAL         0
+#define VMI_CYCLES_AVAILABLE    1
+#define VMI_CYCLES_STOLEN       2
+
+/* The alarm interface 'flags' bits */
+#define VMI_ALARM_COUNTERS      2
+
+#define VMI_ALARM_COUNTER_MASK  0x000000ff
+
+#define VMI_ALARM_WIRED_IRQ0    0x00000000
+#define VMI_ALARM_WIRED_LVTT    0x00010000
+
+#define VMI_ALARM_IS_ONESHOT    0x00000000
+#define VMI_ALARM_IS_PERIODIC   0x00000100
+
+#define CONFIG_VMI_ALARM_HZ    100
+
+#endif
index ebd5887f4b1a39102e4070b190ee5b55a5500e56..6299b51575bb3f0814f2448eda09a53b62c81fe9 100644 (file)
@@ -8,9 +8,20 @@
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent     platform_dma_alloc_coherent
-#define dma_alloc_noncoherent  platform_dma_alloc_coherent     /* coherent mem. is cheap */
+/* coherent mem. is cheap */
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+                     gfp_t flag)
+{
+       return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
 #define dma_free_coherent      platform_dma_free_coherent
-#define dma_free_noncoherent   platform_dma_free_coherent
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+                    dma_addr_t dma_handle)
+{
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
 #define dma_map_single         platform_dma_map_single
 #define dma_map_sg             platform_dma_map_sg
 #define dma_unmap_single       platform_dma_unmap_single
index 01c36b0047474c7272a863a5610ad443078c8a20..f2ad469a6ddfac76c6592b535a489eb2cb27e85f 100644 (file)
@@ -23,7 +23,7 @@
 
 extern struct kimage *ia64_kimage;
 DECLARE_PER_CPU(u64, ia64_mca_pal_base);
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned int relocate_new_kernel_size;
 extern void relocate_new_kernel(unsigned long, unsigned long,
                struct ia64_boot_param *, unsigned long);
 static inline void
diff --git a/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h
new file mode 100644 (file)
index 0000000..0e00c9a
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_IA64_LIBATA_PORTMAP_H
+#define __ASM_IA64_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD                0x1F0
+#define ATA_PRIMARY_CTL                0x3F6
+#define ATA_PRIMARY_IRQ(dev)   isa_irq_to_vector(14)
+
+#define ATA_SECONDARY_CMD      0x170
+#define ATA_SECONDARY_CTL      0x376
+#define ATA_SECONDARY_IRQ(dev) isa_irq_to_vector(15)
+
+#endif
index bc768153f3c95a9cb55020888463f245baaea9d0..e43021a99a20b0e523f9125fcb7b2cdc189b6392 100644 (file)
@@ -32,7 +32,7 @@
 #define PAL_CACHE_FLUSH                1       /* flush i/d cache */
 #define PAL_CACHE_INFO         2       /* get detailed i/d cache info */
 #define PAL_CACHE_INIT         3       /* initialize i/d cache */
-#define PAL_CACHE_SUMMARY      4       /* get summary of cache heirarchy */
+#define PAL_CACHE_SUMMARY      4       /* get summary of cache hierarchy */
 #define PAL_MEM_ATTRIB         5       /* list supported memory attributes */
 #define PAL_PTCE_INFO          6       /* purge TLB info */
 #define PAL_VM_INFO            7       /* return supported virtual memory features */
@@ -113,14 +113,14 @@ typedef s64                               pal_status_t;
                                                 */
 #define PAL_STATUS_REQUIRES_MEMORY     (-9)    /* Call requires PAL memory buffer */
 
-/* Processor cache level in the heirarchy */
+/* Processor cache level in the hierarchy */
 typedef u64                            pal_cache_level_t;
 #define PAL_CACHE_LEVEL_L0             0       /* L0 */
 #define PAL_CACHE_LEVEL_L1             1       /* L1 */
 #define PAL_CACHE_LEVEL_L2             2       /* L2 */
 
 
-/* Processor cache type at a particular level in the heirarchy */
+/* Processor cache type at a particular level in the hierarchy */
 
 typedef u64                            pal_cache_type_t;
 #define PAL_CACHE_TYPE_INSTRUCTION     1       /* Instruction cache */
@@ -272,14 +272,14 @@ typedef struct pal_cache_protection_info_s {
 #define PAL_CACHE_PROT_METHOD_ECC              3       /* ECC protection */
 
 
-/* Processor cache line identification in the heirarchy */
+/* Processor cache line identification in the hierarchy */
 typedef union pal_cache_line_id_u {
        u64                     pclid_data;
        struct {
                u64             cache_type      : 8,    /* 7-0 cache type */
                                level           : 8,    /* 15-8 level of the
                                                         * cache in the
-                                                        * heirarchy.
+                                                        * hierarchy.
                                                         */
                                way             : 8,    /* 23-16 way in the set
                                                         */
@@ -292,7 +292,7 @@ typedef union pal_cache_line_id_u {
                u64             cache_type      : 8,    /* 7-0 cache type */
                                level           : 8,    /* 15-8 level of the
                                                         * cache in the
-                                                        * heirarchy.
+                                                        * hierarchy.
                                                         */
                                way             : 8,    /* 23-16 way in the set
                                                         */
@@ -978,7 +978,7 @@ ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
        return iprv.status;
 }
 
-/* Return summary information about the heirarchy of caches controlled by the processor */
+/* Return summary information about the hierarchy of caches controlled by the processor */
 static inline s64
 ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches)
 {
index f038e33e6d48677d0da1d5150dfc0b5f1f8a6931..2ce4b6b7b34887456961fdc9227a184bcec535b8 100644 (file)
@@ -165,7 +165,8 @@ static __inline__ int atomic_dec_return(atomic_t *v)
        return t;
 }
 
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) \
+       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
@@ -413,6 +414,43 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
        return t;
 }
 
+#define atomic64_cmpxchg(v, o, n) \
+       ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+       long t;
+
+       __asm__ __volatile__ (
+       LWSYNC_ON_SMP
+"1:    ldarx   %0,0,%1         # atomic_add_unless\n\
+       cmpd    0,%0,%3 \n\
+       beq-    2f \n\
+       add     %0,%2,%0 \n"
+"      stdcx.  %0,0,%1 \n\
+       bne-    1b \n"
+       ISYNC_ON_SMP
+"      subf    %0,%2,%0 \n\
+2:"
+       : "=&r" (t)
+       : "r" (&v->counter), "r" (a), "r" (u)
+       : "cc", "memory");
+
+       return t != u;
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #endif /* __powerpc64__ */
 
 #include <asm-generic/atomic.h>
index d7a1bc1551c603086c97a2ee1c85f9ad53803172..05af081222f6ba7c0a1ac8f8cf90b4def3cbb487 100644 (file)
@@ -26,8 +26,8 @@ typedef struct {} dcr_host_t;
 
 #define DCR_MAP_OK(host)       (1)
 
-#define dcr_map(dev, dcr_n, dcr_c)     {}
-#define dcr_unmap(host, dcr_n, dcr_c)  {}
+#define dcr_map(dev, dcr_n, dcr_c)     ((dcr_host_t){})
+#define dcr_unmap(host, dcr_n, dcr_c)  do {} while (0)
 #define dcr_read(host, dcr_n)          mfdcr(dcr_n)
 #define dcr_write(host, dcr_n, value)  mtdcr(dcr_n, value)
 
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
new file mode 100644 (file)
index 0000000..cb0f8aa
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _POWERPC_PMI_H
+#define _POWERPC_PMI_H
+
+/*
+ * Definitions for talking with PMI device on PowerPC
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __KERNEL__
+
+#include <asm/of_device.h>
+
+#define PMI_TYPE_FREQ_CHANGE   0x01
+#define PMI_READ_TYPE          0
+#define PMI_READ_DATA0         1
+#define PMI_READ_DATA1         2
+#define PMI_READ_DATA2         3
+#define PMI_WRITE_TYPE         4
+#define PMI_WRITE_DATA0                5
+#define PMI_WRITE_DATA1                6
+#define PMI_WRITE_DATA2                7
+
+#define PMI_ACK                        0x80
+
+#define PMI_TIMEOUT            100
+
+typedef struct {
+       u8      type;
+       u8      data0;
+       u8      data1;
+       u8      data2;
+} pmi_message_t;
+
+struct pmi_handler {
+       struct list_head node;
+       u8 type;
+       void (*handle_pmi_message) (struct of_device *, pmi_message_t);
+};
+
+void pmi_register_handler(struct of_device *, struct pmi_handler *);
+void pmi_unregister_handler(struct of_device *, struct pmi_handler *);
+
+void pmi_send_message(struct of_device *, pmi_message_t);
+
+#endif /* __KERNEL__ */
+#endif /* _POWERPC_PMI_H */
index 0afee17f33b4f5de4e8ad6cc70b171383809cff9..020ed015a94b4fef829b20f20d1db6d58372e279 100644 (file)
@@ -255,6 +255,8 @@ extern void kdump_move_device_tree(void);
 /* CPU OF node matching */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
 
 /*
  * OF interrupt mapping
index e5982ad465763b2052e55f20d20b5b135e284f17..821581a8b643c23e63f55cb517a1cc81a255dfc8 100644 (file)
@@ -355,13 +355,7 @@ extern struct bus_type ps3_system_bus_type;
 
 /* vuart routines */
 
-struct ps3_vuart_stats {
-       unsigned long bytes_written;
-       unsigned long bytes_read;
-       unsigned long tx_interrupts;
-       unsigned long rx_interrupts;
-       unsigned long disconnect_interrupts;
-};
+struct ps3_vuart_port_priv;
 
 /**
  * struct ps3_vuart_port_device - a device on a vuart port
@@ -370,24 +364,17 @@ struct ps3_vuart_stats {
 struct ps3_vuart_port_device {
        enum ps3_match_id match_id;
        struct device core;
+       struct ps3_vuart_port_priv* priv; /* private driver variables */
 
-       /* private driver variables */
-       unsigned int port_number;
-       u64 interrupt_mask;
-       struct {
-               spinlock_t lock;
-               struct list_head head;
-       } tx_list;
-       struct {
-               unsigned long bytes_held;
-               spinlock_t lock;
-               struct list_head head;
-       } rx_list;
-       struct ps3_vuart_stats stats;
 };
 
 int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
 
+/* system manager */
+
+void ps3_sys_manager_restart(void);
+void ps3_sys_manager_power_off(void);
+
 struct ps3_prealloc {
     const char *name;
     void *address;
index 1babad99c719ba908919f97389479b248585fd8e..fdaac9d762bb5d5e101365be102f7e23ac7e032d 100644 (file)
@@ -150,7 +150,7 @@ struct ucc_slow_info {
        int ucc_num;
        enum qe_clock rx_clock;
        enum qe_clock tx_clock;
-       struct ucc_slow *regs;
+       u32 regs;
        int irq;
        u16 uccm_mask;
        int data_mem_part;
@@ -199,9 +199,9 @@ struct ucc_slow_private {
                                   and length for first BD in a frame */
        u32 tx_base_offset;     /* first BD in Tx BD table offset (In MURAM) */
        u32 rx_base_offset;     /* first BD in Rx BD table offset (In MURAM) */
-       u8 *confBd;             /* next BD for confirm after Tx */
-       u8 *tx_bd;              /* next BD for new Tx request */
-       u8 *rx_bd;              /* next BD to collect after Rx */
+       struct qe_bd *confBd;   /* next BD for confirm after Tx */
+       struct qe_bd *tx_bd;    /* next BD for new Tx request */
+       struct qe_bd *rx_bd;    /* next BD to collect after Rx */
        void *p_rx_frame;       /* accumulating receive frame */
        u16 *p_ucce;            /* a pointer to the event register in memory.
                                 */
index c68e1680da0173d5754d1a1df4944120a5239e58..76a8ccf254a50695c2eba48732112ad2fe90bc1e 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += cpu-features.h
diff --git a/include/asm-sh/bigsur/bigsur.h b/include/asm-sh/bigsur/bigsur.h
deleted file mode 100644 (file)
index 427245f..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- * Hitachi Big Sur Eval Board support
- *
- * Dustin McIntire (dustin@sensoria.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Derived from Hitachi SH7751 reference manual
- * 
- */
-
-#ifndef _ASM_BIGSUR_H_
-#define _ASM_BIGSUR_H_
-
-#include <asm/irq.h>
-#include <asm/hd64465/hd64465.h>
-
-/* 7751 Internal IRQ's used by external CPLD controller */
-#define BIGSUR_IRQ_LOW 0
-#define BIGSUR_IRQ_NUM  14         /* External CPLD level 1 IRQs */
-#define BIGSUR_IRQ_HIGH (BIGSUR_IRQ_LOW + BIGSUR_IRQ_NUM)
-#define BIGSUR_2NDLVL_IRQ_LOW   (HD64465_IRQ_BASE+HD64465_IRQ_NUM)  
-#define BIGSUR_2NDLVL_IRQ_NUM   32 /* Level 2 IRQs = 4 regs * 8 bits */
-#define BIGSUR_2NDLVL_IRQ_HIGH  (BIGSUR_2NDLVL_IRQ_LOW + \
-                                 BIGSUR_2NDLVL_IRQ_NUM)
-
-/* PCI interrupt base number (A_INTA-A_INTD) */
-#define BIGSUR_SH7751_PCI_IRQ_BASE  (BIGSUR_2NDLVL_IRQ_LOW+10)  
-
-/* CPLD registers and external chip addresses */
-#define BIGSUR_HD64464_ADDR    0xB2000000
-#define BIGSUR_DGDR    0xB1FFFE00
-#define BIGSUR_BIDR    0xB1FFFD00
-#define BIGSUR_CSLR    0xB1FFFC00
-#define BIGSUR_SW1R    0xB1FFFB00
-#define BIGSUR_DBGR    0xB1FFFA00
-#define BIGSUR_BDTR    0xB1FFF900
-#define BIGSUR_BDRR    0xB1FFF800
-#define BIGSUR_PPR1    0xB1FFF700
-#define BIGSUR_PPR2    0xB1FFF600
-#define BIGSUR_IDE2    0xB1FFF500
-#define BIGSUR_IDE3    0xB1FFF400
-#define BIGSUR_SPCR    0xB1FFF300
-#define BIGSUR_ETHR    0xB1FE0000
-#define BIGSUR_PPDR    0xB1FDFF00
-#define BIGSUR_ICTL    0xB1FDFE00
-#define BIGSUR_ICMD    0xB1FDFD00
-#define BIGSUR_DMA0    0xB1FDFC00
-#define BIGSUR_DMA1    0xB1FDFB00
-#define BIGSUR_IRQ0    0xB1FDFA00
-#define BIGSUR_IRQ1    0xB1FDF900
-#define BIGSUR_IRQ2    0xB1FDF800
-#define BIGSUR_IRQ3    0xB1FDF700
-#define BIGSUR_IMR0    0xB1FDF600
-#define BIGSUR_IMR1    0xB1FDF500
-#define BIGSUR_IMR2    0xB1FDF400
-#define BIGSUR_IMR3    0xB1FDF300
-#define BIGSUR_IRLMR0  0xB1FDF200
-#define BIGSUR_IRLMR1  0xB1FDF100
-#define BIGSUR_V320USC_ADDR  0xB1000000
-#define BIGSUR_HD64465_ADDR  0xB0000000
-#define BIGSUR_INTERNAL_BASE 0xB0000000
-
-/* SMC ethernet card parameters */
-#define BIGSUR_ETHER_IOPORT            0x220
-
-/* IDE register paramters */
-#define BIGSUR_IDECMD_IOPORT   0x1f0
-#define BIGSUR_IDECTL_IOPORT   0x1f8
-
-/* LED bit position in BIGSUR_CSLR */
-#define BIGSUR_LED  (1<<4)
-
-/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
-#define BIGSUR_LSR0_SIZE    (64*(1<<20)) //64MB
-#define BIGSUR_LSR1_SIZE    (64*(1<<20)) //64MB
-
-#endif /* _ASM_BIGSUR_H_ */
diff --git a/include/asm-sh/bigsur/io.h b/include/asm-sh/bigsur/io.h
deleted file mode 100644 (file)
index 1470ac8..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-sh/bigsur/io.h
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from io_hd64465.h, which bore the message:
- * By Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc. 
- * and from io_hd64461.h, which bore the message:
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for a Hitachi Big Sur Evaluation Board.
- */
-
-#ifndef _ASM_SH_IO_BIGSUR_H
-#define _ASM_SH_IO_BIGSUR_H
-
-#include <linux/types.h>
-
-extern unsigned long bigsur_isa_port2addr(unsigned long offset);
-extern int bigsur_irq_demux(int irq);
-/* Provision for generic secondary demux step -- used by PCMCIA code */
-extern void bigsur_register_irq_demux(int irq,
-               int (*demux)(int irq, void *dev), void *dev);
-extern void bigsur_unregister_irq_demux(int irq);
-/* Set this variable to 1 to see port traffic */
-extern int bigsur_io_debug;
-/* Map a range of ports to a range of kernel virtual memory. */
-extern void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift);
-extern void bigsur_port_unmap(u32 baseport, u32 nports);
-
-#endif /* _ASM_SH_IO_BIGSUR_H */
-
diff --git a/include/asm-sh/bigsur/serial.h b/include/asm-sh/bigsur/serial.h
deleted file mode 100644 (file)
index a08fa82..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * include/asm-sh/bigsur/serial.h
- *
- * Configuration details for Big Sur 16550 based serial ports 
- * i.e. HD64465, PCMCIA, etc.
- */
-
-#ifndef _ASM_SERIAL_BIGSUR_H
-#define _ASM_SERIAL_BIGSUR_H
-#include <asm/hd64465.h>
-
-#define BASE_BAUD (3379200 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-
-#define SERIAL_PORT_DFNS                   \
-        /* UART CLK   PORT IRQ     FLAGS        */                      \
-        { 0, BASE_BAUD, 0x3F8, HD64465_IRQ_UART, STD_COM_FLAGS } /* ttyS0 */ 
-
-/* XXX: This should be moved ino irq.h */
-#define irq_cannonicalize(x) (x)
-
-#endif /* _ASM_SERIAL_BIGSUR_H */
index a294997a84127b02e42174dcb670e17629ab1392..5a117ec43c77b165e31b29ac269697136b1f2a05 100644 (file)
@@ -19,9 +19,9 @@ static void __init check_bugs(void)
        extern unsigned long loops_per_jiffy;
        char *p = &init_utsname()->machine[2]; /* "sh" */
 
-       cpu_data->loops_per_jiffy = loops_per_jiffy;
+       current_cpu_data.loops_per_jiffy = loops_per_jiffy;
 
-       switch (cpu_data->type) {
+       switch (current_cpu_data.type) {
        case CPU_SH7604 ... CPU_SH7619:
                *p++ = '2';
                break;
@@ -54,7 +54,7 @@ static void __init check_bugs(void)
                break;
        }
 
-       printk("CPU: %s\n", get_cpu_subtype());
+       printk("CPU: %s\n", get_cpu_subtype(&current_cpu_data));
 
 #ifndef __LITTLE_ENDIAN__
        /* 'eb' means 'Endian Big' */
index 07f62ec9ff0c8b9309d223f0424b0926afb86f4b..22f12634975b7b350cca273601227cf38a6d0fc1 100644 (file)
@@ -30,5 +30,8 @@ extern void __flush_invalidate_region(void *start, int size);
 
 #define HAVE_ARCH_UNMAPPED_AREA
 
+/* Page flag for lazy dcache write-back for the aliasing UP caches */
+#define PG_dcache_dirty        PG_arch_1
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
index f70d8ef76a15f6b3d980bb4e01eb36516b2bae86..6fabbba228de88ed9a64c7c279d955aa282a53bc 100644 (file)
@@ -36,8 +36,6 @@
  /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
 #define CACHE_ALIAS 0x00001000
 
-#define PG_mapped      PG_arch_1
-
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
index b01a10f312259e9f3e8bef29041a4d47c0f29b04..b3746a936a0966a868bd0a55a6be50e5ab7e3dac 100644 (file)
@@ -17,6 +17,7 @@
  *  so we need them.
  */
 void flush_cache_all(void);
+void flush_dcache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
@@ -38,16 +39,4 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 /* Initialization of P3 area for copy_user_page */
 void p3_cache_init(void);
 
-#define PG_mapped      PG_arch_1
-
-#ifdef CONFIG_MMU
-extern int remap_area_pages(unsigned long addr, unsigned long phys_addr,
-                           unsigned long size, unsigned long flags);
-#else /* CONFIG_MMU */
-static inline int remap_area_pages(unsigned long addr, unsigned long phys_addr,
-                                  unsigned long size, unsigned long flags)
-{
-       return 0;
-}
-#endif /* CONFIG_MMU */
 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
index 3e4b3e6d80c02fb81b8e03dd882eb10c11ca99ab..c135e9cebd9c0c9a74f0479c3e16c1cfd09c38e6 100644 (file)
@@ -3,6 +3,17 @@
 
 #define DMAOR_INIT     ( 0x8000 | DMAOR_DME )
 
+/* SH7751/7760/7780 DMA IRQ sources */
+#define DMTE0_IRQ      34
+#define DMTE1_IRQ      35
+#define DMTE2_IRQ      36
+#define DMTE3_IRQ      37
+#define DMTE4_IRQ      44
+#define DMTE5_IRQ      45
+#define DMTE6_IRQ      46
+#define DMTE7_IRQ      47
+#define DMAE_IRQ       38
+
 #ifdef CONFIG_CPU_SH4A
 #define SH_DMAC_BASE   0xfc808020
 
index 8d0867b98e05141ce77d5bb4f3837e3877e0c124..d3bc7818bbbea2e6631f781739266fb740d0bb7e 100644 (file)
@@ -53,6 +53,10 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
        consistent_free(vaddr, size);
 }
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d, h) (1)
+
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                                  enum dma_data_direction dir)
 {
diff --git a/include/asm-sh/ec3104/ec3104.h b/include/asm-sh/ec3104/ec3104.h
deleted file mode 100644 (file)
index 639cfa4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __ASM_EC3104_H
-#define __ASM_EC3104_H
-
-
-/*
- * Most of the register set is at 0xb0ec0000 - 0xb0ecffff.
- *
- * as far as I've figured it out the register map is:
- * 0xb0ec0000 - id string
- * 0xb0ec0XXX - power management
- * 0xb0ec1XXX - interrupt control
- * 0xb0ec3XXX - ps2 port (touch pad on aero 8000)
- * 0xb0ec6XXX - i2c
- * 0xb0ec7000 - first serial port (proprietary connector on aero 8000)
- * 0xb0ec8000 - second serial port
- * 0xb0ec9000 - third serial port
- * 0xb0eca000 - fourth serial port (keyboard controller on aero 8000)
- * 0xb0eccXXX - GPIO
- * 0xb0ecdXXX - GPIO
- */
-
-#define EC3104_BASE    0xb0ec0000
-
-#define EC3104_SER4_DATA       (EC3104_BASE+0xa000)
-#define EC3104_SER4_IIR                (EC3104_BASE+0xa008)
-#define EC3104_SER4_MCR                (EC3104_BASE+0xa010)
-#define EC3104_SER4_LSR                (EC3104_BASE+0xa014)
-#define EC3104_SER4_MSR                (EC3104_BASE+0xa018)
-
-/*
- * our ISA bus.  this seems to be real ISA.
- */
-#define EC3104_ISA_BASE        0xa5000000
-
-#define EC3104_IRQ     11
-#define EC3104_IRQBASE 64
-
-#define EC3104_IRQ_SER1        EC3104_IRQBASE + 7
-#define EC3104_IRQ_SER2        EC3104_IRQBASE + 8
-#define EC3104_IRQ_SER3        EC3104_IRQBASE + 9
-#define EC3104_IRQ_SER4        EC3104_IRQBASE + 10
-
-#endif /* __ASM_EC3104_H */
diff --git a/include/asm-sh/ec3104/io.h b/include/asm-sh/ec3104/io.h
deleted file mode 100644 (file)
index ea5c8e6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_SH_IO_EC3104_H
-#define _ASM_SH_IO_EC3104_H
-
-#include <linux/types.h>
-
-extern unsigned char ec3104_inb(unsigned long port);
-extern unsigned short ec3104_inw(unsigned long port);
-extern unsigned long ec3104_inl(unsigned long port);
-
-extern void ec3104_outb(unsigned char value, unsigned long port);
-extern void ec3104_outw(unsigned short value, unsigned long port);
-extern void ec3104_outl(unsigned long value, unsigned long port);
-
-extern int ec3104_irq_demux(int irq);
-
-#endif /* _ASM_SH_IO_EC3104_H */
diff --git a/include/asm-sh/ec3104/keyboard.h b/include/asm-sh/ec3104/keyboard.h
deleted file mode 100644 (file)
index c1253a6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-extern unsigned char ec3104_kbd_sysrq_xlate[];
-extern int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int ec3104_kbd_getkeycode(unsigned int scancode);
-extern int ec3104_kbd_translate(unsigned char, unsigned char *, char);
-extern char ec3104_kbd_unexpected_up(unsigned char);
-extern void ec3104_kbd_leds(unsigned char);
-extern void ec3104_kbd_init_hw(void);
-
-#define kbd_sysrq_xlate ec3104_kbd_sysrq_xlate
-#define kbd_setkeycode ec3104_kbd_setkeycode
-#define kbd_getkeycode ec3104_kbd_getkeycode
-#define kbd_translate ec3104_kbd_translate
-#define kbd_unexpected_up ec3104_kbd_unexpected_up
-#define kbd_leds ec3104_kbd_leds
-#define kbd_init_hw ec3104_kbd_init_hw
diff --git a/include/asm-sh/ec3104/serial.h b/include/asm-sh/ec3104/serial.h
deleted file mode 100644 (file)
index cfe4d78..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <asm/ec3104.h>
-/* Naturally we don't know the exact value but 115200 baud has a divisor
- * of 9 and 19200 baud has a divisor of 52, so this seems like a good
- * guess.  */
-#define BASE_BAUD (16800000 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-/* there is a fourth serial port with the expected values as well, but
- * it's got the keyboard controller behind it so we can't really use it
- * (without moving the keyboard driver to userspace, which doesn't sound
- * like a very good idea) */
-#define SERIAL_PORT_DFNS                       \
-       /* UART CLK   PORT IRQ     FLAGS        */                      \
-       { 0, BASE_BAUD, 0x11C00, EC3104_IRQBASE+7, STD_COM_FLAGS }, /* ttyS0 */ \
-       { 0, BASE_BAUD, 0x12000, EC3104_IRQBASE+8, STD_COM_FLAGS }, /* ttyS1 */ \
-       { 0, BASE_BAUD, 0x12400, EC3104_IRQBASE+9, STD_COM_FLAGS }, /* ttyS2 */
-
-/* XXX: This should be moved ino irq.h */
-#define irq_cannonicalize(x) (x)
index bff965ef4b95201626d5056e26f4e00c97975292..8ccf7ae593efaf871b0d8e7ec04e2625ae91eb72 100644 (file)
 /* 3. OFFCHIP_NR_IRQS */
 #if defined(CONFIG_HD64461)
 # define OFFCHIP_NR_IRQS 18
-#elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */
-# define OFFCHIP_NR_IRQS 48
 #elif defined(CONFIG_HD64465)
 # define OFFCHIP_NR_IRQS 16
-#elif defined (CONFIG_SH_EC3104)
-# define OFFCHIP_NR_IRQS 16
 #elif defined (CONFIG_SH_DREAMCAST)
 # define OFFCHIP_NR_IRQS 96
 #elif defined (CONFIG_SH_TITAN)
index 7b26f53fe343f5711f97bbecdec0dd563be36ba6..0095c665d2723ef4d38e34cc939bdd0f9972e312 100644 (file)
@@ -85,10 +85,10 @@ extern int     setjmp(jmp_buf __jmpb);
 #define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
 
 /* Forced breakpoint */
-#define BREAKPOINT() do {                                     \
-  if (kgdb_enabled) {                                         \
-    asm volatile("trapa   #0xff");                            \
-  }                                                           \
+#define BREAKPOINT()                                   \
+do {                                                   \
+       if (kgdb_enabled)                               \
+               __asm__ __volatile__("trapa   #0x3c");  \
 } while (0)
 
 /* KGDB should be able to flush all kernel text space */
index cf47df79bb9415c43a310c16c3c93737ebc2c1d2..eb0358c097d01a3c236b83400e03aa2ac5b757b7 100644 (file)
@@ -1,25 +1,19 @@
 #ifndef __MMU_H
 #define __MMU_H
 
-#if !defined(CONFIG_MMU)
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_id_t[NR_CPUS];
 
 typedef struct {
+#ifdef CONFIG_MMU
+       mm_context_id_t         id;
+       void                    *vdso;
+#else
        struct vm_list_struct   *vmlist;
        unsigned long           end_brk;
+#endif
 } mm_context_t;
 
-#else
-
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_id_t;
-
-typedef struct {
-       mm_context_id_t id;
-       void *vdso;
-} mm_context_t;
-
-#endif /* CONFIG_MMU */
-
 /*
  * Privileged Space Mapping Buffer (PMB) definitions
  */
index 46f04e23bd45ae9133c90c811ec1808f7832a14c..342024425b7df7a484e32fadb8796f089dd111c9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2003 - 2006 Paul Mundt
  *
  * ASID handling idea taken from MIPS implementation.
  */
  *    (b) ASID (Address Space IDentifier)
  */
 
-/*
- * Cache of MMU context last used.
- */
-extern unsigned long mmu_context_cache;
-
 #define MMU_CONTEXT_ASID_MASK          0x000000ff
 #define MMU_CONTEXT_VERSION_MASK       0xffffff00
 #define MMU_CONTEXT_FIRST_VERSION      0x00000100
@@ -32,6 +27,11 @@ extern unsigned long mmu_context_cache;
 /* ASID is 8-bit value, so it can't be 0x100 */
 #define MMU_NO_ASID                    0x100
 
+#define cpu_context(cpu, mm)   ((mm)->context.id[cpu])
+#define cpu_asid(cpu, mm)      (cpu_context((cpu), (mm)) & \
+                                MMU_CONTEXT_ASID_MASK)
+#define asid_cache(cpu)                (cpu_data[cpu].asid_cache)
+
 /*
  * Virtual Page Number mask
  */
@@ -41,18 +41,17 @@ extern unsigned long mmu_context_cache;
 /*
  * Get MMU context if needed.
  */
-static inline void get_mmu_context(struct mm_struct *mm)
+static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
 {
-       unsigned long mc = mmu_context_cache;
+       unsigned long asid = asid_cache(cpu);
 
        /* Check if we have old version of context. */
-       if (((mm->context.id ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+       if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)
                /* It's up to date, do nothing */
                return;
 
        /* It's old, we need to get new context with new version. */
-       mc = ++mmu_context_cache;
-       if (!(mc & MMU_CONTEXT_ASID_MASK)) {
+       if (!(++asid & MMU_CONTEXT_ASID_MASK)) {
                /*
                 * We exhaust ASID of this version.
                 * Flush all TLB and start new cycle.
@@ -63,10 +62,11 @@ static inline void get_mmu_context(struct mm_struct *mm)
                 * Fix version; Note that we avoid version #0
                 * to distingush NO_CONTEXT.
                 */
-               if (!mc)
-                       mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
+               if (!asid)
+                       asid = MMU_CONTEXT_FIRST_VERSION;
        }
-       mm->context.id = mc;
+
+       cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
 /*
@@ -74,9 +74,13 @@ static inline void get_mmu_context(struct mm_struct *mm)
  * instance.
  */
 static inline int init_new_context(struct task_struct *tsk,
-                                      struct mm_struct *mm)
+                                  struct mm_struct *mm)
 {
-       mm->context.id = NO_CONTEXT;
+       int i;
+
+       for (i = 0; i < num_online_cpus(); i++)
+               cpu_context(i, mm) = NO_CONTEXT;
+
        return 0;
 }
 
@@ -117,10 +121,10 @@ static inline unsigned long get_asid(void)
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-static inline void activate_context(struct mm_struct *mm)
+static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
 {
-       get_mmu_context(mm);
-       set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);
+       get_mmu_context(mm, cpu);
+       set_asid(cpu_asid(cpu, mm));
 }
 
 /* MMU_TTB is used for optimizing the fault handling. */
@@ -138,10 +142,15 @@ static inline void switch_mm(struct mm_struct *prev,
                             struct mm_struct *next,
                             struct task_struct *tsk)
 {
+       unsigned int cpu = smp_processor_id();
+
        if (likely(prev != next)) {
+               cpu_set(cpu, next->cpu_vm_mask);
                set_TTB(next->pgd);
-               activate_context(next);
-       }
+               activate_context(next, cpu);
+       } else
+               if (!cpu_test_and_set(cpu, next->cpu_vm_mask))
+                       activate_context(next, cpu);
 }
 
 #define deactivate_mm(tsk,mm)  do { } while (0)
@@ -159,7 +168,7 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 #define destroy_context(mm)            do { } while (0)
 #define set_asid(asid)                 do { } while (0)
 #define get_asid()                     (0)
-#define activate_context(mm)           do { } while (0)
+#define activate_context(mm,cpu)       do { } while (0)
 #define switch_mm(prev,next,tsk)       do { } while (0)
 #define deactivate_mm(tsk,mm)          do { } while (0)
 #define activate_mm(prev,next)         do { } while (0)
@@ -174,14 +183,16 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
  */
 static inline void enable_mmu(void)
 {
+       unsigned int cpu = smp_processor_id();
+
        /* Enable MMU */
        ctrl_outl(MMU_CONTROL_INIT, MMUCR);
        ctrl_barrier();
 
-       if (mmu_context_cache == NO_CONTEXT)
-               mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
+       if (asid_cache(cpu) == NO_CONTEXT)
+               asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;
 
-       set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
+       set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);
 }
 
 static inline void disable_mmu(void)
index 380fd62dd05ade8ac5806711c985ee96f94adf93..ac4b4677f28c49e7cfbfd97e78c94ab141927a0b 100644 (file)
@@ -13,6 +13,8 @@
    [ P4 control   ]            0xE0000000
  */
 
+#ifdef __KERNEL__
+
 /* PAGE_SHIFT determines the page size */
 #if defined(CONFIG_PAGE_SIZE_4KB)
 # define PAGE_SHIFT    12
@@ -51,7 +53,6 @@
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT-PAGE_SHIFT)
 #endif
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 extern void (*clear_page)(void *to);
index 036ca28438661f781aa9d84af95652e9bd1de1c9..9214c015fe14a52e7c318f8ac79c78fcdd659286 100644 (file)
@@ -43,17 +43,17 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 /* PGD bits */
 #define PGDIR_SHIFT    (PTE_SHIFT + PTE_BITS)
 #define PGDIR_BITS     (32 - PGDIR_SHIFT)
-#define PGDIR_SIZE     (1 << PGDIR_SHIFT)
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
 /* Entries per level */
-#define PTRS_PER_PTE   (PAGE_SIZE / 4)
+#define PTRS_PER_PTE   (PAGE_SIZE / (1 << PTE_MAGNITUDE))
 #define PTRS_PER_PGD   (PAGE_SIZE / 4)
 
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS     0
 
-#define PTE_PHYS_MASK  0x1ffff000
+#define PTE_PHYS_MASK          (0x20000000 - PAGE_SIZE)
 
 /*
  * First 1MB map is used by fixed purpose.
@@ -583,11 +583,6 @@ struct mm_struct;
 extern unsigned int kobjsize(const void *objp);
 #endif /* !CONFIG_MMU */
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-#endif
-
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
index e29f2abb92defc7f9d24a6d8d4f0b3a9be7d365e..3e46a7afe764110ba68e8da824596f0f5359abea 100644 (file)
@@ -27,8 +27,6 @@
 #define CCN_CVR                0xff000040
 #define CCN_PRR                0xff000044
 
-const char *get_cpu_subtype(void);
-
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  *
@@ -66,6 +64,7 @@ enum cpu_type {
 struct sh_cpuinfo {
        unsigned int type;
        unsigned long loops_per_jiffy;
+       unsigned long asid_cache;
 
        struct cache_info icache;       /* Primary I-cache */
        struct cache_info dcache;       /* Primary D-cache */
@@ -288,5 +287,8 @@ extern int vsyscall_init(void);
 #define vsyscall_init() do { } while (0)
 #endif
 
+/* arch/sh/kernel/setup.c */
+const char *get_cpu_subtype(struct sh_cpuinfo *c);
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PROCESSOR_H */
index 796b8fcb81a8984ce5d887e49840d3c0f5fd74d3..10565ac7966a4f7c5c43ccd534501f60ee3c9f1f 100644 (file)
 #define IRQ_PCISLOT2   10              /* PCI Slot #2 IRQ */
 #define        IRQ_EXTENTION   11              /* EXTn IRQ */
 
+/* arch/sh/boards/renesas/rts7751r2d/irq.c */
+void init_rts7751r2d_IRQ(void);
+int rts7751r2d_irq_demux(int);
+
 #define __IO_PREFIX rts7751r2d
 #include <asm/io_generic.h>
 
index 8734590d27e8c79c6fb7bb831b1b13c8d923bf5b..21f6d330f18955fb800453dbf721132bd2c52c87 100644 (file)
@@ -9,11 +9,6 @@
 
 #include <linux/kernel.h>
 
-#ifdef CONFIG_SH_EC3104
-#include <asm/serial-ec3104.h>
-#elif defined (CONFIG_SH_BIGSUR)
-#include <asm/serial-bigsur.h>
-#else
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
 
 #else
 
-#define SERIAL_PORT_DFNS                       \
-       /* UART CLK   PORT IRQ     FLAGS        */                      \
-       { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
-       { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }       /* ttyS1 */
+#define SERIAL_PORT_DFNS
 
 #endif
 
-#endif
 #endif /* _ASM_SERIAL_H */
index 879f741105dbd366ed1bbcfdec6570024ae47662..279e70a77c75350a8ce7fc24e5fe707e766d69d6 100644 (file)
@@ -32,12 +32,20 @@ struct thread_info {
 
 #define PREEMPT_ACTIVE         0x10000000
 
-#ifdef CONFIG_4KSTACKS
-#define THREAD_SIZE            (PAGE_SIZE)
+#if defined(CONFIG_4KSTACKS)
+#define THREAD_SIZE_ORDER      (0)
+#elif defined(CONFIG_PAGE_SIZE_4KB)
+#define THREAD_SIZE_ORDER      (1)
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+#define THREAD_SIZE_ORDER      (1)
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+#define THREAD_SIZE_ORDER      (0)
 #else
-#define THREAD_SIZE            (PAGE_SIZE * 2)
+#error "Unknown thread size"
 #endif
-#define STACK_WARN             (THREAD_SIZE / 8)
+
+#define THREAD_SIZE    (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define STACK_WARN     (THREAD_SIZE >> 3)
 
 /*
  * macros/functions for gaining access to the thread information structure
index 28c073b0fbab3e593dd42eebef3594604fc53b9e..455fb8da441e6786abe3895c83faf73e633469a6 100644 (file)
@@ -4,7 +4,6 @@
 /*
  * TLB flushing:
  *
- *  - flush_tlb() flushes the current mm struct TLBs
  *  - flush_tlb_all() flushes all processes TLBs
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  */
+extern void local_flush_tlb_all(void);
+extern void local_flush_tlb_mm(struct mm_struct *mm);
+extern void local_flush_tlb_range(struct vm_area_struct *vma,
+                                 unsigned long start,
+                                 unsigned long end);
+extern void local_flush_tlb_page(struct vm_area_struct *vma,
+                                unsigned long page);
+extern void local_flush_tlb_kernel_range(unsigned long start,
+                                        unsigned long end);
+extern void local_flush_tlb_one(unsigned long asid, unsigned long page);
+
+#ifdef CONFIG_SMP
 
-extern void flush_tlb(void);
 extern void flush_tlb_all(void);
 extern void flush_tlb_mm(struct mm_struct *mm);
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                            unsigned long end);
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-extern void __flush_tlb_page(unsigned long asid, unsigned long page);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long asid, unsigned long page);
+
+#else
+
+#define flush_tlb_all()                        local_flush_tlb_all()
+#define flush_tlb_mm(mm)               local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)      local_flush_tlb_page(vma, page)
+#define flush_tlb_one(asid, page)      local_flush_tlb_one(asid, page)
+
+#define flush_tlb_range(vma, start, end)       \
+       local_flush_tlb_range(vma, start, end)
+
+#define flush_tlb_kernel_range(start, end)     \
+       local_flush_tlb_kernel_range(start, end)
+
+#endif /* CONFIG_SMP */
 
 static inline void flush_tlb_pgtables(struct mm_struct *mm,
                                      unsigned long start, unsigned long end)
-{ /* Nothing to do */
+{
+       /* Nothing to do */
 }
-
-extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
-
 #endif /* __ASM_SH_TLBFLUSH_H */
index 694f51f47941f551b8fef9e3c1fdc8ff99f7ee56..ae9bbdeefbe128035cee2cae9b28419436b814ff 100644 (file)
@@ -17,7 +17,7 @@
 /* User Break Controller */
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define UBC_TYPE_SH7729        (cpu_data->type == CPU_SH7729)
+#define UBC_TYPE_SH7729        (current_cpu_data.type == CPU_SH7729)
 #else
 #define UBC_TYPE_SH7729        0
 #endif
index f982073dc6c68250b580b11c814a5d77afed72dc..17f527bfd455ec72fa369e056f32652138e9a1fb 100644 (file)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
 #define __NR_kexec_load                283
 #define __NR_waitid            284
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key           286
-#define __NR_request_key       287
-#define __NR_keyctl            288
-#define __NR_ioprio_set                289
-#define __NR_ioprio_get                290
-#define __NR_inotify_init      291
-#define __NR_inotify_add_watch 292
-#define __NR_inotify_rm_watch  293
+#define __NR_add_key           285
+#define __NR_request_key       286
+#define __NR_keyctl            287
+#define __NR_ioprio_set                288
+#define __NR_ioprio_get                289
+#define __NR_inotify_init      290
+#define __NR_inotify_add_watch 291
+#define __NR_inotify_rm_watch  292
+/* 293 is unused */
 #define __NR_migrate_pages     294
 #define __NR_openat            295
 #define __NR_mkdirat           296
 #define __NR_mknodat           297
 #define __NR_fchownat          298
 #define __NR_futimesat         299
-#define __NR_newfstatat                300
+#define __NR_fstatat64         300
 #define __NR_unlinkat          301
 #define __NR_renameat          302
 #define __NR_linkat            303
index 99b0807d1c9f4806c1c51f3c4448fce433704828..64c936b22715e89283213cf6b9058117b3fdc3a2 100644 (file)
 #define AC97C_READ                     (1 << 19)
 #define AC97C_WD_BIT                   (1 << 2)
 #define AC97C_INDEX_MASK               0x7f
-/* -------------------------------------------------------------------- */
+
+/* arch/sh/cchips/voyagergx/consistent.c */
+void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
+int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
 #endif /* _VOYAGER_GX_REG_H */
index 8da9609070f471eaac12ae7269c4479eca459b1e..d4dbbe5f7bd9f466451e0ee65572b6accf929277 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <asm/alternative.h>
 
-#if __GNUC__ < 4 || __GNUC_MINOR__ < 1
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
 /* Technically wrong, but this avoids compilation errors on some gcc
    versions. */
 #define ADDR "=m" (*(volatile long *) addr)
index 49dbab09ef2b05ac113aebd464631be17a572ea4..d2af227f06d025c7cccc56cfffc9f4f1501583e9 100644 (file)
@@ -66,6 +66,9 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
 extern void *dma_alloc_coherent(struct device *dev, size_t size,
                                dma_addr_t *dma_handle, gfp_t gfp);
 extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
index fa2086774105500f5ac2d7a5f8e1a6bbef219d38..6216fa3f28026b943dedaccb717c8e7edb871edb 100644 (file)
@@ -46,6 +46,7 @@ extern void e820_mark_nosave_regions(void);
 extern void e820_print_map(char *who);
 extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
 extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
+extern unsigned long e820_hole_size(unsigned long start, unsigned long end);
 
 extern void e820_setup_gap(void);
 extern void e820_register_active_regions(int nid,
@@ -56,6 +57,7 @@ extern void finish_e820_parsing(void);
 extern struct e820map e820;
 
 extern unsigned ebda_addr, ebda_size;
+extern unsigned long nodemap_addr, nodemap_size;
 #endif/*!__ASSEMBLY__*/
 
 #endif/*__E820_HEADER*/
index b39098408b6926a744b0929d46b04e7e446a6a1a..59a66f084611c676be7306d1b458b6e678b492da 100644 (file)
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
 extern int apic_is_clustered_box(void);
+extern int hpet_arch_init(void);
+extern int hpet_timer_stop_set_go(unsigned long tick);
+extern int hpet_reenable(void);
+extern unsigned int hpet_calibrate_tsc(void);
 
 extern int hpet_use_timer;
+extern unsigned long hpet_address;
+extern unsigned long hpet_period;
+extern unsigned long hpet_tick;
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
index 179cce755aa75656380f7f4e9005cebd46010742..552df5f10a6d462026eb10414766efd42a76a347 100644 (file)
@@ -91,7 +91,7 @@ extern void enable_8259A_irq(unsigned int irq);
 extern int i8259A_irq_pending(unsigned int irq);
 extern void make_8259A_irq(unsigned int irq);
 extern void init_8259A(int aeoi);
-extern void FASTCALL(send_IPI_self(int vector));
+extern void send_IPI_self(int vector);
 extern void init_VISWS_APIC_irqs(void);
 extern void setup_IO_APIC(void);
 extern void disable_IO_APIC(void);
index f5d84bb7c9488c3281cc6e386bbc67e97abdd16f..de2cd9a2303a92922a9dea817cd127841bf32765 100644 (file)
@@ -100,7 +100,7 @@ __OUTS(l)
 
 #define IO_SPACE_LIMIT 0xffff
 
-#if defined(__KERNEL__) && __x86_64__
+#if defined(__KERNEL__) && defined(__x86_64__)
 
 #include <linux/vmalloc.h>
 
index 561ecbfd4cb5604bce14e7ed2fc51848dbcae244..f4fb238c89f14212f84b51a9258fc5960a69a46d 100644 (file)
@@ -85,18 +85,8 @@ struct IO_APIC_route_entry {
                mask            :  1,   /* 0: enabled, 1: disabled */
                __reserved_2    : 15;
 
-       union {         struct { __u32
-                                       __reserved_1    : 24,
-                                       physical_dest   :  4,
-                                       __reserved_2    :  4;
-                       } physical;
-
-                       struct { __u32
-                                       __reserved_1    : 24,
-                                       logical_dest    :  8;
-                       } logical;
-       } dest;
-
+       __u32   __reserved_3    : 24,
+               dest            :  8;
 } __attribute__ ((packed));
 
 /*
index 5a11146d6d9cc753f6eb82face2fb15aba39c9c6..177e92b4019beba32d3eef9b645cba0c66c8cd41 100644 (file)
@@ -103,6 +103,8 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status);
 
 extern atomic_t mce_entry;
 
+extern void do_machine_check(struct pt_regs *, long);
+
 #endif
 
 #endif
index c38ebdf6f426ad41ddfc19fc8df42553eae4b5a6..fb558fb1d21106f17e738ee1400e322397d72890 100644 (file)
 
 #include <asm/smp.h>
 
-/* Should really switch to dynamic allocation at some point */
-#define NODEMAPSIZE 0x4fff
-
 /* Simple perfect hash to map physical addresses to node numbers */
 struct memnode {
        int shift;
-       u8 map[NODEMAPSIZE];
-} ____cacheline_aligned;
+       unsigned int mapsize;
+       u8 *map;
+       u8 embedded_map[64-16];
+} ____cacheline_aligned; /* total size = 64 bytes */
 extern struct memnode memnode;
 #define memnode_shift memnode.shift
 #define memnodemap memnode.map
+#define memnodemapsize memnode.mapsize
 
 extern struct pglist_data *node_data[];
 
 static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) 
 { 
        unsigned nid; 
-       VIRTUAL_BUG_ON((addr >> memnode_shift) >= NODEMAPSIZE);
+       VIRTUAL_BUG_ON(!memnodemap);
+       VIRTUAL_BUG_ON((addr >> memnode_shift) >= memnodemapsize);
        nid = memnodemap[addr >> memnode_shift]; 
        VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); 
        return nid; 
@@ -46,5 +47,10 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
 extern int pfn_valid(unsigned long pfn);
 #endif
 
+#ifdef CONFIG_NUMA_EMU
+#define FAKE_NODE_MIN_SIZE     (64*1024*1024)
+#define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1ul))
+#endif
+
 #endif
 #endif
index 16396b1de3e44e2068021f446d8b56f3b6f79448..6c2949a3c677bad80981fd593acb8d7da0e9cf10 100644 (file)
@@ -21,7 +21,7 @@ do {                                                                  \
        unsigned long dummy;                                            \
                                                                        \
        typecheck(atomic_t *, v);                                       \
-       typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);           \
+       typecheck_fn(void (*)(atomic_t *), fail_fn);                    \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   decl (%%rdi)    \n"                     \
@@ -47,7 +47,7 @@ do {                                                                  \
  */
 static inline int
 __mutex_fastpath_lock_retval(atomic_t *count,
-                            int fastcall (*fail_fn)(atomic_t *))
+                            int (*fail_fn)(atomic_t *))
 {
        if (unlikely(atomic_dec_return(count) < 0))
                return fail_fn(count);
@@ -67,7 +67,7 @@ do {                                                                  \
        unsigned long dummy;                                            \
                                                                        \
        typecheck(atomic_t *, v);                                       \
-       typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);           \
+       typecheck_fn(void (*)(atomic_t *), fail_fn);                    \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   incl (%%rdi)    \n"                     \
index 43d4c333a8b19a0c9f9a9a5a8bb218638f551a51..4e28b6060a5ed46ee7c033ebeccb9a7f1703f4f5 100644 (file)
@@ -18,11 +18,6 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
        set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
 }
 
-static inline pmd_t *get_pmd(void)
-{
-       return (pmd_t *)get_zeroed_page(GFP_KERNEL);
-}
-
 static inline void pmd_free(pmd_t *pmd)
 {
        BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
index 59901c690a0d4882744c770c4aabfa39ad605bb7..730bd6028416c5a9c28aa2767b19fdf85b816e78 100644 (file)
@@ -359,15 +359,6 @@ static inline int pmd_large(pmd_t pte) {
 #define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
 #define mk_pte_huge(entry) (pte_val(entry) |= _PAGE_PRESENT | _PAGE_PSE)
  
-/* physical address -> PTE */
-static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ 
-       pte_t pte;
-       pte_val(pte) = physpage | pgprot_val(pgprot); 
-       pte_val(pte) &= __supported_pte_mask;
-       return pte; 
-}
 /* Change flags of a PTE */
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
index a6d2ff5c69b76ea2a5941740dd2206cf45f03726..f54f3abf93ce5a575d0d2b7dc5d4f26776335c71 100644 (file)
@@ -45,11 +45,7 @@ extern u32 pmtmr_ioport;
 #else
 #define pmtmr_ioport 0
 #endif
-extern unsigned long long monotonic_base;
-extern int sysctl_vsyscall;
 extern int nohpet;
-extern unsigned long vxtime_hz;
-extern void time_init_gtod(void);
 
 extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
 
@@ -91,8 +87,6 @@ extern void check_efer(void);
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
 
-extern int unsynchronized_tsc(void);
-
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
 extern unsigned long table_start, table_end;
index b9e5320b76252f06d86fac9f1ac36eeaaa41233b..8c6808a3fba443ab74770b526997fd8a6ea0b447 100644 (file)
 #include <asm/hpet.h>
 #include <asm/system.h>
 #include <asm/processor.h>
+#include <asm/tsc.h>
 #include <linux/compiler.h>
 
 #define CLOCK_TICK_RATE        PIT_TICK_RATE   /* Underlying HZ */
 
-typedef unsigned long long cycles_t;
-
-static inline cycles_t get_cycles (void)
-{
-       unsigned long long ret;
-
-       rdtscll(ret);
-       return ret;
-}
-
-/* Like get_cycles, but make sure the CPU is synchronized. */
-static __always_inline cycles_t get_cycles_sync(void)
-{
-       unsigned long long ret;
-       unsigned eax;
-       /* Don't do an additional sync on CPUs where we know
-          RDTSC is already synchronous. */
-       alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
-                         "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
-       rdtscll(ret);
-       return ret;
-}
-
-extern unsigned int cpu_khz;
-
 extern int read_current_timer(unsigned long *timer_value);
 #define ARCH_HAS_READ_CURRENT_TIMER    1
 
-extern struct vxtime_data vxtime;
+#define USEC_PER_TICK (USEC_PER_SEC / HZ)
+#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
+#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
+
+#define NS_SCALE        10 /* 2^10, carefully chosen */
+#define US_SCALE        32 /* 2^32, arbitralrily chosen */
 
+extern void mark_tsc_unstable(void);
+extern void set_cyc2ns_scale(unsigned long khz);
 #endif
diff --git a/include/asm-x86_64/tsc.h b/include/asm-x86_64/tsc.h
new file mode 100644 (file)
index 0000000..9a0a368
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * linux/include/asm-x86_64/tsc.h
+ *
+ * x86_64 TSC related functions
+ */
+#ifndef _ASM_x86_64_TSC_H
+#define _ASM_x86_64_TSC_H
+
+#include <asm/processor.h>
+
+/*
+ * Standard way to access the cycle counter.
+ */
+typedef unsigned long long cycles_t;
+
+extern unsigned int cpu_khz;
+extern unsigned int tsc_khz;
+
+static inline cycles_t get_cycles(void)
+{
+       unsigned long long ret = 0;
+
+#ifndef CONFIG_X86_TSC
+       if (!cpu_has_tsc)
+               return 0;
+#endif
+
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
+       rdtscll(ret);
+#endif
+       return ret;
+}
+
+/* Like get_cycles, but make sure the CPU is synchronized. */
+static __always_inline cycles_t get_cycles_sync(void)
+{
+       unsigned long long ret;
+#ifdef X86_FEATURE_SYNC_RDTSC
+       unsigned eax;
+
+       /*
+        * Don't do an additional sync on CPUs where we know
+        * RDTSC is already synchronous:
+        */
+       alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
+                         "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
+#else
+       sync_core();
+#endif
+       rdtscll(ret);
+
+       return ret;
+}
+
+extern void tsc_init(void);
+extern void mark_tsc_unstable(void);
+extern int unsynchronized_tsc(void);
+
+/*
+ * Boot-time check whether the TSCs are synchronized across
+ * all CPUs/cores:
+ */
+extern void check_tsc_sync_source(int cpu);
+extern void check_tsc_sync_target(void);
+
+#endif
index 8079e29c14fd4ca1212bea28ac313b523a67b5d3..1981f70fcad1b1212fa1a3d464f8e0b05608f009 100644 (file)
@@ -367,4 +367,18 @@ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
        return copy_user_generic((__force void *)dst, src, size);
 }
 
+#define ARCH_HAS_NOCACHE_UACCESS 1
+extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size, int zerorest);
+
+static inline int __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
+{
+       might_sleep();
+       return __copy_user_nocache(dst, (__force void *)src, size, 1);
+}
+
+static inline int __copy_from_user_inatomic_nocache(void *dst, const void __user *src, unsigned size)
+{
+       return __copy_user_nocache(dst, (__force void *)src, size, 0);
+}
+
 #endif /* __X86_64_UACCESS_H */
index 05cb8dd200de7742456de435aa31c586b5df2776..82b4afe65c914a224a79274edeadfec94addb58d 100644 (file)
@@ -16,51 +16,27 @@ enum vsyscall_num {
 #ifdef __KERNEL__
 #include <linux/seqlock.h>
 
-#define __section_vxtime __attribute__ ((unused, __section__ (".vxtime"), aligned(16)))
 #define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16)))
 #define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
-#define __section_sys_tz __attribute__ ((unused, __section__ (".sys_tz"), aligned(16)))
-#define __section_sysctl_vsyscall __attribute__ ((unused, __section__ (".sysctl_vsyscall"), aligned(16)))
-#define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
-#define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(16)))
 
-#define VXTIME_TSC     1
-#define VXTIME_HPET    2
-#define VXTIME_PMTMR   3
+/* Definitions for CONFIG_GENERIC_TIME definitions */
+#define __section_vsyscall_gtod_data __attribute__ \
+       ((unused, __section__ (".vsyscall_gtod_data"),aligned(16)))
+#define __vsyscall_fn __attribute__ ((unused,__section__(".vsyscall_fn")))
 
 #define VGETCPU_RDTSCP 1
 #define VGETCPU_LSL    2
 
-struct vxtime_data {
-       long hpet_address;      /* HPET base address */
-       int last;
-       unsigned long last_tsc;
-       long quot;
-       long tsc_quot;
-       int mode;
-};
-
 #define hpet_readl(a)           readl((const void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
 #define hpet_writel(d,a)        writel(d, (void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
 
-/* vsyscall space (readonly) */
-extern struct vxtime_data __vxtime;
 extern int __vgetcpu_mode;
-extern struct timespec __xtime;
 extern volatile unsigned long __jiffies;
-extern struct timezone __sys_tz;
-extern seqlock_t __xtime_lock;
 
 /* kernel space (writeable) */
-extern struct vxtime_data vxtime;
 extern int vgetcpu_mode;
 extern struct timezone sys_tz;
-extern int sysctl_vsyscall;
-extern seqlock_t xtime_lock;
-
-extern int sysctl_vsyscall;
-
-#define ARCH_HAVE_XTIME_LOCK 1
+extern struct vsyscall_gtod_data_t vsyscall_gtod_data;
 
 #endif /* __KERNEL__ */
 
index 815f1fb4ce211302a334d447ae61b72d4c25053a..8bcfaa4c66ae78705ed128297d0069cd9f460752 100644 (file)
@@ -75,7 +75,7 @@ enum acpi_address_range_id {
 
 typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 
-typedef int (*acpi_madt_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
+typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 unsigned long acpi_find_rsdp (void);
@@ -85,8 +85,10 @@ int acpi_numa_init (void);
 
 int acpi_table_init (void);
 int acpi_table_parse (char *id, acpi_table_handler handler);
-int acpi_table_parse_madt (enum acpi_madt_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
-int acpi_table_parse_srat (enum acpi_srat_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
+int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+       int entry_id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_srat (enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries);
 int acpi_parse_mcfg (struct acpi_table_header *header);
 void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
 void acpi_table_print_srat_entry (struct acpi_subtable_header *srat);
diff --git a/include/linux/acpi_pmtmr.h b/include/linux/acpi_pmtmr.h
new file mode 100644 (file)
index 0000000..1d0ef1a
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _ACPI_PMTMR_H_
+#define _ACPI_PMTMR_H_
+
+#include <linux/clocksource.h>
+
+/* Number of PMTMR ticks expected during calibration run */
+#define PMTMR_TICKS_PER_SEC 3579545
+
+/* limit it to 24 bits */
+#define ACPI_PM_MASK CLOCKSOURCE_MASK(24)
+
+/* Overrun value */
+#define ACPI_PM_OVRRUN (1<<24)
+
+#ifdef CONFIG_X86_PM_TIMER
+
+extern u32 acpi_pm_read_verified(void);
+extern u32 pmtmr_ioport;
+
+static inline u32 acpi_pm_read_early(void)
+{
+       if (!pmtmr_ioport)
+               return 0;
+       /* mask the output to 24 bits */
+       return acpi_pm_read_verified() & ACPI_PM_MASK;
+}
+
+#else
+
+static inline u32 acpi_pm_read_early(void)
+{
+       return 0;
+}
+
+#endif
+
+#endif
+
index a5c8bb5d80baddd93fd375ce446e27377f60ab8d..abc521cfb08464a7e5a9c3cf11ca60d80f0529af 100644 (file)
@@ -87,10 +87,15 @@ struct agp_memory {
        u32 physical;
        u8 is_bound;
        u8 is_flushed;
+        u8 vmalloc_flag;
 };
 
 #define AGP_NORMAL_MEMORY 0
 
+#define AGP_USER_TYPES (1 << 16)
+#define AGP_USER_MEMORY (AGP_USER_TYPES)
+#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1)
+
 extern struct agp_bridge_data *agp_bridge;
 extern struct list_head agp_bridges;
 
index 18e401ff7eafb6ed6fee60693e65b1c35b3254a8..272736e37990b7d96b71d7f4b0972ee2d7033d77 100644 (file)
@@ -352,7 +352,7 @@ static inline int ata_drive_40wire(const u16 *dev_id)
 {
        if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id))
                return 0;       /* SATA */
-       if (dev_id[93] & 0x4000)
+       if ((dev_id[93] & 0xE000) == 0x6000)
                return 0;       /* 80 wire */
        return 1;
 }
diff --git a/include/linux/atmel_pdc.h b/include/linux/atmel_pdc.h
new file mode 100644 (file)
index 0000000..5058a31
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * include/linux/atmel_pdc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Peripheral Data Controller (PDC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef ATMEL_PDC_H
+#define ATMEL_PDC_H
+
+#define ATMEL_PDC_RPR          0x100   /* Receive Pointer Register */
+#define ATMEL_PDC_RCR          0x104   /* Receive Counter Register */
+#define ATMEL_PDC_TPR          0x108   /* Transmit Pointer Register */
+#define ATMEL_PDC_TCR          0x10c   /* Transmit Counter Register */
+#define ATMEL_PDC_RNPR         0x110   /* Receive Next Pointer Register */
+#define ATMEL_PDC_RNCR         0x114   /* Receive Next Counter Register */
+#define ATMEL_PDC_TNPR         0x118   /* Transmit Next Pointer Register */
+#define ATMEL_PDC_TNCR         0x11c   /* Transmit Next Counter Register */
+
+#define ATMEL_PDC_PTCR         0x120   /* Transfer Control Register */
+#define                ATMEL_PDC_RXTEN         (1 << 0)        /* Receiver Transfer Enable */
+#define                ATMEL_PDC_RXTDIS        (1 << 1)        /* Receiver Transfer Disable */
+#define                ATMEL_PDC_TXTEN         (1 << 8)        /* Transmitter Transfer Enable */
+#define                ATMEL_PDC_TXTDIS        (1 << 9)        /* Transmitter Transfer Disable */
+
+#define ATMEL_PDC_PTSR         0x124   /* Transfer Status Register */
+
+#endif
index 0e07db6cc0d0eeefc1c58e2f4980016afe713d05..229fa012c893472f16a312afd5f008e075e4cf8d 100644 (file)
@@ -89,6 +89,7 @@
 #define AUDIT_MQ_NOTIFY                1314    /* POSIX MQ notify record type */
 #define AUDIT_MQ_GETSETATTR    1315    /* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER     1316    /* For use by 3rd party modules */
+#define AUDIT_FD_PAIR          1317    /* audit record for pipe/socketpair */
 
 #define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
@@ -387,6 +388,7 @@ extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode
 extern int audit_bprm(struct linux_binprm *bprm);
 extern int audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
+extern int __audit_fd_pair(int fd1, int fd2);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
 extern int audit_set_macxattr(const char *name);
 extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
@@ -401,6 +403,12 @@ static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
                return __audit_ipc_obj(ipcp);
        return 0;
 }
+static inline int audit_fd_pair(int fd1, int fd2)
+{
+       if (unlikely(!audit_dummy_context()))
+               return __audit_fd_pair(fd1, fd2);
+       return 0;
+}
 static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
        if (unlikely(!audit_dummy_context()))
@@ -459,6 +467,7 @@ extern int audit_n_rules;
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
+#define audit_fd_pair(n,a) ({ 0; })
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
 #define audit_set_macxattr(n) do { ; } while (0)
index c1e82c51444320f0970162fa76b2065ab3727bf7..2d956cd566aed11bf0333c30cc0a36cca475dac9 100644 (file)
@@ -59,6 +59,7 @@ struct linux_binfmt {
        int (*load_shlib)(struct file *);
        int (*core_dump)(long signr, struct pt_regs * regs, struct file * file);
        unsigned long min_coredump;     /* minimal dump size */
+       int hasvdso;
 };
 
 extern int register_binfmt(struct linux_binfmt *);
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
new file mode 100644 (file)
index 0000000..4ea7e7b
--- /dev/null
@@ -0,0 +1,142 @@
+/*  linux/include/linux/clockchips.h
+ *
+ *  This file contains the structure definitions for clockchips.
+ *
+ *  If you are not a clockchip, or the time of day code, you should
+ *  not be including this file!
+ */
+#ifndef _LINUX_CLOCKCHIPS_H
+#define _LINUX_CLOCKCHIPS_H
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+#include <linux/clocksource.h>
+#include <linux/cpumask.h>
+#include <linux/ktime.h>
+#include <linux/notifier.h>
+
+struct clock_event_device;
+
+/* Clock event mode commands */
+enum clock_event_mode {
+       CLOCK_EVT_MODE_UNUSED = 0,
+       CLOCK_EVT_MODE_SHUTDOWN,
+       CLOCK_EVT_MODE_PERIODIC,
+       CLOCK_EVT_MODE_ONESHOT,
+};
+
+/* Clock event notification values */
+enum clock_event_nofitiers {
+       CLOCK_EVT_NOTIFY_ADD,
+       CLOCK_EVT_NOTIFY_BROADCAST_ON,
+       CLOCK_EVT_NOTIFY_BROADCAST_OFF,
+       CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+       CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+       CLOCK_EVT_NOTIFY_SUSPEND,
+       CLOCK_EVT_NOTIFY_RESUME,
+       CLOCK_EVT_NOTIFY_CPU_DEAD,
+};
+
+/*
+ * Clock event features
+ */
+#define CLOCK_EVT_FEAT_PERIODIC                0x000001
+#define CLOCK_EVT_FEAT_ONESHOT         0x000002
+/*
+ * x86(64) specific misfeatures:
+ *
+ * - Clockevent source stops in C3 State and needs broadcast support.
+ * - Local APIC timer is used as a dummy device.
+ */
+#define CLOCK_EVT_FEAT_C3STOP          0x000004
+#define CLOCK_EVT_FEAT_DUMMY           0x000008
+
+/**
+ * struct clock_event_device - clock event device descriptor
+ * @name:              ptr to clock event name
+ * @hints:             usage hints
+ * @max_delta_ns:      maximum delta value in ns
+ * @min_delta_ns:      minimum delta value in ns
+ * @mult:              nanosecond to cycles multiplier
+ * @shift:             nanoseconds to cycles divisor (power of two)
+ * @rating:            variable to rate clock event devices
+ * @irq:               irq number (only for non cpu local devices)
+ * @cpumask:           cpumask to indicate for which cpus this device works
+ * @set_next_event:    set next event
+ * @set_mode:          set mode function
+ * @evthandler:                Assigned by the framework to be called by the low
+ *                     level handler of the event source
+ * @broadcast:         function to broadcast events
+ * @list:              list head for the management code
+ * @mode:              operating mode assigned by the management code
+ * @next_event:                local storage for the next event in oneshot mode
+ */
+struct clock_event_device {
+       const char              *name;
+       unsigned int            features;
+       unsigned long           max_delta_ns;
+       unsigned long           min_delta_ns;
+       unsigned long           mult;
+       int                     shift;
+       int                     rating;
+       int                     irq;
+       cpumask_t               cpumask;
+       int                     (*set_next_event)(unsigned long evt,
+                                                 struct clock_event_device *);
+       void                    (*set_mode)(enum clock_event_mode mode,
+                                           struct clock_event_device *);
+       void                    (*event_handler)(struct clock_event_device *);
+       void                    (*broadcast)(cpumask_t mask);
+       struct list_head        list;
+       enum clock_event_mode   mode;
+       ktime_t                 next_event;
+};
+
+/*
+ * Calculate a multiplication factor for scaled math, which is used to convert
+ * nanoseconds based values to clock ticks:
+ *
+ * clock_ticks = (nanoseconds * factor) >> shift.
+ *
+ * div_sc is the rearranged equation to calculate a factor from a given clock
+ * ticks / nanoseconds ratio:
+ *
+ * factor = (clock_ticks << shift) / nanoseconds
+ */
+static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec,
+                                  int shift)
+{
+       uint64_t tmp = ((uint64_t)ticks) << shift;
+
+       do_div(tmp, nsec);
+       return (unsigned long) tmp;
+}
+
+/* Clock event layer functions */
+extern unsigned long clockevent_delta2ns(unsigned long latch,
+                                        struct clock_event_device *evt);
+extern void clockevents_register_device(struct clock_event_device *dev);
+
+extern void clockevents_exchange_device(struct clock_event_device *old,
+                                       struct clock_event_device *new);
+extern
+struct clock_event_device *clockevents_request_device(unsigned int features,
+                                                     cpumask_t cpumask);
+extern void clockevents_release_device(struct clock_event_device *dev);
+extern void clockevents_set_mode(struct clock_event_device *dev,
+                                enum clock_event_mode mode);
+extern int clockevents_register_notifier(struct notifier_block *nb);
+extern void clockevents_unregister_notifier(struct notifier_block *nb);
+extern int clockevents_program_event(struct clock_event_device *dev,
+                                    ktime_t expires, ktime_t now);
+
+extern void clockevents_notify(unsigned long reason, void *arg);
+
+#else
+
+static inline void clockevents_resume_events(void) { }
+#define clockevents_notify(reason, arg) do { } while (0)
+
+#endif
+
+#endif
index 1622d23a8dc3e9d7390e6642ee0d9f317aea6492..daa4940cc0f1fa37c9afd87b4ed759aac8c0a6bf 100644 (file)
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/timer.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 
 /* clocksource cycle base type */
 typedef u64 cycle_t;
+struct clocksource;
 
 /**
  * struct clocksource - hardware abstraction for a free running counter
@@ -44,8 +46,8 @@ typedef u64 cycle_t;
  *                     subtraction of non 64 bit counters
  * @mult:              cycle to nanosecond multiplier
  * @shift:             cycle to nanosecond divisor (power of two)
- * @update_callback:   called when safe to alter clocksource values
- * @is_continuous:     defines if clocksource is free-running.
+ * @flags:             flags describing special properties
+ * @vread:             vsyscall based read
  * @cycle_interval:    Used internally by timekeeping core, please ignore.
  * @xtime_interval:    Used internally by timekeeping core, please ignore.
  */
@@ -57,15 +59,30 @@ struct clocksource {
        cycle_t mask;
        u32 mult;
        u32 shift;
-       int (*update_callback)(void);
-       int is_continuous;
+       unsigned long flags;
+       cycle_t (*vread)(void);
 
        /* timekeeping specific data, ignore */
        cycle_t cycle_last, cycle_interval;
        u64 xtime_nsec, xtime_interval;
        s64 error;
+
+#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
+       /* Watchdog related data, used by the framework */
+       struct list_head wd_list;
+       cycle_t wd_last;
+#endif
 };
 
+/*
+ * Clock source flags bits::
+ */
+#define CLOCK_SOURCE_IS_CONTINUOUS             0x01
+#define CLOCK_SOURCE_MUST_VERIFY               0x02
+
+#define CLOCK_SOURCE_WATCHDOG                  0x10
+#define CLOCK_SOURCE_VALID_FOR_HRES            0x20
+
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
 
@@ -178,8 +195,16 @@ static inline void clocksource_calculate_interval(struct clocksource *c,
 
 
 /* used to install a new clocksource */
-int clocksource_register(struct clocksource*);
-void clocksource_reselect(void);
-struct clocksource* clocksource_get_next(void);
+extern int clocksource_register(struct clocksource*);
+extern struct clocksource* clocksource_get_next(void);
+extern void clocksource_change_rating(struct clocksource *cs, int rating);
+
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL
+extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
+#else
+static inline void update_vsyscall(struct timespec *ts, struct clocksource *c)
+{
+}
+#endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
index 7f008f6bfdc36e2d1b430bf2b13bd876f43de1ff..0899e2cdcdd15761c9e1eaccb926acde77294e1c 100644 (file)
@@ -84,9 +84,6 @@ struct cpufreq_policy {
         unsigned int           policy; /* see above */
        struct cpufreq_governor *governor; /* see below */
 
-       struct mutex            lock;   /* CPU ->setpolicy or ->target may
-                                          only be called once a time */
-
        struct work_struct      update; /* if update_policy() needs to be
                                         * called, but you're in IRQ context */
 
@@ -172,11 +169,16 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                   unsigned int relation);
 
 
-extern int cpufreq_driver_getavg(struct cpufreq_policy *policy);
+extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
 
+int lock_policy_rwsem_read(int cpu);
+int lock_policy_rwsem_write(int cpu);
+void unlock_policy_rwsem_read(int cpu);
+void unlock_policy_rwsem_write(int cpu);
+
 
 /*********************************************************************
  *                      CPUFREQ DRIVER INTERFACE                     *
index 047567d34ca77e5da470f7a954e3799a217e14a9..9fa0983d1aa8b70823cc160383f4e0b0b03a1eba 100644 (file)
@@ -33,6 +33,9 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
 
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
 
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+                                     const char *dest);
+
 void debugfs_remove(struct dentry *dentry);
 
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
@@ -70,6 +73,13 @@ static inline struct dentry *debugfs_create_dir(const char *name,
        return ERR_PTR(-ENODEV);
 }
 
+static inline struct dentry *debugfs_create_symlink(const char *name,
+                                                   struct dentry *parent,
+                                                   const char *dest)
+{
+       return ERR_PTR(-ENODEV);
+}
+
 static inline void debugfs_remove(struct dentry *dentry)
 { }
 
index 26e4692f2d1a185c7c3bbe986e970eb1928721d7..d1a3a27c3988fea20a71e0bcd2a8c02283ea009b 100644 (file)
@@ -2,6 +2,7 @@
  * device.h - generic, centralized driver model
  *
  * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
+ * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
  *
  * This file is released under the GPLv2
  *
@@ -101,7 +102,7 @@ extern int bus_unregister_notifier(struct bus_type *bus,
 #define BUS_NOTIFY_UNBIND_DRIVER       0x00000004 /* driver about to be
                                                      unbound */
 
-/* driverfs interface for exporting bus attributes */
+/* sysfs interface for exporting bus attributes */
 
 struct bus_attribute {
        struct attribute        attr;
@@ -146,7 +147,7 @@ extern void put_driver(struct device_driver * drv);
 extern struct device_driver *driver_find(const char *name, struct bus_type *bus);
 extern int driver_probe_done(void);
 
-/* driverfs interface for exporting driver attributes */
+/* sysfs interface for exporting driver attributes */
 
 struct driver_attribute {
        struct attribute        attr;
index a41cc24568cadfa7cc2a6413cd1fe60a788bae77..7eb1d73fc5d1634ee535f777d7d5576b784e9180 100644 (file)
 #include <linux/ext4_fs.h>
 
 /*
- * With AGRESSIVE_TEST defined, the capacity of index/leaf blocks
+ * With AGGRESSIVE_TEST defined, the capacity of index/leaf blocks
  * becomes very small, so index split, in-depth growing and
  * other hard changes happen much more often.
  * This is for debug purposes only.
  */
-#define AGRESSIVE_TEST_
+#define AGGRESSIVE_TEST_
 
 /*
  * With EXTENTS_STATS defined, the number of blocks and extents
index 612472aaa79c1607159794a2257356bde263e9a0..7803014f3a11bae4f353e7b042c0e1835997c7be 100644 (file)
@@ -106,13 +106,18 @@ static inline void account_system_vtime(struct task_struct *tsk)
  * always balanced, so the interrupted value of ->hardirq_context
  * will always be restored.
  */
-#define irq_enter()                                    \
+#define __irq_enter()                                  \
        do {                                            \
                account_system_vtime(current);          \
                add_preempt_count(HARDIRQ_OFFSET);      \
                trace_hardirq_enter();                  \
        } while (0)
 
+/*
+ * Enter irq context (on NO_HZ, update jiffies):
+ */
+extern void irq_enter(void);
+
 /*
  * Exit irq context without processing softirqs:
  */
@@ -128,7 +133,7 @@ static inline void account_system_vtime(struct task_struct *tsk)
  */
 extern void irq_exit(void);
 
-#define nmi_enter()            do { lockdep_off(); irq_enter(); } while (0)
+#define nmi_enter()            do { lockdep_off(); __irq_enter(); } while (0)
 #define nmi_exit()             do { __irq_exit(); lockdep_on(); } while (0)
 
 #endif /* LINUX_HARDIRQ_H */
index fca93025ab5191db9a1d4aeb9734dbfa2f574a20..37f9279192a998f50641d81056a57692a8eaf538 100644 (file)
 #include <linux/list.h>
 #include <linux/wait.h>
 
+struct hrtimer_clock_base;
+struct hrtimer_cpu_base;
+
 /*
  * Mode arguments of xxx_hrtimer functions:
  */
 enum hrtimer_mode {
-       HRTIMER_ABS,    /* Time value is absolute */
-       HRTIMER_REL,    /* Time value is relative to now */
+       HRTIMER_MODE_ABS,       /* Time value is absolute */
+       HRTIMER_MODE_REL,       /* Time value is relative to now */
 };
 
+/*
+ * Return values for the callback function
+ */
 enum hrtimer_restart {
-       HRTIMER_NORESTART,
-       HRTIMER_RESTART,
+       HRTIMER_NORESTART,      /* Timer is not restarted */
+       HRTIMER_RESTART,        /* Timer must be restarted */
 };
 
-#define HRTIMER_INACTIVE       ((void *)1UL)
+/*
+ * hrtimer callback modes:
+ *
+ *     HRTIMER_CB_SOFTIRQ:             Callback must run in softirq context
+ *     HRTIMER_CB_IRQSAFE:             Callback may run in hardirq context
+ *     HRTIMER_CB_IRQSAFE_NO_RESTART:  Callback may run in hardirq context and
+ *                                     does not restart the timer
+ *     HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:  Callback must run in softirq context
+ *                                     Special mode for tick emultation
+ */
+enum hrtimer_cb_mode {
+       HRTIMER_CB_SOFTIRQ,
+       HRTIMER_CB_IRQSAFE,
+       HRTIMER_CB_IRQSAFE_NO_RESTART,
+       HRTIMER_CB_IRQSAFE_NO_SOFTIRQ,
+};
 
-struct hrtimer_base;
+/*
+ * Values to track state of the timer
+ *
+ * Possible states:
+ *
+ * 0x00                inactive
+ * 0x01                enqueued into rbtree
+ * 0x02                callback function running
+ * 0x04                callback pending (high resolution mode)
+ *
+ * Special case:
+ * 0x03                callback function running and enqueued
+ *             (was requeued on another CPU)
+ * The "callback function running and enqueued" status is only possible on
+ * SMP. It happens for example when a posix timer expired and the callback
+ * queued a signal. Between dropping the lock which protects the posix timer
+ * and reacquiring the base lock of the hrtimer, another CPU can deliver the
+ * signal and rearm the timer. We have to preserve the callback running state,
+ * as otherwise the timer could be removed before the softirq code finishes the
+ * the handling of the timer.
+ *
+ * The HRTIMER_STATE_ENQUEUE bit is always or'ed to the current state to
+ * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario.
+ *
+ * All state transitions are protected by cpu_base->lock.
+ */
+#define HRTIMER_STATE_INACTIVE 0x00
+#define HRTIMER_STATE_ENQUEUED 0x01
+#define HRTIMER_STATE_CALLBACK 0x02
+#define HRTIMER_STATE_PENDING  0x04
 
 /**
  * struct hrtimer - the basic hrtimer structure
@@ -46,14 +96,34 @@ struct hrtimer_base;
  *             which the timer is based.
  * @function:  timer expiry callback function
  * @base:      pointer to the timer base (per cpu and per clock)
+ * @state:     state information (See bit values above)
+ * @cb_mode:   high resolution timer feature to select the callback execution
+ *              mode
+ * @cb_entry:  list head to enqueue an expired timer into the callback list
+ * @start_site:        timer statistics field to store the site where the timer
+ *             was started
+ * @start_comm: timer statistics field to store the name of the process which
+ *             started the timer
+ * @start_pid: timer statistics field to store the pid of the task which
+ *             started the timer
  *
- * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
+ * The hrtimer structure must be initialized by hrtimer_init()
  */
 struct hrtimer {
-       struct rb_node          node;
-       ktime_t                 expires;
-       int                     (*function)(struct hrtimer *);
-       struct hrtimer_base     *base;
+       struct rb_node                  node;
+       ktime_t                         expires;
+       enum hrtimer_restart            (*function)(struct hrtimer *);
+       struct hrtimer_clock_base       *base;
+       unsigned long                   state;
+#ifdef CONFIG_HIGH_RES_TIMERS
+       enum hrtimer_cb_mode            cb_mode;
+       struct list_head                cb_entry;
+#endif
+#ifdef CONFIG_TIMER_STATS
+       void                            *start_site;
+       char                            start_comm[16];
+       int                             start_pid;
+#endif
 };
 
 /**
@@ -70,37 +140,114 @@ struct hrtimer_sleeper {
 
 /**
  * struct hrtimer_base - the timer base for a specific clock
- * @index:             clock type index for per_cpu support when moving a timer
- *                     to a base on another cpu.
- * @lock:              lock protecting the base and associated timers
+ * @index:             clock type index for per_cpu support when moving a
+ *                     timer to a base on another cpu.
  * @active:            red black tree root node for the active timers
  * @first:             pointer to the timer node which expires first
  * @resolution:                the resolution of the clock, in nanoseconds
  * @get_time:          function to retrieve the current time of the clock
  * @get_softirq_time:  function to retrieve the current time from the softirq
- * @curr_timer:                the timer which is executing a callback right now
  * @softirq_time:      the time when running the hrtimer queue in the softirq
- * @lock_key:          the lock_class_key for use with lockdep
+ * @cb_pending:                list of timers where the callback is pending
+ * @offset:            offset of this clock to the monotonic base
+ * @reprogram:         function to reprogram the timer event
  */
-struct hrtimer_base {
+struct hrtimer_clock_base {
+       struct hrtimer_cpu_base *cpu_base;
        clockid_t               index;
-       spinlock_t              lock;
        struct rb_root          active;
        struct rb_node          *first;
        ktime_t                 resolution;
        ktime_t                 (*get_time)(void);
        ktime_t                 (*get_softirq_time)(void);
-       struct hrtimer          *curr_timer;
        ktime_t                 softirq_time;
-       struct lock_class_key lock_key;
+#ifdef CONFIG_HIGH_RES_TIMERS
+       ktime_t                 offset;
+       int                     (*reprogram)(struct hrtimer *t,
+                                            struct hrtimer_clock_base *b,
+                                            ktime_t n);
+#endif
+};
+
+#define HRTIMER_MAX_CLOCK_BASES 2
+
+/*
+ * struct hrtimer_cpu_base - the per cpu clock bases
+ * @lock:              lock protecting the base and associated clock bases
+ *                     and timers
+ * @lock_key:          the lock_class_key for use with lockdep
+ * @clock_base:                array of clock bases for this cpu
+ * @curr_timer:                the timer which is executing a callback right now
+ * @expires_next:      absolute time of the next event which was scheduled
+ *                     via clock_set_next_event()
+ * @hres_active:       State of high resolution mode
+ * @check_clocks:      Indictator, when set evaluate time source and clock
+ *                     event devices whether high resolution mode can be
+ *                     activated.
+ * @cb_pending:                Expired timers are moved from the rbtree to this
+ *                     list in the timer interrupt. The list is processed
+ *                     in the softirq.
+ * @nr_events:         Total number of timer interrupt events
+ */
+struct hrtimer_cpu_base {
+       spinlock_t                      lock;
+       struct lock_class_key           lock_key;
+       struct hrtimer_clock_base       clock_base[HRTIMER_MAX_CLOCK_BASES];
+#ifdef CONFIG_HIGH_RES_TIMERS
+       ktime_t                         expires_next;
+       int                             hres_active;
+       struct list_head                cb_pending;
+       unsigned long                   nr_events;
+#endif
 };
 
+#ifdef CONFIG_HIGH_RES_TIMERS
+struct clock_event_device;
+
+extern void clock_was_set(void);
+extern void hrtimer_interrupt(struct clock_event_device *dev);
+
+/*
+ * In high resolution mode the time reference must be read accurate
+ */
+static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+{
+       return timer->base->get_time();
+}
+
+/*
+ * The resolution of the clocks. The resolution value is returned in
+ * the clock_getres() system call to give application programmers an
+ * idea of the (in)accuracy of timers. Timer values are rounded up to
+ * this resolution values.
+ */
+# define KTIME_HIGH_RES                (ktime_t) { .tv64 = 1 }
+# define KTIME_MONOTONIC_RES   KTIME_HIGH_RES
+
+#else
+
+# define KTIME_MONOTONIC_RES   KTIME_LOW_RES
+
 /*
  * clock_was_set() is a NOP for non- high-resolution systems. The
  * time-sorted order guarantees that a timer does not expire early and
  * is expired in the next softirq when the clock was advanced.
  */
-#define clock_was_set()                do { } while (0)
+static inline void clock_was_set(void) { }
+
+/*
+ * In non high resolution mode the time reference is taken from
+ * the base softirq time variable.
+ */
+static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+{
+       return timer->base->softirq_time;
+}
+
+#endif
+
+extern ktime_t ktime_get(void);
+extern ktime_t ktime_get_real(void);
 
 /* Exported timer functions: */
 
@@ -114,19 +261,33 @@ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
 extern int hrtimer_cancel(struct hrtimer *timer);
 extern int hrtimer_try_to_cancel(struct hrtimer *timer);
 
-#define hrtimer_restart(timer) hrtimer_start((timer), (timer)->expires, HRTIMER_ABS)
+static inline int hrtimer_restart(struct hrtimer *timer)
+{
+       return hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
+}
 
 /* Query timers: */
 extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
 extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
 
-#ifdef CONFIG_NO_IDLE_HZ
 extern ktime_t hrtimer_get_next_event(void);
-#endif
 
+/*
+ * A timer is active, when it is enqueued into the rbtree or the callback
+ * function is running.
+ */
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
-       return rb_parent(&timer->node) != &timer->node;
+       return timer->state != HRTIMER_STATE_INACTIVE;
+}
+
+/*
+ * Helper function to check, whether the timer is on one of the queues
+ */
+static inline int hrtimer_is_queued(struct hrtimer *timer)
+{
+       return timer->state &
+               (HRTIMER_STATE_ENQUEUED | HRTIMER_STATE_PENDING);
 }
 
 /* Forward a hrtimer so it expires after now: */
@@ -149,4 +310,53 @@ extern void hrtimer_run_queues(void);
 /* Bootup initialization: */
 extern void __init hrtimers_init(void);
 
+#if BITS_PER_LONG < 64
+extern unsigned long ktime_divns(const ktime_t kt, s64 div);
+#else /* BITS_PER_LONG < 64 */
+# define ktime_divns(kt, div)          (unsigned long)((kt).tv64 / (div))
+#endif
+
+/* Show pending timers: */
+extern void sysrq_timer_list_show(void);
+
+/*
+ * Timer-statistics info:
+ */
+#ifdef CONFIG_TIMER_STATS
+
+extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+                                    void *timerf, char * comm);
+
+static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
+{
+       timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+                                timer->function, timer->start_comm);
+}
+
+extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
+                                                void *addr);
+
+static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
+{
+       __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0));
+}
+
+static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
+{
+       timer->start_site = NULL;
+}
+#else
+static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
+{
+}
+
+static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
+{
+}
+
+static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
+{
+}
+#endif
+
 #endif
index 04e0fa97ac99aa1ae25a928aa6b49ab82875e93a..79c028251c70c29458110f9b4319164d505b7670 100644 (file)
@@ -636,7 +636,6 @@ typedef struct ide_drive_s {
        unsigned int    bios_cyl;       /* BIOS/fdisk/LILO number of cyls */
        unsigned int    cyl;            /* "real" number of cyls */
        unsigned int    drive_data;     /* use by tuneproc/selectproc */
-       unsigned int    usage;          /* current "open()" count for drive */
        unsigned int    failures;       /* current failure count */
        unsigned int    max_failures;   /* maximum allowed failure count */
        u64             probed_capacity;/* initial reported media capacity (ide-cd only currently) */
@@ -736,23 +735,22 @@ typedef struct hwif_s {
        int (*ide_dma_end)(ide_drive_t *drive);
        int (*ide_dma_check)(ide_drive_t *drive);
        int (*ide_dma_on)(ide_drive_t *drive);
-       int (*ide_dma_off_quietly)(ide_drive_t *drive);
+       void (*dma_off_quietly)(ide_drive_t *drive);
        int (*ide_dma_test_irq)(ide_drive_t *drive);
-       int (*ide_dma_host_on)(ide_drive_t *drive);
-       int (*ide_dma_host_off)(ide_drive_t *drive);
+       void (*ide_dma_clear_irq)(ide_drive_t *drive);
+       void (*dma_host_on)(ide_drive_t *drive);
+       void (*dma_host_off)(ide_drive_t *drive);
        int (*ide_dma_lostirq)(ide_drive_t *drive);
        int (*ide_dma_timeout)(ide_drive_t *drive);
 
        void (*OUTB)(u8 addr, unsigned long port);
        void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
        void (*OUTW)(u16 addr, unsigned long port);
-       void (*OUTL)(u32 addr, unsigned long port);
        void (*OUTSW)(unsigned long port, void *addr, u32 count);
        void (*OUTSL)(unsigned long port, void *addr, u32 count);
 
        u8  (*INB)(unsigned long port);
        u16 (*INW)(unsigned long port);
-       u32 (*INL)(unsigned long port);
        void (*INSW)(unsigned long port, void *addr, u32 count);
        void (*INSL)(unsigned long port, void *addr, u32 count);
 
@@ -774,7 +772,6 @@ typedef struct hwif_s {
        unsigned int cursg;
        unsigned int cursg_ofs;
 
-       int             mmio;           /* hosts iomio (0) or custom (2) select */
        int             rqsize;         /* max sectors per request */
        int             irq;            /* our irq number */
 
@@ -802,12 +799,11 @@ typedef struct hwif_s {
        unsigned        udma_four  : 1; /* 1=ATA-66 capable, 0=default */
        unsigned        no_lba48   : 1; /* 1 = cannot do LBA48 */
        unsigned        no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
-       unsigned        no_dsc     : 1; /* 0 default, 1 dsc_overlap disabled */
        unsigned        auto_poll  : 1; /* supports nop auto-poll */
        unsigned        sg_mapped  : 1; /* sg_table and sg_nents are ready */
        unsigned        no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
        unsigned        err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
-       unsigned        atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */
+       unsigned        mmio       : 1; /* host uses MMIO */
 
        struct device   gendev;
        struct completion gendev_rel_comp; /* To deal with device release() */
@@ -1280,8 +1276,9 @@ int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *);
 int __ide_dma_bad_drive(ide_drive_t *);
 int __ide_dma_good_drive(ide_drive_t *);
 int ide_use_dma(ide_drive_t *);
-int __ide_dma_off(ide_drive_t *);
+void ide_dma_off(ide_drive_t *);
 void ide_dma_verbose(ide_drive_t *);
+int ide_set_dma(ide_drive_t *);
 ide_startstop_t ide_dma_intr(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1291,9 +1288,9 @@ extern void ide_destroy_dmatable(ide_drive_t *);
 extern int ide_release_dma(ide_hwif_t *);
 extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int);
 
-extern int __ide_dma_host_off(ide_drive_t *);
-extern int __ide_dma_off_quietly(ide_drive_t *);
-extern int __ide_dma_host_on(ide_drive_t *);
+void ide_dma_host_off(ide_drive_t *);
+void ide_dma_off_quietly(ide_drive_t *);
+void ide_dma_host_on(ide_drive_t *);
 extern int __ide_dma_on(ide_drive_t *);
 extern int __ide_dma_check(ide_drive_t *);
 extern int ide_dma_setup(ide_drive_t *);
@@ -1305,8 +1302,9 @@ extern int __ide_dma_timeout(ide_drive_t *);
 
 #else
 static inline int ide_use_dma(ide_drive_t *drive) { return 0; }
-static inline int __ide_dma_off(ide_drive_t *drive) { return 0; }
+static inline void ide_dma_off(ide_drive_t *drive) { ; }
 static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
+static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifndef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1354,6 +1352,7 @@ extern int ide_dma_enable(ide_drive_t *drive);
 extern char *ide_xfer_verbose(u8 xfer_rate);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
 extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
+int ide_use_fast_pio(ide_drive_t *);
 
 u8 ide_dump_status(ide_drive_t *, const char *, u8);
 
@@ -1367,7 +1366,6 @@ typedef struct ide_pio_data_s {
        u8 pio_mode;
        u8 use_iordy;
        u8 overridden;
-       u8 blacklisted;
        unsigned int cycle_time;
 } ide_pio_data_t;
 
index 5a8ba0b8ccbae860bc8d36b1f6082d94e51402fb..e5ea1411050bfec4c8c1f9d2c6ea0899159cc668 100644 (file)
@@ -42,6 +42,8 @@
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
+ * IRQF_PERCPU - Interrupt is per cpu
+ * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
  */
 #define IRQF_DISABLED          0x00000020
 #define IRQF_SAMPLE_RANDOM     0x00000040
@@ -49,6 +51,7 @@
 #define IRQF_PROBE_SHARED      0x00000100
 #define IRQF_TIMER             0x00000200
 #define IRQF_PERCPU            0x00000400
+#define IRQF_NOBALANCING       0x00000800
 
 /*
  * Migration helpers. Scheduled for removal in 1/2007
@@ -239,6 +242,9 @@ enum
        BLOCK_SOFTIRQ,
        TASKLET_SOFTIRQ,
        SCHED_SOFTIRQ,
+#ifdef CONFIG_HIGH_RES_TIMERS
+       HRTIMER_SOFTIRQ,
+#endif
 };
 
 /* softirq mask and active fields moved to irq_cpustat_t in
index 5504b671357f2cf3adf476244cc81b06f84af137..1939d42c21d266f66ebfa62b4b20e0db1277a599 100644 (file)
@@ -31,7 +31,7 @@ typedef       void fastcall (*irq_flow_handler_t)(unsigned int irq,
 /*
  * IRQ line status.
  *
- * Bits 0-16 are reserved for the IRQF_* bits in linux/interrupt.h
+ * Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h
  *
  * IRQ types
  */
@@ -45,28 +45,30 @@ typedef     void fastcall (*irq_flow_handler_t)(unsigned int irq,
 #define IRQ_TYPE_PROBE         0x00000010      /* Probing in progress */
 
 /* Internal flags */
-#define IRQ_INPROGRESS         0x00010000      /* IRQ handler active - do not enter! */
-#define IRQ_DISABLED           0x00020000      /* IRQ disabled - do not enter! */
-#define IRQ_PENDING            0x00040000      /* IRQ pending - replay on enable */
-#define IRQ_REPLAY             0x00080000      /* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT         0x00100000      /* IRQ is being autodetected */
-#define IRQ_WAITING            0x00200000      /* IRQ not yet seen - for autodetection */
-#define IRQ_LEVEL              0x00400000      /* IRQ level triggered */
-#define IRQ_MASKED             0x00800000      /* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU            0x01000000      /* IRQ is per CPU */
+#define IRQ_INPROGRESS         0x00000100      /* IRQ handler active - do not enter! */
+#define IRQ_DISABLED           0x00000200      /* IRQ disabled - do not enter! */
+#define IRQ_PENDING            0x00000400      /* IRQ pending - replay on enable */
+#define IRQ_REPLAY             0x00000800      /* IRQ has been replayed but not acked yet */
+#define IRQ_AUTODETECT         0x00001000      /* IRQ is being autodetected */
+#define IRQ_WAITING            0x00002000      /* IRQ not yet seen - for autodetection */
+#define IRQ_LEVEL              0x00004000      /* IRQ level triggered */
+#define IRQ_MASKED             0x00008000      /* IRQ masked - shouldn't be seen again */
+#define IRQ_PER_CPU            0x00010000      /* IRQ is per CPU */
+#define IRQ_NOPROBE            0x00020000      /* IRQ is not valid for probing */
+#define IRQ_NOREQUEST          0x00040000      /* IRQ cannot be requested */
+#define IRQ_NOAUTOEN           0x00080000      /* IRQ will not be enabled on request irq */
+#define IRQ_WAKEUP             0x00100000      /* IRQ triggers system wakeup */
+#define IRQ_MOVE_PENDING       0x00200000      /* need to re-target IRQ destination */
+#define IRQ_NO_BALANCING       0x00400000      /* IRQ is excluded from balancing */
+
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
+# define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
 #else
 # define CHECK_IRQ_PER_CPU(var) 0
+# define IRQ_NO_BALANCING_MASK IRQ_NO_BALANCING
 #endif
 
-#define IRQ_NOPROBE            0x02000000      /* IRQ is not valid for probing */
-#define IRQ_NOREQUEST          0x04000000      /* IRQ cannot be requested */
-#define IRQ_NOAUTOEN           0x08000000      /* IRQ will not be enabled on request irq */
-#define IRQ_DELAYED_DISABLE    0x10000000      /* IRQ disable (masking) happens delayed. */
-#define IRQ_WAKEUP             0x20000000      /* IRQ triggers system wakeup */
-#define IRQ_MOVE_PENDING       0x40000000      /* need to re-target IRQ destination */
-
 struct proc_dir_entry;
 struct msi_desc;
 
@@ -127,6 +129,7 @@ struct irq_chip {
  *
  * @handle_irq:                highlevel irq-events handler [if NULL, __do_IRQ()]
  * @chip:              low level interrupt hardware access
+ * @msi_desc:          MSI descriptor
  * @handler_data:      per-IRQ data for the irq_chip methods
  * @chip_data:         platform-specific per-chip private data for the chip
  *                     methods, to allow shared chip implementations
@@ -235,11 +238,21 @@ static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
 
 #endif /* CONFIG_GENERIC_PENDING_IRQ */
 
+extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
+extern int irq_can_set_affinity(unsigned int irq);
+
 #else /* CONFIG_SMP */
 
 #define move_native_irq(x)
 #define move_masked_irq(x)
 
+static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+       return -EINVAL;
+}
+
+static inline int irq_can_set_affinity(unsigned int irq) { return 0; }
+
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_IRQBALANCE
@@ -261,6 +274,11 @@ static inline int select_smp_affinity(unsigned int irq)
 
 extern int no_irq_affinity;
 
+static inline int irq_balancing_disabled(unsigned int irq)
+{
+       return irq_desc[irq].status & IRQ_NO_BALANCING_MASK;
+}
+
 /* Handle irq action chains: */
 extern int handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
diff --git a/include/linux/jffs.h b/include/linux/jffs.h
deleted file mode 100644 (file)
index 9221321..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: jffs.h,v 1.20 2001/09/18 21:33:37 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_H__
-#define __LINUX_JFFS_H__
-
-#include <linux/types.h>
-#include <linux/completion.h>
-
-#define JFFS_VERSION_STRING "1.0"
-
-/* This is a magic number that is used as an identification number for
-   this file system.  It is written to the super_block structure.  */
-#define JFFS_MAGIC_SB_BITMASK 0x07c0  /* 1984 */
-
-/* This is a magic number that every on-flash raw inode begins with.  */
-#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */
-
-/* These two bitmasks are the valid ones for the flash memories we have
-   for the moment.  */
-#define JFFS_EMPTY_BITMASK 0xffffffff
-#define JFFS_DIRTY_BITMASK 0x00000000
-
-/* This is the inode number of the root node.  */
-#define JFFS_MIN_INO 1
-
-/* How many slots in the file hash table should we have?  */
-#define JFFS_HASH_SIZE 40
-
-/* Don't use more than 254 bytes as the maximum allowed length of a file's
-   name due to errors that could occur during the scanning of the flash
-   memory. In fact, a name length of 255 or 0xff, could be the result of
-   an uncompleted write.  For instance, if a raw inode is written to the
-   flash memory and there is a power lossage just before the length of
-   the name is written, the length 255 would be interpreted as an illegal
-   value.  */
-#define JFFS_MAX_NAME_LEN 254
-
-/* Commands for ioctl().  */
-#define JFFS_IOCTL_MAGIC 't'
-#define JFFS_PRINT_HASH _IO(JFFS_IOCTL_MAGIC, 90)
-#define JFFS_PRINT_TREE _IO(JFFS_IOCTL_MAGIC, 91)
-#define JFFS_GET_STATUS _IO(JFFS_IOCTL_MAGIC, 92)
-
-/* XXX: This is something that we should try to get rid of in the future.  */
-#define JFFS_MODIFY_INODE 0x01
-#define JFFS_MODIFY_NAME  0x02
-#define JFFS_MODIFY_DATA  0x04
-#define JFFS_MODIFY_EXIST 0x08
-
-struct jffs_control;
-
-/* The JFFS raw inode structure: Used for storage on physical media.  */
-/* Perhaps the uid, gid, atime, mtime and ctime members should have
-   more space due to future changes in the Linux kernel. Anyhow, since
-   a user of this filesystem probably have to fix a large number of
-   other things, we have decided to not be forward compatible.  */
-struct jffs_raw_inode
-{
-       __u32 magic;      /* A constant magic number.  */
-       __u32 ino;        /* Inode number.  */
-       __u32 pino;       /* Parent's inode number.  */
-       __u32 version;    /* Version number.  */
-       __u32 mode;       /* The file's type or mode.  */
-       __u16 uid;        /* The file's owner.  */
-       __u16 gid;        /* The file's group.  */
-       __u32 atime;      /* Last access time.  */
-       __u32 mtime;      /* Last modification time.  */
-       __u32 ctime;      /* Creation time.  */
-       __u32 offset;     /* Where to begin to write.  */
-       __u32 dsize;      /* Size of the node's data.  */
-       __u32 rsize;      /* How much are going to be replaced?  */
-       __u8 nsize;       /* Name length.  */
-       __u8 nlink;       /* Number of links.  */
-       __u8 spare : 6;   /* For future use.  */
-       __u8 rename : 1;  /* Rename to a name of an already existing file?  */
-       __u8 deleted : 1; /* Has this file been deleted?  */
-       __u8 accurate;    /* The inode is obsolete if accurate == 0.  */
-       __u32 dchksum;    /* Checksum for the data.  */
-       __u16 nchksum;    /* Checksum for the name.  */
-       __u16 chksum;     /* Checksum for the raw inode.  */
-};
-
-/* Define the offset of the accurate byte in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_ACCURATE_OFFSET (sizeof(struct jffs_raw_inode) \
-                                       - 2 * sizeof(__u32) - sizeof(__u8))
-
-/* Define the offset of the chksum member in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_CHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
-                                     - sizeof(__u16))
-
-/* Define the offset of the dchksum member in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_DCHKSUM_OFFSET (sizeof(struct jffs_raw_inode)   \
-                                      - sizeof(__u16) - sizeof(__u16) \
-                                      - sizeof(__u32))
-
-
-/* The RAM representation of the node.  The names of pointers to
-   jffs_nodes are very often just called `n' in the source code.  */
-struct jffs_node
-{
-       __u32 ino;          /* Inode number.  */
-       __u32 version;      /* Version number.  */
-       __u32 data_offset;  /* Logic location of the data to insert.  */
-       __u32 data_size;    /* The amount of data this node inserts.  */
-       __u32 removed_size; /* The amount of data that this node removes.  */
-       __u32 fm_offset;    /* Physical location of the data in the actual
-                              flash memory data chunk.  */
-       __u8 name_size;     /* Size of the name.  */
-       struct jffs_fm *fm; /* Physical memory information.  */
-       struct jffs_node *version_prev;
-       struct jffs_node *version_next;
-       struct jffs_node *range_prev;
-       struct jffs_node *range_next;
-};
-
-
-/* The RAM representation of a file (plain files, directories,
-   links, etc.).  Pointers to jffs_files are normally named `f'
-   in the JFFS source code.  */
-struct jffs_file
-{
-       __u32 ino;    /* Inode number.  */
-       __u32 pino;   /* Parent's inode number.  */
-       __u32 mode;   /* file_type, mode  */
-       __u16 uid;    /* owner  */
-       __u16 gid;    /* group  */
-       __u32 atime;  /* Last access time.  */
-       __u32 mtime;  /* Last modification time.  */
-       __u32 ctime;  /* Creation time.  */
-       __u8 nsize;   /* Name length.  */
-       __u8 nlink;   /* Number of links.  */
-       __u8 deleted; /* Has this file been deleted?  */
-       char *name;   /* The name of this file; NULL-terminated.  */
-       __u32 size;   /* The total size of the file's data.  */
-       __u32 highest_version; /* The highest version number of this file.  */
-       struct jffs_control *c;
-       struct jffs_file *parent;   /* Reference to the parent directory.  */
-       struct jffs_file *children; /* Always NULL for plain files.  */
-       struct jffs_file *sibling_prev; /* Siblings in the same directory.  */
-       struct jffs_file *sibling_next;
-       struct list_head hash;    /* hash list.  */
-       struct jffs_node *range_head;   /* The final data.  */
-       struct jffs_node *range_tail;   /* The first data.  */
-       struct jffs_node *version_head; /* The youngest node.  */
-       struct jffs_node *version_tail; /* The oldest node.  */
-};
-
-
-/* This is just a definition of a simple list used for keeping track of
-   files deleted due to a rename.  This list is only used during the
-   mounting of the file system and only if there have been rename operations
-   earlier.  */
-struct jffs_delete_list
-{
-       __u32 ino;
-       struct jffs_delete_list *next;
-};
-
-
-/* A struct for the overall file system control.  Pointers to
-   jffs_control structs are named `c' in the source code.  */
-struct jffs_control
-{
-       struct super_block *sb;         /* Reference to the VFS super block.  */
-       struct jffs_file *root;         /* The root directory file.  */
-       struct list_head *hash;         /* Hash table for finding files by ino.  */
-       struct jffs_fmcontrol *fmc;     /* Flash memory control structure.  */
-       __u32 hash_len;                 /* The size of the hash table.  */
-       __u32 next_ino;                 /* Next inode number to use for new files.  */
-       __u16 building_fs;              /* Is the file system being built right now?  */
-       struct jffs_delete_list *delete_list; /* Track deleted files.  */
-       pid_t thread_pid;               /* GC thread's PID */
-       struct task_struct *gc_task;    /* GC task struct */
-       struct completion gc_thread_comp; /* GC thread exit mutex */
-       __u32 gc_minfree_threshold;     /* GC trigger thresholds */
-       __u32 gc_maxdirty_threshold;
-};
-
-
-/* Used to inform about flash status.  */
-struct jffs_flash_status
-{
-       __u32 size;
-       __u32 used;
-       __u32 dirty;
-       __u32 begin;
-       __u32 end;
-};
-
-/* This stuff could be used for finding memory leaks.  */
-#define JFFS_MEMORY_DEBUG 0
-
-extern long no_jffs_node;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-extern long no_jffs_control;
-extern long no_jffs_raw_inode;
-extern long no_jffs_node_ref;
-extern long no_jffs_fm;
-extern long no_jffs_fmcontrol;
-extern long no_hash;
-extern long no_name;
-#define DJM(x) x
-#else
-#define DJM(x)
-#endif
-
-#endif /* __LINUX_JFFS_H__ */
index 0ec6e28bccd27b7d2861f5eb442d5b06610d97f3..c080f61fb024fb053e111a8878d9c7b12788c001 100644 (file)
@@ -142,13 +142,13 @@ static inline u64 get_jiffies_64(void)
  *
  * And some not so obvious.
  *
- * Note that we don't want to return MAX_LONG, because
+ * Note that we don't want to return LONG_MAX, because
  * for various timeout reasons we often end up having
  * to wait "jiffies+1" in order to guarantee that we wait
  * at _least_ "jiffies" - so "jiffies+1" had better still
  * be positive.
  */
-#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)
 
 /*
  * We want to do realistic conversions of time so we need to use the same
@@ -259,207 +259,23 @@ static inline u64 get_jiffies_64(void)
 #endif
 
 /*
- * Convert jiffies to milliseconds and back.
- *
- * Avoid unnecessary multiplications/divisions in the
- * two most common HZ cases:
- */
-static inline unsigned int jiffies_to_msecs(const unsigned long j)
-{
-#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
-       return (MSEC_PER_SEC / HZ) * j;
-#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
-       return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
-#else
-       return (j * MSEC_PER_SEC) / HZ;
-#endif
-}
-
-static inline unsigned int jiffies_to_usecs(const unsigned long j)
-{
-#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
-       return (USEC_PER_SEC / HZ) * j;
-#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
-       return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
-#else
-       return (j * USEC_PER_SEC) / HZ;
-#endif
-}
-
-static inline unsigned long msecs_to_jiffies(const unsigned int m)
-{
-       if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
-               return MAX_JIFFY_OFFSET;
-#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
-       return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
-#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
-       return m * (HZ / MSEC_PER_SEC);
-#else
-       return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
-#endif
-}
-
-static inline unsigned long usecs_to_jiffies(const unsigned int u)
-{
-       if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
-               return MAX_JIFFY_OFFSET;
-#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
-       return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
-#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
-       return u * (HZ / USEC_PER_SEC);
-#else
-       return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
-#endif
-}
-
-/*
- * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
- * that a remainder subtract here would not do the right thing as the
- * resolution values don't fall on second boundries.  I.e. the line:
- * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
- *
- * Rather, we just shift the bits off the right.
- *
- * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
- * value to a scaled second value.
- */
-static __inline__ unsigned long
-timespec_to_jiffies(const struct timespec *value)
-{
-       unsigned long sec = value->tv_sec;
-       long nsec = value->tv_nsec + TICK_NSEC - 1;
-
-       if (sec >= MAX_SEC_IN_JIFFIES){
-               sec = MAX_SEC_IN_JIFFIES;
-               nsec = 0;
-       }
-       return (((u64)sec * SEC_CONVERSION) +
-               (((u64)nsec * NSEC_CONVERSION) >>
-                (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-
-}
-
-static __inline__ void
-jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
-{
-       /*
-        * Convert jiffies to nanoseconds and separate with
-        * one divide.
-        */
-       u64 nsec = (u64)jiffies * TICK_NSEC;
-       value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec);
-}
-
-/* Same for "timeval"
- *
- * Well, almost.  The problem here is that the real system resolution is
- * in nanoseconds and the value being converted is in micro seconds.
- * Also for some machines (those that use HZ = 1024, in-particular),
- * there is a LARGE error in the tick size in microseconds.
-
- * The solution we use is to do the rounding AFTER we convert the
- * microsecond part.  Thus the USEC_ROUND, the bits to be shifted off.
- * Instruction wise, this should cost only an additional add with carry
- * instruction above the way it was done above.
- */
-static __inline__ unsigned long
-timeval_to_jiffies(const struct timeval *value)
-{
-       unsigned long sec = value->tv_sec;
-       long usec = value->tv_usec;
-
-       if (sec >= MAX_SEC_IN_JIFFIES){
-               sec = MAX_SEC_IN_JIFFIES;
-               usec = 0;
-       }
-       return (((u64)sec * SEC_CONVERSION) +
-               (((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
-                (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-}
-
-static __inline__ void
-jiffies_to_timeval(const unsigned long jiffies, struct timeval *value)
-{
-       /*
-        * Convert jiffies to nanoseconds and separate with
-        * one divide.
-        */
-       u64 nsec = (u64)jiffies * TICK_NSEC;
-       long tv_usec;
-
-       value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
-       tv_usec /= NSEC_PER_USEC;
-       value->tv_usec = tv_usec;
-}
-
-/*
- * Convert jiffies/jiffies_64 to clock_t and back.
+ * Convert various time units to each other:
  */
-static inline clock_t jiffies_to_clock_t(long x)
-{
-#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
-       return x / (HZ / USER_HZ);
-#else
-       u64 tmp = (u64)x * TICK_NSEC;
-       do_div(tmp, (NSEC_PER_SEC / USER_HZ));
-       return (long)tmp;
-#endif
-}
-
-static inline unsigned long clock_t_to_jiffies(unsigned long x)
-{
-#if (HZ % USER_HZ)==0
-       if (x >= ~0UL / (HZ / USER_HZ))
-               return ~0UL;
-       return x * (HZ / USER_HZ);
-#else
-       u64 jif;
-
-       /* Don't worry about loss of precision here .. */
-       if (x >= ~0UL / HZ * USER_HZ)
-               return ~0UL;
-
-       /* .. but do try to contain it here */
-       jif = x * (u64) HZ;
-       do_div(jif, USER_HZ);
-       return jif;
-#endif
-}
-
-static inline u64 jiffies_64_to_clock_t(u64 x)
-{
-#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
-       do_div(x, HZ / USER_HZ);
-#else
-       /*
-        * There are better ways that don't overflow early,
-        * but even this doesn't overflow in hundreds of years
-        * in 64 bits, so..
-        */
-       x *= TICK_NSEC;
-       do_div(x, (NSEC_PER_SEC / USER_HZ));
-#endif
-       return x;
-}
-
-static inline u64 nsec_to_clock_t(u64 x)
-{
-#if (NSEC_PER_SEC % USER_HZ) == 0
-       do_div(x, (NSEC_PER_SEC / USER_HZ));
-#elif (USER_HZ % 512) == 0
-       x *= USER_HZ/512;
-       do_div(x, (NSEC_PER_SEC / 512));
-#else
-       /*
-         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
-         * overflow after 64.99 years.
-         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
-         */
-       x *= 9;
-       do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2))
-                                 / USER_HZ));
-#endif
-       return x;
-}
+extern unsigned int jiffies_to_msecs(const unsigned long j);
+extern unsigned int jiffies_to_usecs(const unsigned long j);
+extern unsigned long msecs_to_jiffies(const unsigned int m);
+extern unsigned long usecs_to_jiffies(const unsigned int u);
+extern unsigned long timespec_to_jiffies(const struct timespec *value);
+extern void jiffies_to_timespec(const unsigned long jiffies,
+                               struct timespec *value);
+extern unsigned long timeval_to_jiffies(const struct timeval *value);
+extern void jiffies_to_timeval(const unsigned long jiffies,
+                              struct timeval *value);
+extern clock_t jiffies_to_clock_t(long x);
+extern unsigned long clock_t_to_jiffies(unsigned long x);
+extern u64 jiffies_64_to_clock_t(u64 x);
+extern u64 nsec_to_clock_t(u64 x);
+
+#define TIMESTAMP_SIZE 30
 
 #endif
index d02425cdd801c28d94cef85666bdc564ae6c867e..696e5ec63f77b83fdb81cf35299783633637736a 100644 (file)
@@ -125,6 +125,7 @@ extern struct kimage *kexec_crash_image;
 #define KEXEC_ARCH_PPC     (20 << 16)
 #define KEXEC_ARCH_PPC64   (21 << 16)
 #define KEXEC_ARCH_IA_64   (50 << 16)
+#define KEXEC_ARCH_ARM     (40 << 16)
 #define KEXEC_ARCH_S390    (22 << 16)
 #define KEXEC_ARCH_SH      (42 << 16)
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
index 10f505c8431dc320f46d77a88095df20cb475cb8..cc8e674ae27ad3b7a4414773d9bf010e7c91cde8 100644 (file)
 #ifdef CONFIG_KMOD
 /* modprobe exit status on success, -ve on error.  Return value
  * usually useless though. */
+extern void kmod_sysfs_init(void);
 extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
 #else
+static inline void kmod_sysfs_init(void) {};
 static inline int request_module(const char * name, ...) { return -ENOSYS; }
 #endif
 
index 7444a63262318934415604a98b96d94c5bd5964b..c68c7ac6b2323601321f80910f8b2e7a19e03709 100644 (file)
@@ -261,8 +261,7 @@ static inline s64 ktime_to_ns(const ktime_t kt)
  * idea of the (in)accuracy of timers. Timer values are rounded up to
  * this resolution values.
  */
-#define KTIME_REALTIME_RES     (ktime_t){ .tv64 = TICK_NSEC }
-#define KTIME_MONOTONIC_RES    (ktime_t){ .tv64 = TICK_NSEC }
+#define KTIME_LOW_RES          (ktime_t){ .tv64 = TICK_NSEC }
 
 /* Get the monotonic time in timespec format: */
 extern void ktime_get_ts(struct timespec *ts);
index 596e0c18887db5ce778ef1c9defd038383d9febe..86762a9f52ba19bb4622662264750d8c6b943646 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/ata.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
+#include <linux/acpi.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -172,6 +173,7 @@ enum {
        ATA_FLAG_DEBUGMSG       = (1 << 13),
        ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
        ATA_FLAG_IGN_SIMPLEX    = (1 << 15), /* ignore SIMPLEX */
+       ATA_FLAG_NO_IORDY       = (1 << 16), /* controller lacks iordy */
 
        /* The following flag belongs to ap->pflags but is kept in
         * ap->flags because it's referenced in many LLDs and will be
@@ -494,6 +496,10 @@ struct ata_device {
        /* error history */
        struct ata_ering        ering;
        unsigned int            horkage;        /* List of broken features */
+#ifdef CONFIG_SATA_ACPI
+       /* ACPI objects info */
+       acpi_handle obj_handle;
+#endif
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
index 99922bedfcc90acaef644369aee3d5e126b7d46d..57e641e19a8106122783073291cf53adfc36acd0 100644 (file)
@@ -152,7 +152,7 @@ unsigned long __roundup_pow_of_two(unsigned long n)
  * roundup_pow_of_two - round the given value up to nearest power of two
  * @n - parameter
  *
- * round the given balue up to the nearest power of two
+ * round the given value up to the nearest power of two
  * - the result is undefined when n == 0
  * - this can be used to initialise global variables from constant data
  */
index 419d3ef293dd996ba4ee3fda9501feebdd13e0aa..95679eb8571e25534c88729bd5b86654944729d1 100644 (file)
@@ -76,8 +76,6 @@ void sort_extable(struct exception_table_entry *start,
                  struct exception_table_entry *finish);
 void sort_main_extable(void);
 
-extern struct subsystem module_subsys;
-
 #ifdef MODULE
 #define MODULE_GENERIC_TABLE(gtype,name)                       \
 extern const struct gtype##_id __mod_##gtype##_table           \
@@ -467,10 +465,6 @@ int unregister_module_notifier(struct notifier_block * nb);
 
 extern void print_modules(void);
 
-struct device_driver;
-void module_add_driver(struct module *, struct device_driver *);
-void module_remove_driver(struct device_driver *);
-
 #else /* !CONFIG_MODULES... */
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
@@ -568,18 +562,59 @@ static inline void print_modules(void)
 {
 }
 
+#endif /* CONFIG_MODULES */
+
 struct device_driver;
+#ifdef CONFIG_SYSFS
 struct module;
 
-static inline void module_add_driver(struct module *module, struct device_driver *driver)
+extern struct subsystem module_subsys;
+
+int mod_sysfs_init(struct module *mod);
+int mod_sysfs_setup(struct module *mod,
+                          struct kernel_param *kparam,
+                          unsigned int num_params);
+int module_add_modinfo_attrs(struct module *mod);
+void module_remove_modinfo_attrs(struct module *mod);
+
+#else /* !CONFIG_SYSFS */
+
+static inline int mod_sysfs_init(struct module *mod)
 {
+       return 0;
 }
 
-static inline void module_remove_driver(struct device_driver *driver)
+static inline int mod_sysfs_setup(struct module *mod,
+                          struct kernel_param *kparam,
+                          unsigned int num_params)
 {
+       return 0;
 }
 
-#endif /* CONFIG_MODULES */
+static inline int module_add_modinfo_attrs(struct module *mod)
+{
+       return 0;
+}
+
+static inline void module_remove_modinfo_attrs(struct module *mod)
+{ }
+
+#endif /* CONFIG_SYSFS */
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
+
+void module_add_driver(struct module *mod, struct device_driver *drv);
+void module_remove_driver(struct device_driver *drv);
+
+#else /* not both CONFIG_SYSFS && CONFIG_MODULES */
+
+static inline void module_add_driver(struct module *mod, struct device_driver *drv)
+{ }
+
+static inline void module_remove_driver(struct device_driver *drv)
+{ }
+
+#endif
 
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
 
index 4a189dadb1607a0984cb41cac9f389d2a86afc65..c83588c8d08b25aacbc72edc2d3529912c674248 100644 (file)
@@ -59,7 +59,7 @@ struct kparam_array
 };
 
 /* This is the fundamental function for registering boot/module
-   parameters.  perm sets the visibility in driverfs: 000 means it's
+   parameters.  perm sets the visibility in sysfs: 000 means it's
    not there, read bits mean it's readable, write bits mean it's
    writable. */
 #define __module_param_call(prefix, name, set, get, arg, perm)         \
@@ -169,10 +169,22 @@ extern int param_get_string(char *buffer, struct kernel_param *kp);
 
 struct module;
 
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
 extern int module_param_sysfs_setup(struct module *mod,
                                    struct kernel_param *kparam,
                                    unsigned int num_params);
 
 extern void module_param_sysfs_remove(struct module *mod);
+#else
+static inline int module_param_sysfs_setup(struct module *mod,
+                            struct kernel_param *kparam,
+                            unsigned int num_params)
+{
+       return 0;
+}
+
+static inline void module_param_sysfs_remove(struct module *mod)
+{ }
+#endif
 
 #endif /* _LINUX_MODULE_PARAMS_H */
index 1221b7c44158e21bfc653876d22c83c37cf0b64c..fff8c53e54341a106592f210fe8fc78bfb170967 100644 (file)
@@ -92,6 +92,13 @@ struct nand_bbt_descr {
  */
 #define ONENAND_BADBLOCK_POS   0
 
+/*
+ * Bad block scanning errors
+ */
+#define ONENAND_BBT_READ_ERROR         1
+#define ONENAND_BBT_READ_ECC_ERROR     2
+#define ONENAND_BBT_READ_FATAL_ERROR   4
+
 /**
  * struct bbm_info - [GENERIC] Bad Block Table data structure
  * @bbt_erase_shift:   [INTERN] number of address bits in a bbt entry
index 28d461d862bda1d042055c463613a1a87338b698..81f3a314dd76dfc6057ef9f7a82fff3b4d08c652 100644 (file)
@@ -183,7 +183,7 @@ typedef union {
 struct map_info {
        char *name;
        unsigned long size;
-       unsigned long phys;
+       resource_size_t phys;
 #define NO_XIP (-1UL)
 
        void __iomem *virt;
index d644e57703ad0ef256b2099af0b883c06959ce35..6a8570be331bbdb3deb587983953485427901ef5 100644 (file)
@@ -85,6 +85,10 @@ typedef enum {
  *             mode = MTD_OOB_PLACE)
  * @datbuf:    data buffer - if NULL only oob data are read/written
  * @oobbuf:    oob data buffer
+ *
+ * Note, it is allowed to read more then one OOB area at one go, but not write.
+ * The interface assumes that the OOB write requests program only one page's
+ * OOB area.
  */
 struct mtd_oob_ops {
        mtd_oob_mode_t  mode;
@@ -117,18 +121,6 @@ struct mtd_info {
        u_int32_t writesize;
 
        u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
-       u_int32_t ecctype;
-       u_int32_t eccsize;
-
-       /*
-        * Reuse some of the above unused fields in the case of NOR flash
-        * with configurable programming regions to avoid modifying the
-        * user visible structure layout/size.  Only valid when the
-        * MTD_PROGRAM_REGIONS flag is set.
-        * (Maybe we should have an union for those?)
-        */
-#define MTD_PROGREGION_CTRLMODE_VALID(mtd)  (mtd)->oobsize
-#define MTD_PROGREGION_CTRLMODE_INVALID(mtd)  (mtd)->ecctype
 
        // Kernel-only stuff starts here.
        char *name;
index 2071b02f0526f6507d9355015939f09029a51586..97523887fe5d22a9d0e2af49142dc62cdb63e806 100644 (file)
@@ -343,6 +343,7 @@ struct nand_buffers {
  * @options:           [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
  *                     special functionality. See the defines for further explanation
  * @badblockpos:       [INTERN] position of the bad block marker in the oob area
+ * @cellinfo:          [INTERN] MLC/multichip data from chip ident
  * @numchips:          [INTERN] number of physical chips
  * @chipsize:          [INTERN] the size of one chip for multichip arrays
  * @pagemask:          [INTERN] page number mask = number of (pages / chip) - 1
index f775a7af3890087215ce16504a8da68f513310dd..d8af8a95e58d86305227afb9a8385911b4b67b18 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/include/linux/mtd/onenand.h
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -42,14 +42,10 @@ typedef enum {
 
 /**
  * struct onenand_bufferram - OneNAND BufferRAM Data
- * @block:             block address in BufferRAM
- * @page:              page address in BufferRAM
- * @valid:             valid flag
+ * @blockpage:         block & page address in BufferRAM
  */
 struct onenand_bufferram {
-       int block;
-       int page;
-       int valid;
+       int     blockpage;
 };
 
 /**
@@ -63,7 +59,6 @@ struct onenand_bufferram {
  *                     partly be set to inform onenand_scan about
  * @erase_shift:       [INTERN] number of address bits in a block
  * @page_shift:                [INTERN] number of address bits in a page
- * @ppb_shift:         [INTERN] number of address bits in a pages per block
  * @page_mask:         [INTERN] a page per block mask
  * @bufferram_index:   [INTERN] BufferRAM index
  * @bufferram:         [INTERN] BufferRAM info
@@ -103,7 +98,6 @@ struct onenand_chip {
 
        unsigned int            erase_shift;
        unsigned int            page_shift;
-       unsigned int            ppb_shift;      /* Pages per block shift */
        unsigned int            page_mask;
 
        unsigned int            bufferram_index;
@@ -150,6 +144,9 @@ struct onenand_chip {
 #define ONENAND_SET_SYS_CFG1(v, this)                                  \
        (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))
 
+#define ONENAND_IS_DDP(this)                                           \
+       (this->device_id & ONENAND_DEVICE_IS_DDP)
+
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)                (addr & 0x1)
 
index e31c8f5d42712601744823dd22c5f31be157f333..af94719890e7676ea090620e6b6b24b50e24407f 100644 (file)
@@ -3,7 +3,8 @@
  *
  *  OneNAND Register header file
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #define ONENAND_VERSION_PROCESS_SHIFT  (8)
 
 /*
- * Start Address 1 F100h (R/W)
+ * Start Address 1 F100h (R/W) & Start Address 2 F101h (R/W)
  */
 #define ONENAND_DDP_SHIFT              (15)
+#define ONENAND_DDP_CHIP0              (0)
+#define ONENAND_DDP_CHIP1              (1 << ONENAND_DDP_SHIFT)
 
 /*
  * Start Address 8 F107h (R/W)
index 86831e3594f67f7cdf15f6d4570b69c7b6f7caa4..0dc07d5f33545ae37ec667f74ef16a3b593f7ad6 100644 (file)
 #define __LINUX_MTD_PHYSMAP__
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+struct map_info;
+
 struct physmap_flash_data {
        unsigned int            width;
        void                    (*set_vpp)(struct map_info *, int);
index db05182ca0e87f122adc3b4c1dbff6622c6c5fbb..1be5be88debe77c5e51aed74ef77fb8697974b5f 100644 (file)
@@ -105,12 +105,11 @@ struct nfs4_ace {
        uint32_t        access_mask;
        int             whotype;
        uid_t           who;
-       struct list_head l_ace;
 };
 
 struct nfs4_acl {
        uint32_t        naces;
-       struct list_head ace_head;
+       struct nfs4_ace aces[0];
 };
 
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
index 22aff4d01f20e0e59e02c6ee4f4a7c16c7fd76af..409b6e02f337cdf757ecfbf90fb009a6632aa611 100644 (file)
 
 #include <linux/posix_acl.h>
 
-struct nfs4_acl *nfs4_acl_new(void);
-void nfs4_acl_free(struct nfs4_acl *);
-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
+ * fit in a page: */
+#define NFS4_ACL_MAX 170
+
+struct nfs4_acl *nfs4_acl_new(int);
+void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 int nfs4_acl_get_whotype(char *, u32);
 int nfs4_acl_write_who(int who, char *p);
 int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
index 045e38cdbe646f966abf370cddb8d573b4770d62..9f62d6182d32824b3e9f8afd22b01532b98680af 100644 (file)
@@ -74,19 +74,20 @@ struct svc_export {
        uid_t                   ex_anon_uid;
        gid_t                   ex_anon_gid;
        int                     ex_fsid;
+       unsigned char *         ex_uuid; /* 16 byte fsid */
        struct nfsd4_fs_locations ex_fslocs;
 };
 
 /* an "export key" (expkey) maps a filehandlefragement to an
- * svc_export for a given client.  There can be two per export, one
- * for type 0 (dev/ino), one for type 1 (fsid)
+ * svc_export for a given client.  There can be several per export,
+ * for the different fsid types.
  */
 struct svc_expkey {
        struct cache_head       h;
 
        struct auth_domain *    ek_client;
        int                     ek_fsidtype;
-       u32                     ek_fsid[3];
+       u32                     ek_fsid[6];
 
        struct vfsmount *       ek_mnt;
        struct dentry *         ek_dentry;
index 4b7c4b568f6d685fbe53ab231f459c477d3f9e3a..72feac581aa354572b89fd3d5d3e9feb8839fe5c 100644 (file)
@@ -254,18 +254,6 @@ void               nfsd_lockd_shutdown(void);
  */
 extern struct timeval  nfssvc_boot;
 
-static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
-{
-       if (fh->fh_export->ex_flags & NFSEXP_FSID) {
-               struct vfsmount *mnt = fh->fh_export->ex_mnt;
-               if (!old_valid_dev(mnt->mnt_sb->s_dev) ||
-                   (reffh->fh_version == 1 && reffh->fh_fsid_type == 1))
-                       return 1;
-       }
-       return 0;
-}
-
-
 #ifdef CONFIG_NFSD_V4
 
 /* before processing a COMPOUND operation, we have to check that there
index d9c6c382165dd23165d025ae4cd044db9dcf7f8b..11e568ee0eeb877b69ea1e78f320f203bffb6a39 100644 (file)
@@ -165,38 +165,91 @@ typedef struct svc_fh {
 
 } svc_fh;
 
-static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino)
-{
-       fsidv[0] = htonl((MAJOR(dev)<<16) |
-                       MINOR(dev));
-       fsidv[1] = ino_t_to_u32(ino);
-}
+enum nfsd_fsid {
+       FSID_DEV = 0,
+       FSID_NUM,
+       FSID_MAJOR_MINOR,
+       FSID_ENCODE_DEV,
+       FSID_UUID4_INUM,
+       FSID_UUID8,
+       FSID_UUID16,
+       FSID_UUID16_INUM,
+};
 
-static inline void mk_fsid_v1(u32 *fsidv, u32 fsid)
-{
-       fsidv[0] = fsid;
-}
+enum fsid_source {
+       FSIDSOURCE_DEV,
+       FSIDSOURCE_FSID,
+       FSIDSOURCE_UUID,
+};
+extern enum fsid_source fsid_source(struct svc_fh *fhp);
 
-static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino)
-{
-       fsidv[0] = htonl(MAJOR(dev));
-       fsidv[1] = htonl(MINOR(dev));
-       fsidv[2] = ino_t_to_u32(ino);
-}
 
-static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino)
+/* This might look a little large to "inline" but in all calls except
+ * one, 'vers' is constant so moste of the function disappears.
+ */
+static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
+                          u32 fsid, unsigned char *uuid)
 {
-       fsidv[0] = new_encode_dev(dev);
-       fsidv[1] = ino_t_to_u32(ino);
+       u32 *up;
+       switch(vers) {
+       case FSID_DEV:
+               fsidv[0] = htonl((MAJOR(dev)<<16) |
+                                MINOR(dev));
+               fsidv[1] = ino_t_to_u32(ino);
+               break;
+       case FSID_NUM:
+               fsidv[0] = fsid;
+               break;
+       case FSID_MAJOR_MINOR:
+               fsidv[0] = htonl(MAJOR(dev));
+               fsidv[1] = htonl(MINOR(dev));
+               fsidv[2] = ino_t_to_u32(ino);
+               break;
+
+       case FSID_ENCODE_DEV:
+               fsidv[0] = new_encode_dev(dev);
+               fsidv[1] = ino_t_to_u32(ino);
+               break;
+
+       case FSID_UUID4_INUM:
+               /* 4 byte fsid and inode number */
+               up = (u32*)uuid;
+               fsidv[0] = ino_t_to_u32(ino);
+               fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
+               break;
+
+       case FSID_UUID8:
+               /* 8 byte fsid  */
+               up = (u32*)uuid;
+               fsidv[0] = up[0] ^ up[2];
+               fsidv[1] = up[1] ^ up[3];
+               break;
+
+       case FSID_UUID16:
+               /* 16 byte fsid - NFSv3+ only */
+               memcpy(fsidv, uuid, 16);
+               break;
+
+       case FSID_UUID16_INUM:
+               /* 8 byte inode and 16 byte fsid */
+               *(u64*)fsidv = (u64)ino;
+               memcpy(fsidv+2, uuid, 16);
+               break;
+       default: BUG();
+       }
 }
 
 static inline int key_len(int type)
 {
        switch(type) {
-       case 0: return 8;
-       case 1: return 4;
-       case 2: return 12;
-       case 3: return 8;
+       case FSID_DEV:          return 8;
+       case FSID_NUM:          return 4;
+       case FSID_MAJOR_MINOR:  return 12;
+       case FSID_ENCODE_DEV:   return 8;
+       case FSID_UUID4_INUM:   return 8;
+       case FSID_UUID8:        return 8;
+       case FSID_UUID16:       return 16;
+       case FSID_UUID16_INUM:  return 24;
        default: return 0;
        }
 }
index acb4ed1302479ac4f1833466905024e013de41e7..29af2d5df0972cdac25fd2c73e42cd49976efa8a 100644 (file)
 #ifdef ARCH_HAS_NMI_WATCHDOG
 #include <asm/nmi.h>
 extern void touch_nmi_watchdog(void);
+extern void acpi_nmi_disable(void);
+extern void acpi_nmi_enable(void);
 #else
-# define touch_nmi_watchdog() touch_softlockup_watchdog()
+static inline void touch_nmi_watchdog(void)
+{
+       touch_softlockup_watchdog();
+}
+static inline void acpi_nmi_disable(void) { }
+static inline void acpi_nmi_enable(void) { }
 #endif
 
 #ifndef trigger_all_cpu_backtrace
index 98c8765a488e831cad0e35adef583fcf0c93cbe2..2c4b6842dfb91950d5007a3947aa4a0306a8940d 100644 (file)
@@ -854,5 +854,8 @@ extern int pci_pci_problems;
 #define PCIPCI_ALIMAGIK                32      /* Need low latency setting */
 #define PCIAGP_FAIL            64      /* No PCI to AGP DMA */
 
+extern unsigned long pci_cardbus_io_size;
+extern unsigned long pci_cardbus_mem_size;
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index 182a96f77c8437d28987bd93a12dcb2eccef98ab..600308fdf9ce31b6ece7efc34dbbc6fe633888e6 100644 (file)
 #define PCI_VENDOR_ID_PASEMI           0x1959
 
 #define PCI_VENDOR_ID_ATTANSIC         0x1969
+#define PCI_DEVICE_ID_ATTANSIC_L1      0x1048
 
 #define PCI_VENDOR_ID_JMICRON          0x197B
 #define PCI_DEVICE_ID_JMICRON_JMB360   0x2360
index 2e132473cbe5635caeeaa745a57df8887498e500..be4652a0545a0226cb23264e923f9692968e866b 100644 (file)
@@ -113,8 +113,6 @@ extern struct vfsmount *proc_mnt;
 extern int proc_fill_super(struct super_block *,void *,int);
 extern struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
 
-extern int proc_match(int, const char *,struct proc_dir_entry *);
-
 /*
  * These are generic /proc routines that use the internal
  * "struct proc_dir_entry" tree to traverse the filesystem.
index 6b0648cfdffcf869ee59784db66e81ae8991a382..52c9eb9b6df2b15af03ac0dc8a618bf0ad72e93a 100644 (file)
@@ -2,7 +2,7 @@
 #define __LINUX_SEQLOCK_H
 /*
  * Reader/writer consistent mechanism without starving writers. This type of
- * lock for data where the reader wants a consitent set of information
+ * lock for data where the reader wants a consistent set of information
  * and is willing to retry if the information changes.  Readers never
  * block but they may have to retry if a writer is in
  * progress. Writers do not wait for readers. 
index cf23813cbec2a449cadec31f9d68e50e4a4f0bf3..586aaba917208ced8590539809f11228e6ee816d 100644 (file)
 /*Digi jsm */
 #define PORT_JSM        69
 
-#define PORT_IP3106    70
+#define PORT_PNX8XXX   70
 
 /* Hilscher netx */
 #define PORT_NETX      71
diff --git a/include/linux/serial_ip3106.h b/include/linux/serial_ip3106.h
deleted file mode 100644 (file)
index f500ac6..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Embedded Alley Solutions, source@embeddedalley.com.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _LINUX_SERIAL_IP3106_H
-#define _LINUX_SERIAL_IP3106_H
-
-#include <linux/serial_core.h>
-#include <linux/device.h>
-
-#define IP3106_NR_PORTS                2
-
-struct ip3106_port {
-       struct uart_port        port;
-       struct timer_list       timer;
-       unsigned int            old_status;
-};
-
-/* register offsets */
-#define IP3106_LCR             0
-#define IP3106_MCR             0x004
-#define IP3106_BAUD            0x008
-#define IP3106_CFG             0x00c
-#define IP3106_FIFO            0x028
-#define IP3106_ISTAT           0xfe0
-#define IP3106_IEN             0xfe4
-#define IP3106_ICLR            0xfe8
-#define IP3106_ISET            0xfec
-#define IP3106_PD              0xff4
-#define IP3106_MID             0xffc
-
-#define IP3106_UART_LCR_TXBREAK                (1<<30)
-#define IP3106_UART_LCR_PAREVN         0x10000000
-#define IP3106_UART_LCR_PAREN          0x08000000
-#define IP3106_UART_LCR_2STOPB         0x04000000
-#define IP3106_UART_LCR_8BIT           0x01000000
-#define IP3106_UART_LCR_TX_RST         0x00040000
-#define IP3106_UART_LCR_RX_RST         0x00020000
-#define IP3106_UART_LCR_RX_NEXT                0x00010000
-
-#define IP3106_UART_MCR_SCR            0xFF000000
-#define IP3106_UART_MCR_DCD            0x00800000
-#define IP3106_UART_MCR_CTS            0x00100000
-#define IP3106_UART_MCR_LOOP           0x00000010
-#define IP3106_UART_MCR_RTS            0x00000002
-#define IP3106_UART_MCR_DTR            0x00000001
-
-#define IP3106_UART_INT_TX             0x00000080
-#define IP3106_UART_INT_EMPTY          0x00000040
-#define IP3106_UART_INT_RCVTO          0x00000020
-#define IP3106_UART_INT_RX             0x00000010
-#define IP3106_UART_INT_RXOVRN         0x00000008
-#define IP3106_UART_INT_FRERR          0x00000004
-#define IP3106_UART_INT_BREAK          0x00000002
-#define IP3106_UART_INT_PARITY         0x00000001
-#define IP3106_UART_INT_ALLRX          0x0000003F
-#define IP3106_UART_INT_ALLTX          0x000000C0
-
-#define IP3106_UART_FIFO_TXFIFO                0x001F0000
-#define IP3106_UART_FIFO_TXFIFO_STA    (0x1f<<16)
-#define IP3106_UART_FIFO_RXBRK         0x00008000
-#define IP3106_UART_FIFO_RXFE          0x00004000
-#define IP3106_UART_FIFO_RXPAR         0x00002000
-#define IP3106_UART_FIFO_RXFIFO                0x00001F00
-#define IP3106_UART_FIFO_RBRTHR                0x000000FF
-
-#endif
diff --git a/include/linux/serial_pnx8xxx.h b/include/linux/serial_pnx8xxx.h
new file mode 100644 (file)
index 0000000..de6c19c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Embedded Alley Solutions, source@embeddedalley.com.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_SERIAL_PNX8XXX_H
+#define _LINUX_SERIAL_PNX8XXX_H
+
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#define PNX8XXX_NR_PORTS       2
+
+struct pnx8xxx_port {
+       struct uart_port        port;
+       struct timer_list       timer;
+       unsigned int            old_status;
+};
+
+/* register offsets */
+#define PNX8XXX_LCR            0
+#define PNX8XXX_MCR            0x004
+#define PNX8XXX_BAUD           0x008
+#define PNX8XXX_CFG            0x00c
+#define PNX8XXX_FIFO           0x028
+#define PNX8XXX_ISTAT          0xfe0
+#define PNX8XXX_IEN            0xfe4
+#define PNX8XXX_ICLR           0xfe8
+#define PNX8XXX_ISET           0xfec
+#define PNX8XXX_PD             0xff4
+#define PNX8XXX_MID            0xffc
+
+#define PNX8XXX_UART_LCR_TXBREAK       (1<<30)
+#define PNX8XXX_UART_LCR_PAREVN                0x10000000
+#define PNX8XXX_UART_LCR_PAREN         0x08000000
+#define PNX8XXX_UART_LCR_2STOPB                0x04000000
+#define PNX8XXX_UART_LCR_8BIT          0x01000000
+#define PNX8XXX_UART_LCR_TX_RST                0x00040000
+#define PNX8XXX_UART_LCR_RX_RST                0x00020000
+#define PNX8XXX_UART_LCR_RX_NEXT       0x00010000
+
+#define PNX8XXX_UART_MCR_SCR           0xFF000000
+#define PNX8XXX_UART_MCR_DCD           0x00800000
+#define PNX8XXX_UART_MCR_CTS           0x00100000
+#define PNX8XXX_UART_MCR_LOOP          0x00000010
+#define PNX8XXX_UART_MCR_RTS           0x00000002
+#define PNX8XXX_UART_MCR_DTR           0x00000001
+
+#define PNX8XXX_UART_INT_TX            0x00000080
+#define PNX8XXX_UART_INT_EMPTY         0x00000040
+#define PNX8XXX_UART_INT_RCVTO         0x00000020
+#define PNX8XXX_UART_INT_RX            0x00000010
+#define PNX8XXX_UART_INT_RXOVRN                0x00000008
+#define PNX8XXX_UART_INT_FRERR         0x00000004
+#define PNX8XXX_UART_INT_BREAK         0x00000002
+#define PNX8XXX_UART_INT_PARITY                0x00000001
+#define PNX8XXX_UART_INT_ALLRX         0x0000003F
+#define PNX8XXX_UART_INT_ALLTX         0x000000C0
+
+#define PNX8XXX_UART_FIFO_TXFIFO       0x001F0000
+#define PNX8XXX_UART_FIFO_TXFIFO_STA   (0x1f<<16)
+#define PNX8XXX_UART_FIFO_RXBRK                0x00008000
+#define PNX8XXX_UART_FIFO_RXFE         0x00004000
+#define PNX8XXX_UART_FIFO_RXPAR                0x00002000
+#define PNX8XXX_UART_FIFO_RXFIFO       0x00001F00
+#define PNX8XXX_UART_FIFO_RBRTHR       0x000000FF
+
+#endif
index ac2c70e7f76083e80325983ff1111bbd1c71492d..1ebf0455e224966a1af04789391704de119d6e2b 100644 (file)
@@ -108,12 +108,6 @@ static inline void serio_drv_write_wakeup(struct serio *serio)
                serio->drv->write_wakeup(serio);
 }
 
-static inline void serio_cleanup(struct serio *serio)
-{
-       if (serio->drv && serio->drv->cleanup)
-               serio->drv->cleanup(serio);
-}
-
 /*
  * Use the following functions to manipulate serio's per-port
  * driver-specific data.
index 60fce3c928570166fdf354eee838adc22dc24d37..b7c7307ceec6bc8865104713559d800d6e1967c8 100644 (file)
@@ -78,7 +78,6 @@ void          rpc_unregister_sysctl(void);
  * module currently registers its sysctl table dynamically, the sysctl path
  * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
  */
-#define CTL_SUNRPC     7249    /* arbitrary and hopefully unused */
 
 enum {
        CTL_RPCDEBUG = 1,
index 665412c4f4b910cdc8c60da3174a1f48ccbbd61d..2c5fb38d939260909fe7f549fd9f5159acbfe868 100644 (file)
@@ -53,7 +53,6 @@ struct __sysctl_args {
 
 /* For internal pattern-matching use only: */
 #ifdef __KERNEL__
-#define CTL_ANY                -1      /* Matches any name */
 #define CTL_NONE       0
 #define CTL_UNNUMBERED CTL_NONE        /* sysctl without a binary number */
 #endif
@@ -69,7 +68,13 @@ enum
        CTL_DEV=7,              /* Devices */
        CTL_BUS=8,              /* Busses */
        CTL_ABI=9,              /* Binary emulation */
-       CTL_CPU=10              /* CPU stuff (speed scaling, etc) */
+       CTL_CPU=10,             /* CPU stuff (speed scaling, etc) */
+       CTL_ARLAN=254,          /* arlan wireless driver */
+       CTL_APPLDATA=2120,      /* s390 appldata */
+       CTL_S390DBF=5677,       /* s390 debug */
+       CTL_SUNRPC=7249,        /* sunrpc debug */
+       CTL_PM=9899,            /* frv power management */
+       CTL_FRV=9898,           /* frv specific sysctls */
 };
 
 /* CTL_BUS names: */
@@ -202,6 +207,11 @@ enum
        VM_PANIC_ON_OOM=33,     /* panic at out-of-memory */
        VM_VDSO_ENABLED=34,     /* map VDSO into new processes? */
        VM_MIN_SLAB=35,          /* Percent pages ignored by zone reclaim */
+
+       /* s390 vm cmm sysctls */
+       VM_CMM_PAGES=1111,
+       VM_CMM_TIMED_PAGES=1112,
+       VM_CMM_TIMEOUT=1113,
 };
 
 
@@ -803,6 +813,7 @@ enum
        FS_AIO_NR=18,   /* current system-wide number of aio requests */
        FS_AIO_MAX_NR=19,       /* system-wide maximum number of aio requests */
        FS_INOTIFY=20,  /* inotify submenu */
+       FS_OCFS2=988,   /* ocfs2 */
 };
 
 /* /proc/sys/fs/quota/ */
@@ -913,7 +924,11 @@ enum
 #ifdef __KERNEL__
 #include <linux/list.h>
 
-extern void sysctl_init(void);
+/* For the /proc/sys support */
+struct ctl_table;
+extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
+extern void sysctl_head_finish(struct ctl_table_header *prev);
+extern int sysctl_perm(struct ctl_table *table, int op);
 
 typedef struct ctl_table ctl_table;
 
@@ -1007,9 +1022,9 @@ struct ctl_table
        int maxlen;
        mode_t mode;
        ctl_table *child;
+       ctl_table *parent;              /* Automatically set */
        proc_handler *proc_handler;     /* Callback for text formatting */
        ctl_handler *strategy;          /* Callback function for all r/w */
-       struct proc_dir_entry *de;      /* /proc control block */
        void *extra1;
        void *extra2;
 };
@@ -1024,8 +1039,8 @@ struct ctl_table_header
        struct completion *unregistering;
 };
 
-struct ctl_table_header * register_sysctl_table(ctl_table * table
-                                               int insert_at_head);
+struct ctl_table_header * register_sysctl_table(ctl_table * table);
+
 void unregister_sysctl_table(struct ctl_table_header * table);
 
 #else /* __KERNEL__ */
diff --git a/include/linux/tick.h b/include/linux/tick.h
new file mode 100644 (file)
index 0000000..9a7252e
--- /dev/null
@@ -0,0 +1,109 @@
+/*  linux/include/linux/tick.h
+ *
+ *  This file contains the structure definitions for tick related functions
+ *
+ */
+#ifndef _LINUX_TICK_H
+#define _LINUX_TICK_H
+
+#include <linux/clockchips.h>
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+enum tick_device_mode {
+       TICKDEV_MODE_PERIODIC,
+       TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+       struct clock_event_device *evtdev;
+       enum tick_device_mode mode;
+};
+
+enum tick_nohz_mode {
+       NOHZ_MODE_INACTIVE,
+       NOHZ_MODE_LOWRES,
+       NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:       hrtimer to schedule the periodic tick in high
+ *                     resolution mode
+ * @idle_tick:         Store the last idle tick expiry time when the tick
+ *                     timer is modified for idle sleeps. This is necessary
+ *                     to resume the tick timer operation in the timeline
+ *                     when the CPU returns from idle
+ * @tick_stopped:      Indicator that the idle tick has been stopped
+ * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
+ * @idle_calls:                Total number of idle calls
+ * @idle_sleeps:       Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:    Time when the idle call was entered
+ * @idle_sleeptime:    Sum of the time slept in idle with sched tick stopped
+ */
+struct tick_sched {
+       struct hrtimer                  sched_timer;
+       unsigned long                   check_clocks;
+       enum tick_nohz_mode             nohz_mode;
+       ktime_t                         idle_tick;
+       int                             tick_stopped;
+       unsigned long                   idle_jiffies;
+       unsigned long                   idle_calls;
+       unsigned long                   idle_sleeps;
+       ktime_t                         idle_entrytime;
+       ktime_t                         idle_sleeptime;
+       unsigned long                   last_jiffies;
+       unsigned long                   next_jiffies;
+       ktime_t                         idle_expires;
+};
+
+extern void __init tick_init(void);
+extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
+
+# ifdef CONFIG_HIGH_RES_TIMERS
+extern int tick_init_highres(void);
+extern int tick_program_event(ktime_t expires, int force);
+extern void tick_setup_sched_timer(void);
+extern void tick_cancel_sched_timer(int cpu);
+# else
+static inline void tick_cancel_sched_timer(int cpu) { }
+# endif /* HIGHRES */
+
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern struct tick_device *tick_get_broadcast_device(void);
+extern cpumask_t *tick_get_broadcast_mask(void);
+
+#  ifdef CONFIG_TICK_ONESHOT
+extern cpumask_t *tick_get_broadcast_oneshot_mask(void);
+#  endif
+
+# endif /* BROADCAST */
+
+# ifdef CONFIG_TICK_ONESHOT
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+# else
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
+# endif
+
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+static inline void tick_cancel_sched_timer(int cpu) { }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
+
+# ifdef CONFIG_NO_HZ
+extern void tick_nohz_stop_sched_tick(void);
+extern void tick_nohz_restart_sched_tick(void);
+extern void tick_nohz_update_jiffies(void);
+# else
+static inline void tick_nohz_stop_sched_tick(void) { }
+static inline void tick_nohz_restart_sched_tick(void) { }
+static inline void tick_nohz_update_jiffies(void) { }
+# endif /* !NO_HZ */
+
+#endif
index 55cee172d723914eed0770f178f95ae6bd7b122b..8ea8dea713c7c5d7a7da0fcd2e72d3d70f9112af 100644 (file)
@@ -90,8 +90,9 @@ static inline struct timespec timespec_sub(struct timespec lhs,
 
 extern struct timespec xtime;
 extern struct timespec wall_to_monotonic;
-extern seqlock_t xtime_lock;
+extern seqlock_t xtime_lock __attribute__((weak));
 
+extern unsigned long read_persistent_clock(void);
 void timekeeping_init(void);
 
 static inline unsigned long get_seconds(void)
index fb5edaaf0ebd11a05500ef64e1e56df5fa4f295b..719113b652dd55e31bd1f0afd039a55b1d972de0 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_TIMER_H
 
 #include <linux/list.h>
+#include <linux/ktime.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
@@ -15,6 +16,11 @@ struct timer_list {
        unsigned long data;
 
        struct tvec_t_base_s *base;
+#ifdef CONFIG_TIMER_STATS
+       void *start_site;
+       char start_comm[16];
+       int start_pid;
+#endif
 };
 
 extern struct tvec_t_base_s boot_tvec_bases;
@@ -61,7 +67,65 @@ extern int del_timer(struct timer_list * timer);
 extern int __mod_timer(struct timer_list *timer, unsigned long expires);
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
 
+/*
+ * Return when the next timer-wheel timeout occurs (in absolute jiffies),
+ * locks the timer base:
+ */
 extern unsigned long next_timer_interrupt(void);
+/*
+ * Return when the next timer-wheel timeout occurs (in absolute jiffies),
+ * locks the timer base and does the comparison against the given
+ * jiffie.
+ */
+extern unsigned long get_next_timer_interrupt(unsigned long now);
+
+/*
+ * Timer-statistics info:
+ */
+#ifdef CONFIG_TIMER_STATS
+
+extern void init_timer_stats(void);
+
+extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+                                    void *timerf, char * comm);
+
+static inline void timer_stats_account_timer(struct timer_list *timer)
+{
+       timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+                                timer->function, timer->start_comm);
+}
+
+extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
+                                              void *addr);
+
+static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
+{
+       __timer_stats_timer_set_start_info(timer, __builtin_return_address(0));
+}
+
+static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
+{
+       timer->start_site = NULL;
+}
+#else
+static inline void init_timer_stats(void)
+{
+}
+
+static inline void timer_stats_account_timer(struct timer_list *timer)
+{
+}
+
+static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
+{
+}
+
+static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
+{
+}
+#endif
+
+extern void delayed_work_timer_fn(unsigned long __data);
 
 /**
  * add_timer - start a timer
@@ -96,7 +160,7 @@ static inline void add_timer(struct timer_list *timer)
 extern void init_timers(void);
 extern void run_local_timers(void);
 struct hrtimer;
-extern int it_real_fn(struct hrtimer *);
+extern enum hrtimer_restart it_real_fn(struct hrtimer *);
 
 unsigned long __round_jiffies(unsigned long j, int cpu);
 unsigned long __round_jiffies_relative(unsigned long j, int cpu);
index 9a24e500c3113291b9304e218b935fdc300ab87a..da929dbbea2a1c9ab246ee134bb83dcd9ec5c935 100644 (file)
@@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec)
 
 #define TICK_LENGTH_SHIFT      32
 
+#ifdef CONFIG_NO_HZ
+#define NTP_INTERVAL_FREQ  (2)
+#else
+#define NTP_INTERVAL_FREQ  (HZ)
+#endif
+#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
+
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
 
index b5c226a87ed87640252139a6dda2f701aa4636bc..a8e8d1ecebb17b4bbcd6e36c93d18947e78624b1 100644 (file)
@@ -935,7 +935,7 @@ struct usb_iso_packet_descriptor {
        unsigned int offset;
        unsigned int length;            /* expected length */
        unsigned int actual_length;
-       unsigned int status;
+       int status;
 };
 
 struct urb;
index ba617c3724552a91bca0147b8150b8ddad549691..956edf3bbecb3d13769bc7e21e7053a16161e346 100644 (file)
@@ -73,6 +73,13 @@ struct usb_cdc_acm_descriptor {
        __u8    bmCapabilities;
 } __attribute__ ((packed));
 
+/* capabilities from 5.2.3.3 */
+
+#define USB_CDC_COMM_FEATURE   0x01
+#define USB_CDC_CAP_LINE       0x02
+#define USB_CDC_CAP_BRK        0x04
+#define USB_CDC_CAP_NOTIFY     0x08
+
 /* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
 struct usb_cdc_union_desc {
        __u8    bLength;
index ae7833749fa2c3b0f6e0cbc69744efe6734dcdff..245c72531228346982598506248d68fa03d16461 100644 (file)
@@ -367,7 +367,7 @@ struct usb_debug_descriptor {
        /* bulk endpoints with 8 byte maxpacket */
        __u8  bDebugInEndpoint;
        __u8  bDebugOutEndpoint;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -396,7 +396,7 @@ struct usb_security_descriptor {
 
        __le16 wTotalLength;
        __u8  bNumEncryptionTypes;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -410,7 +410,7 @@ struct usb_key_descriptor {
        __u8  tTKID[3];
        __u8  bReserved;
        __u8  bKeyData[0];
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -426,7 +426,7 @@ struct usb_encryption_descriptor {
 #define        USB_ENC_TYPE_RSA_1              3       /* rsa3072/sha1 auth */
        __u8  bEncryptionValue;         /* use in SET_ENCRYPTION */
        __u8  bAuthKeyIndex;
-};
+} __attribute__((packed));
 
 
 /*-------------------------------------------------------------------------*/
@@ -438,7 +438,7 @@ struct usb_bos_descriptor {
 
        __le16 wTotalLength;
        __u8  bNumDeviceCaps;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -447,7 +447,7 @@ struct usb_dev_cap_header {
        __u8  bLength;
        __u8  bDescriptorType;
        __u8  bDevCapabilityType;
-};
+} __attribute__((packed));
 
 #define        USB_CAP_TYPE_WIRELESS_USB       1
 
@@ -475,7 +475,7 @@ struct usb_wireless_cap_descriptor {        /* Ultra Wide Band */
        __u8  bmFFITXPowerInfo; /* FFI power levels */
        __le16 bmBandGroup;
        __u8  bReserved;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -496,7 +496,7 @@ struct usb_wireless_ep_comp_descriptor {
 #define USB_ENDPOINT_SWITCH_NO         0
 #define USB_ENDPOINT_SWITCH_SWITCH     1
 #define USB_ENDPOINT_SWITCH_SCALE      2
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -512,7 +512,7 @@ struct usb_handshake {
        __u8 CDID[16];
        __u8 nonce[16];
        __u8 MIC[8];
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -524,7 +524,7 @@ struct usb_connection_context {
        __u8 CHID[16];          /* persistent host id */
        __u8 CDID[16];          /* device id (unique w/in host context) */
        __u8 CK[16];            /* connection key */
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
index 33dcd857669643309f4f17ae206555f782160545..32acbae28d24d34a1ea9d011945e7cc5e9e3ee06 100644 (file)
@@ -54,6 +54,8 @@
  * @write_wait: a wait_queue_head_t used by the port.
  * @work: work queue entry for the line discipline waking up.
  * @open_count: number of times this port has been opened.
+ * @throttled: nonzero if the read urb is inactive to throttle the device
+ * @throttle_req: nonzero if the tty wants to throttle us
  *
  * This structure is used by the usb-serial core and drivers for the specific
  * ports of a device.
@@ -88,6 +90,8 @@ struct usb_serial_port {
        wait_queue_head_t       write_wait;
        struct work_struct      work;
        int                     open_count;
+       char                    throttled;
+       char                    throttle_req;
        struct device           dev;
 };
 #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
@@ -269,6 +273,8 @@ extern int usb_serial_generic_write_room (struct usb_serial_port *port);
 extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
 extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_throttle (struct usb_serial_port *port);
+extern void usb_serial_generic_unthrottle (struct usb_serial_port *port);
 extern void usb_serial_generic_shutdown (struct usb_serial *serial);
 extern int usb_serial_generic_register (int debug);
 extern void usb_serial_generic_deregister (void);
index 2ae76fe52ff75e483806cd48c2f3e29fadfd89ac..1b792b9286bae2a499fd5aa46ff1b4ccc1a5aeec 100644 (file)
@@ -46,7 +46,9 @@
        US_FLAG(MAX_SECTORS_64, 0x00000400)                     \
                /* Sets max_sectors to 64    */                 \
        US_FLAG(IGNORE_DEVICE,  0x00000800)                     \
-               /* Don't claim device */
+               /* Don't claim device */                        \
+       US_FLAG(CAPACITY_HEURISTICS,    0x00001000)             \
+               /* sometimes sizes is too big */
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
index 617d8a1c59aeb0c38b82cb6e06ec201f43091f4b..342dd5a7e8bb822f139955bb91ba9cab069b3e2f 100644 (file)
@@ -159,9 +159,9 @@ struct usbdevfs_ioctl32 {
 #define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
 #define USBDEVFS_DISCARDURB        _IO('U', 11)
 #define USBDEVFS_REAPURB           _IOW('U', 12, void *)
-#define USBDEVFS_REAPURB32         _IOW('U', 12, u32)
+#define USBDEVFS_REAPURB32         _IOW('U', 12, __u32)
 #define USBDEVFS_REAPURBNDELAY     _IOW('U', 13, void *)
-#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, u32)
+#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, __u32)
 #define USBDEVFS_DISCSIGNAL        _IOR('U', 14, struct usbdevfs_disconnectsignal)
 #define USBDEVFS_CLAIMINTERFACE    _IOR('U', 15, unsigned int)
 #define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
index f913c30d7b8976754e4c0008eb5c2db8eca44e08..8e501a75a7645cb8d65c811b1bd85c44e406a550 100644 (file)
@@ -36,12 +36,6 @@ struct mtd_oob_buf {
 #define MTD_CAP_NORFLASH       (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
 #define MTD_CAP_NANDFLASH      (MTD_WRITEABLE)
 
-
-// Types of automatic ECC/Checksum available
-#define MTD_ECC_NONE           0       // No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip  1       // Automatic ECC on DiskOnChip
-#define MTD_ECC_SW             2       // SW ECC for Toshiba & Samsung devices
-
 /* ECC byte placement */
 #define MTD_NANDECC_OFF                0       // Switch off ECC (Not recommended)
 #define MTD_NANDECC_PLACE      1       // Use the given placement in the structure (YAFFS1 legacy mode)
@@ -61,6 +55,8 @@ struct mtd_info_user {
        uint32_t erasesize;
        uint32_t writesize;
        uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+       /* The below two fields are obsolete and broken, do not use them
+        * (TODO: remove at some point) */
        uint32_t ecctype;
        uint32_t eccsize;
 };
index c1da8558339a266e7c1d0fecf7c20c22379edd44..eae7e2e844974b903dd3b0094a5ead23da7546ac 100644 (file)
@@ -95,6 +95,7 @@
 #define PRODID_QUATECH_DUAL_RS232      0x0012
 #define PRODID_QUATECH_DUAL_RS232_D1   0x0007
 #define PRODID_QUATECH_DUAL_RS232_D2   0x0052
+#define PRODID_QUATECH_DUAL_RS232_G    0x004d
 #define PRODID_QUATECH_QUAD_RS232      0x001b
 #define PRODID_QUATECH_DUAL_RS422      0x000e
 #define PRODID_QUATECH_QUAD_RS422      0x0045
index c094e501286229bbc699bc74534c088235a7a436..c36750ff6ae82caf596aaee36d25de55e9d4316a 100644 (file)
@@ -110,6 +110,12 @@ static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)
        dev_addr->broadcast[9] = (unsigned char) pkey;
 }
 
+static inline void ib_addr_get_mgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(gid, dev_addr->broadcast + 4, sizeof *gid);
+}
+
 static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr,
                                    union ib_gid *gid)
 {
index 97715b0c20b69f6e50b75b2c03e24fa50758fdb6..5e26b2f53f86e198f1c8893c72d460d624a4c419 100644 (file)
@@ -285,18 +285,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
                       void *context,
                       struct ib_sa_query **query);
 
-int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
-                            struct ib_device *device, u8 port_num,
-                            u8 method,
-                            struct ib_sa_mcmember_rec *rec,
-                            ib_sa_comp_mask comp_mask,
-                            int timeout_ms, gfp_t gfp_mask,
-                            void (*callback)(int status,
-                                             struct ib_sa_mcmember_rec *resp,
-                                             void *context),
-                            void *context,
-                            struct ib_sa_query **query);
-
 int ib_sa_service_rec_query(struct ib_sa_client *client,
                         struct ib_device *device, u8 port_num,
                         u8 method,
@@ -309,93 +297,82 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
                         void *context,
                         struct ib_sa_query **sa_query);
 
+struct ib_sa_multicast {
+       struct ib_sa_mcmember_rec rec;
+       ib_sa_comp_mask         comp_mask;
+       int                     (*callback)(int status,
+                                           struct ib_sa_multicast *multicast);
+       void                    *context;
+};
+
 /**
- * ib_sa_mcmember_rec_set - Start an MCMember set query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
+ * ib_sa_join_multicast - Initiates a join request to the specified multicast
+ *   group.
+ * @client: SA client
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ *   group.
+ * @rec: SA multicast member record specifying group attributes.
+ * @comp_mask: Component mask indicating which group attributes of %rec are
+ *   valid.
+ * @gfp_mask: GFP mask for memory allocations.
+ * @callback: User callback invoked once the join operation completes.
+ * @context: User specified context stored with the ib_sa_multicast structure.
  *
- * Send an MCMember Set query to the SA (eg to join a multicast
- * group).  The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query.  The resp parameter of
- * the callback is only valid if status is 0.
+ * This call initiates a multicast join request with the SA for the specified
+ * multicast group.  If the join operation is started successfully, it returns
+ * an ib_sa_multicast structure that is used to track the multicast operation.
+ * Users must free this structure by calling ib_free_multicast, even if the
+ * join operation later fails.  (The callback status is non-zero.)
  *
- * If the return value of ib_sa_mcmember_rec_set() is negative, it is
- * an error code.  Otherwise it is a query ID that can be used to
- * cancel the query.
+ * If the join operation fails; status will be non-zero, with the following
+ * failures possible:
+ * -ETIMEDOUT: The request timed out.
+ * -EIO: An error occurred sending the query.
+ * -EINVAL: The MCMemberRecord values differed from the existing group's.
+ * -ENETRESET: Indicates that an fatal error has occurred on the multicast
+ *   group, and the user must rejoin the group to continue using it.
  */
-static inline int
-ib_sa_mcmember_rec_set(struct ib_sa_client *client,
-                      struct ib_device *device, u8 port_num,
-                      struct ib_sa_mcmember_rec *rec,
-                      ib_sa_comp_mask comp_mask,
-                      int timeout_ms, gfp_t gfp_mask,
-                      void (*callback)(int status,
-                                       struct ib_sa_mcmember_rec *resp,
-                                       void *context),
-                      void *context,
-                      struct ib_sa_query **query)
-{
-       return ib_sa_mcmember_rec_query(client, device, port_num,
-                                       IB_MGMT_METHOD_SET,
-                                       rec, comp_mask,
-                                       timeout_ms, gfp_mask, callback,
-                                       context, query);
-}
+struct ib_sa_multicast *ib_sa_join_multicast(struct ib_sa_client *client,
+                                            struct ib_device *device, u8 port_num,
+                                            struct ib_sa_mcmember_rec *rec,
+                                            ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+                                            int (*callback)(int status,
+                                                            struct ib_sa_multicast
+                                                                   *multicast),
+                                            void *context);
 
 /**
- * ib_sa_mcmember_rec_delete - Start an MCMember delete query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
- *
- * Send an MCMember Delete query to the SA (eg to leave a multicast
- * group).  The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query.  The resp parameter of
- * the callback is only valid if status is 0.
+ * ib_free_multicast - Frees the multicast tracking structure, and releases
+ *    any reference on the multicast group.
+ * @multicast: Multicast tracking structure allocated by ib_join_multicast.
  *
- * If the return value of ib_sa_mcmember_rec_delete() is negative, it
- * is an error code.  Otherwise it is a query ID that can be used to
- * cancel the query.
+ * This call blocks until the multicast identifier is destroyed.  It may
+ * not be called from within the multicast callback; however, returning a non-
+ * zero value from the callback will result in destroying the multicast
+ * tracking structure.
+ */
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast);
+
+/**
+ * ib_get_mcmember_rec - Looks up a multicast member record by its MGID and
+ *   returns it if found.
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ *   group.
+ * @mgid: MGID of multicast group.
+ * @rec: Location to copy SA multicast member record.
  */
-static inline int
-ib_sa_mcmember_rec_delete(struct ib_sa_client *client,
-                         struct ib_device *device, u8 port_num,
-                         struct ib_sa_mcmember_rec *rec,
-                         ib_sa_comp_mask comp_mask,
-                         int timeout_ms, gfp_t gfp_mask,
-                         void (*callback)(int status,
-                                          struct ib_sa_mcmember_rec *resp,
-                                          void *context),
-                         void *context,
-                         struct ib_sa_query **query)
-{
-       return ib_sa_mcmember_rec_query(client, device, port_num,
-                                       IB_SA_METHOD_DELETE,
-                                       rec, comp_mask,
-                                       timeout_ms, gfp_mask, callback,
-                                       context, query);
-}
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+                          union ib_gid *mgid, struct ib_sa_mcmember_rec *rec);
+
+/**
+ * ib_init_ah_from_mcmember - Initialize address handle attributes based on
+ * an SA multicast member record.
+ */
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+                            struct ib_sa_mcmember_rec *rec,
+                            struct ib_ah_attr *ah_attr);
 
 /**
  * ib_init_ah_from_path - Initialize address handle attributes based on an SA
index 36cd8a8526a06f39b40af1b5106967ec67394f97..2d6a7705eae7fbafbbaab4a8a9d8d6c9fde8ceac 100644 (file)
@@ -52,10 +52,13 @@ enum rdma_cm_event_type {
        RDMA_CM_EVENT_ESTABLISHED,
        RDMA_CM_EVENT_DISCONNECTED,
        RDMA_CM_EVENT_DEVICE_REMOVAL,
+       RDMA_CM_EVENT_MULTICAST_JOIN,
+       RDMA_CM_EVENT_MULTICAST_ERROR
 };
 
 enum rdma_port_space {
        RDMA_PS_SDP  = 0x0001,
+       RDMA_PS_IPOIB= 0x0002,
        RDMA_PS_TCP  = 0x0106,
        RDMA_PS_UDP  = 0x0111,
        RDMA_PS_SCTP = 0x0183
@@ -294,5 +297,21 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
  */
 int rdma_disconnect(struct rdma_cm_id *id);
 
-#endif /* RDMA_CM_H */
+/**
+ * rdma_join_multicast - Join the multicast group specified by the given
+ *   address.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to join.
+ * @context: User-defined context associated with the join request, returned
+ * to the user through the private_data pointer in multicast events.
+ */
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+                       void *context);
 
+/**
+ * rdma_leave_multicast - Leave the multicast group specified by the given
+ *   address.
+ */
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
+
+#endif /* RDMA_CM_H */
index 9b176df1d66706d2eef11daff8409a93464365fa..950424b38f1605b17adc6d41a961e7f629cf0c01 100644 (file)
@@ -44,7 +44,7 @@
 int rdma_set_ib_paths(struct rdma_cm_id *id,
                      struct ib_sa_path_rec *path_rec, int num_paths);
 
-/* Global qkey for UD QPs and multicast groups. */
-#define RDMA_UD_QKEY 0x01234567
+/* Global qkey for UDP QPs and multicast groups. */
+#define RDMA_UDP_QKEY 0x01234567
 
 #endif /* RDMA_CM_IB_H */
index 9572ab8eeac19e74fbd393c4b34d90fca23dc8ab..f632b0c007c9808eb0f50e60bdab3b30c0775e38 100644 (file)
@@ -38,7 +38,7 @@
 #include <rdma/ib_user_verbs.h>
 #include <rdma/ib_user_sa.h>
 
-#define RDMA_USER_CM_ABI_VERSION       3
+#define RDMA_USER_CM_ABI_VERSION       4
 
 #define RDMA_MAX_PRIVATE_DATA          256
 
@@ -58,7 +58,9 @@ enum {
        RDMA_USER_CM_CMD_GET_EVENT,
        RDMA_USER_CM_CMD_GET_OPTION,
        RDMA_USER_CM_CMD_SET_OPTION,
-       RDMA_USER_CM_CMD_NOTIFY
+       RDMA_USER_CM_CMD_NOTIFY,
+       RDMA_USER_CM_CMD_JOIN_MCAST,
+       RDMA_USER_CM_CMD_LEAVE_MCAST
 };
 
 /*
@@ -188,6 +190,13 @@ struct rdma_ucm_notify {
        __u32 event;
 };
 
+struct rdma_ucm_join_mcast {
+       __u64 response;         /* rdma_ucm_create_id_resp */
+       __u64 uid;
+       struct sockaddr_in6 addr;
+       __u32 id;
+};
+
 struct rdma_ucm_get_event {
        __u64 response;
 };
index ebf31b16dc49eee41786123bad30f36405faae20..9dd37e2f5a84df84deb91554f85372966cf2e6d8 100644 (file)
@@ -122,6 +122,7 @@ struct scsi_device {
        unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
        unsigned select_no_atn:1;
        unsigned fix_capacity:1;        /* READ_CAPACITY is too high by 1 */
+       unsigned guess_capacity:1;      /* READ_CAPACITY might be too high by 1 */
        unsigned retry_hwerror:1;       /* Retry HARDWARE_ERROR */
 
        unsigned int device_blocked;    /* Device returned QUEUE_FULL. */
index 46d5e70d72157bcca6b0ca4abefb8da76e1d940a..07d6e77ae895638b031e70e7411d36da4ebae93f 100644 (file)
@@ -83,8 +83,5 @@ struct tgt_event {
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
 #define TGT_RING_SIZE (1UL << 16)
-#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
-#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
-#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
 
 #endif
index cca1d4926d2aa47333749967577087df93b9ec52..3c18baa65a729cd1578ab45b281ed1d5ba2d01dd 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/transport_class.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
 
 struct scsi_transport_template {
        /* the attribute containers */
index eb7ce96ddf3ad4c103718f7501196a78b6615003..23e45a4cf0e44ffe4a3074fe72e39c47e4518081 100644 (file)
 #define FXWC_SPDIFLEFT          (1<<22)                /* 0x00400000 */
 #define FXWC_SPDIFRIGHT         (1<<23)                /* 0x00800000 */
 
-#define A_TBLSZ        `               0x43    /* Effects Tank Internal Table Size. Only low byte or register used */
+#define A_TBLSZ                        0x43    /* Effects Tank Internal Table Size. Only low byte or register used */
 
 #define TCBS                   0x44            /* Tank cache buffer size register                      */
 #define TCBS_MASK              0x00000007      /* Tank cache buffer size field                         */
index c39b3802cf18afbb43637a516663c589b11b3b03..a9ba7ee699394aff8e3363d1bff2b10acf0d7bf7 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
 #define CONFIG_SND_VERSION "1.0.14rc2"
-#define CONFIG_SND_DATE " (Fri Feb 09 13:50:10 2007 UTC)"
+#define CONFIG_SND_DATE " (Wed Feb 14 07:42:13 2007 UTC)"
index ad33c979e0b32d3e2f2c1a21bc641003b02ad1fd..f977086e118a9ee936a4fd77e3cb5490857b7624 100644 (file)
@@ -125,6 +125,12 @@ config IPC_NS
          environments, to use ipc namespaces to provide different ipc
          objects for different servers.  If unsure, say N.
 
+config SYSVIPC_SYSCTL
+       bool
+       depends on SYSVIPC
+       depends on SYSCTL
+       default y
+
 config POSIX_MQUEUE
        bool "POSIX Message Queues"
        depends on NET && EXPERIMENTAL
index d206c7548fe6f80aa14f508d89f7a5f76c4216cd..40ff3b4048952993ed790b684800d3d36d56106b 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
index 4e9e92bb2b89623507e1c145a6c9a275da7686a6..953500b02ac4136f4ad30aa0ea6b285019234131 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/efi.h>
+#include <linux/tick.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
 #include <linux/unistd.h>
@@ -86,7 +87,6 @@ extern void init_IRQ(void);
 extern void fork_init(unsigned long);
 extern void mca_init(void);
 extern void sbus_init(void);
-extern void sysctl_init(void);
 extern void signals_init(void);
 extern void pidhash_init(void);
 extern void pidmap_init(void);
@@ -516,6 +516,7 @@ asmlinkage void __init start_kernel(void)
  * enable them
  */
        lock_kernel();
+       tick_init();
        boot_cpu_init();
        page_address_init();
        printk(KERN_NOTICE);
@@ -702,8 +703,8 @@ static void __init do_basic_setup(void)
        usermodehelper_init();
        driver_init();
 
-#ifdef CONFIG_SYSCTL
-       sysctl_init();
+#ifdef CONFIG_PROC_FS
+       init_irq_proc();
 #endif
 
        do_initcalls();
@@ -727,7 +728,49 @@ static void run_init_process(char *init_filename)
        kernel_execve(init_filename, argv_init, envp_init);
 }
 
-static int init(void * unused)
+/* This is a non __init function. Force it to be noinline otherwise gcc
+ * makes it inline to init() and it becomes part of init.text section
+ */
+static int noinline init_post(void)
+{
+       free_initmem();
+       unlock_kernel();
+       mark_rodata_ro();
+       system_state = SYSTEM_RUNNING;
+       numa_default_policy();
+
+       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+       (void) sys_dup(0);
+       (void) sys_dup(0);
+
+       if (ramdisk_execute_command) {
+               run_init_process(ramdisk_execute_command);
+               printk(KERN_WARNING "Failed to execute %s\n",
+                               ramdisk_execute_command);
+       }
+
+       /*
+        * We try each of these until one succeeds.
+        *
+        * The Bourne shell can be used instead of init if we are
+        * trying to recover a really broken machine.
+        */
+       if (execute_command) {
+               run_init_process(execute_command);
+               printk(KERN_WARNING "Failed to execute %s.  Attempting "
+                                       "defaults...\n", execute_command);
+       }
+       run_init_process("/sbin/init");
+       run_init_process("/etc/init");
+       run_init_process("/bin/init");
+       run_init_process("/bin/sh");
+
+       panic("No init found.  Try passing init= option to kernel.");
+}
+
+static int __init init(void * unused)
 {
        lock_kernel();
        /*
@@ -775,39 +818,6 @@ static int init(void * unused)
         * we're essentially up and running. Get rid of the
         * initmem segments and start the user-mode stuff..
         */
-       free_initmem();
-       unlock_kernel();
-       mark_rodata_ro();
-       system_state = SYSTEM_RUNNING;
-       numa_default_policy();
-
-       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
-
-       (void) sys_dup(0);
-       (void) sys_dup(0);
-
-       if (ramdisk_execute_command) {
-               run_init_process(ramdisk_execute_command);
-               printk(KERN_WARNING "Failed to execute %s\n",
-                               ramdisk_execute_command);
-       }
-
-       /*
-        * We try each of these until one succeeds.
-        *
-        * The Bourne shell can be used instead of init if we are 
-        * trying to recover a really broken machine.
-        */
-       if (execute_command) {
-               run_init_process(execute_command);
-               printk(KERN_WARNING "Failed to execute %s.  Attempting "
-                                       "defaults...\n", execute_command);
-       }
-       run_init_process("/sbin/init");
-       run_init_process("/etc/init");
-       run_init_process("/bin/init");
-       run_init_process("/bin/sh");
-
-       panic("No init found.  Try passing init= option to kernel.");
+       init_post();
+       return 0;
 }
index 6c01ec1cc48d4848fd98c28d11362e790703005d..9d17d70ee02d0165e4f94e5eacda6ea7c808a469 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/utsname.h>
 #include <linux/utsrelease.h>
 #include <linux/version.h>
-#include <linux/sched.h>
 
 #define version(a) Version_ ## a
 #define version_string(a) version(a)
index 0a6d626cd79400cb1b8e6c560063145887e055a8..b93bba6652f1e7abc068d96ea3490e9491939684 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
 obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o
+obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
 
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
new file mode 100644 (file)
index 0000000..a88934a
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (C) 2007
+ *
+ *  Author: Eric Biederman <ebiederm@xmision.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 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/ipc.h>
+#include <linux/nsproxy.h>
+#include <linux/sysctl.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_IPC_NS
+static void *get_ipc(ctl_table *table)
+{
+       char *which = table->data;
+       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+       which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
+       return which;
+}
+#else
+#define get_ipc(T) ((T)->data)
+#endif
+
+#ifdef CONFIG_PROC_FS
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table ipc_table;
+       memcpy(&ipc_table, table, sizeof(ipc_table));
+       ipc_table.data = get_ipc(table);
+
+       return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
+}
+
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+       struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table ipc_table;
+       memcpy(&ipc_table, table, sizeof(ipc_table));
+       ipc_table.data = get_ipc(table);
+
+       return proc_doulongvec_minmax(&ipc_table, write, filp, buffer,
+                                       lenp, ppos);
+}
+
+#else
+#define proc_ipc_doulongvec_minmax NULL
+#define proc_ipc_dointvec         NULL
+#endif
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+/* The generic sysctl ipc data routine. */
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       size_t len;
+       void *data;
+
+       /* Get out of I don't have a variable */
+       if (!table->data || !table->maxlen)
+               return -ENOTDIR;
+
+       data = get_ipc(table);
+       if (!data)
+               return -ENOTDIR;
+
+       if (oldval && oldlenp) {
+               if (get_user(len, oldlenp))
+                       return -EFAULT;
+               if (len) {
+                       if (len > table->maxlen)
+                               len = table->maxlen;
+                       if (copy_to_user(oldval, data, len))
+                               return -EFAULT;
+                       if (put_user(len, oldlenp))
+                               return -EFAULT;
+               }
+       }
+
+       if (newval && newlen) {
+               if (newlen > table->maxlen)
+                       newlen = table->maxlen;
+
+               if (copy_from_user(data, newval, newlen))
+                       return -EFAULT;
+       }
+       return 1;
+}
+#else
+#define sysctl_ipc_data NULL
+#endif
+
+static struct ctl_table ipc_kern_table[] = {
+       {
+               .ctl_name       = KERN_SHMMAX,
+               .procname       = "shmmax",
+               .data           = &init_ipc_ns.shm_ctlmax,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_SHMALL,
+               .procname       = "shmall",
+               .data           = &init_ipc_ns.shm_ctlall,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_SHMMNI,
+               .procname       = "shmmni",
+               .data           = &init_ipc_ns.shm_ctlmni,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_MSGMAX,
+               .procname       = "msgmax",
+               .data           = &init_ipc_ns.msg_ctlmax,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_MSGMNI,
+               .procname       = "msgmni",
+               .data           = &init_ipc_ns.msg_ctlmni,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_MSGMNB,
+               .procname       =  "msgmnb",
+               .data           = &init_ipc_ns.msg_ctlmnb,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
+       },
+       {
+               .ctl_name       = KERN_SEM,
+               .procname       = "sem",
+               .data           = &init_ipc_ns.sem_ctls,
+               .maxlen         = 4*sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
+       },
+       {}
+};
+
+static struct ctl_table ipc_root_table[] = {
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0555,
+               .child          = ipc_kern_table,
+       },
+       {}
+};
+
+static int __init ipc_sysctl_init(void)
+{
+       register_sysctl_table(ipc_root_table);
+       return 0;
+}
+
+__initcall(ipc_sysctl_init);
index 7a8ce610fda27b5cd31e6b67abb572ae6a9ef5c5..0b5ecbe5f0456c121f2af016292fb0123f4bf4cd 100644 (file)
@@ -1255,7 +1255,7 @@ static int __init init_mqueue_fs(void)
                return -ENOMEM;
 
        /* ignore failues - they are not fatal */
-       mq_sysctl_table = register_sysctl_table(mq_sysctl_root, 0);
+       mq_sysctl_table = register_sysctl_table(mq_sysctl_root);
 
        error = register_filesystem(&mqueue_fs_type);
        if (error)
index 14f4d45e0ae95fbdeb4fe40d4815b495ec3d571f..ac6b27abb1adf21bccafac0dc9dde9c5929ffe83 100644 (file)
@@ -47,6 +47,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
+obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
 obj-$(CONFIG_UTS_NS) += utsname.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
index d9b690ac684b9c6a638cee37d11949d62ef22992..76c9a11b72d64c738402159b55a39012fee6142b 100644 (file)
@@ -2,7 +2,7 @@
  * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
  * System-call specific features have moved to auditsc.c
  *
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -65,7 +65,9 @@
  * (Initialization happens after skb_init is called.) */
 static int     audit_initialized;
 
-/* No syscall auditing will take place unless audit_enabled != 0. */
+/* 0 - no auditing
+ * 1 - auditing enabled
+ * 2 - auditing enabled and configuration is locked/unchangeable. */
 int            audit_enabled;
 
 /* Default state when kernel boots without any parameters. */
@@ -239,102 +241,150 @@ void audit_log_lost(const char *message)
 
 static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
 {
-       int old = audit_rate_limit;
+       int res, rc = 0, old = audit_rate_limit;
+
+       /* check if we are locked */
+       if (audit_enabled == 2)
+               res = 0;
+       else
+               res = 1;
 
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               int rc;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-                       return rc;
-               else
+               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
                        audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_rate_limit=%d old=%d by auid=%u subj=%s",
-                               limit, old, loginuid, ctx);
-               kfree(ctx);
-       } else
-               audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                       "audit_rate_limit=%d old=%d by auid=%u",
-                       limit, old, loginuid);
-       audit_rate_limit = limit;
-       return 0;
+                               "audit_rate_limit=%d old=%d by auid=%u"
+                               " subj=%s res=%d",
+                               limit, old, loginuid, ctx, res);
+                       kfree(ctx);
+               } else
+                       res = 0; /* Something weird, deny request */
+       }
+       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+               "audit_rate_limit=%d old=%d by auid=%u res=%d",
+               limit, old, loginuid, res);
+
+       /* If we are allowed, make the change */
+       if (res == 1)
+               audit_rate_limit = limit;
+       /* Not allowed, update reason */
+       else if (rc == 0)
+               rc = -EPERM;
+       return rc;
 }
 
 static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
 {
-       int old = audit_backlog_limit;
+       int res, rc = 0, old = audit_backlog_limit;
+
+       /* check if we are locked */
+       if (audit_enabled == 2)
+               res = 0;
+       else
+               res = 1;
 
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               int rc;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-                       return rc;
-               else
+               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
                        audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                           "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
-                               limit, old, loginuid, ctx);
-               kfree(ctx);
-       } else
-               audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                       "audit_backlog_limit=%d old=%d by auid=%u",
-                       limit, old, loginuid);
-       audit_backlog_limit = limit;
-       return 0;
+                               "audit_backlog_limit=%d old=%d by auid=%u"
+                               " subj=%s res=%d",
+                               limit, old, loginuid, ctx, res);
+                       kfree(ctx);
+               } else
+                       res = 0; /* Something weird, deny request */
+       }
+       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+               "audit_backlog_limit=%d old=%d by auid=%u res=%d",
+               limit, old, loginuid, res);
+
+       /* If we are allowed, make the change */
+       if (res == 1)
+               audit_backlog_limit = limit;
+       /* Not allowed, update reason */
+       else if (rc == 0)
+               rc = -EPERM;
+       return rc;
 }
 
 static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
 {
-       int old = audit_enabled;
+       int res, rc = 0, old = audit_enabled;
 
-       if (state != 0 && state != 1)
+       if (state < 0 || state > 2)
                return -EINVAL;
 
+       /* check if we are locked */
+       if (audit_enabled == 2)
+               res = 0;
+       else
+               res = 1;
+
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               int rc;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-                       return rc;
-               else
+               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
                        audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_enabled=%d old=%d by auid=%u subj=%s",
-                               state, old, loginuid, ctx);
-               kfree(ctx);
-       } else
-               audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                       "audit_enabled=%d old=%d by auid=%u",
-                       state, old, loginuid);
-       audit_enabled = state;
-       return 0;
+                               "audit_enabled=%d old=%d by auid=%u"
+                               " subj=%s res=%d",
+                               state, old, loginuid, ctx, res);
+                       kfree(ctx);
+               } else
+                       res = 0; /* Something weird, deny request */
+       }
+       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+               "audit_enabled=%d old=%d by auid=%u res=%d",
+               state, old, loginuid, res);
+
+       /* If we are allowed, make the change */
+       if (res == 1)
+               audit_enabled = state;
+       /* Not allowed, update reason */
+       else if (rc == 0)
+               rc = -EPERM;
+       return rc;
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
 {
-       int old = audit_failure;
+       int res, rc = 0, old = audit_failure;
 
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
 
+       /* check if we are locked */
+       if (audit_enabled == 2)
+               res = 0;
+       else
+               res = 1;
+
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               int rc;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-                       return rc;
-               else
+               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
                        audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_failure=%d old=%d by auid=%u subj=%s",
-                               state, old, loginuid, ctx);
-               kfree(ctx);
-       } else
-               audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                       "audit_failure=%d old=%d by auid=%u",
-                       state, old, loginuid);
-       audit_failure = state;
-       return 0;
+                               "audit_failure=%d old=%d by auid=%u"
+                               " subj=%s res=%d",
+                               state, old, loginuid, ctx, res);
+                       kfree(ctx);
+               } else
+                       res = 0; /* Something weird, deny request */
+       }
+       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+               "audit_failure=%d old=%d by auid=%u res=%d",
+               state, old, loginuid, res);
+
+       /* If we are allowed, make the change */
+       if (res == 1)
+               audit_failure = state;
+       /* Not allowed, update reason */
+       else if (rc == 0)
+               rc = -EPERM;
+       return rc;
 }
 
 static int kauditd_thread(void *dummy)
@@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_DEL:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule))
                        return -EINVAL;
+               if (audit_enabled == 2) {
+                       ab = audit_log_start(NULL, GFP_KERNEL,
+                                       AUDIT_CONFIG_CHANGE);
+                       if (ab) {
+                               audit_log_format(ab,
+                                                "pid=%d uid=%u auid=%u",
+                                                pid, uid, loginuid);
+                               if (sid) {
+                                       if (selinux_sid_to_string(
+                                                       sid, &ctx, &len)) {
+                                               audit_log_format(ab,
+                                                       " ssid=%u", sid);
+                                               /* Maybe call audit_panic? */
+                                       } else
+                                               audit_log_format(ab,
+                                                       " subj=%s", ctx);
+                                       kfree(ctx);
+                               }
+                               audit_log_format(ab, " audit_enabled=%d res=0",
+                                       audit_enabled);
+                               audit_log_end(ab);
+                       }
+                       return -EPERM;
+               }
                /* fallthrough */
        case AUDIT_LIST:
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_DEL_RULE:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
                        return -EINVAL;
+               if (audit_enabled == 2) {
+                       ab = audit_log_start(NULL, GFP_KERNEL,
+                                       AUDIT_CONFIG_CHANGE);
+                       if (ab) {
+                               audit_log_format(ab,
+                                                "pid=%d uid=%u auid=%u",
+                                                pid, uid, loginuid);
+                               if (sid) {
+                                       if (selinux_sid_to_string(
+                                                       sid, &ctx, &len)) {
+                                               audit_log_format(ab,
+                                                       " ssid=%u", sid);
+                                               /* Maybe call audit_panic? */
+                                       } else
+                                               audit_log_format(ab,
+                                                       " subj=%s", ctx);
+                                       kfree(ctx);
+                               }
+                               audit_log_format(ab, " audit_enabled=%d res=0",
+                                       audit_enabled);
+                               audit_log_end(ab);
+                       }
+                       return -EPERM;
+               }
                /* fallthrough */
        case AUDIT_LIST_RULES:
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
index 87865f8b4ce3ecdebad12707c6867a302bedee69..3749193aed8cf805a5c96fea00331379735c45ea 100644 (file)
@@ -937,9 +937,10 @@ static void audit_update_watch(struct audit_parent *parent,
                }
 
                ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-               audit_log_format(ab, "audit updated rules specifying path=");
+               audit_log_format(ab, "op=updated rules specifying path=");
                audit_log_untrustedstring(ab, owatch->path);
                audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
+               audit_log_format(ab, " list=%d res=1", r->listnr);
                audit_log_end(ab);
 
                audit_remove_watch(owatch);
@@ -969,14 +970,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
                        e = container_of(r, struct audit_entry, rule);
 
                        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-                       audit_log_format(ab, "audit implicitly removed rule path=");
+                       audit_log_format(ab, "op=remove rule path=");
                        audit_log_untrustedstring(ab, w->path);
                        if (r->filterkey) {
                                audit_log_format(ab, " key=");
                                audit_log_untrustedstring(ab, r->filterkey);
                        } else
                                audit_log_format(ab, " key=(null)");
-                       audit_log_format(ab, " list=%d", r->listnr);
+                       audit_log_format(ab, " list=%d res=1", r->listnr);
                        audit_log_end(ab);
 
                        list_del(&r->rlist);
@@ -1410,7 +1411,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
                        audit_log_format(ab, " subj=%s", ctx);
                kfree(ctx);
        }
-       audit_log_format(ab, " %s rule key=", action);
+       audit_log_format(ab, " op=%s rule key=", action);
        if (rule->filterkey)
                audit_log_untrustedstring(ab, rule->filterkey);
        else
index 298897559ca4ab9d346566cfac6d50791371e9d3..359955800dd2ecb30827ad6b53daff9014088d19 100644 (file)
@@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr {
        char                    a[0];
 };
 
+struct audit_aux_data_fd_pair {
+       struct  audit_aux_data d;
+       int     fd[2];
+};
+
 struct audit_aux_data_path {
        struct audit_aux_data   d;
        struct dentry           *dentry;
@@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
                        break; }
 
+               case AUDIT_FD_PAIR: {
+                       struct audit_aux_data_fd_pair *axs = (void *)aux;
+                       audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
+                       break; }
+
                }
                audit_log_end(ab);
        }
@@ -1814,6 +1824,36 @@ int audit_socketcall(int nargs, unsigned long *args)
        return 0;
 }
 
+/**
+ * __audit_fd_pair - record audit data for pipe and socketpair
+ * @fd1: the first file descriptor
+ * @fd2: the second file descriptor
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_fd_pair(int fd1, int fd2)
+{
+       struct audit_context *context = current->audit_context;
+       struct audit_aux_data_fd_pair *ax;
+
+       if (likely(!context)) {
+               return 0;
+       }
+
+       ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+       if (!ax) {
+               return -ENOMEM;
+       }
+
+       ax->fd[0] = fd1;
+       ax->fd[1] = fd2;
+
+       ax->d.type = AUDIT_FD_PAIR;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
 /**
  * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
  * @len: data length in user space
index 0b6293d94d96b412bfb8f33af4903728cf418a7b..d154cc786489f3928bbaefe5d31e8da4f78b2481 100644 (file)
@@ -858,7 +858,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
        init_sigpending(&sig->shared_pending);
        INIT_LIST_HEAD(&sig->posix_timers);
 
-       hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL);
+       hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        sig->it_real_incr.tv64 = 0;
        sig->real_timer.function = it_real_fn;
        sig->tsk = tsk;
index 5a737de857d37e5d84bd7da9044c92ce22170a94..e749e7df14b1a598c201f61b4d9b5bf8fb7c3d97 100644 (file)
@@ -1134,7 +1134,7 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
 
        if (sec != MAX_SCHEDULE_TIMEOUT) {
                to = &timeout;
-               hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+               hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
                hrtimer_init_sleeper(to, current);
                to->timer.expires = ktime_set(sec, nsec);
        }
index f44e499e8fcab4130bfa1a77558aabaf24458fe2..476cb0c0b4a432bce65c1f113011aa60cd3060b0 100644 (file)
@@ -1,8 +1,9 @@
 /*
  *  linux/kernel/hrtimer.c
  *
- *  Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
- *  Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner
  *
  *  High-resolution kernel timers
  *
  */
 
 #include <linux/cpu.h>
+#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
 #include <linux/hrtimer.h>
 #include <linux/notifier.h>
 #include <linux/syscalls.h>
+#include <linux/kallsyms.h>
 #include <linux/interrupt.h>
+#include <linux/tick.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
 
 #include <asm/uaccess.h>
 
@@ -45,7 +51,7 @@
  *
  * returns the time in ktime_t format
  */
-static ktime_t ktime_get(void)
+ktime_t ktime_get(void)
 {
        struct timespec now;
 
@@ -59,7 +65,7 @@ static ktime_t ktime_get(void)
  *
  * returns the time in ktime_t format
  */
-static ktime_t ktime_get_real(void)
+ktime_t ktime_get_real(void)
 {
        struct timespec now;
 
@@ -79,21 +85,22 @@ EXPORT_SYMBOL_GPL(ktime_get_real);
  * This ensures that we capture erroneous accesses to these clock ids
  * rather than moving them into the range of valid clock id's.
  */
-
-#define MAX_HRTIMER_BASES 2
-
-static DEFINE_PER_CPU(struct hrtimer_base, hrtimer_bases[MAX_HRTIMER_BASES]) =
+DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
+
+       .clock_base =
        {
-               .index = CLOCK_REALTIME,
-               .get_time = &ktime_get_real,
-               .resolution = KTIME_REALTIME_RES,
-       },
-       {
-               .index = CLOCK_MONOTONIC,
-               .get_time = &ktime_get,
-               .resolution = KTIME_MONOTONIC_RES,
-       },
+               {
+                       .index = CLOCK_REALTIME,
+                       .get_time = &ktime_get_real,
+                       .resolution = KTIME_LOW_RES,
+               },
+               {
+                       .index = CLOCK_MONOTONIC,
+                       .get_time = &ktime_get,
+                       .resolution = KTIME_LOW_RES,
+               },
+       }
 };
 
 /**
@@ -125,20 +132,35 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
  * Get the coarse grained time at the softirq based on xtime and
  * wall_to_monotonic.
  */
-static void hrtimer_get_softirq_time(struct hrtimer_base *base)
+static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 {
        ktime_t xtim, tomono;
+       struct timespec xts;
        unsigned long seq;
 
        do {
                seq = read_seqbegin(&xtime_lock);
-               xtim = timespec_to_ktime(xtime);
-               tomono = timespec_to_ktime(wall_to_monotonic);
-
+#ifdef CONFIG_NO_HZ
+               getnstimeofday(&xts);
+#else
+               xts = xtime;
+#endif
        } while (read_seqretry(&xtime_lock, seq));
 
-       base[CLOCK_REALTIME].softirq_time = xtim;
-       base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
+       xtim = timespec_to_ktime(xts);
+       tomono = timespec_to_ktime(wall_to_monotonic);
+       base->clock_base[CLOCK_REALTIME].softirq_time = xtim;
+       base->clock_base[CLOCK_MONOTONIC].softirq_time =
+               ktime_add(xtim, tomono);
+}
+
+/*
+ * Helper function to check, whether the timer is running the callback
+ * function
+ */
+static inline int hrtimer_callback_running(struct hrtimer *timer)
+{
+       return timer->state & HRTIMER_STATE_CALLBACK;
 }
 
 /*
@@ -147,8 +169,6 @@ static void hrtimer_get_softirq_time(struct hrtimer_base *base)
  */
 #ifdef CONFIG_SMP
 
-#define set_curr_timer(b, t)           do { (b)->curr_timer = (t); } while (0)
-
 /*
  * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
  * means that all timers which are tied to this base via timer->base are
@@ -161,19 +181,20 @@ static void hrtimer_get_softirq_time(struct hrtimer_base *base)
  * possible to set timer->base = NULL and drop the lock: the timer remains
  * locked.
  */
-static struct hrtimer_base *lock_hrtimer_base(const struct hrtimer *timer,
-                                             unsigned long *flags)
+static
+struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
+                                            unsigned long *flags)
 {
-       struct hrtimer_base *base;
+       struct hrtimer_clock_base *base;
 
        for (;;) {
                base = timer->base;
                if (likely(base != NULL)) {
-                       spin_lock_irqsave(&base->lock, *flags);
+                       spin_lock_irqsave(&base->cpu_base->lock, *flags);
                        if (likely(base == timer->base))
                                return base;
                        /* The timer has migrated to another CPU: */
-                       spin_unlock_irqrestore(&base->lock, *flags);
+                       spin_unlock_irqrestore(&base->cpu_base->lock, *flags);
                }
                cpu_relax();
        }
@@ -182,12 +203,14 @@ static struct hrtimer_base *lock_hrtimer_base(const struct hrtimer *timer,
 /*
  * Switch the timer base to the current CPU when possible.
  */
-static inline struct hrtimer_base *
-switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
+static inline struct hrtimer_clock_base *
+switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
-       struct hrtimer_base *new_base;
+       struct hrtimer_clock_base *new_base;
+       struct hrtimer_cpu_base *new_cpu_base;
 
-       new_base = &__get_cpu_var(hrtimer_bases)[base->index];
+       new_cpu_base = &__get_cpu_var(hrtimer_bases);
+       new_base = &new_cpu_base->clock_base[base->index];
 
        if (base != new_base) {
                /*
@@ -199,13 +222,13 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
                 * completed. There is no conflict as we hold the lock until
                 * the timer is enqueued.
                 */
-               if (unlikely(base->curr_timer == timer))
+               if (unlikely(hrtimer_callback_running(timer)))
                        return base;
 
                /* See the comment in lock_timer_base() */
                timer->base = NULL;
-               spin_unlock(&base->lock);
-               spin_lock(&new_base->lock);
+               spin_unlock(&base->cpu_base->lock);
+               spin_lock(&new_base->cpu_base->lock);
                timer->base = new_base;
        }
        return new_base;
@@ -213,19 +236,17 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
 
 #else /* CONFIG_SMP */
 
-#define set_curr_timer(b, t)           do { } while (0)
-
-static inline struct hrtimer_base *
+static inline struct hrtimer_clock_base *
 lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
 {
-       struct hrtimer_base *base = timer->base;
+       struct hrtimer_clock_base *base = timer->base;
 
-       spin_lock_irqsave(&base->lock, *flags);
+       spin_lock_irqsave(&base->cpu_base->lock, *flags);
 
        return base;
 }
 
-#define switch_hrtimer_base(t, b)      (b)
+# define switch_hrtimer_base(t, b)     (b)
 
 #endif /* !CONFIG_SMP */
 
@@ -256,15 +277,12 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
 
        return ktime_add(kt, tmp);
 }
-
-#else /* CONFIG_KTIME_SCALAR */
-
 # endif /* !CONFIG_KTIME_SCALAR */
 
 /*
  * Divide a ktime value by a nanosecond value
  */
-static unsigned long ktime_divns(const ktime_t kt, s64 div)
+unsigned long ktime_divns(const ktime_t kt, s64 div)
 {
        u64 dclc, inc, dns;
        int sft = 0;
@@ -281,18 +299,311 @@ static unsigned long ktime_divns(const ktime_t kt, s64 div)
 
        return (unsigned long) dclc;
 }
-
-#else /* BITS_PER_LONG < 64 */
-# define ktime_divns(kt, div)          (unsigned long)((kt).tv64 / (div))
 #endif /* BITS_PER_LONG >= 64 */
 
+/* High resolution timer related functions */
+#ifdef CONFIG_HIGH_RES_TIMERS
+
+/*
+ * High resolution timer enabled ?
+ */
+static int hrtimer_hres_enabled __read_mostly  = 1;
+
+/*
+ * Enable / Disable high resolution mode
+ */
+static int __init setup_hrtimer_hres(char *str)
+{
+       if (!strcmp(str, "off"))
+               hrtimer_hres_enabled = 0;
+       else if (!strcmp(str, "on"))
+               hrtimer_hres_enabled = 1;
+       else
+               return 0;
+       return 1;
+}
+
+__setup("highres=", setup_hrtimer_hres);
+
+/*
+ * hrtimer_high_res_enabled - query, if the highres mode is enabled
+ */
+static inline int hrtimer_is_hres_enabled(void)
+{
+       return hrtimer_hres_enabled;
+}
+
+/*
+ * Is the high resolution mode active ?
+ */
+static inline int hrtimer_hres_active(void)
+{
+       return __get_cpu_var(hrtimer_bases).hres_active;
+}
+
+/*
+ * Reprogram the event source with checking both queues for the
+ * next event
+ * Called with interrupts disabled and base->lock held
+ */
+static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
+{
+       int i;
+       struct hrtimer_clock_base *base = cpu_base->clock_base;
+       ktime_t expires;
+
+       cpu_base->expires_next.tv64 = KTIME_MAX;
+
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
+               struct hrtimer *timer;
+
+               if (!base->first)
+                       continue;
+               timer = rb_entry(base->first, struct hrtimer, node);
+               expires = ktime_sub(timer->expires, base->offset);
+               if (expires.tv64 < cpu_base->expires_next.tv64)
+                       cpu_base->expires_next = expires;
+       }
+
+       if (cpu_base->expires_next.tv64 != KTIME_MAX)
+               tick_program_event(cpu_base->expires_next, 1);
+}
+
+/*
+ * Shared reprogramming for clock_realtime and clock_monotonic
+ *
+ * When a timer is enqueued and expires earlier than the already enqueued
+ * timers, we have to check, whether it expires earlier than the timer for
+ * which the clock event device was armed.
+ *
+ * Called with interrupts disabled and base->cpu_base.lock held
+ */
+static int hrtimer_reprogram(struct hrtimer *timer,
+                            struct hrtimer_clock_base *base)
+{
+       ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next;
+       ktime_t expires = ktime_sub(timer->expires, base->offset);
+       int res;
+
+       /*
+        * When the callback is running, we do not reprogram the clock event
+        * device. The timer callback is either running on a different CPU or
+        * the callback is executed in the hrtimer_interupt context. The
+        * reprogramming is handled either by the softirq, which called the
+        * callback or at the end of the hrtimer_interrupt.
+        */
+       if (hrtimer_callback_running(timer))
+               return 0;
+
+       if (expires.tv64 >= expires_next->tv64)
+               return 0;
+
+       /*
+        * Clockevents returns -ETIME, when the event was in the past.
+        */
+       res = tick_program_event(expires, 0);
+       if (!IS_ERR_VALUE(res))
+               *expires_next = expires;
+       return res;
+}
+
+
+/*
+ * Retrigger next event is called after clock was set
+ *
+ * Called with interrupts disabled via on_each_cpu()
+ */
+static void retrigger_next_event(void *arg)
+{
+       struct hrtimer_cpu_base *base;
+       struct timespec realtime_offset;
+       unsigned long seq;
+
+       if (!hrtimer_hres_active())
+               return;
+
+       do {
+               seq = read_seqbegin(&xtime_lock);
+               set_normalized_timespec(&realtime_offset,
+                                       -wall_to_monotonic.tv_sec,
+                                       -wall_to_monotonic.tv_nsec);
+       } while (read_seqretry(&xtime_lock, seq));
+
+       base = &__get_cpu_var(hrtimer_bases);
+
+       /* Adjust CLOCK_REALTIME offset */
+       spin_lock(&base->lock);
+       base->clock_base[CLOCK_REALTIME].offset =
+               timespec_to_ktime(realtime_offset);
+
+       hrtimer_force_reprogram(base);
+       spin_unlock(&base->lock);
+}
+
+/*
+ * Clock realtime was set
+ *
+ * Change the offset of the realtime clock vs. the monotonic
+ * clock.
+ *
+ * We might have to reprogram the high resolution timer interrupt. On
+ * SMP we call the architecture specific code to retrigger _all_ high
+ * resolution timer interrupts. On UP we just disable interrupts and
+ * call the high resolution interrupt code.
+ */
+void clock_was_set(void)
+{
+       /* Retrigger the CPU local events everywhere */
+       on_each_cpu(retrigger_next_event, NULL, 0, 1);
+}
+
+/*
+ * Check, whether the timer is on the callback pending list
+ */
+static inline int hrtimer_cb_pending(const struct hrtimer *timer)
+{
+       return timer->state & HRTIMER_STATE_PENDING;
+}
+
+/*
+ * Remove a timer from the callback pending list
+ */
+static inline void hrtimer_remove_cb_pending(struct hrtimer *timer)
+{
+       list_del_init(&timer->cb_entry);
+}
+
+/*
+ * Initialize the high resolution related parts of cpu_base
+ */
+static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
+{
+       base->expires_next.tv64 = KTIME_MAX;
+       base->hres_active = 0;
+       INIT_LIST_HEAD(&base->cb_pending);
+}
+
+/*
+ * Initialize the high resolution related parts of a hrtimer
+ */
+static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
+{
+       INIT_LIST_HEAD(&timer->cb_entry);
+}
+
+/*
+ * When High resolution timers are active, try to reprogram. Note, that in case
+ * the state has HRTIMER_STATE_CALLBACK set, no reprogramming and no expiry
+ * check happens. The timer gets enqueued into the rbtree. The reprogramming
+ * and expiry check is done in the hrtimer_interrupt or in the softirq.
+ */
+static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+                                           struct hrtimer_clock_base *base)
+{
+       if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
+
+               /* Timer is expired, act upon the callback mode */
+               switch(timer->cb_mode) {
+               case HRTIMER_CB_IRQSAFE_NO_RESTART:
+                       /*
+                        * We can call the callback from here. No restart
+                        * happens, so no danger of recursion
+                        */
+                       BUG_ON(timer->function(timer) != HRTIMER_NORESTART);
+                       return 1;
+               case HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:
+                       /*
+                        * This is solely for the sched tick emulation with
+                        * dynamic tick support to ensure that we do not
+                        * restart the tick right on the edge and end up with
+                        * the tick timer in the softirq ! The calling site
+                        * takes care of this.
+                        */
+                       return 1;
+               case HRTIMER_CB_IRQSAFE:
+               case HRTIMER_CB_SOFTIRQ:
+                       /*
+                        * Move everything else into the softirq pending list !
+                        */
+                       list_add_tail(&timer->cb_entry,
+                                     &base->cpu_base->cb_pending);
+                       timer->state = HRTIMER_STATE_PENDING;
+                       raise_softirq(HRTIMER_SOFTIRQ);
+                       return 1;
+               default:
+                       BUG();
+               }
+       }
+       return 0;
+}
+
+/*
+ * Switch to high resolution mode
+ */
+static void hrtimer_switch_to_hres(void)
+{
+       struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
+       unsigned long flags;
+
+       if (base->hres_active)
+               return;
+
+       local_irq_save(flags);
+
+       if (tick_init_highres()) {
+               local_irq_restore(flags);
+               return;
+       }
+       base->hres_active = 1;
+       base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
+       base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES;
+
+       tick_setup_sched_timer();
+
+       /* "Retrigger" the interrupt to get things going */
+       retrigger_next_event(NULL);
+       local_irq_restore(flags);
+       printk(KERN_INFO "Switched to high resolution mode on CPU %d\n",
+              smp_processor_id());
+}
+
+#else
+
+static inline int hrtimer_hres_active(void) { return 0; }
+static inline int hrtimer_is_hres_enabled(void) { return 0; }
+static inline void hrtimer_switch_to_hres(void) { }
+static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
+static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+                                           struct hrtimer_clock_base *base)
+{
+       return 0;
+}
+static inline int hrtimer_cb_pending(struct hrtimer *timer) { return 0; }
+static inline void hrtimer_remove_cb_pending(struct hrtimer *timer) { }
+static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
+static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { }
+
+#endif /* CONFIG_HIGH_RES_TIMERS */
+
+#ifdef CONFIG_TIMER_STATS
+void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, void *addr)
+{
+       if (timer->start_site)
+               return;
+
+       timer->start_site = addr;
+       memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
+       timer->start_pid = current->pid;
+}
+#endif
+
 /*
  * Counterpart to lock_timer_base above:
  */
 static inline
 void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
 {
-       spin_unlock_irqrestore(&timer->base->lock, *flags);
+       spin_unlock_irqrestore(&timer->base->cpu_base->lock, *flags);
 }
 
 /**
@@ -342,7 +653,8 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
  * The timer is inserted in expiry order. Insertion into the
  * red black tree is O(log(n)). Must hold the base lock.
  */
-static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+static void enqueue_hrtimer(struct hrtimer *timer,
+                           struct hrtimer_clock_base *base, int reprogram)
 {
        struct rb_node **link = &base->active.rb_node;
        struct rb_node *parent = NULL;
@@ -368,39 +680,85 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
         * Insert the timer to the rbtree and check whether it
         * replaces the first pending timer
         */
-       rb_link_node(&timer->node, parent, link);
-       rb_insert_color(&timer->node, &base->active);
-
        if (!base->first || timer->expires.tv64 <
-           rb_entry(base->first, struct hrtimer, node)->expires.tv64)
+           rb_entry(base->first, struct hrtimer, node)->expires.tv64) {
+               /*
+                * Reprogram the clock event device. When the timer is already
+                * expired hrtimer_enqueue_reprogram has either called the
+                * callback or added it to the pending list and raised the
+                * softirq.
+                *
+                * This is a NOP for !HIGHRES
+                */
+               if (reprogram && hrtimer_enqueue_reprogram(timer, base))
+                       return;
+
                base->first = &timer->node;
+       }
+
+       rb_link_node(&timer->node, parent, link);
+       rb_insert_color(&timer->node, &base->active);
+       /*
+        * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
+        * state of a possibly running callback.
+        */
+       timer->state |= HRTIMER_STATE_ENQUEUED;
 }
 
 /*
  * __remove_hrtimer - internal function to remove a timer
  *
  * Caller must hold the base lock.
+ *
+ * High resolution timer mode reprograms the clock event device when the
+ * timer is the one which expires next. The caller can disable this by setting
+ * reprogram to zero. This is useful, when the context does a reprogramming
+ * anyway (e.g. timer interrupt)
  */
-static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+static void __remove_hrtimer(struct hrtimer *timer,
+                            struct hrtimer_clock_base *base,
+                            unsigned long newstate, int reprogram)
 {
-       /*
-        * Remove the timer from the rbtree and replace the
-        * first entry pointer if necessary.
-        */
-       if (base->first == &timer->node)
-               base->first = rb_next(&timer->node);
-       rb_erase(&timer->node, &base->active);
-       rb_set_parent(&timer->node, &timer->node);
+       /* High res. callback list. NOP for !HIGHRES */
+       if (hrtimer_cb_pending(timer))
+               hrtimer_remove_cb_pending(timer);
+       else {
+               /*
+                * Remove the timer from the rbtree and replace the
+                * first entry pointer if necessary.
+                */
+               if (base->first == &timer->node) {
+                       base->first = rb_next(&timer->node);
+                       /* Reprogram the clock event device. if enabled */
+                       if (reprogram && hrtimer_hres_active())
+                               hrtimer_force_reprogram(base->cpu_base);
+               }
+               rb_erase(&timer->node, &base->active);
+       }
+       timer->state = newstate;
 }
 
 /*
  * remove hrtimer, called with base lock held
  */
 static inline int
-remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
-       if (hrtimer_active(timer)) {
-               __remove_hrtimer(timer, base);
+       if (hrtimer_is_queued(timer)) {
+               int reprogram;
+
+               /*
+                * Remove the timer and force reprogramming when high
+                * resolution mode is active and the timer is on the current
+                * CPU. If we remove a timer on another CPU, reprogramming is
+                * skipped. The interrupt event on this CPU is fired and
+                * reprogramming happens in the interrupt handler. This is a
+                * rare case and less expensive than a smp call.
+                */
+               timer_stats_hrtimer_clear_start_info(timer);
+               reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
+               __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
+                                reprogram);
                return 1;
        }
        return 0;
@@ -419,7 +777,7 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
 int
 hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
 {
-       struct hrtimer_base *base, *new_base;
+       struct hrtimer_clock_base *base, *new_base;
        unsigned long flags;
        int ret;
 
@@ -431,7 +789,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
        /* Switch the timer base, if necessary: */
        new_base = switch_hrtimer_base(timer, base);
 
-       if (mode == HRTIMER_REL) {
+       if (mode == HRTIMER_MODE_REL) {
                tim = ktime_add(tim, new_base->get_time());
                /*
                 * CONFIG_TIME_LOW_RES is a temporary way for architectures
@@ -446,7 +804,9 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
        }
        timer->expires = tim;
 
-       enqueue_hrtimer(timer, new_base);
+       timer_stats_hrtimer_set_start_info(timer);
+
+       enqueue_hrtimer(timer, new_base, base == new_base);
 
        unlock_hrtimer_base(timer, &flags);
 
@@ -466,13 +826,13 @@ EXPORT_SYMBOL_GPL(hrtimer_start);
  */
 int hrtimer_try_to_cancel(struct hrtimer *timer)
 {
-       struct hrtimer_base *base;
+       struct hrtimer_clock_base *base;
        unsigned long flags;
        int ret = -1;
 
        base = lock_hrtimer_base(timer, &flags);
 
-       if (base->curr_timer != timer)
+       if (!hrtimer_callback_running(timer))
                ret = remove_hrtimer(timer, base);
 
        unlock_hrtimer_base(timer, &flags);
@@ -508,19 +868,19 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
  */
 ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
 {
-       struct hrtimer_base *base;
+       struct hrtimer_clock_base *base;
        unsigned long flags;
        ktime_t rem;
 
        base = lock_hrtimer_base(timer, &flags);
-       rem = ktime_sub(timer->expires, timer->base->get_time());
+       rem = ktime_sub(timer->expires, base->get_time());
        unlock_hrtimer_base(timer, &flags);
 
        return rem;
 }
 EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
 
-#ifdef CONFIG_NO_IDLE_HZ
+#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
 /**
  * hrtimer_get_next_event - get the time until next expiry event
  *
@@ -529,26 +889,31 @@ EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
  */
 ktime_t hrtimer_get_next_event(void)
 {
-       struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+       struct hrtimer_clock_base *base = cpu_base->clock_base;
        ktime_t delta, mindelta = { .tv64 = KTIME_MAX };
        unsigned long flags;
        int i;
 
-       for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) {
-               struct hrtimer *timer;
+       spin_lock_irqsave(&cpu_base->lock, flags);
 
-               spin_lock_irqsave(&base->lock, flags);
-               if (!base->first) {
-                       spin_unlock_irqrestore(&base->lock, flags);
-                       continue;
+       if (!hrtimer_hres_active()) {
+               for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
+                       struct hrtimer *timer;
+
+                       if (!base->first)
+                               continue;
+
+                       timer = rb_entry(base->first, struct hrtimer, node);
+                       delta.tv64 = timer->expires.tv64;
+                       delta = ktime_sub(delta, base->get_time());
+                       if (delta.tv64 < mindelta.tv64)
+                               mindelta.tv64 = delta.tv64;
                }
-               timer = rb_entry(base->first, struct hrtimer, node);
-               delta.tv64 = timer->expires.tv64;
-               spin_unlock_irqrestore(&base->lock, flags);
-               delta = ktime_sub(delta, base->get_time());
-               if (delta.tv64 < mindelta.tv64)
-                       mindelta.tv64 = delta.tv64;
        }
+
+       spin_unlock_irqrestore(&cpu_base->lock, flags);
+
        if (mindelta.tv64 < 0)
                mindelta.tv64 = 0;
        return mindelta;
@@ -564,17 +929,23 @@ ktime_t hrtimer_get_next_event(void)
 void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
                  enum hrtimer_mode mode)
 {
-       struct hrtimer_base *bases;
+       struct hrtimer_cpu_base *cpu_base;
 
        memset(timer, 0, sizeof(struct hrtimer));
 
-       bases = __raw_get_cpu_var(hrtimer_bases);
+       cpu_base = &__raw_get_cpu_var(hrtimer_bases);
 
-       if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
+       if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
                clock_id = CLOCK_MONOTONIC;
 
-       timer->base = &bases[clock_id];
-       rb_set_parent(&timer->node, &timer->node);
+       timer->base = &cpu_base->clock_base[clock_id];
+       hrtimer_init_timer_hres(timer);
+
+#ifdef CONFIG_TIMER_STATS
+       timer->start_site = NULL;
+       timer->start_pid = -1;
+       memset(timer->start_comm, 0, TASK_COMM_LEN);
+#endif
 }
 EXPORT_SYMBOL_GPL(hrtimer_init);
 
@@ -588,21 +959,159 @@ EXPORT_SYMBOL_GPL(hrtimer_init);
  */
 int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
 {
-       struct hrtimer_base *bases;
+       struct hrtimer_cpu_base *cpu_base;
 
-       bases = __raw_get_cpu_var(hrtimer_bases);
-       *tp = ktime_to_timespec(bases[which_clock].resolution);
+       cpu_base = &__raw_get_cpu_var(hrtimer_bases);
+       *tp = ktime_to_timespec(cpu_base->clock_base[which_clock].resolution);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(hrtimer_get_res);
 
+#ifdef CONFIG_HIGH_RES_TIMERS
+
+/*
+ * High resolution timer interrupt
+ * Called with interrupts disabled
+ */
+void hrtimer_interrupt(struct clock_event_device *dev)
+{
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+       struct hrtimer_clock_base *base;
+       ktime_t expires_next, now;
+       int i, raise = 0;
+
+       BUG_ON(!cpu_base->hres_active);
+       cpu_base->nr_events++;
+       dev->next_event.tv64 = KTIME_MAX;
+
+ retry:
+       now = ktime_get();
+
+       expires_next.tv64 = KTIME_MAX;
+
+       base = cpu_base->clock_base;
+
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+               ktime_t basenow;
+               struct rb_node *node;
+
+               spin_lock(&cpu_base->lock);
+
+               basenow = ktime_add(now, base->offset);
+
+               while ((node = base->first)) {
+                       struct hrtimer *timer;
+
+                       timer = rb_entry(node, struct hrtimer, node);
+
+                       if (basenow.tv64 < timer->expires.tv64) {
+                               ktime_t expires;
+
+                               expires = ktime_sub(timer->expires,
+                                                   base->offset);
+                               if (expires.tv64 < expires_next.tv64)
+                                       expires_next = expires;
+                               break;
+                       }
+
+                       /* Move softirq callbacks to the pending list */
+                       if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
+                               __remove_hrtimer(timer, base,
+                                                HRTIMER_STATE_PENDING, 0);
+                               list_add_tail(&timer->cb_entry,
+                                             &base->cpu_base->cb_pending);
+                               raise = 1;
+                               continue;
+                       }
+
+                       __remove_hrtimer(timer, base,
+                                        HRTIMER_STATE_CALLBACK, 0);
+                       timer_stats_account_hrtimer(timer);
+
+                       /*
+                        * Note: We clear the CALLBACK bit after
+                        * enqueue_hrtimer to avoid reprogramming of
+                        * the event hardware. This happens at the end
+                        * of this function anyway.
+                        */
+                       if (timer->function(timer) != HRTIMER_NORESTART) {
+                               BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+                               enqueue_hrtimer(timer, base, 0);
+                       }
+                       timer->state &= ~HRTIMER_STATE_CALLBACK;
+               }
+               spin_unlock(&cpu_base->lock);
+               base++;
+       }
+
+       cpu_base->expires_next = expires_next;
+
+       /* Reprogramming necessary ? */
+       if (expires_next.tv64 != KTIME_MAX) {
+               if (tick_program_event(expires_next, 0))
+                       goto retry;
+       }
+
+       /* Raise softirq ? */
+       if (raise)
+               raise_softirq(HRTIMER_SOFTIRQ);
+}
+
+static void run_hrtimer_softirq(struct softirq_action *h)
+{
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+       spin_lock_irq(&cpu_base->lock);
+
+       while (!list_empty(&cpu_base->cb_pending)) {
+               enum hrtimer_restart (*fn)(struct hrtimer *);
+               struct hrtimer *timer;
+               int restart;
+
+               timer = list_entry(cpu_base->cb_pending.next,
+                                  struct hrtimer, cb_entry);
+
+               timer_stats_account_hrtimer(timer);
+
+               fn = timer->function;
+               __remove_hrtimer(timer, timer->base, HRTIMER_STATE_CALLBACK, 0);
+               spin_unlock_irq(&cpu_base->lock);
+
+               restart = fn(timer);
+
+               spin_lock_irq(&cpu_base->lock);
+
+               timer->state &= ~HRTIMER_STATE_CALLBACK;
+               if (restart == HRTIMER_RESTART) {
+                       BUG_ON(hrtimer_active(timer));
+                       /*
+                        * Enqueue the timer, allow reprogramming of the event
+                        * device
+                        */
+                       enqueue_hrtimer(timer, timer->base, 1);
+               } else if (hrtimer_active(timer)) {
+                       /*
+                        * If the timer was rearmed on another CPU, reprogram
+                        * the event device.
+                        */
+                       if (timer->base->first == &timer->node)
+                               hrtimer_reprogram(timer, timer->base);
+               }
+       }
+       spin_unlock_irq(&cpu_base->lock);
+}
+
+#endif /* CONFIG_HIGH_RES_TIMERS */
+
 /*
  * Expire the per base hrtimer-queue:
  */
-static inline void run_hrtimer_queue(struct hrtimer_base *base)
+static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
+                                    int index)
 {
        struct rb_node *node;
+       struct hrtimer_clock_base *base = &cpu_base->clock_base[index];
 
        if (!base->first)
                return;
@@ -610,53 +1119,72 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
        if (base->get_softirq_time)
                base->softirq_time = base->get_softirq_time();
 
-       spin_lock_irq(&base->lock);
+       spin_lock_irq(&cpu_base->lock);
 
        while ((node = base->first)) {
                struct hrtimer *timer;
-               int (*fn)(struct hrtimer *);
+               enum hrtimer_restart (*fn)(struct hrtimer *);
                int restart;
 
                timer = rb_entry(node, struct hrtimer, node);
                if (base->softirq_time.tv64 <= timer->expires.tv64)
                        break;
 
+               timer_stats_account_hrtimer(timer);
+
                fn = timer->function;
-               set_curr_timer(base, timer);
-               __remove_hrtimer(timer, base);
-               spin_unlock_irq(&base->lock);
+               __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
+               spin_unlock_irq(&cpu_base->lock);
 
                restart = fn(timer);
 
-               spin_lock_irq(&base->lock);
+               spin_lock_irq(&cpu_base->lock);
 
+               timer->state &= ~HRTIMER_STATE_CALLBACK;
                if (restart != HRTIMER_NORESTART) {
                        BUG_ON(hrtimer_active(timer));
-                       enqueue_hrtimer(timer, base);
+                       enqueue_hrtimer(timer, base, 0);
                }
        }
-       set_curr_timer(base, NULL);
-       spin_unlock_irq(&base->lock);
+       spin_unlock_irq(&cpu_base->lock);
 }
 
 /*
  * Called from timer softirq every jiffy, expire hrtimers:
+ *
+ * For HRT its the fall back code to run the softirq in the timer
+ * softirq context in case the hrtimer initialization failed or has
+ * not been done yet.
  */
 void hrtimer_run_queues(void)
 {
-       struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
        int i;
 
-       hrtimer_get_softirq_time(base);
+       if (hrtimer_hres_active())
+               return;
+
+       /*
+        * This _is_ ugly: We have to check in the softirq context,
+        * whether we can switch to highres and / or nohz mode. The
+        * clocksource switch happens in the timer interrupt with
+        * xtime_lock held. Notification from there only sets the
+        * check bit in the tick_oneshot code, otherwise we might
+        * deadlock vs. xtime_lock.
+        */
+       if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))
+               hrtimer_switch_to_hres();
 
-       for (i = 0; i < MAX_HRTIMER_BASES; i++)
-               run_hrtimer_queue(&base[i]);
+       hrtimer_get_softirq_time(cpu_base);
+
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+               run_hrtimer_queue(cpu_base, i);
 }
 
 /*
  * Sleep related functions:
  */
-static int hrtimer_wakeup(struct hrtimer *timer)
+static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
 {
        struct hrtimer_sleeper *t =
                container_of(timer, struct hrtimer_sleeper, timer);
@@ -673,6 +1201,9 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
 {
        sl->timer.function = hrtimer_wakeup;
        sl->task = task;
+#ifdef CONFIG_HIGH_RES_TIMERS
+       sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART;
+#endif
 }
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
@@ -683,10 +1214,11 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
                set_current_state(TASK_INTERRUPTIBLE);
                hrtimer_start(&t->timer, t->timer.expires, mode);
 
-               schedule();
+               if (likely(t->task))
+                       schedule();
 
                hrtimer_cancel(&t->timer);
-               mode = HRTIMER_ABS;
+               mode = HRTIMER_MODE_ABS;
 
        } while (t->task && !signal_pending(current));
 
@@ -702,10 +1234,10 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 
        restart->fn = do_no_restart_syscall;
 
-       hrtimer_init(&t.timer, restart->arg0, HRTIMER_ABS);
+       hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
        t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
 
-       if (do_nanosleep(&t, HRTIMER_ABS))
+       if (do_nanosleep(&t, HRTIMER_MODE_ABS))
                return 0;
 
        rmtp = (struct timespec __user *) restart->arg1;
@@ -738,7 +1270,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
                return 0;
 
        /* Absolute timers do not update the rmtp value and restart: */
-       if (mode == HRTIMER_ABS)
+       if (mode == HRTIMER_MODE_ABS)
                return -ERESTARTNOHAND;
 
        if (rmtp) {
@@ -771,7 +1303,7 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
        if (!timespec_valid(&tu))
                return -EINVAL;
 
-       return hrtimer_nanosleep(&tu, rmtp, HRTIMER_REL, CLOCK_MONOTONIC);
+       return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
 /*
@@ -779,56 +1311,60 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
  */
 static void __devinit init_hrtimers_cpu(int cpu)
 {
-       struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
+       struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
        int i;
 
-       for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) {
-               spin_lock_init(&base->lock);
-               lockdep_set_class(&base->lock, &base->lock_key);
-       }
+       spin_lock_init(&cpu_base->lock);
+       lockdep_set_class(&cpu_base->lock, &cpu_base->lock_key);
+
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+               cpu_base->clock_base[i].cpu_base = cpu_base;
+
+       hrtimer_init_hres(cpu_base);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void migrate_hrtimer_list(struct hrtimer_base *old_base,
-                               struct hrtimer_base *new_base)
+static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
+                               struct hrtimer_clock_base *new_base)
 {
        struct hrtimer *timer;
        struct rb_node *node;
 
        while ((node = rb_first(&old_base->active))) {
                timer = rb_entry(node, struct hrtimer, node);
-               __remove_hrtimer(timer, old_base);
+               BUG_ON(hrtimer_callback_running(timer));
+               __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
                timer->base = new_base;
-               enqueue_hrtimer(timer, new_base);
+               /*
+                * Enqueue the timer. Allow reprogramming of the event device
+                */
+               enqueue_hrtimer(timer, new_base, 1);
        }
 }
 
 static void migrate_hrtimers(int cpu)
 {
-       struct hrtimer_base *old_base, *new_base;
+       struct hrtimer_cpu_base *old_base, *new_base;
        int i;
 
        BUG_ON(cpu_online(cpu));
-       old_base = per_cpu(hrtimer_bases, cpu);
-       new_base = get_cpu_var(hrtimer_bases);
-
-       local_irq_disable();
+       old_base = &per_cpu(hrtimer_bases, cpu);
+       new_base = &get_cpu_var(hrtimer_bases);
 
-       for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+       tick_cancel_sched_timer(cpu);
 
-               spin_lock(&new_base->lock);
-               spin_lock(&old_base->lock);
-
-               BUG_ON(old_base->curr_timer);
+       local_irq_disable();
 
-               migrate_hrtimer_list(old_base, new_base);
+       spin_lock(&new_base->lock);
+       spin_lock(&old_base->lock);
 
-               spin_unlock(&old_base->lock);
-               spin_unlock(&new_base->lock);
-               old_base++;
-               new_base++;
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+               migrate_hrtimer_list(&old_base->clock_base[i],
+                                    &new_base->clock_base[i]);
        }
+       spin_unlock(&old_base->lock);
+       spin_unlock(&new_base->lock);
 
        local_irq_enable();
        put_cpu_var(hrtimer_bases);
@@ -848,6 +1384,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+               clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &cpu);
                migrate_hrtimers(cpu);
                break;
 #endif
@@ -868,5 +1405,8 @@ void __init hrtimers_init(void)
        hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
                          (void *)(long)smp_processor_id());
        register_cpu_notifier(&hrtimers_nb);
+#ifdef CONFIG_HIGH_RES_TIMERS
+       open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq, NULL);
+#endif
 }
 
index 475e8a71bcdc19772b312461b95ba0b171f1790e..0133f4f9e9f0c71633ccff2d4029f479148d0af9 100644 (file)
@@ -168,7 +168,7 @@ EXPORT_SYMBOL(set_irq_data);
 /**
  *     set_irq_data - set irq type data for an irq
  *     @irq:   Interrupt number
- *     @data:  Pointer to interrupt specific data
+ *     @entry: Pointer to MSI descriptor data
  *
  *     Set the hardware irq controller data for an irq
  */
@@ -230,10 +230,6 @@ static void default_enable(unsigned int irq)
  */
 static void default_disable(unsigned int irq)
 {
-       struct irq_desc *desc = irq_desc + irq;
-
-       if (!(desc->status & IRQ_DELAYED_DISABLE))
-               desc->chip->mask(irq);
 }
 
 /*
@@ -298,13 +294,18 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 
        if (unlikely(desc->status & IRQ_INPROGRESS))
                goto out_unlock;
-       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
        kstat_cpu(cpu).irqs[irq]++;
 
        action = desc->action;
-       if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+       if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+               if (desc->chip->mask)
+                       desc->chip->mask(irq);
+               desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+               desc->status |= IRQ_PENDING;
                goto out_unlock;
+       }
 
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING | IRQ_PENDING);
        desc->status |= IRQ_INPROGRESS;
        spin_unlock(&desc->lock);
 
@@ -396,11 +397,13 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 
        /*
         * If its disabled or no action available
-        * keep it masked and get out of here
+        * then mask it and get out of here:
         */
        action = desc->action;
        if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
                desc->status |= IRQ_PENDING;
+               if (desc->chip->mask)
+                       desc->chip->mask(irq);
                goto out;
        }
 
@@ -562,10 +565,8 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 
        /* Uninstall? */
        if (handle == handle_bad_irq) {
-               if (desc->chip != &no_irq_chip) {
-                       desc->chip->mask(irq);
-                       desc->chip->ack(irq);
-               }
+               if (desc->chip != &no_irq_chip)
+                       mask_ack_irq(desc, irq);
                desc->status |= IRQ_DISABLED;
                desc->depth = 1;
        }
index 7c85d69188efce43ba19429c7da8cb3f9677a9ae..5597c157442a19a5e5bbe7de068d86c261e98951 100644 (file)
@@ -38,6 +38,46 @@ void synchronize_irq(unsigned int irq)
 }
 EXPORT_SYMBOL(synchronize_irq);
 
+/**
+ *     irq_can_set_affinity - Check if the affinity of a given irq can be set
+ *     @irq:           Interrupt to check
+ *
+ */
+int irq_can_set_affinity(unsigned int irq)
+{
+       struct irq_desc *desc = irq_desc + irq;
+
+       if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
+           !desc->chip->set_affinity)
+               return 0;
+
+       return 1;
+}
+
+/**
+ *     irq_set_affinity - Set the irq affinity of a given irq
+ *     @irq:           Interrupt to set affinity
+ *     @cpumask:       cpumask
+ *
+ */
+int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+       struct irq_desc *desc = irq_desc + irq;
+
+       if (!desc->chip->set_affinity)
+               return -EINVAL;
+
+       set_balance_irq_affinity(irq, cpumask);
+
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+       set_pending_irq(irq, cpumask);
+#else
+       desc->affinity = cpumask;
+       desc->chip->set_affinity(irq, cpumask);
+#endif
+       return 0;
+}
+
 #endif
 
 /**
@@ -281,6 +321,10 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        if (new->flags & IRQF_PERCPU)
                desc->status |= IRQ_PER_CPU;
 #endif
+       /* Exclude IRQ from balancing */
+       if (new->flags & IRQF_NOBALANCING)
+               desc->status |= IRQ_NO_BALANCING;
+
        if (!shared) {
                irq_chip_set_defaults(desc->chip);
 
@@ -461,7 +505,7 @@ int request_irq(unsigned int irq, irq_handler_t handler,
        /*
         * Lockdep wants atomic interrupt handlers:
         */
-       irqflags |= SA_INTERRUPT;
+       irqflags |= IRQF_DISABLED;
 #endif
        /*
         * Sanity-check: shared interrupts must pass in a real dev-ID,
index 6d3be06e8ce6362d2f2e106452c9c5383ebc6cfc..2db91eb54ad8bb539b2dccdcb059d6872c2191a4 100644 (file)
@@ -16,26 +16,6 @@ static struct proc_dir_entry *root_irq_dir;
 
 #ifdef CONFIG_SMP
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
-       set_balance_irq_affinity(irq, mask_val);
-
-       /*
-        * Save these away for later use. Re-progam when the
-        * interrupt is pending
-        */
-       set_pending_irq(irq, mask_val);
-}
-#else
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
-       set_balance_irq_affinity(irq, mask_val);
-       irq_desc[irq].affinity = mask_val;
-       irq_desc[irq].chip->set_affinity(irq, mask_val);
-}
-#endif
-
 static int irq_affinity_read_proc(char *page, char **start, off_t off,
                                  int count, int *eof, void *data)
 {
@@ -55,7 +35,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
        cpumask_t new_value, tmp;
 
        if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
-                               CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+           irq_balancing_disabled(irq))
                return -EIO;
 
        err = cpumask_parse_user(buffer, count, new_value);
@@ -73,7 +53,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
                   code to set default SMP affinity. */
                return select_smp_affinity(irq) ? -EINVAL : full_count;
 
-       proc_set_irq_affinity(irq, new_value);
+       irq_set_affinity(irq, new_value);
 
        return full_count;
 }
index 204ed7939e757222466c6e594fbb56a1b1eb46b3..307c6a632ef6baa7ff0cec46273293d4cc84afc6 100644 (file)
@@ -128,18 +128,13 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
 /*
  * The timer is automagically restarted, when interval != 0
  */
-int it_real_fn(struct hrtimer *timer)
+enum hrtimer_restart it_real_fn(struct hrtimer *timer)
 {
        struct signal_struct *sig =
            container_of(timer, struct signal_struct, real_timer);
 
        send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);
 
-       if (sig->it_real_incr.tv64 != 0) {
-               hrtimer_forward(timer, timer->base->softirq_time,
-                               sig->it_real_incr);
-               return HRTIMER_RESTART;
-       }
        return HRTIMER_NORESTART;
 }
 
@@ -231,11 +226,14 @@ again:
                        spin_unlock_irq(&tsk->sighand->siglock);
                        goto again;
                }
-               tsk->signal->it_real_incr =
-                       timeval_to_ktime(value->it_interval);
                expires = timeval_to_ktime(value->it_value);
-               if (expires.tv64 != 0)
-                       hrtimer_start(timer, expires, HRTIMER_REL);
+               if (expires.tv64 != 0) {
+                       tsk->signal->it_real_incr =
+                               timeval_to_ktime(value->it_interval);
+                       hrtimer_start(timer, expires, HRTIMER_MODE_REL);
+               } else
+                       tsk->signal->it_real_incr.tv64 = 0;
+
                spin_unlock_irq(&tsk->sighand->siglock);
                break;
        case ITIMER_VIRTUAL:
index 3a7379aa31ca6b0a92bec377a23e5c9debed72db..9f923f8ce6a0cd3c225f73eb79c865777ac60967 100644 (file)
@@ -36,6 +36,8 @@
 #include <linux/resource.h>
 #include <asm/uaccess.h>
 
+extern int delete_module(const char *name, unsigned int flags);
+
 extern int max_threads;
 
 static struct workqueue_struct *khelper_wq;
@@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq;
        modprobe_path is set via /proc/sys.
 */
 char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+struct module_kobject kmod_mk;
 
 /**
  * request_module - try to load a kernel module
@@ -75,6 +78,11 @@ int request_module(const char *fmt, ...)
        static atomic_t kmod_concurrent = ATOMIC_INIT(0);
 #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
        static int kmod_loop_msg;
+       char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
+       char *uevent_envp[2] = {
+               modalias,
+               NULL
+       };
 
        va_start(args, fmt);
        ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
@@ -82,6 +90,12 @@ int request_module(const char *fmt, ...)
        if (ret >= MODULE_NAME_LEN)
                return -ENAMETOOLONG;
 
+       strcpy(&modalias[strlen("MODALIAS=")], module_name);
+       kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
+
+       if (modprobe_path[0] == '\0')
+               goto out;
+
        /* If modprobe needs a service that is in a module, we get a recursive
         * loop.  Limit the number of running kmod threads to max_threads/2 or
         * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
@@ -108,9 +122,115 @@ int request_module(const char *fmt, ...)
 
        ret = call_usermodehelper(modprobe_path, argv, envp, 1);
        atomic_dec(&kmod_concurrent);
+out:
        return ret;
 }
 EXPORT_SYMBOL(request_module);
+
+static ssize_t store_mod_request(struct module_attribute *mattr,
+                                struct module *mod,
+                             const char *buffer, size_t count)
+{
+       char name[MODULE_NAME_LEN];
+       int ret;
+
+       if (count < 1 || count+1 > MODULE_NAME_LEN)
+               return -EINVAL;
+       memcpy(name, buffer, count);
+       name[count] = '\0';
+       if (name[count-1] == '\n')
+               name[count-1] = '\0';
+
+       ret = request_module(name);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+static struct module_attribute mod_request = {
+       .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
+       .store = store_mod_request,
+};
+
+#ifdef CONFIG_MODULE_UNLOAD
+static ssize_t store_mod_unload(struct module_attribute *mattr,
+                           struct module *mod,
+                           const char *buffer, size_t count)
+{
+       char name[MODULE_NAME_LEN];
+       int ret;
+
+       if (count < 1 || count+1 > MODULE_NAME_LEN)
+               return -EINVAL;
+       memcpy(name, buffer, count);
+       name[count] = '\0';
+       if (name[count-1] == '\n')
+               name[count-1] = '\0';
+
+       ret = delete_module(name, O_NONBLOCK);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+static struct module_attribute mod_unload = {
+       .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
+       .store = store_mod_unload,
+};
+#endif
+
+static ssize_t show_mod_request_helper(struct module_attribute *mattr,
+                                      struct module *mod,
+                                      char *buffer)
+{
+       return sprintf(buffer, "%s\n", modprobe_path);
+}
+
+static ssize_t store_mod_request_helper(struct module_attribute *mattr,
+                                       struct module *mod,
+                                       const char *buffer, size_t count)
+{
+       if (count < 1 || count+1 > KMOD_PATH_LEN)
+               return -EINVAL;
+       memcpy(modprobe_path, buffer, count);
+       modprobe_path[count] = '\0';
+       if (modprobe_path[count-1] == '\n')
+               modprobe_path[count-1] = '\0';
+       return count;
+}
+
+static struct module_attribute mod_request_helper = {
+       .attr = {
+               .name = "mod_request_helper",
+               .mode = S_IWUSR | S_IRUGO,
+               .owner = THIS_MODULE
+       },
+       .show = show_mod_request_helper,
+       .store = store_mod_request_helper,
+};
+
+void __init kmod_sysfs_init(void)
+{
+       int ret;
+
+       kmod_mk.mod = THIS_MODULE;
+       kobj_set_kset_s(&kmod_mk, module_subsys);
+       kobject_set_name(&kmod_mk.kobj, "kmod");
+       kobject_init(&kmod_mk.kobj);
+       ret = kobject_add(&kmod_mk.kobj);
+       if (ret < 0)
+               goto out;
+
+       ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
+       ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
+#ifdef CONFIG_MODULE_UNLOAD
+       ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
+#endif
+
+       kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
+out:
+       return;
+}
 #endif /* CONFIG_KMOD */
 
 struct subprocess_info {
@@ -217,7 +337,10 @@ static int wait_for_helper(void *data)
                        sub_info->retval = ret;
        }
 
-       complete(sub_info->complete);
+       if (sub_info->wait < 0)
+               kfree(sub_info);
+       else
+               complete(sub_info->complete);
        return 0;
 }
 
@@ -239,6 +362,9 @@ static void __call_usermodehelper(struct work_struct *work)
                pid = kernel_thread(____call_usermodehelper, sub_info,
                                    CLONE_VFORK | SIGCHLD);
 
+       if (wait < 0)
+               return;
+
        if (pid < 0) {
                sub_info->retval = pid;
                complete(sub_info->complete);
@@ -253,6 +379,9 @@ static void __call_usermodehelper(struct work_struct *work)
  * @envp: null-terminated environment list
  * @session_keyring: session keyring for process (NULL for an empty keyring)
  * @wait: wait for the application to finish and return status.
+ *        when -1 don't wait at all, but you get no useful error back when
+ *        the program couldn't be exec'ed. This makes it safe to call
+ *        from interrupt context.
  *
  * Runs a user-space application.  The application is started
  * asynchronously if wait is not set, and runs as a child of keventd.
@@ -265,17 +394,8 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
                             struct key *session_keyring, int wait)
 {
        DECLARE_COMPLETION_ONSTACK(done);
-       struct subprocess_info sub_info = {
-               .work           = __WORK_INITIALIZER(sub_info.work,
-                                                    __call_usermodehelper),
-               .complete       = &done,
-               .path           = path,
-               .argv           = argv,
-               .envp           = envp,
-               .ring           = session_keyring,
-               .wait           = wait,
-               .retval         = 0,
-       };
+       struct subprocess_info *sub_info;
+       int retval;
 
        if (!khelper_wq)
                return -EBUSY;
@@ -283,9 +403,25 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
        if (path[0] == '\0')
                return 0;
 
-       queue_work(khelper_wq, &sub_info.work);
+       sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
+       if (!sub_info)
+               return -ENOMEM;
+
+       INIT_WORK(&sub_info->work, __call_usermodehelper);
+       sub_info->complete = &done;
+       sub_info->path = path;
+       sub_info->argv = argv;
+       sub_info->envp = envp;
+       sub_info->ring = session_keyring;
+       sub_info->wait = wait;
+
+       queue_work(khelper_wq, &sub_info->work);
+       if (wait < 0) /* task has freed sub_info */
+               return 0;
        wait_for_completion(&done);
-       return sub_info.retval;
+       retval = sub_info->retval;
+       kfree(sub_info);
+       return retval;
 }
 EXPORT_SYMBOL(call_usermodehelper_keys);
 
index 88fc611b3ae907a3677a2549b4c809f187729b8c..58f35e586ee3b508e693e3cd010a69982ae76b5f 100644 (file)
@@ -10,7 +10,6 @@
  * Code for /proc/lockdep and /proc/lockdep_stats:
  *
  */
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
index 8a94e054230c07abb5371c8e8b4e369f3e8476bd..8c25b1a04fa6d8f3dbbda8f57a045cc2d32714bd 100644 (file)
@@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod)
        mutex_lock(&module_mutex);
 }
 
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
+int delete_module(const char *name, unsigned int flags)
 {
        struct module *mod;
-       char name[MODULE_NAME_LEN];
        int ret, forced = 0;
 
-       if (!capable(CAP_SYS_MODULE))
-               return -EPERM;
-
-       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
-               return -EFAULT;
-       name[MODULE_NAME_LEN-1] = '\0';
-
        if (mutex_lock_interruptible(&module_mutex) != 0)
                return -EINTR;
 
@@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
        return ret;
 }
 
+asmlinkage long
+sys_delete_module(const char __user *name_user, unsigned int flags)
+{
+       char name[MODULE_NAME_LEN];
+
+       if (!capable(CAP_SYS_MODULE))
+               return -EPERM;
+
+       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+               return -EFAULT;
+       name[MODULE_NAME_LEN-1] = '\0';
+
+       return delete_module(name, flags);
+}
+
 static void print_unload_info(struct seq_file *m, struct module *mod)
 {
        struct module_use *use;
@@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod)
 }
 #endif /* CONFIG_KALLSYMS */
 
-static int module_add_modinfo_attrs(struct module *mod)
+#ifdef CONFIG_SYSFS
+int module_add_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        struct module_attribute *temp_attr;
@@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod)
        return error;
 }
 
-static void module_remove_modinfo_attrs(struct module *mod)
+void module_remove_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        int i;
@@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod)
        }
        kfree(mod->modinfo_attrs);
 }
+#endif
 
-static int mod_sysfs_init(struct module *mod)
+#ifdef CONFIG_SYSFS
+int mod_sysfs_init(struct module *mod)
 {
        int err;
 
@@ -1133,7 +1142,7 @@ out:
        return err;
 }
 
-static int mod_sysfs_setup(struct module *mod,
+int mod_sysfs_setup(struct module *mod,
                           struct kernel_param *kparam,
                           unsigned int num_params)
 {
@@ -1169,16 +1178,14 @@ out_unreg:
 out:
        return err;
 }
+#endif
 
 static void mod_kobject_remove(struct module *mod)
 {
        module_remove_modinfo_attrs(mod);
        module_param_sysfs_remove(mod);
-       if (mod->mkobj.drivers_dir)
-               kobject_unregister(mod->mkobj.drivers_dir);
-       if (mod->holders_dir)
-               kobject_unregister(mod->holders_dir);
-
+       kobject_unregister(mod->mkobj.drivers_dir);
+       kobject_unregister(mod->holders_dir);
        kobject_unregister(&mod->mkobj.kobj);
 }
 
@@ -2345,6 +2352,7 @@ void print_modules(void)
        printk("\n");
 }
 
+#ifdef CONFIG_SYSFS
 static char *make_driver_name(struct device_driver *drv)
 {
        char *driver_name;
@@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv)
        }
 }
 EXPORT_SYMBOL(module_remove_driver);
+#endif
 
 #ifdef CONFIG_MODVERSIONS
 /* Generate the signature for struct module here, too, for modversions. */
index 841539d72c55cdbb674b7a91786847c37ec5acdb..d17436cdea1b39a7cb0efc96801bf0655dcb8fb5 100644 (file)
@@ -13,7 +13,6 @@
  *  Released under the General Public License (GPL).
  */
 #include <linux/mutex.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/poison.h>
index 553cf7d6a4be113f0dcb89f1be51aa9989d51453..7a751570b56d78222d9f2510938834f3391bfc45 100644 (file)
@@ -30,8 +30,6 @@
 #define DEBUGP(fmt, a...)
 #endif
 
-static struct kobj_type module_ktype;
-
 static inline char dash2underscore(char c)
 {
        if (c == '-')
@@ -391,6 +389,7 @@ struct module_param_attrs
        struct param_attribute attrs[0];
 };
 
+#ifdef CONFIG_SYSFS
 #define to_param_attr(n) container_of(n, struct param_attribute, mattr);
 
 static ssize_t param_attr_show(struct module_attribute *mattr,
@@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
                return len;
        return err;
 }
+#endif
 
 #ifdef CONFIG_MODULES
 #define __modinit
@@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
 #define __modinit __init
 #endif
 
+#ifdef CONFIG_SYSFS
 /*
  * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
  * @mk: struct module_kobject (contains parent kobject)
@@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk,
        return mp;
 }
 
-
 #ifdef CONFIG_MODULES
-
 /*
  * module_param_sysfs_setup - setup sysfs support for one module
  * @mod: module
@@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void)
 
 
 /* module-related sysfs stuff */
-#ifdef CONFIG_SYSFS
 
 #define to_module_attr(n) container_of(n, struct module_attribute, attr);
 #define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
@@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = {
        .store = module_attr_store,
 };
 
+static struct kobj_type module_ktype;
+
 static int uevent_filter(struct kset *kset, struct kobject *kobj)
 {
        struct kobj_type *ktype = get_ktype(kobj);
@@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = {
        .filter = uevent_filter,
 };
 
-#else
-static struct sysfs_ops module_sysfs_ops = {
-       .show = NULL,
-       .store = NULL,
-};
-#endif
+decl_subsys(module, &module_ktype, &module_uevent_ops);
 
 static struct kobj_type module_ktype = {
        .sysfs_ops =    &module_sysfs_ops,
 };
 
-decl_subsys(module, &module_ktype, &module_uevent_ops);
-
 /*
  * param_sysfs_init - wrapper for built-in params support
  */
@@ -714,11 +707,21 @@ static int __init param_sysfs_init(void)
        }
 
        param_sysfs_builtin();
+       kmod_sysfs_init();
 
        return 0;
 }
 subsys_initcall(param_sysfs_init);
 
+#else
+#if 0
+static struct sysfs_ops module_sysfs_ops = {
+       .show = NULL,
+       .store = NULL,
+};
+#endif
+#endif
+
 EXPORT_SYMBOL(param_set_byte);
 EXPORT_SYMBOL(param_get_byte);
 EXPORT_SYMBOL(param_set_short);
index 7c3e1e6dfb5b5eef84f61f6259e764703846d9fd..657f77697415b2879c07b85e759e8d19b0880b93 100644 (file)
@@ -304,7 +304,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
                 * should be able to see it.
                 */
                struct task_struct *p;
-               read_lock(&tasklist_lock);
+               rcu_read_lock();
                p = find_task_by_pid(pid);
                if (p) {
                        if (CPUCLOCK_PERTHREAD(which_clock)) {
@@ -312,12 +312,17 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
                                        error = cpu_clock_sample(which_clock,
                                                                 p, &rtn);
                                }
-                       } else if (p->tgid == pid && p->signal) {
-                               error = cpu_clock_sample_group(which_clock,
-                                                              p, &rtn);
+                       } else {
+                               read_lock(&tasklist_lock);
+                               if (p->tgid == pid && p->signal) {
+                                       error =
+                                           cpu_clock_sample_group(which_clock,
+                                                                  p, &rtn);
+                               }
+                               read_unlock(&tasklist_lock);
                        }
                }
-               read_unlock(&tasklist_lock);
+               rcu_read_unlock();
        }
 
        if (error)
index a1bf616178394f1906a11bb2bb063d16cb3b5902..44318ca71978d9afae52c6149153d323e08a06b5 100644 (file)
@@ -145,7 +145,7 @@ static int common_timer_set(struct k_itimer *, int,
                            struct itimerspec *, struct itimerspec *);
 static int common_timer_del(struct k_itimer *timer);
 
-static int posix_timer_fn(struct hrtimer *data);
+static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
 
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 
@@ -334,12 +334,12 @@ EXPORT_SYMBOL_GPL(posix_timer_event);
 
  * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
  */
-static int posix_timer_fn(struct hrtimer *timer)
+static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
 {
        struct k_itimer *timr;
        unsigned long flags;
        int si_private = 0;
-       int ret = HRTIMER_NORESTART;
+       enum hrtimer_restart ret = HRTIMER_NORESTART;
 
        timr = container_of(timer, struct k_itimer, it.real.timer);
        spin_lock_irqsave(&timr->it_lock, flags);
@@ -356,7 +356,7 @@ static int posix_timer_fn(struct hrtimer *timer)
                if (timr->it.real.interval.tv64 != 0) {
                        timr->it_overrun +=
                                hrtimer_forward(timer,
-                                               timer->base->softirq_time,
+                                               hrtimer_cb_get_time(timer),
                                                timr->it.real.interval);
                        ret = HRTIMER_RESTART;
                        ++timr->it_requeue_pending;
@@ -722,7 +722,7 @@ common_timer_set(struct k_itimer *timr, int flags,
        if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
                return 0;
 
-       mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+       mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL;
        hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
        timr->it.real.timer.function = posix_timer_fn;
 
@@ -734,7 +734,7 @@ common_timer_set(struct k_itimer *timr, int flags,
        /* SIGEV_NONE timers are not queued ! See common_timer_get */
        if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
                /* Setup correct expiry time for relative timers */
-               if (mode == HRTIMER_REL)
+               if (mode == HRTIMER_MODE_REL)
                        timer->expires = ktime_add(timer->expires,
                                                   timer->base->get_time());
                return 0;
@@ -950,7 +950,8 @@ static int common_nsleep(const clockid_t which_clock, int flags,
                         struct timespec *tsave, struct timespec __user *rmtp)
 {
        return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
-                                HRTIMER_ABS : HRTIMER_REL, which_clock);
+                                HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+                                which_clock);
 }
 
 asmlinkage long
index 0c151877ff71ad117e2d751e34ce528606d7eea2..4b47e59248df00375ce5fda81e760f89e14f9a22 100644 (file)
@@ -54,7 +54,7 @@ int console_printk[4] = {
 };
 
 /*
- * Low lever drivers may need that to know if they can schedule in
+ * Low level drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
  */
 int oops_in_progress;
index 2a3f886365808241e329222772d28dfadf87da62..bdb55a33f9691e2f79765eeba502d075f71d067c 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
index 4ab17da46fd80de1690744f9022691923942cb70..180978cb2f7524b180863967be0391d32f47783d 100644 (file)
@@ -625,7 +625,7 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
        /* Setup the timer, when timeout != NULL */
        if (unlikely(timeout))
                hrtimer_start(&timeout->timer, timeout->timer.expires,
-                             HRTIMER_ABS);
+                             HRTIMER_MODE_ABS);
 
        for (;;) {
                /* Try to acquire the lock: */
index 08f86178aa34da228080edbdd8649a2a5b3a9d71..0dc757246d89b02c96593df44ff8d75acb93e711 100644 (file)
@@ -1853,6 +1853,13 @@ context_switch(struct rq *rq, struct task_struct *prev,
        struct mm_struct *mm = next->mm;
        struct mm_struct *oldmm = prev->active_mm;
 
+       /*
+        * For paravirt, this is coupled with an exit in switch_to to
+        * combine the page table reload and the switch backend into
+        * one hypercall.
+        */
+       arch_enter_lazy_cpu_mode();
+
        if (!mm) {
                next->active_mm = oldmm;
                atomic_inc(&oldmm->mm_count);
index 8072e568bbe0c41e68cffc8efa291488b4dcf0e7..e2a7d4bf7d57aac779c29384da8c06ed034fad1f 100644 (file)
@@ -456,26 +456,50 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
        int signr = __dequeue_signal(&tsk->pending, mask, info);
-       if (!signr)
+       if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
                                         mask, info);
+               /*
+                * itimer signal ?
+                *
+                * itimers are process shared and we restart periodic
+                * itimers in the signal delivery path to prevent DoS
+                * attacks in the high resolution timer case. This is
+                * compliant with the old way of self restarting
+                * itimers, as the SIGALRM is a legacy signal and only
+                * queued once. Changing the restart behaviour to
+                * restart the timer in the signal dequeue path is
+                * reducing the timer noise on heavy loaded !highres
+                * systems too.
+                */
+               if (unlikely(signr == SIGALRM)) {
+                       struct hrtimer *tmr = &tsk->signal->real_timer;
+
+                       if (!hrtimer_is_queued(tmr) &&
+                           tsk->signal->it_real_incr.tv64 != 0) {
+                               hrtimer_forward(tmr, tmr->base->get_time(),
+                                               tsk->signal->it_real_incr);
+                               hrtimer_restart(tmr);
+                       }
+               }
+       }
        recalc_sigpending_tsk(tsk);
-       if (signr && unlikely(sig_kernel_stop(signr))) {
-               /*
-                * Set a marker that we have dequeued a stop signal.  Our
-                * caller might release the siglock and then the pending
-                * stop signal it is about to process is no longer in the
-                * pending bitmasks, but must still be cleared by a SIGCONT
-                * (and overruled by a SIGKILL).  So those cases clear this
-                * shared flag after we've set it.  Note that this flag may
-                * remain set after the signal we return is ignored or
-                * handled.  That doesn't matter because its only purpose
-                * is to alert stop-signal processing code when another
-                * processor has come along and cleared the flag.
-                */
-               if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
-                       tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
-       }
+       if (signr && unlikely(sig_kernel_stop(signr))) {
+               /*
+                * Set a marker that we have dequeued a stop signal.  Our
+                * caller might release the siglock and then the pending
+                * stop signal it is about to process is no longer in the
+                * pending bitmasks, but must still be cleared by a SIGCONT
+                * (and overruled by a SIGKILL).  So those cases clear this
+                * shared flag after we've set it.  Note that this flag may
+                * remain set after the signal we return is ignored or
+                * handled.  That doesn't matter because its only purpose
+                * is to alert stop-signal processing code when another
+                * processor has come along and cleared the flag.
+                */
+               if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
+                       tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+       }
        if ( signr &&
             ((info->si_code & __SI_MASK) == __SI_TIMER) &&
             info->si_sys_private){
index 918e52df090e88ee0a03096bee651e6c3a4d6dce..8b75008e2bd84bc91db15681896ab1a631091378 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kthread.h>
 #include <linux/rcupdate.h>
 #include <linux/smp.h>
+#include <linux/tick.h>
 
 #include <asm/irq.h>
 /*
@@ -273,6 +274,18 @@ EXPORT_SYMBOL(do_softirq);
 
 #endif
 
+/*
+ * Enter an interrupt context.
+ */
+void irq_enter(void)
+{
+       __irq_enter();
+#ifdef CONFIG_NO_HZ
+       if (idle_cpu(smp_processor_id()))
+               tick_nohz_update_jiffies();
+#endif
+}
+
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
 # define invoke_softirq()      __do_softirq()
 #else
@@ -289,6 +302,12 @@ void irq_exit(void)
        sub_preempt_count(IRQ_EXIT_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
+
+#ifdef CONFIG_NO_HZ
+       /* Make sure that timer wheel updates are propagated */
+       if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
+               tick_nohz_stop_sched_tick();
+#endif
        preempt_enable_no_resched();
 }
 
index e0ac6cd79fcf6955c6105815b4c8ab4d9d53e97f..3ca1d5ff0319ea70321f196ab28b7b368179f271 100644 (file)
@@ -90,12 +90,6 @@ extern char modprobe_path[];
 #ifdef CONFIG_CHR_DEV_SG
 extern int sg_big_buff;
 #endif
-#ifdef CONFIG_SYSVIPC
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos);
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos);
-#endif
 
 #ifdef __sparc__
 extern char reboot_command [];
@@ -135,18 +129,6 @@ static int parse_table(int __user *, int, void __user *, size_t __user *,
                void __user *, size_t, ctl_table *);
 #endif
 
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos);
-
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen);
-
-#ifdef CONFIG_SYSVIPC
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen);
-#endif
 
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
@@ -177,60 +159,6 @@ int sysctl_legacy_va_layout;
 #endif
 
 
-static void *get_uts(ctl_table *table, int write)
-{
-       char *which = table->data;
-#ifdef CONFIG_UTS_NS
-       struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
-       which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
-#endif
-       if (!write)
-               down_read(&uts_sem);
-       else
-               down_write(&uts_sem);
-       return which;
-}
-
-static void put_uts(ctl_table *table, int write, void *which)
-{
-       if (!write)
-               up_read(&uts_sem);
-       else
-               up_write(&uts_sem);
-}
-
-#ifdef CONFIG_SYSVIPC
-static void *get_ipc(ctl_table *table, int write)
-{
-       char *which = table->data;
-       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-       which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
-       return which;
-}
-#else
-#define get_ipc(T,W) ((T)->data)
-#endif
-
-/* /proc declarations: */
-
-#ifdef CONFIG_PROC_SYSCTL
-
-static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
-static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_opensys(struct inode *, struct file *);
-
-const struct file_operations proc_sys_file_operations = {
-       .open           = proc_opensys,
-       .read           = proc_readsys,
-       .write          = proc_writesys,
-};
-
-extern struct proc_dir_entry *proc_sys_root;
-
-static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
-static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
-#endif
-
 /* The default sysctl tables: */
 
 static ctl_table root_table[] = {
@@ -277,51 +205,6 @@ static ctl_table root_table[] = {
 };
 
 static ctl_table kern_table[] = {
-       {
-               .ctl_name       = KERN_OSTYPE,
-               .procname       = "ostype",
-               .data           = init_uts_ns.name.sysname,
-               .maxlen         = sizeof(init_uts_ns.name.sysname),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_uts_string,
-       },
-       {
-               .ctl_name       = KERN_OSRELEASE,
-               .procname       = "osrelease",
-               .data           = init_uts_ns.name.release,
-               .maxlen         = sizeof(init_uts_ns.name.release),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_uts_string,
-       },
-       {
-               .ctl_name       = KERN_VERSION,
-               .procname       = "version",
-               .data           = init_uts_ns.name.version,
-               .maxlen         = sizeof(init_uts_ns.name.version),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_uts_string,
-       },
-       {
-               .ctl_name       = KERN_NODENAME,
-               .procname       = "hostname",
-               .data           = init_uts_ns.name.nodename,
-               .maxlen         = sizeof(init_uts_ns.name.nodename),
-               .mode           = 0644,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_uts_string,
-       },
-       {
-               .ctl_name       = KERN_DOMAINNAME,
-               .procname       = "domainname",
-               .data           = init_uts_ns.name.domainname,
-               .maxlen         = sizeof(init_uts_ns.name.domainname),
-               .mode           = 0644,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_uts_string,
-       },
        {
                .ctl_name       = KERN_PANIC,
                .procname       = "panic",
@@ -478,71 +361,6 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
-#ifdef CONFIG_SYSVIPC
-       {
-               .ctl_name       = KERN_SHMMAX,
-               .procname       = "shmmax",
-               .data           = &init_ipc_ns.shm_ctlmax,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_doulongvec_minmax,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_SHMALL,
-               .procname       = "shmall",
-               .data           = &init_ipc_ns.shm_ctlall,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_doulongvec_minmax,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_SHMMNI,
-               .procname       = "shmmni",
-               .data           = &init_ipc_ns.shm_ctlmni,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_MSGMAX,
-               .procname       = "msgmax",
-               .data           = &init_ipc_ns.msg_ctlmax,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_MSGMNI,
-               .procname       = "msgmni",
-               .data           = &init_ipc_ns.msg_ctlmni,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_MSGMNB,
-               .procname       =  "msgmnb",
-               .data           = &init_ipc_ns.msg_ctlmnb,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
-       },
-       {
-               .ctl_name       = KERN_SEM,
-               .procname       = "sem",
-               .data           = &init_ipc_ns.sem_ctls,
-               .maxlen         = 4*sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
-       },
-#endif
 #ifdef CONFIG_MAGIC_SYSRQ
        {
                .ctl_name       = KERN_SYSRQ,
@@ -1043,6 +861,12 @@ static ctl_table vm_table[] = {
        { .ctl_name = 0 }
 };
 
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+static ctl_table binfmt_misc_table[] = {
+       { .ctl_name = 0 }
+};
+#endif
+
 static ctl_table fs_table[] = {
        {
                .ctl_name       = FS_NRINODE,
@@ -1166,6 +990,14 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "binfmt_misc",
+               .mode           = 0555,
+               .child          = binfmt_misc_table,
+       },
+#endif
        { .ctl_name = 0 }
 };
 
@@ -1177,8 +1009,6 @@ static ctl_table dev_table[] = {
        { .ctl_name = 0 }
 };
 
-extern void init_irq_proc (void);
-
 static DEFINE_SPINLOCK(sysctl_lock);
 
 /* called under sysctl_lock */
@@ -1220,19 +1050,47 @@ static void start_unregistering(struct ctl_table_header *p)
        list_del_init(&p->ctl_entry);
 }
 
-void __init sysctl_init(void)
+void sysctl_head_finish(struct ctl_table_header *head)
 {
-#ifdef CONFIG_PROC_SYSCTL
-       register_proc_table(root_table, proc_sys_root, &root_table_header);
-       init_irq_proc();
-#endif
+       if (!head)
+               return;
+       spin_lock(&sysctl_lock);
+       unuse_table(head);
+       spin_unlock(&sysctl_lock);
+}
+
+struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
+{
+       struct ctl_table_header *head;
+       struct list_head *tmp;
+       spin_lock(&sysctl_lock);
+       if (prev) {
+               tmp = &prev->ctl_entry;
+               unuse_table(prev);
+               goto next;
+       }
+       tmp = &root_table_header.ctl_entry;
+       for (;;) {
+               head = list_entry(tmp, struct ctl_table_header, ctl_entry);
+
+               if (!use_table(head))
+                       goto next;
+               spin_unlock(&sysctl_lock);
+               return head;
+       next:
+               tmp = tmp->next;
+               if (tmp == &root_table_header.ctl_entry)
+                       break;
+       }
+       spin_unlock(&sysctl_lock);
+       return NULL;
 }
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
               void __user *newval, size_t newlen)
 {
-       struct list_head *tmp;
+       struct ctl_table_header *head;
        int error = -ENOTDIR;
 
        if (nlen <= 0 || nlen >= CTL_MAXNAME)
@@ -1242,26 +1100,16 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
                if (!oldlenp || get_user(old_len, oldlenp))
                        return -EFAULT;
        }
-       spin_lock(&sysctl_lock);
-       tmp = &root_table_header.ctl_entry;
-       do {
-               struct ctl_table_header *head =
-                       list_entry(tmp, struct ctl_table_header, ctl_entry);
-
-               if (!use_table(head))
-                       continue;
-
-               spin_unlock(&sysctl_lock);
 
+       for (head = sysctl_head_next(NULL); head;
+                       head = sysctl_head_next(head)) {
                error = parse_table(name, nlen, oldval, oldlenp, 
                                        newval, newlen, head->ctl_table);
-
-               spin_lock(&sysctl_lock);
-               unuse_table(head);
-               if (error != -ENOTDIR)
+               if (error != -ENOTDIR) {
+                       sysctl_head_finish(head);
                        break;
-       } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
-       spin_unlock(&sysctl_lock);
+               }
+       }
        return error;
 }
 
@@ -1282,7 +1130,7 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
- * ctl_perm does NOT grant the superuser all rights automatically, because
+ * sysctl_perm does NOT grant the superuser all rights automatically, because
  * some sysctl variables are readonly even to root.
  */
 
@@ -1297,7 +1145,7 @@ static int test_perm(int mode, int op)
        return -EACCES;
 }
 
-static inline int ctl_perm(ctl_table *table, int op)
+int sysctl_perm(ctl_table *table, int op)
 {
        int error;
        error = security_sysctl(table, op);
@@ -1321,19 +1169,11 @@ repeat:
        for ( ; table->ctl_name || table->procname; table++) {
                if (!table->ctl_name)
                        continue;
-               if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
+               if (n == table->ctl_name) {
                        int error;
                        if (table->child) {
-                               if (ctl_perm(table, 001))
+                               if (sysctl_perm(table, 001))
                                        return -EPERM;
-                               if (table->strategy) {
-                                       error = table->strategy(
-                                               table, name, nlen,
-                                               oldval, oldlenp,
-                                               newval, newlen);
-                                       if (error)
-                                               return error;
-                               }
                                name++;
                                nlen--;
                                table = table->child;
@@ -1361,7 +1201,7 @@ int do_sysctl_strategy (ctl_table *table,
                op |= 004;
        if (newval) 
                op |= 002;
-       if (ctl_perm(table, op))
+       if (sysctl_perm(table, op))
                return -EPERM;
 
        if (table->strategy) {
@@ -1400,10 +1240,26 @@ int do_sysctl_strategy (ctl_table *table,
 }
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
+static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
+{
+       for (; table->ctl_name || table->procname; table++) {
+               table->parent = parent;
+               if (table->child)
+                       sysctl_set_parent(table, table->child);
+       }
+}
+
+static __init int sysctl_init(void)
+{
+       sysctl_set_parent(NULL, root_table);
+       return 0;
+}
+
+core_initcall(sysctl_init);
+
 /**
  * register_sysctl_table - register a sysctl hierarchy
  * @table: the top-level table structure
- * @insert_at_head: whether the entry should be inserted in front or at the end
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. An entry with a ctl_name of 0 terminates the table. 
@@ -1469,8 +1325,7 @@ int do_sysctl_strategy (ctl_table *table,
  * This routine returns %NULL on a failure to register, and a pointer
  * to the table header on success.
  */
-struct ctl_table_header *register_sysctl_table(ctl_table * table, 
-                                              int insert_at_head)
+struct ctl_table_header *register_sysctl_table(ctl_table * table)
 {
        struct ctl_table_header *tmp;
        tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
@@ -1480,15 +1335,10 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
        INIT_LIST_HEAD(&tmp->ctl_entry);
        tmp->used = 0;
        tmp->unregistering = NULL;
+       sysctl_set_parent(NULL, table);
        spin_lock(&sysctl_lock);
-       if (insert_at_head)
-               list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
-       else
-               list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
+       list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
        spin_unlock(&sysctl_lock);
-#ifdef CONFIG_PROC_SYSCTL
-       register_proc_table(table, proc_sys_root, tmp);
-#endif
        return tmp;
 }
 
@@ -1504,9 +1354,6 @@ void unregister_sysctl_table(struct ctl_table_header * header)
        might_sleep();
        spin_lock(&sysctl_lock);
        start_unregistering(header);
-#ifdef CONFIG_PROC_SYSCTL
-       unregister_proc_table(header->ctl_table, proc_sys_root);
-#endif
        spin_unlock(&sysctl_lock);
        kfree(header);
 }
@@ -1530,155 +1377,6 @@ void unregister_sysctl_table(struct ctl_table_header * table)
 
 #ifdef CONFIG_PROC_SYSCTL
 
-/* Scan the sysctl entries in table and add them all into /proc */
-static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
-{
-       struct proc_dir_entry *de;
-       int len;
-       mode_t mode;
-       
-       for (; table->ctl_name || table->procname; table++) {
-               /* Can't do anything without a proc name. */
-               if (!table->procname)
-                       continue;
-               /* Maybe we can't do anything with it... */
-               if (!table->proc_handler && !table->child) {
-                       printk(KERN_WARNING "SYSCTL: Can't register %s\n",
-                               table->procname);
-                       continue;
-               }
-
-               len = strlen(table->procname);
-               mode = table->mode;
-
-               de = NULL;
-               if (table->proc_handler)
-                       mode |= S_IFREG;
-               else {
-                       mode |= S_IFDIR;
-                       for (de = root->subdir; de; de = de->next) {
-                               if (proc_match(len, table->procname, de))
-                                       break;
-                       }
-                       /* If the subdir exists already, de is non-NULL */
-               }
-
-               if (!de) {
-                       de = create_proc_entry(table->procname, mode, root);
-                       if (!de)
-                               continue;
-                       de->set = set;
-                       de->data = (void *) table;
-                       if (table->proc_handler)
-                               de->proc_fops = &proc_sys_file_operations;
-               }
-               table->de = de;
-               if (de->mode & S_IFDIR)
-                       register_proc_table(table->child, de, set);
-       }
-}
-
-/*
- * Unregister a /proc sysctl table and any subdirectories.
- */
-static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
-{
-       struct proc_dir_entry *de;
-       for (; table->ctl_name || table->procname; table++) {
-               if (!(de = table->de))
-                       continue;
-               if (de->mode & S_IFDIR) {
-                       if (!table->child) {
-                               printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
-                               continue;
-                       }
-                       unregister_proc_table(table->child, de);
-
-                       /* Don't unregister directories which still have entries.. */
-                       if (de->subdir)
-                               continue;
-               }
-
-               /*
-                * In any case, mark the entry as goner; we'll keep it
-                * around if it's busy, but we'll know to do nothing with
-                * its fields.  We are under sysctl_lock here.
-                */
-               de->data = NULL;
-
-               /* Don't unregister proc entries that are still being used.. */
-               if (atomic_read(&de->count))
-                       continue;
-
-               table->de = NULL;
-               remove_proc_entry(table->procname, root);
-       }
-}
-
-static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
-                         size_t count, loff_t *ppos)
-{
-       int op;
-       struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
-       struct ctl_table *table;
-       size_t res;
-       ssize_t error = -ENOTDIR;
-       
-       spin_lock(&sysctl_lock);
-       if (de && de->data && use_table(de->set)) {
-               /*
-                * at that point we know that sysctl was not unregistered
-                * and won't be until we finish
-                */
-               spin_unlock(&sysctl_lock);
-               table = (struct ctl_table *) de->data;
-               if (!table || !table->proc_handler)
-                       goto out;
-               error = -EPERM;
-               op = (write ? 002 : 004);
-               if (ctl_perm(table, op))
-                       goto out;
-               
-               /* careful: calling conventions are nasty here */
-               res = count;
-               error = (*table->proc_handler)(table, write, file,
-                                               buf, &res, ppos);
-               if (!error)
-                       error = res;
-       out:
-               spin_lock(&sysctl_lock);
-               unuse_table(de->set);
-       }
-       spin_unlock(&sysctl_lock);
-       return error;
-}
-
-static int proc_opensys(struct inode *inode, struct file *file)
-{
-       if (file->f_mode & FMODE_WRITE) {
-               /*
-                * sysctl entries that are not writable,
-                * are _NOT_ writable, capabilities or not.
-                */
-               if (!(inode->i_mode & S_IWUSR))
-                       return -EPERM;
-       }
-
-       return 0;
-}
-
-static ssize_t proc_readsys(struct file * file, char __user * buf,
-                           size_t count, loff_t *ppos)
-{
-       return do_rw_proc(0, file, buf, count, ppos);
-}
-
-static ssize_t proc_writesys(struct file * file, const char __user * buf,
-                            size_t count, loff_t *ppos)
-{
-       return do_rw_proc(1, file, (char __user *) buf, count, ppos);
-}
-
 static int _proc_do_string(void* data, int maxlen, int write,
                           struct file *filp, void __user *buffer,
                           size_t *lenp, loff_t *ppos)
@@ -1762,21 +1460,6 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
                               buffer, lenp, ppos);
 }
 
-/*
- *     Special case of dostring for the UTS structure. This has locks
- *     to observe. Should this be in kernel/sys.c ????
- */
-
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       int r;
-       void *which;
-       which = get_uts(table, write);
-       r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos);
-       put_uts(table, write, which);
-       return r;
-}
 
 static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
                                 int *valp,
@@ -2362,27 +2045,6 @@ int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
                                do_proc_dointvec_ms_jiffies_conv, NULL);
 }
 
-#ifdef CONFIG_SYSVIPC
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-       void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       void *which;
-       which = get_ipc(table, write);
-       return __do_proc_dointvec(which, table, write, filp, buffer,
-                       lenp, ppos, NULL, NULL);
-}
-
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
-       struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       void *which;
-       which = get_ipc(table, write);
-       return __do_proc_doulongvec_minmax(which, table, write, filp, buffer,
-                       lenp, ppos, 1l, 1l);
-}
-
-#endif
-
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
                           void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2413,31 +2075,6 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
        return -ENOSYS;
 }
 
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-#ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
-               struct file *filp, void __user *buffer,
-               size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-#endif
-
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2648,62 +2285,6 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
 }
 
 
-/* The generic string strategy routine: */
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen)
-{
-       struct ctl_table uts_table;
-       int r, write;
-       write = newval && newlen;
-       memcpy(&uts_table, table, sizeof(uts_table));
-       uts_table.data = get_uts(table, write);
-       r = sysctl_string(&uts_table, name, nlen,
-               oldval, oldlenp, newval, newlen);
-       put_uts(table, write, uts_table.data);
-       return r;
-}
-
-#ifdef CONFIG_SYSVIPC
-/* The generic sysctl ipc data routine. */
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-               void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen)
-{
-       size_t len;
-       void *data;
-
-       /* Get out of I don't have a variable */
-       if (!table->data || !table->maxlen)
-               return -ENOTDIR;
-
-       data = get_ipc(table, 1);
-       if (!data)
-               return -ENOTDIR;
-
-       if (oldval && oldlenp) {
-               if (get_user(len, oldlenp))
-                       return -EFAULT;
-               if (len) {
-                       if (len > table->maxlen)
-                               len = table->maxlen;
-                       if (copy_to_user(oldval, data, len))
-                               return -EFAULT;
-                       if (put_user(len, oldlenp))
-                               return -EFAULT;
-               }
-       }
-
-       if (newval && newlen) {
-               if (newlen > table->maxlen)
-                       newlen = table->maxlen;
-
-               if (copy_from_user(data, newval, newlen))
-                       return -EFAULT;
-       }
-       return 1;
-}
-#endif
 
 #else /* CONFIG_SYSCTL_SYSCALL */
 
@@ -2769,20 +2350,6 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return -ENOSYS;
 }
 
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen)
-{
-       return -ENOSYS;
-}
-#ifdef CONFIG_SYSVIPC
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-               void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen)
-{
-       return -ENOSYS;
-}
-#endif
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
index 0e017bff4c19e77daeb657669618c757399dde03..c6c80ea5d0ead904ac73030616ba02c5b2a5f7d9 100644 (file)
@@ -470,6 +470,260 @@ struct timeval ns_to_timeval(const s64 nsec)
        return tv;
 }
 
+/*
+ * Convert jiffies to milliseconds and back.
+ *
+ * Avoid unnecessary multiplications/divisions in the
+ * two most common HZ cases:
+ */
+unsigned int jiffies_to_msecs(const unsigned long j)
+{
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+       return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+       return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
+#else
+       return (j * MSEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_msecs);
+
+unsigned int jiffies_to_usecs(const unsigned long j)
+{
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+       return (USEC_PER_SEC / HZ) * j;
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+       return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
+#else
+       return (j * USEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_usecs);
+
+/*
+ * When we convert to jiffies then we interpret incoming values
+ * the following way:
+ *
+ * - negative values mean 'infinite timeout' (MAX_JIFFY_OFFSET)
+ *
+ * - 'too large' values [that would result in larger than
+ *   MAX_JIFFY_OFFSET values] mean 'infinite timeout' too.
+ *
+ * - all other values are converted to jiffies by either multiplying
+ *   the input value by a factor or dividing it with a factor
+ *
+ * We must also be careful about 32-bit overflows.
+ */
+unsigned long msecs_to_jiffies(const unsigned int m)
+{
+       /*
+        * Negative value, means infinite timeout:
+        */
+       if ((int)m < 0)
+               return MAX_JIFFY_OFFSET;
+
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+       /*
+        * HZ is equal to or smaller than 1000, and 1000 is a nice
+        * round multiple of HZ, divide with the factor between them,
+        * but round upwards:
+        */
+       return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+       /*
+        * HZ is larger than 1000, and HZ is a nice round multiple of
+        * 1000 - simply multiply with the factor between them.
+        *
+        * But first make sure the multiplication result cannot
+        * overflow:
+        */
+       if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+               return MAX_JIFFY_OFFSET;
+
+       return m * (HZ / MSEC_PER_SEC);
+#else
+       /*
+        * Generic case - multiply, round and divide. But first
+        * check that if we are doing a net multiplication, that
+        * we wouldnt overflow:
+        */
+       if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+               return MAX_JIFFY_OFFSET;
+
+       return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
+#endif
+}
+EXPORT_SYMBOL(msecs_to_jiffies);
+
+unsigned long usecs_to_jiffies(const unsigned int u)
+{
+       if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
+               return MAX_JIFFY_OFFSET;
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+       return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+       return u * (HZ / USEC_PER_SEC);
+#else
+       return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
+#endif
+}
+EXPORT_SYMBOL(usecs_to_jiffies);
+
+/*
+ * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
+ * that a remainder subtract here would not do the right thing as the
+ * resolution values don't fall on second boundries.  I.e. the line:
+ * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
+ *
+ * Rather, we just shift the bits off the right.
+ *
+ * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
+ * value to a scaled second value.
+ */
+unsigned long
+timespec_to_jiffies(const struct timespec *value)
+{
+       unsigned long sec = value->tv_sec;
+       long nsec = value->tv_nsec + TICK_NSEC - 1;
+
+       if (sec >= MAX_SEC_IN_JIFFIES){
+               sec = MAX_SEC_IN_JIFFIES;
+               nsec = 0;
+       }
+       return (((u64)sec * SEC_CONVERSION) +
+               (((u64)nsec * NSEC_CONVERSION) >>
+                (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
+
+}
+EXPORT_SYMBOL(timespec_to_jiffies);
+
+void
+jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
+{
+       /*
+        * Convert jiffies to nanoseconds and separate with
+        * one divide.
+        */
+       u64 nsec = (u64)jiffies * TICK_NSEC;
+       value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec);
+}
+EXPORT_SYMBOL(jiffies_to_timespec);
+
+/* Same for "timeval"
+ *
+ * Well, almost.  The problem here is that the real system resolution is
+ * in nanoseconds and the value being converted is in micro seconds.
+ * Also for some machines (those that use HZ = 1024, in-particular),
+ * there is a LARGE error in the tick size in microseconds.
+
+ * The solution we use is to do the rounding AFTER we convert the
+ * microsecond part.  Thus the USEC_ROUND, the bits to be shifted off.
+ * Instruction wise, this should cost only an additional add with carry
+ * instruction above the way it was done above.
+ */
+unsigned long
+timeval_to_jiffies(const struct timeval *value)
+{
+       unsigned long sec = value->tv_sec;
+       long usec = value->tv_usec;
+
+       if (sec >= MAX_SEC_IN_JIFFIES){
+               sec = MAX_SEC_IN_JIFFIES;
+               usec = 0;
+       }
+       return (((u64)sec * SEC_CONVERSION) +
+               (((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
+                (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
+}
+
+void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value)
+{
+       /*
+        * Convert jiffies to nanoseconds and separate with
+        * one divide.
+        */
+       u64 nsec = (u64)jiffies * TICK_NSEC;
+       long tv_usec;
+
+       value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
+       tv_usec /= NSEC_PER_USEC;
+       value->tv_usec = tv_usec;
+}
+
+/*
+ * Convert jiffies/jiffies_64 to clock_t and back.
+ */
+clock_t jiffies_to_clock_t(long x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+       return x / (HZ / USER_HZ);
+#else
+       u64 tmp = (u64)x * TICK_NSEC;
+       do_div(tmp, (NSEC_PER_SEC / USER_HZ));
+       return (long)tmp;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_clock_t);
+
+unsigned long clock_t_to_jiffies(unsigned long x)
+{
+#if (HZ % USER_HZ)==0
+       if (x >= ~0UL / (HZ / USER_HZ))
+               return ~0UL;
+       return x * (HZ / USER_HZ);
+#else
+       u64 jif;
+
+       /* Don't worry about loss of precision here .. */
+       if (x >= ~0UL / HZ * USER_HZ)
+               return ~0UL;
+
+       /* .. but do try to contain it here */
+       jif = x * (u64) HZ;
+       do_div(jif, USER_HZ);
+       return jif;
+#endif
+}
+EXPORT_SYMBOL(clock_t_to_jiffies);
+
+u64 jiffies_64_to_clock_t(u64 x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+       do_div(x, HZ / USER_HZ);
+#else
+       /*
+        * There are better ways that don't overflow early,
+        * but even this doesn't overflow in hundreds of years
+        * in 64 bits, so..
+        */
+       x *= TICK_NSEC;
+       do_div(x, (NSEC_PER_SEC / USER_HZ));
+#endif
+       return x;
+}
+
+EXPORT_SYMBOL(jiffies_64_to_clock_t);
+
+u64 nsec_to_clock_t(u64 x)
+{
+#if (NSEC_PER_SEC % USER_HZ) == 0
+       do_div(x, (NSEC_PER_SEC / USER_HZ));
+#elif (USER_HZ % 512) == 0
+       x *= USER_HZ/512;
+       do_div(x, (NSEC_PER_SEC / 512));
+#else
+       /*
+         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+       x *= 9;
+       do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2)) /
+                                 USER_HZ));
+#endif
+       return x;
+}
+
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
 {
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
new file mode 100644 (file)
index 0000000..f663511
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# Timer subsystem related configuration options
+#
+config TICK_ONESHOT
+       bool
+       default n
+
+config NO_HZ
+       bool "Tickless System (Dynamic Ticks)"
+       depends on GENERIC_TIME && GENERIC_CLOCKEVENTS
+       select TICK_ONESHOT
+       help
+         This option enables a tickless system: timer interrupts will
+         only trigger on an as-needed basis both when the system is
+         busy and when the system is idle.
+
+config HIGH_RES_TIMERS
+       bool "High Resolution Timer Support"
+       depends on GENERIC_TIME && GENERIC_CLOCKEVENTS
+       select TICK_ONESHOT
+       help
+         This option enables high resolution timer support. If your
+         hardware is not capable then this option only increases
+         the size of the kernel image.
+
index 61a3907d16fb5caa0ef0391b3e52b70a08a6844e..93bccba1f265e3b49df7d5bc54810ec5e3e39b2d 100644 (file)
@@ -1 +1,8 @@
-obj-y += ntp.o clocksource.o jiffies.o
+obj-y += ntp.o clocksource.o jiffies.o timer_list.o
+
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += clockevents.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += tick-broadcast.o
+obj-$(CONFIG_TICK_ONESHOT)                     += tick-oneshot.o
+obj-$(CONFIG_TICK_ONESHOT)                     += tick-sched.o
+obj-$(CONFIG_TIMER_STATS)                      += timer_stats.o
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
new file mode 100644 (file)
index 0000000..67932ea
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * linux/kernel/time/clockevents.c
+ *
+ * This file contains functions which manage clock event devices.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+
+#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <linux/sysdev.h>
+
+/* The registered clock event devices */
+static LIST_HEAD(clockevent_devices);
+static LIST_HEAD(clockevents_released);
+
+/* Notification for clock events */
+static RAW_NOTIFIER_HEAD(clockevents_chain);
+
+/* Protection for the above */
+static DEFINE_SPINLOCK(clockevents_lock);
+
+/**
+ * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
+ * @latch:     value to convert
+ * @evt:       pointer to clock event device descriptor
+ *
+ * Math helper, returns latch value converted to nanoseconds (bound checked)
+ */
+unsigned long clockevent_delta2ns(unsigned long latch,
+                                 struct clock_event_device *evt)
+{
+       u64 clc = ((u64) latch << evt->shift);
+
+       do_div(clc, evt->mult);
+       if (clc < 1000)
+               clc = 1000;
+       if (clc > LONG_MAX)
+               clc = LONG_MAX;
+
+       return (unsigned long) clc;
+}
+
+/**
+ * clockevents_set_mode - set the operating mode of a clock event device
+ * @dev:       device to modify
+ * @mode:      new mode
+ *
+ * Must be called with interrupts disabled !
+ */
+void clockevents_set_mode(struct clock_event_device *dev,
+                                enum clock_event_mode mode)
+{
+       if (dev->mode != mode) {
+               dev->set_mode(mode, dev);
+               dev->mode = mode;
+       }
+}
+
+/**
+ * clockevents_program_event - Reprogram the clock event device.
+ * @expires:   absolute expiry time (monotonic clock)
+ *
+ * Returns 0 on success, -ETIME when the event is in the past.
+ */
+int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
+                             ktime_t now)
+{
+       unsigned long long clc;
+       int64_t delta;
+
+       delta = ktime_to_ns(ktime_sub(expires, now));
+
+       if (delta <= 0)
+               return -ETIME;
+
+       dev->next_event = expires;
+
+       if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
+               return 0;
+
+       if (delta > dev->max_delta_ns)
+               delta = dev->max_delta_ns;
+       if (delta < dev->min_delta_ns)
+               delta = dev->min_delta_ns;
+
+       clc = delta * dev->mult;
+       clc >>= dev->shift;
+
+       return dev->set_next_event((unsigned long) clc, dev);
+}
+
+/**
+ * clockevents_register_notifier - register a clock events change listener
+ */
+int clockevents_register_notifier(struct notifier_block *nb)
+{
+       int ret;
+
+       spin_lock(&clockevents_lock);
+       ret = raw_notifier_chain_register(&clockevents_chain, nb);
+       spin_unlock(&clockevents_lock);
+
+       return ret;
+}
+
+/**
+ * clockevents_unregister_notifier - unregister a clock events change listener
+ */
+void clockevents_unregister_notifier(struct notifier_block *nb)
+{
+       spin_lock(&clockevents_lock);
+       raw_notifier_chain_unregister(&clockevents_chain, nb);
+       spin_unlock(&clockevents_lock);
+}
+
+/*
+ * Notify about a clock event change. Called with clockevents_lock
+ * held.
+ */
+static void clockevents_do_notify(unsigned long reason, void *dev)
+{
+       raw_notifier_call_chain(&clockevents_chain, reason, dev);
+}
+
+/*
+ * Called after a notify add to make devices availble which were
+ * released from the notifier call.
+ */
+static void clockevents_notify_released(void)
+{
+       struct clock_event_device *dev;
+
+       while (!list_empty(&clockevents_released)) {
+               dev = list_entry(clockevents_released.next,
+                                struct clock_event_device, list);
+               list_del(&dev->list);
+               list_add(&dev->list, &clockevent_devices);
+               clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+       }
+}
+
+/**
+ * clockevents_register_device - register a clock event device
+ * @dev:       device to register
+ */
+void clockevents_register_device(struct clock_event_device *dev)
+{
+       BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+
+       spin_lock(&clockevents_lock);
+
+       list_add(&dev->list, &clockevent_devices);
+       clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+       clockevents_notify_released();
+
+       spin_unlock(&clockevents_lock);
+}
+
+/*
+ * Noop handler when we shut down an event device
+ */
+static void clockevents_handle_noop(struct clock_event_device *dev)
+{
+}
+
+/**
+ * clockevents_exchange_device - release and request clock devices
+ * @old:       device to release (can be NULL)
+ * @new:       device to request (can be NULL)
+ *
+ * Called from the notifier chain. clockevents_lock is held already
+ */
+void clockevents_exchange_device(struct clock_event_device *old,
+                                struct clock_event_device *new)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       /*
+        * Caller releases a clock event device. We queue it into the
+        * released list and do a notify add later.
+        */
+       if (old) {
+               old->event_handler = clockevents_handle_noop;
+               clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
+               list_del(&old->list);
+               list_add(&old->list, &clockevents_released);
+       }
+
+       if (new) {
+               BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
+               clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN);
+       }
+       local_irq_restore(flags);
+}
+
+/**
+ * clockevents_request_device
+ */
+struct clock_event_device *clockevents_request_device(unsigned int features,
+                                                     cpumask_t cpumask)
+{
+       struct clock_event_device *cur, *dev = NULL;
+       struct list_head *tmp;
+
+       spin_lock(&clockevents_lock);
+
+       list_for_each(tmp, &clockevent_devices) {
+               cur = list_entry(tmp, struct clock_event_device, list);
+
+               if ((cur->features & features) == features &&
+                   cpus_equal(cpumask, cur->cpumask)) {
+                       if (!dev || dev->rating < cur->rating)
+                               dev = cur;
+               }
+       }
+
+       clockevents_exchange_device(NULL, dev);
+
+       spin_unlock(&clockevents_lock);
+
+       return dev;
+}
+
+/**
+ * clockevents_release_device
+ */
+void clockevents_release_device(struct clock_event_device *dev)
+{
+       spin_lock(&clockevents_lock);
+
+       clockevents_exchange_device(dev, NULL);
+       clockevents_notify_released();
+
+       spin_unlock(&clockevents_lock);
+}
+
+/**
+ * clockevents_notify - notification about relevant events
+ */
+void clockevents_notify(unsigned long reason, void *arg)
+{
+       spin_lock(&clockevents_lock);
+       clockevents_do_notify(reason, arg);
+
+       switch (reason) {
+       case CLOCK_EVT_NOTIFY_CPU_DEAD:
+               /*
+                * Unregister the clock event devices which were
+                * released from the users in the notify chain.
+                */
+               while (!list_empty(&clockevents_released)) {
+                       struct clock_event_device *dev;
+
+                       dev = list_entry(clockevents_released.next,
+                                        struct clock_event_device, list);
+                       list_del(&dev->list);
+               }
+               break;
+       default:
+               break;
+       }
+       spin_unlock(&clockevents_lock);
+}
+EXPORT_SYMBOL_GPL(clockevents_notify);
+
+#ifdef CONFIG_SYSFS
+
+/**
+ * clockevents_show_registered - sysfs interface for listing clockevents
+ * @dev:       unused
+ * @buf:       char buffer to be filled with clock events list
+ *
+ * Provides sysfs interface for listing registered clock event devices
+ */
+static ssize_t clockevents_show_registered(struct sys_device *dev, char *buf)
+{
+       struct list_head *tmp;
+       char *p = buf;
+       int cpu;
+
+       spin_lock(&clockevents_lock);
+
+       list_for_each(tmp, &clockevent_devices) {
+               struct clock_event_device *ce;
+
+               ce = list_entry(tmp, struct clock_event_device, list);
+               p += sprintf(p, "%-20s F:%04x M:%d", ce->name,
+                            ce->features, ce->mode);
+               p += sprintf(p, " C:");
+               if (!cpus_equal(ce->cpumask, cpu_possible_map)) {
+                       for_each_cpu_mask(cpu, ce->cpumask)
+                               p += sprintf(p, " %d", cpu);
+               } else {
+                       /*
+                        * FIXME: Add the cpu which is handling this sucker
+                        */
+               }
+               p += sprintf(p, "\n");
+       }
+
+       spin_unlock(&clockevents_lock);
+
+       return p - buf;
+}
+
+/*
+ * Sysfs setup bits:
+ */
+static SYSDEV_ATTR(registered, 0600,
+                  clockevents_show_registered, NULL);
+
+static struct sysdev_class clockevents_sysclass = {
+       set_kset_name("clockevents"),
+};
+
+static struct sys_device clockevents_sys_device = {
+       .id     = 0,
+       .cls    = &clockevents_sysclass,
+};
+
+static int __init clockevents_sysfs_init(void)
+{
+       int error = sysdev_class_register(&clockevents_sysclass);
+
+       if (!error)
+               error = sysdev_register(&clockevents_sys_device);
+       if (!error)
+               error = sysdev_create_file(
+                               &clockevents_sys_device,
+                               &attr_registered);
+       return error;
+}
+device_initcall(clockevents_sysfs_init);
+#endif
index d9ef176c4e092eebf93acc31dd14dcbd362603c0..193a0793af95440dfbf712fab6432e5e9553d275 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
+#include <linux/tick.h>
 
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
@@ -48,6 +49,7 @@ extern struct clocksource clocksource_jiffies;
  */
 static struct clocksource *curr_clocksource = &clocksource_jiffies;
 static struct clocksource *next_clocksource;
+static struct clocksource *clocksource_override;
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
 static char override_name[32];
@@ -62,9 +64,123 @@ static int __init clocksource_done_booting(void)
        finished_booting = 1;
        return 0;
 }
-
 late_initcall(clocksource_done_booting);
 
+#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
+static LIST_HEAD(watchdog_list);
+static struct clocksource *watchdog;
+static struct timer_list watchdog_timer;
+static DEFINE_SPINLOCK(watchdog_lock);
+static cycle_t watchdog_last;
+/*
+ * Interval: 0.5sec Treshold: 0.0625s
+ */
+#define WATCHDOG_INTERVAL (HZ >> 1)
+#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
+
+static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
+{
+       if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
+               return;
+
+       printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
+              cs->name, delta);
+       cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
+       clocksource_change_rating(cs, 0);
+       cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
+       list_del(&cs->wd_list);
+}
+
+static void clocksource_watchdog(unsigned long data)
+{
+       struct clocksource *cs, *tmp;
+       cycle_t csnow, wdnow;
+       int64_t wd_nsec, cs_nsec;
+
+       spin_lock(&watchdog_lock);
+
+       wdnow = watchdog->read();
+       wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask);
+       watchdog_last = wdnow;
+
+       list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
+               csnow = cs->read();
+               /* Initialized ? */
+               if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
+                       if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
+                           (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
+                               cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+                               /*
+                                * We just marked the clocksource as
+                                * highres-capable, notify the rest of the
+                                * system as well so that we transition
+                                * into high-res mode:
+                                */
+                               tick_clock_notify();
+                       }
+                       cs->flags |= CLOCK_SOURCE_WATCHDOG;
+                       cs->wd_last = csnow;
+               } else {
+                       cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
+                       cs->wd_last = csnow;
+                       /* Check the delta. Might remove from the list ! */
+                       clocksource_ratewd(cs, cs_nsec - wd_nsec);
+               }
+       }
+
+       if (!list_empty(&watchdog_list)) {
+               __mod_timer(&watchdog_timer,
+                           watchdog_timer.expires + WATCHDOG_INTERVAL);
+       }
+       spin_unlock(&watchdog_lock);
+}
+static void clocksource_check_watchdog(struct clocksource *cs)
+{
+       struct clocksource *cse;
+       unsigned long flags;
+
+       spin_lock_irqsave(&watchdog_lock, flags);
+       if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
+               int started = !list_empty(&watchdog_list);
+
+               list_add(&cs->wd_list, &watchdog_list);
+               if (!started && watchdog) {
+                       watchdog_last = watchdog->read();
+                       watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
+                       add_timer(&watchdog_timer);
+               }
+       } else if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) {
+                       cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+
+               if (!watchdog || cs->rating > watchdog->rating) {
+                       if (watchdog)
+                               del_timer(&watchdog_timer);
+                       watchdog = cs;
+                       init_timer(&watchdog_timer);
+                       watchdog_timer.function = clocksource_watchdog;
+
+                       /* Reset watchdog cycles */
+                       list_for_each_entry(cse, &watchdog_list, wd_list)
+                               cse->flags &= ~CLOCK_SOURCE_WATCHDOG;
+                       /* Start if list is not empty */
+                       if (!list_empty(&watchdog_list)) {
+                               watchdog_last = watchdog->read();
+                               watchdog_timer.expires =
+                                       jiffies + WATCHDOG_INTERVAL;
+                               add_timer(&watchdog_timer);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&watchdog_lock, flags);
+}
+#else
+static void clocksource_check_watchdog(struct clocksource *cs)
+{
+       if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
+               cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+}
+#endif
+
 /**
  * clocksource_get_next - Returns the selected clocksource
  *
@@ -84,60 +200,54 @@ struct clocksource *clocksource_get_next(void)
 }
 
 /**
- * select_clocksource - Finds the best registered clocksource.
+ * select_clocksource - Selects the best registered clocksource.
  *
  * Private function. Must hold clocksource_lock when called.
  *
- * Looks through the list of registered clocksources, returning
- * the one with the highest rating value. If there is a clocksource
- * name that matches the override string, it returns that clocksource.
+ * Select the clocksource with the best rating, or the clocksource,
+ * which is selected by userspace override.
  */
 static struct clocksource *select_clocksource(void)
 {
-       struct clocksource *best = NULL;
-       struct list_head *tmp;
+       struct clocksource *next;
 
-       list_for_each(tmp, &clocksource_list) {
-               struct clocksource *src;
+       if (list_empty(&clocksource_list))
+               return NULL;
 
-               src = list_entry(tmp, struct clocksource, list);
-               if (!best)
-                       best = src;
-
-               /* check for override: */
-               if (strlen(src->name) == strlen(override_name) &&
-                   !strcmp(src->name, override_name)) {
-                       best = src;
-                       break;
-               }
-               /* pick the highest rating: */
-               if (src->rating > best->rating)
-                       best = src;
-       }
+       if (clocksource_override)
+               next = clocksource_override;
+       else
+               next = list_entry(clocksource_list.next, struct clocksource,
+                                 list);
+
+       if (next == curr_clocksource)
+               return NULL;
 
-       return best;
+       return next;
 }
 
-/**
- * is_registered_source - Checks if clocksource is registered
- * @c:         pointer to a clocksource
- *
- * Private helper function. Must hold clocksource_lock when called.
- *
- * Returns one if the clocksource is already registered, zero otherwise.
+/*
+ * Enqueue the clocksource sorted by rating
  */
-static int is_registered_source(struct clocksource *c)
+static int clocksource_enqueue(struct clocksource *c)
 {
-       int len = strlen(c->name);
-       struct list_head *tmp;
+       struct list_head *tmp, *entry = &clocksource_list;
 
        list_for_each(tmp, &clocksource_list) {
-               struct clocksource *src;
-
-               src = list_entry(tmp, struct clocksource, list);
-               if (strlen(src->name) == len && !strcmp(src->name, c->name))
-                       return 1;
+               struct clocksource *cs;
+
+               cs = list_entry(tmp, struct clocksource, list);
+               if (cs == c)
+                       return -EBUSY;
+               /* Keep track of the place, where to insert */
+               if (cs->rating >= c->rating)
+                       entry = tmp;
        }
+       list_add(&c->list, entry);
+
+       if (strlen(c->name) == strlen(override_name) &&
+           !strcmp(c->name, override_name))
+               clocksource_override = c;
 
        return 0;
 }
@@ -150,42 +260,35 @@ static int is_registered_source(struct clocksource *c)
  */
 int clocksource_register(struct clocksource *c)
 {
-       int ret = 0;
        unsigned long flags;
+       int ret;
 
        spin_lock_irqsave(&clocksource_lock, flags);
-       /* check if clocksource is already registered */
-       if (is_registered_source(c)) {
-               printk("register_clocksource: Cannot register %s. "
-                      "Already registered!", c->name);
-               ret = -EBUSY;
-       } else {
-               /* register it */
-               list_add(&c->list, &clocksource_list);
-               /* scan the registered clocksources, and pick the best one */
+       ret = clocksource_enqueue(c);
+       if (!ret)
                next_clocksource = select_clocksource();
-       }
        spin_unlock_irqrestore(&clocksource_lock, flags);
+       if (!ret)
+               clocksource_check_watchdog(c);
        return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
 
 /**
- * clocksource_reselect - Rescan list for next clocksource
+ * clocksource_change_rating - Change the rating of a registered clocksource
  *
- * A quick helper function to be used if a clocksource changes its
- * rating. Forces the clocksource list to be re-scanned for the best
- * clocksource.
  */
-void clocksource_reselect(void)
+void clocksource_change_rating(struct clocksource *cs, int rating)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&clocksource_lock, flags);
+       list_del(&cs->list);
+       cs->rating = rating;
+       clocksource_enqueue(cs);
        next_clocksource = select_clocksource();
        spin_unlock_irqrestore(&clocksource_lock, flags);
 }
-EXPORT_SYMBOL(clocksource_reselect);
 
 #ifdef CONFIG_SYSFS
 /**
@@ -221,7 +324,11 @@ sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
 static ssize_t sysfs_override_clocksource(struct sys_device *dev,
                                          const char *buf, size_t count)
 {
+       struct clocksource *ovr = NULL;
+       struct list_head *tmp;
        size_t ret = count;
+       int len;
+
        /* strings from sysfs write are not 0 terminated! */
        if (count >= sizeof(override_name))
                return -EINVAL;
@@ -229,17 +336,32 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
        /* strip of \n: */
        if (buf[count-1] == '\n')
                count--;
-       if (count < 1)
-               return -EINVAL;
 
        spin_lock_irq(&clocksource_lock);
 
-       /* copy the name given: */
-       memcpy(override_name, buf, count);
+       if (count > 0)
+               memcpy(override_name, buf, count);
        override_name[count] = 0;
 
-       /* try to select it: */
-       next_clocksource = select_clocksource();
+       len = strlen(override_name);
+       if (len) {
+               ovr = clocksource_override;
+               /* try to select it: */
+               list_for_each(tmp, &clocksource_list) {
+                       struct clocksource *cs;
+
+                       cs = list_entry(tmp, struct clocksource, list);
+                       if (strlen(cs->name) == len &&
+                           !strcmp(cs->name, override_name))
+                               ovr = cs;
+               }
+       }
+
+       /* Reselect, when the override name has changed */
+       if (ovr != clocksource_override) {
+               clocksource_override = ovr;
+               next_clocksource = select_clocksource();
+       }
 
        spin_unlock_irq(&clocksource_lock);
 
index a99b2a6e6a07354781da79b6067b1944d438d5f9..3be8da8fed7efa1a972fca3c0c249dc7f1a983fa 100644 (file)
@@ -62,7 +62,6 @@ struct clocksource clocksource_jiffies = {
        .mask           = 0xffffffff, /*32bits*/
        .mult           = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
        .shift          = JIFFIES_SHIFT,
-       .is_continuous  = 0, /* tick based, not free running */
 };
 
 static int __init init_jiffies_clocksource(void)
index 3afeaa3a73f998dd422e1518c6c4256749207538..eb12509e00bdd964fb2ed552aa8402a703f363ae 100644 (file)
@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base;
 
 #define MAX_TICKADJ            500             /* microsecs */
 #define MAX_TICKADJ_SCALED     (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
-                                 TICK_LENGTH_SHIFT) / HZ)
+                                 TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
 
 /*
  * phase-lock loop variables
@@ -46,13 +46,17 @@ long time_adjust;
 
 static void ntp_update_frequency(void)
 {
-       tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
-       tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
-       tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+       u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
+                               << TICK_LENGTH_SHIFT;
+       second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
+       second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
 
-       do_div(tick_length_base, HZ);
+       tick_length_base = second_length;
 
-       tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
+       do_div(second_length, HZ);
+       tick_nsec = second_length >> TICK_LENGTH_SHIFT;
+
+       do_div(tick_length_base, NTP_INTERVAL_FREQ);
 }
 
 /**
@@ -162,7 +166,7 @@ void second_overflow(void)
                        tick_length -= MAX_TICKADJ_SCALED;
                } else {
                        tick_length += (s64)(time_adjust * NSEC_PER_USEC /
-                                            HZ) << TICK_LENGTH_SHIFT;
+                                       NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
                        time_adjust = 0;
                }
        }
@@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc)
                    result = -EINVAL;
                    goto leave;
                }
-               time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC);
+               time_freq = ((s64)txc->freq * NSEC_PER_USEC)
+                               >> (SHIFT_USEC - SHIFT_NSEC);
            }
 
            if (txc->modes & ADJ_MAXERROR) {
@@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc)
                    freq_adj += time_freq;
                    freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
                    time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
-                   time_offset = (time_offset / HZ) << SHIFT_UPDATE;
+                   time_offset = (time_offset / NTP_INTERVAL_FREQ)
+                                       << SHIFT_UPDATE;
                } /* STA_PLL */
            } /* txc->modes & ADJ_OFFSET */
            if (txc->modes & ADJ_TICK)
@@ -324,8 +330,10 @@ leave:     if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
        if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
            txc->offset    = save_adjust;
        else
-           txc->offset    = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
-       txc->freq          = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC);
+           txc->offset    = shift_right(time_offset, SHIFT_UPDATE)
+                               * NTP_INTERVAL_FREQ / 1000;
+       txc->freq          = (time_freq / NSEC_PER_USEC)
+                               << (SHIFT_USEC - SHIFT_NSEC);
        txc->maxerror      = time_maxerror;
        txc->esterror      = time_esterror;
        txc->status        = time_status;
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
new file mode 100644 (file)
index 0000000..12b3efe
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * linux/kernel/time/tick-broadcast.c
+ *
+ * This file contains functions which emulate a local clock-event
+ * device via a broadcast event source.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/*
+ * Broadcast support for broken x86 hardware, where the local apic
+ * timer stops in C3 state.
+ */
+
+struct tick_device tick_broadcast_device;
+static cpumask_t tick_broadcast_mask;
+static DEFINE_SPINLOCK(tick_broadcast_lock);
+
+/*
+ * Debugging: see timer_list.c
+ */
+struct tick_device *tick_get_broadcast_device(void)
+{
+       return &tick_broadcast_device;
+}
+
+cpumask_t *tick_get_broadcast_mask(void)
+{
+       return &tick_broadcast_mask;
+}
+
+/*
+ * Start the device in periodic mode
+ */
+static void tick_broadcast_start_periodic(struct clock_event_device *bc)
+{
+       if (bc && bc->mode == CLOCK_EVT_MODE_SHUTDOWN)
+               tick_setup_periodic(bc, 1);
+}
+
+/*
+ * Check, if the device can be utilized as broadcast device:
+ */
+int tick_check_broadcast_device(struct clock_event_device *dev)
+{
+       if (tick_broadcast_device.evtdev ||
+           (dev->features & CLOCK_EVT_FEAT_C3STOP))
+               return 0;
+
+       clockevents_exchange_device(NULL, dev);
+       tick_broadcast_device.evtdev = dev;
+       if (!cpus_empty(tick_broadcast_mask))
+               tick_broadcast_start_periodic(dev);
+       return 1;
+}
+
+/*
+ * Check, if the device is the broadcast device
+ */
+int tick_is_broadcast_device(struct clock_event_device *dev)
+{
+       return (dev && tick_broadcast_device.evtdev == dev);
+}
+
+/*
+ * Check, if the device is disfunctional and a place holder, which
+ * needs to be handled by the broadcast device.
+ */
+int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       /*
+        * Devices might be registered with both periodic and oneshot
+        * mode disabled. This signals, that the device needs to be
+        * operated from the broadcast device and is a placeholder for
+        * the cpu local device.
+        */
+       if (!tick_device_is_functional(dev)) {
+               dev->event_handler = tick_handle_periodic;
+               cpu_set(cpu, tick_broadcast_mask);
+               tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
+               ret = 1;
+       }
+
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+       return ret;
+}
+
+/*
+ * Broadcast the event to the cpus, which are set in the mask
+ */
+int tick_do_broadcast(cpumask_t mask)
+{
+       int ret = 0, cpu = smp_processor_id();
+       struct tick_device *td;
+
+       /*
+        * Check, if the current cpu is in the mask
+        */
+       if (cpu_isset(cpu, mask)) {
+               cpu_clear(cpu, mask);
+               td = &per_cpu(tick_cpu_device, cpu);
+               td->evtdev->event_handler(td->evtdev);
+               ret = 1;
+       }
+
+       if (!cpus_empty(mask)) {
+               /*
+                * It might be necessary to actually check whether the devices
+                * have different broadcast functions. For now, just use the
+                * one of the first device. This works as long as we have this
+                * misfeature only on x86 (lapic)
+                */
+               cpu = first_cpu(mask);
+               td = &per_cpu(tick_cpu_device, cpu);
+               td->evtdev->broadcast(mask);
+               ret = 1;
+       }
+       return ret;
+}
+
+/*
+ * Periodic broadcast:
+ * - invoke the broadcast handlers
+ */
+static void tick_do_periodic_broadcast(void)
+{
+       cpumask_t mask;
+
+       spin_lock(&tick_broadcast_lock);
+
+       cpus_and(mask, cpu_online_map, tick_broadcast_mask);
+       tick_do_broadcast(mask);
+
+       spin_unlock(&tick_broadcast_lock);
+}
+
+/*
+ * Event handler for periodic broadcast ticks
+ */
+static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
+{
+       dev->next_event.tv64 = KTIME_MAX;
+
+       tick_do_periodic_broadcast();
+
+       /*
+        * The device is in periodic mode. No reprogramming necessary:
+        */
+       if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
+               return;
+
+       /*
+        * Setup the next period for devices, which do not have
+        * periodic mode:
+        */
+       for (;;) {
+               ktime_t next = ktime_add(dev->next_event, tick_period);
+
+               if (!clockevents_program_event(dev, next, ktime_get()))
+                       return;
+               tick_do_periodic_broadcast();
+       }
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop
+ */
+static void tick_do_broadcast_on_off(void *why)
+{
+       struct clock_event_device *bc, *dev;
+       struct tick_device *td;
+       unsigned long flags, *reason = why;
+       int cpu;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       cpu = smp_processor_id();
+       td = &per_cpu(tick_cpu_device, cpu);
+       dev = td->evtdev;
+       bc = tick_broadcast_device.evtdev;
+
+       /*
+        * Is the device in broadcast mode forever or is it not
+        * affected by the powerstate ?
+        */
+       if (!dev || !tick_device_is_functional(dev) ||
+           !(dev->features & CLOCK_EVT_FEAT_C3STOP))
+               goto out;
+
+       if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) {
+               if (!cpu_isset(cpu, tick_broadcast_mask)) {
+                       cpu_set(cpu, tick_broadcast_mask);
+                       if (td->mode == TICKDEV_MODE_PERIODIC)
+                               clockevents_set_mode(dev,
+                                                    CLOCK_EVT_MODE_SHUTDOWN);
+               }
+       } else {
+               if (cpu_isset(cpu, tick_broadcast_mask)) {
+                       cpu_clear(cpu, tick_broadcast_mask);
+                       if (td->mode == TICKDEV_MODE_PERIODIC)
+                               tick_setup_periodic(dev, 0);
+               }
+       }
+
+       if (cpus_empty(tick_broadcast_mask))
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+       else {
+               if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+                       tick_broadcast_start_periodic(bc);
+               else
+                       tick_broadcast_setup_oneshot(bc);
+       }
+out:
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop.
+ */
+void tick_broadcast_on_off(unsigned long reason, int *oncpu)
+{
+       int cpu = get_cpu();
+
+       if (cpu == *oncpu)
+               tick_do_broadcast_on_off(&reason);
+       else
+               smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
+                                        &reason, 1, 1);
+       put_cpu();
+}
+
+/*
+ * Set the periodic handler depending on broadcast on/off
+ */
+void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
+{
+       if (!broadcast)
+               dev->event_handler = tick_handle_periodic;
+       else
+               dev->event_handler = tick_handle_periodic_broadcast;
+}
+
+/*
+ * Remove a CPU from broadcasting
+ */
+void tick_shutdown_broadcast(unsigned int *cpup)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+       unsigned int cpu = *cpup;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       bc = tick_broadcast_device.evtdev;
+       cpu_clear(cpu, tick_broadcast_mask);
+
+       if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
+               if (bc && cpus_empty(tick_broadcast_mask))
+                       clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+       }
+
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+#ifdef CONFIG_TICK_ONESHOT
+
+static cpumask_t tick_broadcast_oneshot_mask;
+
+/*
+ * Debugging: see timer_list.c
+ */
+cpumask_t *tick_get_broadcast_oneshot_mask(void)
+{
+       return &tick_broadcast_oneshot_mask;
+}
+
+static int tick_broadcast_set_event(ktime_t expires, int force)
+{
+       struct clock_event_device *bc = tick_broadcast_device.evtdev;
+       ktime_t now = ktime_get();
+       int res;
+
+       for(;;) {
+               res = clockevents_program_event(bc, expires, now);
+               if (!res || !force)
+                       return res;
+               now = ktime_get();
+               expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
+       }
+}
+
+/*
+ * Reprogram the broadcast device:
+ *
+ * Called with tick_broadcast_lock held and interrupts disabled.
+ */
+static int tick_broadcast_reprogram(void)
+{
+       ktime_t expires = { .tv64 = KTIME_MAX };
+       struct tick_device *td;
+       int cpu;
+
+       /*
+        * Find the event which expires next:
+        */
+       for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
+            cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
+               td = &per_cpu(tick_cpu_device, cpu);
+               if (td->evtdev->next_event.tv64 < expires.tv64)
+                       expires = td->evtdev->next_event;
+       }
+
+       if (expires.tv64 == KTIME_MAX)
+               return 0;
+
+       return tick_broadcast_set_event(expires, 0);
+}
+
+/*
+ * Handle oneshot mode broadcasting
+ */
+static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
+{
+       struct tick_device *td;
+       cpumask_t mask;
+       ktime_t now;
+       int cpu;
+
+       spin_lock(&tick_broadcast_lock);
+again:
+       dev->next_event.tv64 = KTIME_MAX;
+       mask = CPU_MASK_NONE;
+       now = ktime_get();
+       /* Find all expired events */
+       for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
+            cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
+               td = &per_cpu(tick_cpu_device, cpu);
+               if (td->evtdev->next_event.tv64 <= now.tv64)
+                       cpu_set(cpu, mask);
+       }
+
+       /*
+        * Wakeup the cpus which have an expired event. The broadcast
+        * device is reprogrammed in the return from idle code.
+        */
+       if (!tick_do_broadcast(mask)) {
+               /*
+                * The global event did not expire any CPU local
+                * events. This happens in dyntick mode, as the
+                * maximum PIT delta is quite small.
+                */
+               if (tick_broadcast_reprogram())
+                       goto again;
+       }
+       spin_unlock(&tick_broadcast_lock);
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop
+ */
+void tick_broadcast_oneshot_control(unsigned long reason)
+{
+       struct clock_event_device *bc, *dev;
+       struct tick_device *td;
+       unsigned long flags;
+       int cpu;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       /*
+        * Periodic mode does not care about the enter/exit of power
+        * states
+        */
+       if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+               goto out;
+
+       bc = tick_broadcast_device.evtdev;
+       cpu = smp_processor_id();
+       td = &per_cpu(tick_cpu_device, cpu);
+       dev = td->evtdev;
+
+       if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
+               goto out;
+
+       if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
+               if (!cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
+                       cpu_set(cpu, tick_broadcast_oneshot_mask);
+                       clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+                       if (dev->next_event.tv64 < bc->next_event.tv64)
+                               tick_broadcast_set_event(dev->next_event, 1);
+               }
+       } else {
+               if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
+                       cpu_clear(cpu, tick_broadcast_oneshot_mask);
+                       clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+                       if (dev->next_event.tv64 != KTIME_MAX)
+                               tick_program_event(dev->next_event, 1);
+               }
+       }
+
+out:
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+/**
+ * tick_broadcast_setup_highres - setup the broadcast device for highres
+ */
+void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+       if (bc->mode != CLOCK_EVT_MODE_ONESHOT) {
+               bc->event_handler = tick_handle_oneshot_broadcast;
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+               bc->next_event.tv64 = KTIME_MAX;
+       }
+}
+
+/*
+ * Select oneshot operating mode for the broadcast device
+ */
+void tick_broadcast_switch_to_oneshot(void)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
+       bc = tick_broadcast_device.evtdev;
+       if (bc)
+               tick_broadcast_setup_oneshot(bc);
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+
+/*
+ * Remove a dead CPU from broadcasting
+ */
+void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+       unsigned int cpu = *cpup;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       bc = tick_broadcast_device.evtdev;
+       cpu_clear(cpu, tick_broadcast_oneshot_mask);
+
+       if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT) {
+               if (bc && cpus_empty(tick_broadcast_oneshot_mask))
+                       clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+       }
+
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+#endif
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
new file mode 100644 (file)
index 0000000..4500e34
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * linux/kernel/time/tick-common.c
+ *
+ * This file contains the base functions to manage periodic tick
+ * related events.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/*
+ * Tick devices
+ */
+DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
+/*
+ * Tick next event: keeps track of the tick time
+ */
+ktime_t tick_next_period;
+ktime_t tick_period;
+static int tick_do_timer_cpu = -1;
+DEFINE_SPINLOCK(tick_device_lock);
+
+/*
+ * Debugging: see timer_list.c
+ */
+struct tick_device *tick_get_device(int cpu)
+{
+       return &per_cpu(tick_cpu_device, cpu);
+}
+
+/**
+ * tick_is_oneshot_available - check for a oneshot capable event device
+ */
+int tick_is_oneshot_available(void)
+{
+       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+
+       return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT);
+}
+
+/*
+ * Periodic tick
+ */
+static void tick_periodic(int cpu)
+{
+       if (tick_do_timer_cpu == cpu) {
+               write_seqlock(&xtime_lock);
+
+               /* Keep track of the next tick event */
+               tick_next_period = ktime_add(tick_next_period, tick_period);
+
+               do_timer(1);
+               write_sequnlock(&xtime_lock);
+       }
+
+       update_process_times(user_mode(get_irq_regs()));
+       profile_tick(CPU_PROFILING);
+}
+
+/*
+ * Event handler for periodic ticks
+ */
+void tick_handle_periodic(struct clock_event_device *dev)
+{
+       int cpu = smp_processor_id();
+
+       tick_periodic(cpu);
+
+       if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
+               return;
+       /*
+        * Setup the next period for devices, which do not have
+        * periodic mode:
+        */
+       for (;;) {
+               ktime_t next = ktime_add(dev->next_event, tick_period);
+
+               if (!clockevents_program_event(dev, next, ktime_get()))
+                       return;
+               tick_periodic(cpu);
+       }
+}
+
+/*
+ * Setup the device for a periodic tick
+ */
+void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
+{
+       tick_set_periodic_handler(dev, broadcast);
+
+       /* Broadcast setup ? */
+       if (!tick_device_is_functional(dev))
+               return;
+
+       if (dev->features & CLOCK_EVT_FEAT_PERIODIC) {
+               clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
+       } else {
+               unsigned long seq;
+               ktime_t next;
+
+               do {
+                       seq = read_seqbegin(&xtime_lock);
+                       next = tick_next_period;
+               } while (read_seqretry(&xtime_lock, seq));
+
+               clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+
+               for (;;) {
+                       if (!clockevents_program_event(dev, next, ktime_get()))
+                               return;
+                       next = ktime_add(next, tick_period);
+               }
+       }
+}
+
+/*
+ * Setup the tick device
+ */
+static void tick_setup_device(struct tick_device *td,
+                             struct clock_event_device *newdev, int cpu,
+                             cpumask_t cpumask)
+{
+       ktime_t next_event;
+       void (*handler)(struct clock_event_device *) = NULL;
+
+       /*
+        * First device setup ?
+        */
+       if (!td->evtdev) {
+               /*
+                * If no cpu took the do_timer update, assign it to
+                * this cpu:
+                */
+               if (tick_do_timer_cpu == -1) {
+                       tick_do_timer_cpu = cpu;
+                       tick_next_period = ktime_get();
+                       tick_period = ktime_set(0, NSEC_PER_SEC / HZ);
+               }
+
+               /*
+                * Startup in periodic mode first.
+                */
+               td->mode = TICKDEV_MODE_PERIODIC;
+       } else {
+               handler = td->evtdev->event_handler;
+               next_event = td->evtdev->next_event;
+       }
+
+       td->evtdev = newdev;
+
+       /*
+        * When the device is not per cpu, pin the interrupt to the
+        * current cpu:
+        */
+       if (!cpus_equal(newdev->cpumask, cpumask))
+               irq_set_affinity(newdev->irq, cpumask);
+
+       /*
+        * When global broadcasting is active, check if the current
+        * device is registered as a placeholder for broadcast mode.
+        * This allows us to handle this x86 misfeature in a generic
+        * way.
+        */
+       if (tick_device_uses_broadcast(newdev, cpu))
+               return;
+
+       if (td->mode == TICKDEV_MODE_PERIODIC)
+               tick_setup_periodic(newdev, 0);
+       else
+               tick_setup_oneshot(newdev, handler, next_event);
+}
+
+/*
+ * Check, if the new registered device should be used.
+ */
+static int tick_check_new_device(struct clock_event_device *newdev)
+{
+       struct clock_event_device *curdev;
+       struct tick_device *td;
+       int cpu, ret = NOTIFY_OK;
+       unsigned long flags;
+       cpumask_t cpumask;
+
+       spin_lock_irqsave(&tick_device_lock, flags);
+
+       cpu = smp_processor_id();
+       if (!cpu_isset(cpu, newdev->cpumask))
+               goto out;
+
+       td = &per_cpu(tick_cpu_device, cpu);
+       curdev = td->evtdev;
+       cpumask = cpumask_of_cpu(cpu);
+
+       /* cpu local device ? */
+       if (!cpus_equal(newdev->cpumask, cpumask)) {
+
+               /*
+                * If the cpu affinity of the device interrupt can not
+                * be set, ignore it.
+                */
+               if (!irq_can_set_affinity(newdev->irq))
+                       goto out_bc;
+
+               /*
+                * If we have a cpu local device already, do not replace it
+                * by a non cpu local device
+                */
+               if (curdev && cpus_equal(curdev->cpumask, cpumask))
+                       goto out_bc;
+       }
+
+       /*
+        * If we have an active device, then check the rating and the oneshot
+        * feature.
+        */
+       if (curdev) {
+               /*
+                * Prefer one shot capable devices !
+                */
+               if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) &&
+                   !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))
+                       goto out_bc;
+               /*
+                * Check the rating
+                */
+               if (curdev->rating >= newdev->rating)
+                       goto out_bc;
+       }
+
+       /*
+        * Replace the eventually existing device by the new
+        * device. If the current device is the broadcast device, do
+        * not give it back to the clockevents layer !
+        */
+       if (tick_is_broadcast_device(curdev)) {
+               clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN);
+               curdev = NULL;
+       }
+       clockevents_exchange_device(curdev, newdev);
+       tick_setup_device(td, newdev, cpu, cpumask);
+       if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
+               tick_oneshot_notify();
+
+       spin_unlock_irqrestore(&tick_device_lock, flags);
+       return NOTIFY_STOP;
+
+out_bc:
+       /*
+        * Can the new device be used as a broadcast device ?
+        */
+       if (tick_check_broadcast_device(newdev))
+               ret = NOTIFY_STOP;
+out:
+       spin_unlock_irqrestore(&tick_device_lock, flags);
+
+       return ret;
+}
+
+/*
+ * Shutdown an event device on a given cpu:
+ *
+ * This is called on a life CPU, when a CPU is dead. So we cannot
+ * access the hardware device itself.
+ * We just set the mode and remove it from the lists.
+ */
+static void tick_shutdown(unsigned int *cpup)
+{
+       struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
+       struct clock_event_device *dev = td->evtdev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tick_device_lock, flags);
+       td->mode = TICKDEV_MODE_PERIODIC;
+       if (dev) {
+               /*
+                * Prevent that the clock events layer tries to call
+                * the set mode function!
+                */
+               dev->mode = CLOCK_EVT_MODE_UNUSED;
+               clockevents_exchange_device(dev, NULL);
+               td->evtdev = NULL;
+       }
+       spin_unlock_irqrestore(&tick_device_lock, flags);
+}
+
+/*
+ * Notification about clock event devices
+ */
+static int tick_notify(struct notifier_block *nb, unsigned long reason,
+                              void *dev)
+{
+       switch (reason) {
+
+       case CLOCK_EVT_NOTIFY_ADD:
+               return tick_check_new_device(dev);
+
+       case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+       case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
+               tick_broadcast_on_off(reason, dev);
+               break;
+
+       case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
+       case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
+               tick_broadcast_oneshot_control(reason);
+               break;
+
+       case CLOCK_EVT_NOTIFY_CPU_DEAD:
+               tick_shutdown_broadcast_oneshot(dev);
+               tick_shutdown_broadcast(dev);
+               tick_shutdown(dev);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block tick_notifier = {
+       .notifier_call = tick_notify,
+};
+
+/**
+ * tick_init - initialize the tick control
+ *
+ * Register the notifier with the clockevents framework
+ */
+void __init tick_init(void)
+{
+       clockevents_register_notifier(&tick_notifier);
+}
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
new file mode 100644 (file)
index 0000000..54861a0
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * tick internal variable and functions used by low/high res code
+ */
+DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
+extern spinlock_t tick_device_lock;
+extern ktime_t tick_next_period;
+extern ktime_t tick_period;
+
+extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
+extern void tick_handle_periodic(struct clock_event_device *dev);
+
+/*
+ * NO_HZ / high resolution timer shared code
+ */
+#ifdef CONFIG_TICK_ONESHOT
+extern void tick_setup_oneshot(struct clock_event_device *newdev,
+                              void (*handler)(struct clock_event_device *),
+                              ktime_t nextevt);
+extern int tick_program_event(ktime_t expires, int force);
+extern void tick_oneshot_notify(void);
+extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
+
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+extern void tick_broadcast_oneshot_control(unsigned long reason);
+extern void tick_broadcast_switch_to_oneshot(void);
+extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+# else /* BROADCAST */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+       BUG();
+}
+static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline void tick_broadcast_switch_to_oneshot(void) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+# endif /* !BROADCAST */
+
+#else /* !ONESHOT */
+static inline
+void tick_setup_oneshot(struct clock_event_device *newdev,
+                       void (*handler)(struct clock_event_device *),
+                       ktime_t nextevt)
+{
+       BUG();
+}
+static inline int tick_program_event(ktime_t expires, int force)
+{
+       return 0;
+}
+static inline void tick_oneshot_notify(void) { }
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+       BUG();
+}
+static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+#endif /* !TICK_ONESHOT */
+
+/*
+ * Broadcasting support
+ */
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern int tick_do_broadcast(cpumask_t mask);
+
+extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
+extern int tick_check_broadcast_device(struct clock_event_device *dev);
+extern int tick_is_broadcast_device(struct clock_event_device *dev);
+extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
+extern void tick_shutdown_broadcast(unsigned int *cpup);
+
+extern void
+tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+
+#else /* !BROADCAST */
+
+static inline int tick_check_broadcast_device(struct clock_event_device *dev)
+{
+       return 0;
+}
+
+static inline int tick_is_broadcast_device(struct clock_event_device *dev)
+{
+       return 0;
+}
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
+                                            int cpu)
+{
+       return 0;
+}
+static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
+static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
+static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
+
+/*
+ * Set the periodic handler in non broadcast mode
+ */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev,
+                                            int broadcast)
+{
+       dev->event_handler = tick_handle_periodic;
+}
+#endif /* !BROADCAST */
+
+/*
+ * Check, if the device is functional or a dummy for broadcast
+ */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+       return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
new file mode 100644 (file)
index 0000000..2e8b7ff
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * linux/kernel/time/tick-oneshot.c
+ *
+ * This file contains functions which manage high resolution tick
+ * related events.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/**
+ * tick_program_event
+ */
+int tick_program_event(ktime_t expires, int force)
+{
+       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+       ktime_t now = ktime_get();
+
+       while (1) {
+               int ret = clockevents_program_event(dev, expires, now);
+
+               if (!ret || !force)
+                       return ret;
+               now = ktime_get();
+               expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
+       }
+}
+
+/**
+ * tick_setup_oneshot - setup the event device for oneshot mode (hres or nohz)
+ */
+void tick_setup_oneshot(struct clock_event_device *newdev,
+                       void (*handler)(struct clock_event_device *),
+                       ktime_t next_event)
+{
+       newdev->event_handler = handler;
+       clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
+       clockevents_program_event(newdev, next_event, ktime_get());
+}
+
+/**
+ * tick_switch_to_oneshot - switch to oneshot mode
+ */
+int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
+{
+       struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+       struct clock_event_device *dev = td->evtdev;
+
+       if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
+           !tick_device_is_functional(dev))
+               return -EINVAL;
+
+       td->mode = TICKDEV_MODE_ONESHOT;
+       dev->event_handler = handler;
+       clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+       tick_broadcast_switch_to_oneshot();
+       return 0;
+}
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+/**
+ * tick_init_highres - switch to high resolution mode
+ *
+ * Called with interrupts disabled.
+ */
+int tick_init_highres(void)
+{
+       return tick_switch_to_oneshot(hrtimer_interrupt);
+}
+#endif
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
new file mode 100644 (file)
index 0000000..95e41f7
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ *  linux/kernel/time/tick-sched.c
+ *
+ *  Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner
+ *
+ *  No idle tick implementation for low and high resolution timers
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/*
+ * Per cpu nohz control structure
+ */
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+
+/*
+ * The time, when the last jiffy update happened. Protected by xtime_lock.
+ */
+static ktime_t last_jiffies_update;
+
+struct tick_sched *tick_get_tick_sched(int cpu)
+{
+       return &per_cpu(tick_cpu_sched, cpu);
+}
+
+/*
+ * Must be called with interrupts disabled !
+ */
+static void tick_do_update_jiffies64(ktime_t now)
+{
+       unsigned long ticks = 0;
+       ktime_t delta;
+
+       /* Reevalute with xtime_lock held */
+       write_seqlock(&xtime_lock);
+
+       delta = ktime_sub(now, last_jiffies_update);
+       if (delta.tv64 >= tick_period.tv64) {
+
+               delta = ktime_sub(delta, tick_period);
+               last_jiffies_update = ktime_add(last_jiffies_update,
+                                               tick_period);
+
+               /* Slow path for long timeouts */
+               if (unlikely(delta.tv64 >= tick_period.tv64)) {
+                       s64 incr = ktime_to_ns(tick_period);
+
+                       ticks = ktime_divns(delta, incr);
+
+                       last_jiffies_update = ktime_add_ns(last_jiffies_update,
+                                                          incr * ticks);
+               }
+               do_timer(++ticks);
+       }
+       write_sequnlock(&xtime_lock);
+}
+
+/*
+ * Initialize and return retrieve the jiffies update.
+ */
+static ktime_t tick_init_jiffy_update(void)
+{
+       ktime_t period;
+
+       write_seqlock(&xtime_lock);
+       /* Did we start the jiffies update yet ? */
+       if (last_jiffies_update.tv64 == 0)
+               last_jiffies_update = tick_next_period;
+       period = last_jiffies_update;
+       write_sequnlock(&xtime_lock);
+       return period;
+}
+
+/*
+ * NOHZ - aka dynamic tick functionality
+ */
+#ifdef CONFIG_NO_HZ
+/*
+ * NO HZ enabled ?
+ */
+static int tick_nohz_enabled __read_mostly  = 1;
+
+/*
+ * Enable / Disable tickless mode
+ */
+static int __init setup_tick_nohz(char *str)
+{
+       if (!strcmp(str, "off"))
+               tick_nohz_enabled = 0;
+       else if (!strcmp(str, "on"))
+               tick_nohz_enabled = 1;
+       else
+               return 0;
+       return 1;
+}
+
+__setup("nohz=", setup_tick_nohz);
+
+/**
+ * tick_nohz_update_jiffies - update jiffies when idle was interrupted
+ *
+ * Called from interrupt entry when the CPU was idle
+ *
+ * In case the sched_tick was stopped on this CPU, we have to check if jiffies
+ * must be updated. Otherwise an interrupt handler could use a stale jiffy
+ * value. We do this unconditionally on any cpu, as we don't know whether the
+ * cpu, which has the update task assigned is in a long sleep.
+ */
+void tick_nohz_update_jiffies(void)
+{
+       int cpu = smp_processor_id();
+       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+       unsigned long flags;
+       ktime_t now;
+
+       if (!ts->tick_stopped)
+               return;
+
+       cpu_clear(cpu, nohz_cpu_mask);
+       now = ktime_get();
+
+       local_irq_save(flags);
+       tick_do_update_jiffies64(now);
+       local_irq_restore(flags);
+}
+
+/**
+ * tick_nohz_stop_sched_tick - stop the idle tick from the idle task
+ *
+ * When the next event is more than a tick into the future, stop the idle tick
+ * Called either from the idle loop or from irq_exit() when an idle period was
+ * just interrupted by an interrupt which did not cause a reschedule.
+ */
+void tick_nohz_stop_sched_tick(void)
+{
+       unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
+       struct tick_sched *ts;
+       ktime_t last_update, expires, now, delta;
+       int cpu;
+
+       local_irq_save(flags);
+
+       cpu = smp_processor_id();
+       ts = &per_cpu(tick_cpu_sched, cpu);
+
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+               goto end;
+
+       if (need_resched())
+               goto end;
+
+       cpu = smp_processor_id();
+       BUG_ON(local_softirq_pending());
+
+       now = ktime_get();
+       /*
+        * When called from irq_exit we need to account the idle sleep time
+        * correctly.
+        */
+       if (ts->tick_stopped) {
+               delta = ktime_sub(now, ts->idle_entrytime);
+               ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
+       }
+
+       ts->idle_entrytime = now;
+       ts->idle_calls++;
+
+       /* Read jiffies and the time when jiffies were updated last */
+       do {
+               seq = read_seqbegin(&xtime_lock);
+               last_update = last_jiffies_update;
+               last_jiffies = jiffies;
+       } while (read_seqretry(&xtime_lock, seq));
+
+       /* Get the next timer wheel timer */
+       next_jiffies = get_next_timer_interrupt(last_jiffies);
+       delta_jiffies = next_jiffies - last_jiffies;
+
+       /*
+        * Do not stop the tick, if we are only one off
+        * or if the cpu is required for rcu
+        */
+       if (!ts->tick_stopped && (delta_jiffies == 1 || rcu_needs_cpu(cpu)))
+               goto out;
+
+       /* Schedule the tick, if we are at least one jiffie off */
+       if ((long)delta_jiffies >= 1) {
+
+               if (rcu_needs_cpu(cpu))
+                       delta_jiffies = 1;
+               else
+                       cpu_set(cpu, nohz_cpu_mask);
+               /*
+                * nohz_stop_sched_tick can be called several times before
+                * the nohz_restart_sched_tick is called. This happens when
+                * interrupts arrive which do not cause a reschedule. In the
+                * first call we save the current tick time, so we can restart
+                * the scheduler tick in nohz_restart_sched_tick.
+                */
+               if (!ts->tick_stopped) {
+                       ts->idle_tick = ts->sched_timer.expires;
+                       ts->tick_stopped = 1;
+                       ts->idle_jiffies = last_jiffies;
+               }
+               /*
+                * calculate the expiry time for the next timer wheel
+                * timer
+                */
+               expires = ktime_add_ns(last_update, tick_period.tv64 *
+                                      delta_jiffies);
+               ts->idle_expires = expires;
+               ts->idle_sleeps++;
+
+               if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
+                       hrtimer_start(&ts->sched_timer, expires,
+                                     HRTIMER_MODE_ABS);
+                       /* Check, if the timer was already in the past */
+                       if (hrtimer_active(&ts->sched_timer))
+                               goto out;
+               } else if(!tick_program_event(expires, 0))
+                               goto out;
+               /*
+                * We are past the event already. So we crossed a
+                * jiffie boundary. Update jiffies and raise the
+                * softirq.
+                */
+               tick_do_update_jiffies64(ktime_get());
+               cpu_clear(cpu, nohz_cpu_mask);
+       }
+       raise_softirq_irqoff(TIMER_SOFTIRQ);
+out:
+       ts->next_jiffies = next_jiffies;
+       ts->last_jiffies = last_jiffies;
+end:
+       local_irq_restore(flags);
+}
+
+/**
+ * nohz_restart_sched_tick - restart the idle tick from the idle task
+ *
+ * Restart the idle tick when the CPU is woken up from idle
+ */
+void tick_nohz_restart_sched_tick(void)
+{
+       int cpu = smp_processor_id();
+       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+       unsigned long ticks;
+       ktime_t now, delta;
+
+       if (!ts->tick_stopped)
+               return;
+
+       /* Update jiffies first */
+       now = ktime_get();
+
+       local_irq_disable();
+       tick_do_update_jiffies64(now);
+       cpu_clear(cpu, nohz_cpu_mask);
+
+       /* Account the idle time */
+       delta = ktime_sub(now, ts->idle_entrytime);
+       ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
+
+       /*
+        * We stopped the tick in idle. Update process times would miss the
+        * time we slept as update_process_times does only a 1 tick
+        * accounting. Enforce that this is accounted to idle !
+        */
+       ticks = jiffies - ts->idle_jiffies;
+       /*
+        * We might be one off. Do not randomly account a huge number of ticks!
+        */
+       if (ticks && ticks < LONG_MAX) {
+               add_preempt_count(HARDIRQ_OFFSET);
+               account_system_time(current, HARDIRQ_OFFSET,
+                                   jiffies_to_cputime(ticks));
+               sub_preempt_count(HARDIRQ_OFFSET);
+       }
+
+       /*
+        * Cancel the scheduled timer and restore the tick
+        */
+       ts->tick_stopped  = 0;
+       hrtimer_cancel(&ts->sched_timer);
+       ts->sched_timer.expires = ts->idle_tick;
+
+       while (1) {
+               /* Forward the time to expire in the future */
+               hrtimer_forward(&ts->sched_timer, now, tick_period);
+
+               if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
+                       hrtimer_start(&ts->sched_timer,
+                                     ts->sched_timer.expires,
+                                     HRTIMER_MODE_ABS);
+                       /* Check, if the timer was already in the past */
+                       if (hrtimer_active(&ts->sched_timer))
+                               break;
+               } else {
+                       if (!tick_program_event(ts->sched_timer.expires, 0))
+                               break;
+               }
+               /* Update jiffies and reread time */
+               tick_do_update_jiffies64(now);
+               now = ktime_get();
+       }
+       local_irq_enable();
+}
+
+static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now)
+{
+       hrtimer_forward(&ts->sched_timer, now, tick_period);
+       return tick_program_event(ts->sched_timer.expires, 0);
+}
+
+/*
+ * The nohz low res interrupt handler
+ */
+static void tick_nohz_handler(struct clock_event_device *dev)
+{
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+       struct pt_regs *regs = get_irq_regs();
+       ktime_t now = ktime_get();
+
+       dev->next_event.tv64 = KTIME_MAX;
+
+       /* Check, if the jiffies need an update */
+       tick_do_update_jiffies64(now);
+
+       /*
+        * When we are idle and the tick is stopped, we have to touch
+        * the watchdog as we might not schedule for a really long
+        * time. This happens on complete idle SMP systems while
+        * waiting on the login prompt. We also increment the "start
+        * of idle" jiffy stamp so the idle accounting adjustment we
+        * do when we go busy again does not account too much ticks.
+        */
+       if (ts->tick_stopped) {
+               touch_softlockup_watchdog();
+               ts->idle_jiffies++;
+       }
+
+       update_process_times(user_mode(regs));
+       profile_tick(CPU_PROFILING);
+
+       /* Do not restart, when we are in the idle loop */
+       if (ts->tick_stopped)
+               return;
+
+       while (tick_nohz_reprogram(ts, now)) {
+               now = ktime_get();
+               tick_do_update_jiffies64(now);
+       }
+}
+
+/**
+ * tick_nohz_switch_to_nohz - switch to nohz mode
+ */
+static void tick_nohz_switch_to_nohz(void)
+{
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+       ktime_t next;
+
+       if (!tick_nohz_enabled)
+               return;
+
+       local_irq_disable();
+       if (tick_switch_to_oneshot(tick_nohz_handler)) {
+               local_irq_enable();
+               return;
+       }
+
+       ts->nohz_mode = NOHZ_MODE_LOWRES;
+
+       /*
+        * Recycle the hrtimer in ts, so we can share the
+        * hrtimer_forward with the highres code.
+        */
+       hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       /* Get the next period */
+       next = tick_init_jiffy_update();
+
+       for (;;) {
+               ts->sched_timer.expires = next;
+               if (!tick_program_event(next, 0))
+                       break;
+               next = ktime_add(next, tick_period);
+       }
+       local_irq_enable();
+
+       printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n",
+              smp_processor_id());
+}
+
+#else
+
+static inline void tick_nohz_switch_to_nohz(void) { }
+
+#endif /* NO_HZ */
+
+/*
+ * High resolution timer specific code
+ */
+#ifdef CONFIG_HIGH_RES_TIMERS
+/*
+ * We rearm the timer until we get disabled by the idle code
+ * Called with interrupts disabled and timer->base->cpu_base->lock held.
+ */
+static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
+{
+       struct tick_sched *ts =
+               container_of(timer, struct tick_sched, sched_timer);
+       struct hrtimer_cpu_base *base = timer->base->cpu_base;
+       struct pt_regs *regs = get_irq_regs();
+       ktime_t now = ktime_get();
+
+       /* Check, if the jiffies need an update */
+       tick_do_update_jiffies64(now);
+
+       /*
+        * Do not call, when we are not in irq context and have
+        * no valid regs pointer
+        */
+       if (regs) {
+               /*
+                * When we are idle and the tick is stopped, we have to touch
+                * the watchdog as we might not schedule for a really long
+                * time. This happens on complete idle SMP systems while
+                * waiting on the login prompt. We also increment the "start of
+                * idle" jiffy stamp so the idle accounting adjustment we do
+                * when we go busy again does not account too much ticks.
+                */
+               if (ts->tick_stopped) {
+                       touch_softlockup_watchdog();
+                       ts->idle_jiffies++;
+               }
+               /*
+                * update_process_times() might take tasklist_lock, hence
+                * drop the base lock. sched-tick hrtimers are per-CPU and
+                * never accessible by userspace APIs, so this is safe to do.
+                */
+               spin_unlock(&base->lock);
+               update_process_times(user_mode(regs));
+               profile_tick(CPU_PROFILING);
+               spin_lock(&base->lock);
+       }
+
+       /* Do not restart, when we are in the idle loop */
+       if (ts->tick_stopped)
+               return HRTIMER_NORESTART;
+
+       hrtimer_forward(timer, now, tick_period);
+
+       return HRTIMER_RESTART;
+}
+
+/**
+ * tick_setup_sched_timer - setup the tick emulation timer
+ */
+void tick_setup_sched_timer(void)
+{
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+       ktime_t now = ktime_get();
+
+       /*
+        * Emulate tick processing via per-CPU hrtimers:
+        */
+       hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       ts->sched_timer.function = tick_sched_timer;
+       ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+
+       /* Get the next period */
+       ts->sched_timer.expires = tick_init_jiffy_update();
+
+       for (;;) {
+               hrtimer_forward(&ts->sched_timer, now, tick_period);
+               hrtimer_start(&ts->sched_timer, ts->sched_timer.expires,
+                             HRTIMER_MODE_ABS);
+               /* Check, if the timer was already in the past */
+               if (hrtimer_active(&ts->sched_timer))
+                       break;
+               now = ktime_get();
+       }
+
+#ifdef CONFIG_NO_HZ
+       if (tick_nohz_enabled)
+               ts->nohz_mode = NOHZ_MODE_HIGHRES;
+#endif
+}
+
+void tick_cancel_sched_timer(int cpu)
+{
+       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+
+       if (ts->sched_timer.base)
+               hrtimer_cancel(&ts->sched_timer);
+       ts->tick_stopped = 0;
+       ts->nohz_mode = NOHZ_MODE_INACTIVE;
+}
+#endif /* HIGH_RES_TIMERS */
+
+/**
+ * Async notification about clocksource changes
+ */
+void tick_clock_notify(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               set_bit(0, &per_cpu(tick_cpu_sched, cpu).check_clocks);
+}
+
+/*
+ * Async notification about clock event changes
+ */
+void tick_oneshot_notify(void)
+{
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+
+       set_bit(0, &ts->check_clocks);
+}
+
+/**
+ * Check, if a change happened, which makes oneshot possible.
+ *
+ * Called cyclic from the hrtimer softirq (driven by the timer
+ * softirq) allow_nohz signals, that we can switch into low-res nohz
+ * mode, because high resolution timers are disabled (either compile
+ * or runtime).
+ */
+int tick_check_oneshot_change(int allow_nohz)
+{
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+
+       if (!test_and_clear_bit(0, &ts->check_clocks))
+               return 0;
+
+       if (ts->nohz_mode != NOHZ_MODE_INACTIVE)
+               return 0;
+
+       if (!timekeeping_is_continuous() || !tick_is_oneshot_available())
+               return 0;
+
+       if (!allow_nohz)
+               return 1;
+
+       tick_nohz_switch_to_nohz();
+       return 0;
+}
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
new file mode 100644 (file)
index 0000000..f82c635
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * kernel/time/timer_list.c
+ *
+ * List pending timers
+ *
+ * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/tick.h>
+
+#include <asm/uaccess.h>
+
+typedef void (*print_fn_t)(struct seq_file *m, unsigned int *classes);
+
+DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
+
+/*
+ * This allows printing both to /proc/timer_list and
+ * to the console (on SysRq-Q):
+ */
+#define SEQ_printf(m, x...)                    \
+ do {                                          \
+       if (m)                                  \
+               seq_printf(m, x);               \
+       else                                    \
+               printk(x);                      \
+ } while (0)
+
+static void print_name_offset(struct seq_file *m, void *sym)
+{
+       unsigned long addr = (unsigned long)sym;
+       char namebuf[KSYM_NAME_LEN+1];
+       unsigned long size, offset;
+       const char *sym_name;
+       char *modname;
+
+       sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
+       if (sym_name)
+               SEQ_printf(m, "%s", sym_name);
+       else
+               SEQ_printf(m, "<%p>", sym);
+}
+
+static void
+print_timer(struct seq_file *m, struct hrtimer *timer, int idx, u64 now)
+{
+#ifdef CONFIG_TIMER_STATS
+       char tmp[TASK_COMM_LEN + 1];
+#endif
+       SEQ_printf(m, " #%d: ", idx);
+       print_name_offset(m, timer);
+       SEQ_printf(m, ", ");
+       print_name_offset(m, timer->function);
+       SEQ_printf(m, ", S:%02lx", timer->state);
+#ifdef CONFIG_TIMER_STATS
+       SEQ_printf(m, ", ");
+       print_name_offset(m, timer->start_site);
+       memcpy(tmp, timer->start_comm, TASK_COMM_LEN);
+       tmp[TASK_COMM_LEN] = 0;
+       SEQ_printf(m, ", %s/%d", tmp, timer->start_pid);
+#endif
+       SEQ_printf(m, "\n");
+       SEQ_printf(m, " # expires at %Ld nsecs [in %Ld nsecs]\n",
+               (unsigned long long)ktime_to_ns(timer->expires),
+               (unsigned long long)(ktime_to_ns(timer->expires) - now));
+}
+
+static void
+print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base,
+                   u64 now)
+{
+       struct hrtimer *timer, tmp;
+       unsigned long next = 0, i;
+       struct rb_node *curr;
+       unsigned long flags;
+
+next_one:
+       i = 0;
+       spin_lock_irqsave(&base->cpu_base->lock, flags);
+
+       curr = base->first;
+       /*
+        * Crude but we have to do this O(N*N) thing, because
+        * we have to unlock the base when printing:
+        */
+       while (curr && i < next) {
+               curr = rb_next(curr);
+               i++;
+       }
+
+       if (curr) {
+
+               timer = rb_entry(curr, struct hrtimer, node);
+               tmp = *timer;
+               spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+
+               print_timer(m, &tmp, i, now);
+               next++;
+               goto next_one;
+       }
+       spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+}
+
+static void
+print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
+{
+       SEQ_printf(m, "  .index:      %d\n",
+                       base->index);
+       SEQ_printf(m, "  .resolution: %Ld nsecs\n",
+                       (unsigned long long)ktime_to_ns(base->resolution));
+       SEQ_printf(m,   "  .get_time:   ");
+       print_name_offset(m, base->get_time);
+       SEQ_printf(m,   "\n");
+#ifdef CONFIG_HIGH_RES_TIMERS
+       SEQ_printf(m, "  .offset:     %Ld nsecs\n",
+                       ktime_to_ns(base->offset));
+#endif
+       SEQ_printf(m,   "active timers:\n");
+       print_active_timers(m, base, now);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+       struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
+       int i;
+
+       SEQ_printf(m, "\ncpu: %d\n", cpu);
+       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+               SEQ_printf(m, " clock %d:\n", i);
+               print_base(m, cpu_base->clock_base + i, now);
+       }
+#define P(x) \
+       SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(cpu_base->x))
+#define P_ns(x) \
+       SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
+               (u64)(ktime_to_ns(cpu_base->x)))
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+       P_ns(expires_next);
+       P(hres_active);
+       P(nr_events);
+#endif
+#undef P
+#undef P_ns
+
+#ifdef CONFIG_TICK_ONESHOT
+# define P(x) \
+       SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(ts->x))
+# define P_ns(x) \
+       SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
+               (u64)(ktime_to_ns(ts->x)))
+       {
+               struct tick_sched *ts = tick_get_tick_sched(cpu);
+               P(nohz_mode);
+               P_ns(idle_tick);
+               P(tick_stopped);
+               P(idle_jiffies);
+               P(idle_calls);
+               P(idle_sleeps);
+               P_ns(idle_entrytime);
+               P_ns(idle_sleeptime);
+               P(last_jiffies);
+               P(next_jiffies);
+               P_ns(idle_expires);
+               SEQ_printf(m, "jiffies: %Ld\n", (u64)jiffies);
+       }
+#endif
+
+#undef P
+#undef P_ns
+}
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+static void
+print_tickdevice(struct seq_file *m, struct tick_device *td)
+{
+       struct clock_event_device *dev = td->evtdev;
+
+       SEQ_printf(m, "\nTick Device: mode:     %d\n", td->mode);
+
+       SEQ_printf(m, "Clock Event Device: ");
+       if (!dev) {
+               SEQ_printf(m, "<NULL>\n");
+               return;
+       }
+       SEQ_printf(m, "%s\n", dev->name);
+       SEQ_printf(m, " max_delta_ns:   %ld\n", dev->max_delta_ns);
+       SEQ_printf(m, " min_delta_ns:   %ld\n", dev->min_delta_ns);
+       SEQ_printf(m, " mult:           %ld\n", dev->mult);
+       SEQ_printf(m, " shift:          %d\n", dev->shift);
+       SEQ_printf(m, " mode:           %d\n", dev->mode);
+       SEQ_printf(m, " next_event:     %Ld nsecs\n",
+                  (unsigned long long) ktime_to_ns(dev->next_event));
+
+       SEQ_printf(m, " set_next_event: ");
+       print_name_offset(m, dev->set_next_event);
+       SEQ_printf(m, "\n");
+
+       SEQ_printf(m, " set_mode:       ");
+       print_name_offset(m, dev->set_mode);
+       SEQ_printf(m, "\n");
+
+       SEQ_printf(m, " event_handler:  ");
+       print_name_offset(m, dev->event_handler);
+       SEQ_printf(m, "\n");
+}
+
+static void timer_list_show_tickdevices(struct seq_file *m)
+{
+       int cpu;
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+       print_tickdevice(m, tick_get_broadcast_device());
+       SEQ_printf(m, "tick_broadcast_mask: %08lx\n",
+                  tick_get_broadcast_mask()->bits[0]);
+#ifdef CONFIG_TICK_ONESHOT
+       SEQ_printf(m, "tick_broadcast_oneshot_mask: %08lx\n",
+                  tick_get_broadcast_oneshot_mask()->bits[0]);
+#endif
+       SEQ_printf(m, "\n");
+#endif
+       for_each_online_cpu(cpu)
+                  print_tickdevice(m, tick_get_device(cpu));
+       SEQ_printf(m, "\n");
+}
+#else
+static void timer_list_show_tickdevices(struct seq_file *m) { }
+#endif
+
+static int timer_list_show(struct seq_file *m, void *v)
+{
+       u64 now = ktime_to_ns(ktime_get());
+       int cpu;
+
+       SEQ_printf(m, "Timer List Version: v0.3\n");
+       SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
+       SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
+
+       for_each_online_cpu(cpu)
+               print_cpu(m, cpu, now);
+
+       SEQ_printf(m, "\n");
+       timer_list_show_tickdevices(m);
+
+       return 0;
+}
+
+void sysrq_timer_list_show(void)
+{
+       timer_list_show(NULL, NULL);
+}
+
+static int timer_list_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, timer_list_show, NULL);
+}
+
+static struct file_operations timer_list_fops = {
+       .open           = timer_list_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init init_timer_list_procfs(void)
+{
+       struct proc_dir_entry *pe;
+
+       pe = create_proc_entry("timer_list", 0644, NULL);
+       if (!pe)
+               return -ENOMEM;
+
+       pe->proc_fops = &timer_list_fops;
+
+       return 0;
+}
+__initcall(init_timer_list_procfs);
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
new file mode 100644 (file)
index 0000000..1bc4882
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * kernel/time/timer_stats.c
+ *
+ * Collect timer usage statistics.
+ *
+ * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * timer_stats is based on timer_top, a similar functionality which was part of
+ * Con Kolivas dyntick patch set. It was developed by Daniel Petrini at the
+ * Instituto Nokia de Tecnologia - INdT - Manaus. timer_top's design was based
+ * on dynamic allocation of the statistics entries and linear search based
+ * lookup combined with a global lock, rather than the static array, hash
+ * and per-CPU locking which is used by timer_stats. It was written for the
+ * pre hrtimer kernel code and therefore did not take hrtimers into account.
+ * Nevertheless it provided the base for the timer_stats implementation and
+ * was a helpful source of inspiration. Kudos to Daniel and the Nokia folks
+ * for this effort.
+ *
+ * timer_top.c is
+ *     Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus
+ *     Written by Daniel Petrini <d.pensator@gmail.com>
+ *     timer_top.c was released under the GNU General Public License version 2
+ *
+ * We export the addresses and counting of timer functions being called,
+ * the pid and cmdline from the owner process if applicable.
+ *
+ * Start/stop data collection:
+ * # echo 1[0] >/proc/timer_stats
+ *
+ * Display the information collected so far:
+ * # cat /proc/timer_stats
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+
+#include <asm/uaccess.h>
+
+/*
+ * This is our basic unit of interest: a timer expiry event identified
+ * by the timer, its start/expire functions and the PID of the task that
+ * started the timer. We count the number of times an event happens:
+ */
+struct entry {
+       /*
+        * Hash list:
+        */
+       struct entry            *next;
+
+       /*
+        * Hash keys:
+        */
+       void                    *timer;
+       void                    *start_func;
+       void                    *expire_func;
+       pid_t                   pid;
+
+       /*
+        * Number of timeout events:
+        */
+       unsigned long           count;
+
+       /*
+        * We save the command-line string to preserve
+        * this information past task exit:
+        */
+       char                    comm[TASK_COMM_LEN + 1];
+
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Spinlock protecting the tables - not taken during lookup:
+ */
+static DEFINE_SPINLOCK(table_lock);
+
+/*
+ * Per-CPU lookup locks for fast hash lookup:
+ */
+static DEFINE_PER_CPU(spinlock_t, lookup_lock);
+
+/*
+ * Mutex to serialize state changes with show-stats activities:
+ */
+static DEFINE_MUTEX(show_mutex);
+
+/*
+ * Collection status, active/inactive:
+ */
+static int __read_mostly active;
+
+/*
+ * Beginning/end timestamps of measurement:
+ */
+static ktime_t time_start, time_stop;
+
+/*
+ * tstat entry structs only get allocated while collection is
+ * active and never freed during that time - this simplifies
+ * things quite a bit.
+ *
+ * They get freed when a new collection period is started.
+ */
+#define MAX_ENTRIES_BITS       10
+#define MAX_ENTRIES            (1UL << MAX_ENTRIES_BITS)
+
+static unsigned long nr_entries;
+static struct entry entries[MAX_ENTRIES];
+
+static atomic_t overflow_count;
+
+static void reset_entries(void)
+{
+       nr_entries = 0;
+       memset(entries, 0, sizeof(entries));
+       atomic_set(&overflow_count, 0);
+}
+
+static struct entry *alloc_entry(void)
+{
+       if (nr_entries >= MAX_ENTRIES)
+               return NULL;
+
+       return entries + nr_entries++;
+}
+
+/*
+ * The entries are in a hash-table, for fast lookup:
+ */
+#define TSTAT_HASH_BITS                (MAX_ENTRIES_BITS - 1)
+#define TSTAT_HASH_SIZE                (1UL << TSTAT_HASH_BITS)
+#define TSTAT_HASH_MASK                (TSTAT_HASH_SIZE - 1)
+
+#define __tstat_hashfn(entry)                                          \
+       (((unsigned long)(entry)->timer       ^                         \
+         (unsigned long)(entry)->start_func  ^                         \
+         (unsigned long)(entry)->expire_func ^                         \
+         (unsigned long)(entry)->pid           ) & TSTAT_HASH_MASK)
+
+#define tstat_hashentry(entry) (tstat_hash_table + __tstat_hashfn(entry))
+
+static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
+
+static int match_entries(struct entry *entry1, struct entry *entry2)
+{
+       return entry1->timer       == entry2->timer       &&
+              entry1->start_func  == entry2->start_func  &&
+              entry1->expire_func == entry2->expire_func &&
+              entry1->pid         == entry2->pid;
+}
+
+/*
+ * Look up whether an entry matching this item is present
+ * in the hash already. Must be called with irqs off and the
+ * lookup lock held:
+ */
+static struct entry *tstat_lookup(struct entry *entry, char *comm)
+{
+       struct entry **head, *curr, *prev;
+
+       head = tstat_hashentry(entry);
+       curr = *head;
+
+       /*
+        * The fastpath is when the entry is already hashed,
+        * we do this with the lookup lock held, but with the
+        * table lock not held:
+        */
+       while (curr) {
+               if (match_entries(curr, entry))
+                       return curr;
+
+               curr = curr->next;
+       }
+       /*
+        * Slowpath: allocate, set up and link a new hash entry:
+        */
+       prev = NULL;
+       curr = *head;
+
+       spin_lock(&table_lock);
+       /*
+        * Make sure we have not raced with another CPU:
+        */
+       while (curr) {
+               if (match_entries(curr, entry))
+                       goto out_unlock;
+
+               prev = curr;
+               curr = curr->next;
+       }
+
+       curr = alloc_entry();
+       if (curr) {
+               *curr = *entry;
+               curr->count = 0;
+               memcpy(curr->comm, comm, TASK_COMM_LEN);
+               if (prev)
+                       prev->next = curr;
+               else
+                       *head = curr;
+               curr->next = NULL;
+       }
+ out_unlock:
+       spin_unlock(&table_lock);
+
+       return curr;
+}
+
+/**
+ * timer_stats_update_stats - Update the statistics for a timer.
+ * @timer:     pointer to either a timer_list or a hrtimer
+ * @pid:       the pid of the task which set up the timer
+ * @startf:    pointer to the function which did the timer setup
+ * @timerf:    pointer to the timer callback function of the timer
+ * @comm:      name of the process which set up the timer
+ *
+ * When the timer is already registered, then the event counter is
+ * incremented. Otherwise the timer is registered in a free slot.
+ */
+void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+                             void *timerf, char * comm)
+{
+       /*
+        * It doesnt matter which lock we take:
+        */
+       spinlock_t *lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+       struct entry *entry, input;
+       unsigned long flags;
+
+       input.timer = timer;
+       input.start_func = startf;
+       input.expire_func = timerf;
+       input.pid = pid;
+
+       spin_lock_irqsave(lock, flags);
+       if (!active)
+               goto out_unlock;
+
+       entry = tstat_lookup(&input, comm);
+       if (likely(entry))
+               entry->count++;
+       else
+               atomic_inc(&overflow_count);
+
+ out_unlock:
+       spin_unlock_irqrestore(lock, flags);
+}
+
+static void print_name_offset(struct seq_file *m, unsigned long addr)
+{
+       char namebuf[KSYM_NAME_LEN+1];
+       unsigned long size, offset;
+       const char *sym_name;
+       char *modname;
+
+       sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
+       if (sym_name)
+               seq_printf(m, "%s", sym_name);
+       else
+               seq_printf(m, "<%p>", (void *)addr);
+}
+
+static int tstats_show(struct seq_file *m, void *v)
+{
+       struct timespec period;
+       struct entry *entry;
+       unsigned long ms;
+       long events = 0;
+       ktime_t time;
+       int i;
+
+       mutex_lock(&show_mutex);
+       /*
+        * If still active then calculate up to now:
+        */
+       if (active)
+               time_stop = ktime_get();
+
+       time = ktime_sub(time_stop, time_start);
+
+       period = ktime_to_timespec(time);
+       ms = period.tv_nsec / 1000000;
+
+       seq_puts(m, "Timer Stats Version: v0.1\n");
+       seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
+       if (atomic_read(&overflow_count))
+               seq_printf(m, "Overflow: %d entries\n",
+                       atomic_read(&overflow_count));
+
+       for (i = 0; i < nr_entries; i++) {
+               entry = entries + i;
+               seq_printf(m, "%4lu, %5d %-16s ",
+                               entry->count, entry->pid, entry->comm);
+
+               print_name_offset(m, (unsigned long)entry->start_func);
+               seq_puts(m, " (");
+               print_name_offset(m, (unsigned long)entry->expire_func);
+               seq_puts(m, ")\n");
+
+               events += entry->count;
+       }
+
+       ms += period.tv_sec * 1000;
+       if (!ms)
+               ms = 1;
+
+       if (events && period.tv_sec)
+               seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events,
+                          events / period.tv_sec, events * 1000 / ms);
+       else
+               seq_printf(m, "%ld total events\n", events);
+
+       mutex_unlock(&show_mutex);
+
+       return 0;
+}
+
+/*
+ * After a state change, make sure all concurrent lookup/update
+ * activities have stopped:
+ */
+static void sync_access(void)
+{
+       unsigned long flags;
+       int cpu;
+
+       for_each_online_cpu(cpu) {
+               spin_lock_irqsave(&per_cpu(lookup_lock, cpu), flags);
+               /* nothing */
+               spin_unlock_irqrestore(&per_cpu(lookup_lock, cpu), flags);
+       }
+}
+
+static ssize_t tstats_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *offs)
+{
+       char ctl[2];
+
+       if (count != 2 || *offs)
+               return -EINVAL;
+
+       if (copy_from_user(ctl, buf, count))
+               return -EFAULT;
+
+       mutex_lock(&show_mutex);
+       switch (ctl[0]) {
+       case '0':
+               if (active) {
+                       active = 0;
+                       time_stop = ktime_get();
+                       sync_access();
+               }
+               break;
+       case '1':
+               if (!active) {
+                       reset_entries();
+                       time_start = ktime_get();
+                       active = 1;
+               }
+               break;
+       default:
+               count = -EINVAL;
+       }
+       mutex_unlock(&show_mutex);
+
+       return count;
+}
+
+static int tstats_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, tstats_show, NULL);
+}
+
+static struct file_operations tstats_fops = {
+       .open           = tstats_open,
+       .read           = seq_read,
+       .write          = tstats_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+void __init init_timer_stats(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               spin_lock_init(&per_cpu(lookup_lock, cpu));
+}
+
+static int __init init_tstats_procfs(void)
+{
+       struct proc_dir_entry *pe;
+
+       pe = create_proc_entry("timer_stats", 0644, NULL);
+       if (!pe)
+               return -ENOMEM;
+
+       pe->proc_fops = &tstats_fops;
+
+       return 0;
+}
+__initcall(init_tstats_procfs);
index 8533c379608281070f7d74c6afcef953ccfd4327..cb1b86a9c52f5749f767625ffe6f6895f4b476aa 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
+#include <linux/tick.h>
+#include <linux/kallsyms.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -262,6 +264,18 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
+#ifdef CONFIG_TIMER_STATS
+void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
+{
+       if (timer->start_site)
+               return;
+
+       timer->start_site = addr;
+       memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
+       timer->start_pid = current->pid;
+}
+#endif
+
 /**
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
@@ -273,11 +287,16 @@ void fastcall init_timer(struct timer_list *timer)
 {
        timer->entry.next = NULL;
        timer->base = __raw_get_cpu_var(tvec_bases);
+#ifdef CONFIG_TIMER_STATS
+       timer->start_site = NULL;
+       timer->start_pid = -1;
+       memset(timer->start_comm, 0, TASK_COMM_LEN);
+#endif
 }
 EXPORT_SYMBOL(init_timer);
 
 static inline void detach_timer(struct timer_list *timer,
-                                       int clear_pending)
+                               int clear_pending)
 {
        struct list_head *entry = &timer->entry;
 
@@ -324,6 +343,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
        unsigned long flags;
        int ret = 0;
 
+       timer_stats_timer_set_start_info(timer);
        BUG_ON(!timer->function);
 
        base = lock_timer_base(timer, &flags);
@@ -374,6 +394,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
        tvec_base_t *base = per_cpu(tvec_bases, cpu);
        unsigned long flags;
 
+       timer_stats_timer_set_start_info(timer);
        BUG_ON(timer_pending(timer) || !timer->function);
        spin_lock_irqsave(&base->lock, flags);
        timer->base = base;
@@ -406,6 +427,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
 {
        BUG_ON(!timer->function);
 
+       timer_stats_timer_set_start_info(timer);
        /*
         * This is a common optimization triggered by the
         * networking code - if the timer is re-modified
@@ -436,6 +458,7 @@ int del_timer(struct timer_list *timer)
        unsigned long flags;
        int ret = 0;
 
+       timer_stats_timer_clear_start_info(timer);
        if (timer_pending(timer)) {
                base = lock_timer_base(timer, &flags);
                if (timer_pending(timer)) {
@@ -569,6 +592,8 @@ static inline void __run_timers(tvec_base_t *base)
                        fn = timer->function;
                        data = timer->data;
 
+                       timer_stats_account_timer(timer);
+
                        set_running_timer(base, timer);
                        detach_timer(timer, 1);
                        spin_unlock_irq(&base->lock);
@@ -591,105 +616,124 @@ static inline void __run_timers(tvec_base_t *base)
        spin_unlock_irq(&base->lock);
 }
 
-#ifdef CONFIG_NO_IDLE_HZ
+#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
 /*
  * Find out when the next timer event is due to happen. This
  * is used on S/390 to stop all activity when a cpus is idle.
  * This functions needs to be called disabled.
  */
-unsigned long next_timer_interrupt(void)
+static unsigned long __next_timer_interrupt(tvec_base_t *base)
 {
-       tvec_base_t *base;
-       struct list_head *list;
+       unsigned long timer_jiffies = base->timer_jiffies;
+       unsigned long expires = timer_jiffies + (LONG_MAX >> 1);
+       int index, slot, array, found = 0;
        struct timer_list *nte;
-       unsigned long expires;
-       unsigned long hr_expires = MAX_JIFFY_OFFSET;
-       ktime_t hr_delta;
        tvec_t *varray[4];
-       int i, j;
-
-       hr_delta = hrtimer_get_next_event();
-       if (hr_delta.tv64 != KTIME_MAX) {
-               struct timespec tsdelta;
-               tsdelta = ktime_to_timespec(hr_delta);
-               hr_expires = timespec_to_jiffies(&tsdelta);
-               if (hr_expires < 3)
-                       return hr_expires + jiffies;
-       }
-       hr_expires += jiffies;
-
-       base = __get_cpu_var(tvec_bases);
-       spin_lock(&base->lock);
-       expires = base->timer_jiffies + (LONG_MAX >> 1);
-       list = NULL;
 
        /* Look for timer events in tv1. */
-       j = base->timer_jiffies & TVR_MASK;
+       index = slot = timer_jiffies & TVR_MASK;
        do {
-               list_for_each_entry(nte, base->tv1.vec + j, entry) {
+               list_for_each_entry(nte, base->tv1.vec + slot, entry) {
+                       found = 1;
                        expires = nte->expires;
-                       if (j < (base->timer_jiffies & TVR_MASK))
-                               list = base->tv2.vec + (INDEX(0));
-                       goto found;
+                       /* Look at the cascade bucket(s)? */
+                       if (!index || slot < index)
+                               goto cascade;
+                       return expires;
                }
-               j = (j + 1) & TVR_MASK;
-       } while (j != (base->timer_jiffies & TVR_MASK));
+               slot = (slot + 1) & TVR_MASK;
+       } while (slot != index);
+
+cascade:
+       /* Calculate the next cascade event */
+       if (index)
+               timer_jiffies += TVR_SIZE - index;
+       timer_jiffies >>= TVR_BITS;
 
        /* Check tv2-tv5. */
        varray[0] = &base->tv2;
        varray[1] = &base->tv3;
        varray[2] = &base->tv4;
        varray[3] = &base->tv5;
-       for (i = 0; i < 4; i++) {
-               j = INDEX(i);
+
+       for (array = 0; array < 4; array++) {
+               tvec_t *varp = varray[array];
+
+               index = slot = timer_jiffies & TVN_MASK;
                do {
-                       if (list_empty(varray[i]->vec + j)) {
-                               j = (j + 1) & TVN_MASK;
-                               continue;
-                       }
-                       list_for_each_entry(nte, varray[i]->vec + j, entry)
+                       list_for_each_entry(nte, varp->vec + slot, entry) {
+                               found = 1;
                                if (time_before(nte->expires, expires))
                                        expires = nte->expires;
-                       if (j < (INDEX(i)) && i < 3)
-                               list = varray[i + 1]->vec + (INDEX(i + 1));
-                       goto found;
-               } while (j != (INDEX(i)));
-       }
-found:
-       if (list) {
-               /*
-                * The search wrapped. We need to look at the next list
-                * from next tv element that would cascade into tv element
-                * where we found the timer element.
-                */
-               list_for_each_entry(nte, list, entry) {
-                       if (time_before(nte->expires, expires))
-                               expires = nte->expires;
-               }
+                       }
+                       /*
+                        * Do we still search for the first timer or are
+                        * we looking up the cascade buckets ?
+                        */
+                       if (found) {
+                               /* Look at the cascade bucket(s)? */
+                               if (!index || slot < index)
+                                       break;
+                               return expires;
+                       }
+                       slot = (slot + 1) & TVN_MASK;
+               } while (slot != index);
+
+               if (index)
+                       timer_jiffies += TVN_SIZE - index;
+               timer_jiffies >>= TVN_BITS;
        }
-       spin_unlock(&base->lock);
+       return expires;
+}
 
-       /*
-        * It can happen that other CPUs service timer IRQs and increment
-        * jiffies, but we have not yet got a local timer tick to process
-        * the timer wheels.  In that case, the expiry time can be before
-        * jiffies, but since the high-resolution timer here is relative to
-        * jiffies, the default expression when high-resolution timers are
-        * not active,
-        *
-        *   time_before(MAX_JIFFY_OFFSET + jiffies, expires)
-        *
-        * would falsely evaluate to true.  If that is the case, just
-        * return jiffies so that we can immediately fire the local timer
-        */
-       if (time_before(expires, jiffies))
-               return jiffies;
+/*
+ * Check, if the next hrtimer event is before the next timer wheel
+ * event:
+ */
+static unsigned long cmp_next_hrtimer_event(unsigned long now,
+                                           unsigned long expires)
+{
+       ktime_t hr_delta = hrtimer_get_next_event();
+       struct timespec tsdelta;
+
+       if (hr_delta.tv64 == KTIME_MAX)
+               return expires;
 
-       if (time_before(hr_expires, expires))
-               return hr_expires;
+       if (hr_delta.tv64 <= TICK_NSEC)
+               return now;
 
+       tsdelta = ktime_to_timespec(hr_delta);
+       now += timespec_to_jiffies(&tsdelta);
+       if (time_before(now, expires))
+               return now;
        return expires;
 }
+
+/**
+ * next_timer_interrupt - return the jiffy of the next pending timer
+ */
+unsigned long get_next_timer_interrupt(unsigned long now)
+{
+       tvec_base_t *base = __get_cpu_var(tvec_bases);
+       unsigned long expires;
+
+       spin_lock(&base->lock);
+       expires = __next_timer_interrupt(base);
+       spin_unlock(&base->lock);
+
+       if (time_before_eq(expires, now))
+               return now;
+
+       return cmp_next_hrtimer_event(now, expires);
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+unsigned long next_timer_interrupt(void)
+{
+       return get_next_timer_interrupt(jiffies);
+}
+#endif
+
 #endif
 
 /******************************************************************/
@@ -832,32 +876,35 @@ EXPORT_SYMBOL(do_settimeofday);
  *
  * Accumulates current time interval and initializes new clocksource
  */
-static int change_clocksource(void)
+static void change_clocksource(void)
 {
        struct clocksource *new;
        cycle_t now;
        u64 nsec;
+
        new = clocksource_get_next();
-       if (clock != new) {
-               now = clocksource_read(new);
-               nsec =  __get_nsec_offset();
-               timespec_add_ns(&xtime, nsec);
-
-               clock = new;
-               clock->cycle_last = now;
-               printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-                      clock->name);
-               return 1;
-       } else if (clock->update_callback) {
-               return clock->update_callback();
-       }
-       return 0;
+
+       if (clock == new)
+               return;
+
+       now = clocksource_read(new);
+       nsec =  __get_nsec_offset();
+       timespec_add_ns(&xtime, nsec);
+
+       clock = new;
+       clock->cycle_last = now;
+
+       clock->error = 0;
+       clock->xtime_nsec = 0;
+       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+
+       tick_clock_notify();
+
+       printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+              clock->name);
 }
 #else
-static inline int change_clocksource(void)
-{
-       return 0;
-}
+static inline void change_clocksource(void) { }
 #endif
 
 /**
@@ -871,33 +918,56 @@ int timekeeping_is_continuous(void)
        do {
                seq = read_seqbegin(&xtime_lock);
 
-               ret = clock->is_continuous;
+               ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
 
        } while (read_seqretry(&xtime_lock, seq));
 
        return ret;
 }
 
+/**
+ * read_persistent_clock -  Return time in seconds from the persistent clock.
+ *
+ * Weak dummy function for arches that do not yet support it.
+ * Returns seconds from epoch using the battery backed persistent clock.
+ * Returns zero if unsupported.
+ *
+ *  XXX - Do be sure to remove it once all arches implement it.
+ */
+unsigned long __attribute__((weak)) read_persistent_clock(void)
+{
+       return 0;
+}
+
 /*
  * timekeeping_init - Initializes the clocksource and common timekeeping values
  */
 void __init timekeeping_init(void)
 {
        unsigned long flags;
+       unsigned long sec = read_persistent_clock();
 
        write_seqlock_irqsave(&xtime_lock, flags);
 
        ntp_clear();
 
        clock = clocksource_get_next();
-       clocksource_calculate_interval(clock, tick_nsec);
+       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
        clock->cycle_last = clocksource_read(clock);
 
+       xtime.tv_sec = sec;
+       xtime.tv_nsec = 0;
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+
        write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
-
+/* flag for if timekeeping is suspended */
 static int timekeeping_suspended;
+/* time in seconds when suspend began */
+static unsigned long timekeeping_suspend_time;
+
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:       unused
@@ -909,13 +979,26 @@ static int timekeeping_suspended;
 static int timekeeping_resume(struct sys_device *dev)
 {
        unsigned long flags;
+       unsigned long now = read_persistent_clock();
 
        write_seqlock_irqsave(&xtime_lock, flags);
-       /* restart the last cycle value */
+
+       if (now && (now > timekeeping_suspend_time)) {
+               unsigned long sleep_length = now - timekeeping_suspend_time;
+
+               xtime.tv_sec += sleep_length;
+               wall_to_monotonic.tv_sec -= sleep_length;
+       }
+       /* re-base the last cycle value */
        clock->cycle_last = clocksource_read(clock);
        clock->error = 0;
        timekeeping_suspended = 0;
        write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       touch_softlockup_watchdog();
+       /* Resume hrtimers */
+       clock_was_set();
+
        return 0;
 }
 
@@ -925,6 +1008,7 @@ static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
 
        write_seqlock_irqsave(&xtime_lock, flags);
        timekeeping_suspended = 1;
+       timekeeping_suspend_time = read_persistent_clock();
        write_sequnlock_irqrestore(&xtime_lock, flags);
        return 0;
 }
@@ -1089,11 +1173,8 @@ static void update_wall_time(void)
        clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
 
        /* check to see if there is a new clocksource to use */
-       if (change_clocksource()) {
-               clock->error = 0;
-               clock->xtime_nsec = 0;
-               clocksource_calculate_interval(clock, tick_nsec);
-       }
+       change_clocksource();
+       update_vsyscall(&xtime, clock);
 }
 
 /*
@@ -1162,11 +1243,9 @@ static inline void calc_load(unsigned long ticks)
  * This read-write spinlock protects us from races in SMP while
  * playing with xtime and avenrun.
  */
-#ifndef ARCH_HAVE_XTIME_LOCK
-__cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
+__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
 
 EXPORT_SYMBOL(xtime_lock);
-#endif
 
 /*
  * This function runs timers and the timer-tq in bottom half context.
@@ -1175,7 +1254,8 @@ static void run_timer_softirq(struct softirq_action *h)
 {
        tvec_base_t *base = __get_cpu_var(tvec_bases);
 
-       hrtimer_run_queues();
+       hrtimer_run_queues();
+
        if (time_after_eq(jiffies, base->timer_jiffies))
                __run_timers(base);
 }
@@ -1621,6 +1701,8 @@ void __init init_timers(void)
        int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                                (void *)(long)smp_processor_id());
 
+       init_timer_stats();
+
        BUG_ON(err == NOTIFY_BAD);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
index baacc36914152271e01343e5a4de233e7b8780ba..658f638c402c48fbb307b1a8242c6dfe16d9a1ac 100644 (file)
@@ -22,8 +22,6 @@
 #include <linux/acct.h>
 #include <linux/jiffies.h>
 
-
-#define USEC_PER_TICK  (USEC_PER_SEC/HZ)
 /*
  * fill in basic accounting fields
  */
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
new file mode 100644 (file)
index 0000000..f22b9db
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  Copyright (C) 2007
+ *
+ *  Author: Eric Biederman <ebiederm@xmision.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 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/uts.h>
+#include <linux/utsname.h>
+#include <linux/version.h>
+#include <linux/sysctl.h>
+
+static void *get_uts(ctl_table *table, int write)
+{
+       char *which = table->data;
+#ifdef CONFIG_UTS_NS
+       struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
+       which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
+#endif
+       if (!write)
+               down_read(&uts_sem);
+       else
+               down_write(&uts_sem);
+       return which;
+}
+
+static void put_uts(ctl_table *table, int write, void *which)
+{
+       if (!write)
+               up_read(&uts_sem);
+       else
+               up_write(&uts_sem);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ *     Special case of dostring for the UTS structure. This has locks
+ *     to observe. Should this be in kernel/sys.c ????
+ */
+static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table uts_table;
+       int r;
+       memcpy(&uts_table, table, sizeof(uts_table));
+       uts_table.data = get_uts(table, write);
+       r = proc_dostring(&uts_table,write,filp,buffer,lenp, ppos);
+       put_uts(table, write, uts_table.data);
+       return r;
+}
+#else
+#define proc_do_uts_string NULL
+#endif
+
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+/* The generic string strategy routine: */
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen)
+{
+       struct ctl_table uts_table;
+       int r, write;
+       write = newval && newlen;
+       memcpy(&uts_table, table, sizeof(uts_table));
+       uts_table.data = get_uts(table, write);
+       r = sysctl_string(&uts_table, name, nlen,
+               oldval, oldlenp, newval, newlen);
+       put_uts(table, write, uts_table.data);
+       return r;
+}
+#else
+#define sysctl_uts_string NULL
+#endif
+
+static struct ctl_table uts_kern_table[] = {
+       {
+               .ctl_name       = KERN_OSTYPE,
+               .procname       = "ostype",
+               .data           = init_uts_ns.name.sysname,
+               .maxlen         = sizeof(init_uts_ns.name.sysname),
+               .mode           = 0444,
+               .proc_handler   = proc_do_uts_string,
+               .strategy       = sysctl_uts_string,
+       },
+       {
+               .ctl_name       = KERN_OSRELEASE,
+               .procname       = "osrelease",
+               .data           = init_uts_ns.name.release,
+               .maxlen         = sizeof(init_uts_ns.name.release),
+               .mode           = 0444,
+               .proc_handler   = proc_do_uts_string,
+               .strategy       = sysctl_uts_string,
+       },
+       {
+               .ctl_name       = KERN_VERSION,
+               .procname       = "version",
+               .data           = init_uts_ns.name.version,
+               .maxlen         = sizeof(init_uts_ns.name.version),
+               .mode           = 0444,
+               .proc_handler   = proc_do_uts_string,
+               .strategy       = sysctl_uts_string,
+       },
+       {
+               .ctl_name       = KERN_NODENAME,
+               .procname       = "hostname",
+               .data           = init_uts_ns.name.nodename,
+               .maxlen         = sizeof(init_uts_ns.name.nodename),
+               .mode           = 0644,
+               .proc_handler   = proc_do_uts_string,
+               .strategy       = sysctl_uts_string,
+       },
+       {
+               .ctl_name       = KERN_DOMAINNAME,
+               .procname       = "domainname",
+               .data           = init_uts_ns.name.domainname,
+               .maxlen         = sizeof(init_uts_ns.name.domainname),
+               .mode           = 0644,
+               .proc_handler   = proc_do_uts_string,
+               .strategy       = sysctl_uts_string,
+       },
+       {}
+};
+
+static struct ctl_table uts_root_table[] = {
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0555,
+               .child          = uts_kern_table,
+       },
+       {}
+};
+
+static int __init utsname_sysctl_init(void)
+{
+       register_sysctl_table(uts_root_table);
+       return 0;
+}
+
+__initcall(utsname_sysctl_init);
index 020d1fff57dce7839735bf7df6362a57ff747b55..b6fa5e63085d65b42f46fe97735751b6f402cab4 100644 (file)
@@ -218,7 +218,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work)
 }
 EXPORT_SYMBOL_GPL(queue_work);
 
-static void delayed_work_timer_fn(unsigned long __data)
+void delayed_work_timer_fn(unsigned long __data)
 {
        struct delayed_work *dwork = (struct delayed_work *)__data;
        struct workqueue_struct *wq = get_wq_data(&dwork->work);
@@ -245,6 +245,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq,
        struct timer_list *timer = &dwork->timer;
        struct work_struct *work = &dwork->work;
 
+       timer_stats_timer_set_start_info(timer);
        if (delay == 0)
                return queue_work(wq, work);
 
@@ -593,8 +594,10 @@ EXPORT_SYMBOL(schedule_work);
  * After waiting for a given time this puts a job in the kernel-global
  * workqueue.
  */
-int fastcall schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
+int fastcall schedule_delayed_work(struct delayed_work *dwork,
+                                       unsigned long delay)
 {
+       timer_stats_timer_set_start_info(&dwork->timer);
        return queue_delayed_work(keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work);
index 63f04c15e6f52924c98f91c1281c54cbdcb01ae9..4448f91b865c10a48933a6a8d1c4ea645266b90c 100644 (file)
@@ -134,6 +134,17 @@ config SCHEDSTATS
          application, you can say N to avoid the very slight overhead
          this adds.
 
+config TIMER_STATS
+       bool "Collect kernel timers statistics"
+       depends on DEBUG_KERNEL && PROC_FS
+       help
+         If you say Y here, additional code will be inserted into the
+         timer routines to collect statistics about kernel timers being
+         reprogrammed. The statistics can be read from /proc/timer_stats.
+         The statistics collection is started by writing 1 to /proc/timer_stats,
+         writing 0 stops it. This feature is useful to collect information
+         about timer usage patterns in kernel and userspace.
+
 config DEBUG_SLAB
        bool "Debug slab memory allocations"
        depends on DEBUG_KERNEL && SLAB
index 2a668dd7cac7cb81e6cc44e1ebe61e12225e3934..eb38849aa71702445e7e8e42744ad384fe512f48 100644 (file)
@@ -274,21 +274,21 @@ int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
 
                rc = pci_request_region(pdev, i, name);
                if (rc)
-                       goto err_region;
+                       goto err_inval;
 
                rc = -ENOMEM;
                if (!pcim_iomap(pdev, i, 0))
-                       goto err_iomap;
+                       goto err_region;
        }
 
        return 0;
 
- err_iomap:
-       pcim_iounmap(pdev, iomap[i]);
  err_region:
        pci_release_region(pdev, i);
  err_inval:
        while (--i >= 0) {
+               if (!(mask & (1 << i)))
+                       continue;
                pcim_iounmap(pdev, iomap[i]);
                pci_release_region(pdev, i);
        }
index 2782f49e906ec3e2315028041ca54681239e55a7..f4f6176dcd1286313c57ae80239ec1f0f7bbf65e 100644 (file)
@@ -171,7 +171,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
                return -ENOENT;
        if (!kobj->k_name)
                kobj->k_name = kobj->name;
-       if (!kobj->k_name) {
+       if (!*kobj->k_name) {
                pr_debug("kobject attempted to be registered with no name!\n");
                WARN_ON(1);
                return -EINVAL;
@@ -326,6 +326,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
 /**
  *     kobject_rename - change the name of an object
  *     @kobj:  object in question.
+ *     @new_parent: object's new parent
  *     @new_name: object's new name
  */
 
index 9e2a002c5b543305105c69a77410177882538b1b..88c98a2ec8d93efd79b230ca98feed8658f406a4 100644 (file)
@@ -40,7 +40,7 @@
  *       configuration according to the specified parameters.
  *   (3) User starts the search(es) by calling _find() or _next() to
  *       fetch subsequent occurrences. A state variable is provided
- *       to the algorihtm to store persistent variables.
+ *       to the algorithm to store persistent variables.
  *   (4) Core eventually resets the search offset and forwards the find()
  *       request to the algorithm.
  *   (5) Algorithm calls get_next_block() provided by the user continously
index 00414849a86712c40ce174c900fe9b67cc9eb096..d1060b8d3cd65ba696afce181c09fd1c2585f196 100644 (file)
@@ -2079,21 +2079,27 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
                /* Limit the size of the copy to the caller's write size */
                bytes = min(bytes, count);
 
-               /*
-                * Limit the size of the copy to that of the current segment,
-                * because fault_in_pages_readable() doesn't know how to walk
-                * segments.
+               /* We only need to worry about prefaulting when writes are from
+                * user-space.  NFSd uses vfs_writev with several non-aligned
+                * segments in the vector, and limiting to one segment a time is
+                * a noticeable performance for re-write
                 */
-               bytes = min(bytes, cur_iov->iov_len - iov_base);
-
-               /*
-                * Bring in the user page that we will copy from _first_.
-                * Otherwise there's a nasty deadlock on copying from the
-                * same page as we're writing to, without it being marked
-                * up-to-date.
-                */
-               fault_in_pages_readable(buf, bytes);
+               if (!segment_eq(get_fs(), KERNEL_DS)) {
+                       /*
+                        * Limit the size of the copy to that of the current
+                        * segment, because fault_in_pages_readable() doesn't
+                        * know how to walk segments.
+                        */
+                       bytes = min(bytes, cur_iov->iov_len - iov_base);
 
+                       /*
+                        * Bring in the user page that we will copy from
+                        * _first_.  Otherwise there's a nasty deadlock on
+                        * copying from the same page as we're writing to,
+                        * without it being marked up-to-date.
+                        */
+                       fault_in_pages_readable(buf, bytes);
+               }
                page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
                if (!page) {
                        status = -ENOMEM;
index 95c5f49f0a1ada33c90e292010149ab8f3e404b9..5efe0ded69b1857935d0295e9999210e4999a516 100644 (file)
@@ -77,8 +77,16 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag
         * PTE array for our address.
         */
        nr = PTRS_PER_PTE - ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE-1));
-       if (nr > pages)
-               nr = pages;
+
+       /*
+        * Don't overrun this vma
+        */
+       nr = min(nr, (vma->vm_end - addr) >> PAGE_SHIFT);
+
+       /*
+        * Don't return more than the caller asked for
+        */
+       nr = min(nr, pages);
 
        pgd = pgd_offset(vma->vm_mm, addr);
        if (pgd_none_or_clear_bad(pgd))
@@ -116,10 +124,17 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag
                                /* migration entries are always uptodate */
                                present = 1;
                        } else {
+#ifdef CONFIG_SWAP
                                pgoff = entry.val;
                                present = mincore_page(&swapper_space, pgoff);
+#else
+                               WARN_ON(1);
+                               present = 1;
+#endif
                        }
                }
+
+               vec[i] = present;
        }
        pte_unmap_unlock(ptep-1, ptl);
 
@@ -130,6 +145,9 @@ none_mapped:
                pgoff = linear_page_index(vma, addr);
                for (i = 0; i < nr; i++, pgoff++)
                        vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+       } else {
+               for (i = 0; i < nr; i++)
+                       vec[i] = 0;
        }
 
        return nr;
index d64e6a502958315d3f4400610ea5d2889478c1c8..675d9ba8e591bf78803a09ecd3fcfa32596224b7 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 0b98fe2fa2f65a8c53eb0991db09a4aa2ed7ff44..ace6386384bcee286cb7646cb86d078e65015868 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index be0da59323b3cb2faf70404da18f7ab0a9528852..578f2a3d692d2019a22b56105cef81c56ab10c4f 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 40b0af7437a2e0d5acbbcbfc59e5bc1ab37d5b6f..7df1778e221a6f9ab3782789ffeb51af61ceb165 100644 (file)
@@ -73,7 +73,7 @@ static struct ctl_table_header *atalk_table_header;
 
 void atalk_register_sysctl(void)
 {
-       atalk_table_header = register_sysctl_table(atalk_root_table, 1);
+       atalk_table_header = register_sysctl_table(atalk_root_table);
 }
 
 void atalk_unregister_sysctl(void)
index 3060fd0ba4b9fb51ca79a8079f22365433cc4470..6afa77d63bb534ac53e954515da36e3256b0af82 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/atm.h>
 #include <linux/atmdev.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #include "signaling.h"
index 986945527691204684958cbc7c06ee8dff886ee1..3d804d61f6569e0ea0b0963d0abd50bc12204575 100644 (file)
@@ -1437,7 +1437,6 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <asm/param.h>
 #include <asm/atomic.h>
index 4df7cdd72aa18de02a3dee725c145638d0a79f3d..1378f61c5c3178876aeffb0438621efdb91394c7 100644 (file)
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/atmdev.h>
 #include <linux/capability.h>
 #include <linux/kernel.h>
index 419e7188d5a770da0f8e0b4aab4f226d01762955..7e7964dd987bc99a311084c285ea27e225082b57 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index b787678220fff4d6df193d720208fa67ed981b0f..528c874d9828df06f6d2c880b808d31da4164041 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index edcaa897027cc031861b6d6bc66c5720a2c25b55..e37d217a986a6bc0de5ab3aa05f7d0c96014b96b 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 4d22d4430ec8a85128484685c4886ca4adc73cfa..9569dd3fa466e0e0e275b01bc10a2013edb47eda 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index aff3e652c2d110ad55448ae2e41dd15fcac5affc..16be0c14780a18415bf203f617b8cb1c4cdb0808 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/string.h>
index e9d94291581ea1a67d53f39989ed26aef5fd0320..4a6b26becadc67fb3cd6da9ca307d1708526a228 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 8d62d86816150b9d814f1edc469f065c48a48b80..7f818bbcd1c5e1a7030057453545b4d120c60216 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index f84047d1e8ce1760f35ae81e3b24c1e3448f1be4..223835092b7afe743ca7d1050e9fe473457652b6 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index f6ed283e9de82fb2baee56e73580f5bc117fb5f4..a8eef88d86529d510e857e568c34be681d80bcfd 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 2b3c801ae48684716f58e4bc489e9bcb4f68375b..277f81bb979a6f0dc0d19b754a0f7e356753f7c7 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index e3528b1a7802b61b3f0caa5da791c84235f87fc2..f2f6918ac9bb69cae0c93f084b5955aed97f460c 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 85c58c49b4d0bd2873abfc76167102c0dfa4e7a6..b6c577e3c9140a6b216f23b267b2338a22d3632c 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 59a41b1e61f53bd2c1894dc243bc0f0bffa56857..75c76647b2cbdf62d0d76948d4558ec272d41cfa 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index d23a27f25d2fd63c94568482c07a3696b607c3ca..443a8367663807c4265e002268b88e9be0acf221 100644 (file)
@@ -245,7 +245,7 @@ void ax25_register_sysctl(void)
 
        ax25_dir_table[0].child = ax25_table;
 
-       ax25_table_header = register_sysctl_table(ax25_root_table, 1);
+       ax25_table_header = register_sysctl_table(ax25_root_table);
 }
 
 void ax25_unregister_sysctl(void)
index 6d7311cee1b4c7161caf18ed84ecdb0a2aba51d4..10292e77604612f371e0e26d9b59d446f4897b34 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index 0c5ccd95517fcef43adf46a41a70171fe1d08927..19be7861e51ead07db64e1fafb06956cc425e0d1 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index 67ee0bd80f5f838f1904ea90aaf1aad37606f41a..f3403fdb59f8e6f9c38338f25398024410d50dca 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index 00d845e3d30789e0e36baa7847e9825378f7292f..936d3fc479cdd9d2029a729e1a6ba63b4a7ab11d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index dc3ecb19a5cd9d3dd8d1ee03d8f2fc80100cd161..f928d2b2a17dac5c81a7660108e895b5640a1263 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index 33bda40aceb840d662ed468c1c663ee6806f88df..8b8a6c1dbd9905534628f492f8d329e03d6f71ff 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
index a0744e653f0912fce9e40ce1a55706c3dd763733..7712d76f06ba8b22ba394d57d7e0d007034fe383 100644 (file)
@@ -957,7 +957,7 @@ int __init br_netfilter_init(void)
        if (ret < 0)
                return ret;
 #ifdef CONFIG_SYSCTL
-       brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
+       brnf_sysctl_header = register_sysctl_table(brnf_net_table);
        if (brnf_sysctl_header == NULL) {
                printk(KERN_WARNING
                       "br_netfilter: can't register to sysctl.\n");
index 5818d70b8e8d3bec53c5d6696beed715439d770d..34c49799f9b303a11d70c3c1f6839fe403a2e43c 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 /* used for print_string */
-#include <linux/sched.h>
 #include <linux/tty.h>
 
 #include <linux/kmod.h>
index 9c970749a3b0fcb56f9c1386d3edcdf6fc97b54e..1f32866d09b7f3ba6deae83fdffd7044fb8e3b6a 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/file.h>
 #include <linux/icmpv6.h>
index c4e754e86e9634f1a55c76a4d8a500343e70936c..56b310c0c860af79db12593d6efbe48f793e034d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 61dd9d3951f1017697fe223a988e876466c5194d..764bccb3d99265b2a014b41167d999cf1574e639 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/types.h>
index 8123a31d919daacfd8b782a5f3e9401e7fa08e7d..8d185a089c53cdce1dced05fe08a6cd48f4d8f9e 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fcntl.h>
 #include <linux/socket.h>
index 4fb1cb9b79b9bf98233daef4088349a904dc1822..755c37fdaee799c734962a1739dafdbb71882ff5 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
index 512eed91785dc5dbab2de12a4603473dddc6b791..3183142c6044000b93829b4e340a3675a0c7d146 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/socket.h>
-#include <linux/sched.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #ifdef CONFIG_SYSCTL
@@ -2708,7 +2707,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
        t->neigh_proto_dir[0].child    = t->neigh_neigh_dir;
        t->neigh_root_dir[0].child     = t->neigh_proto_dir;
 
-       t->sysctl_header = register_sysctl_table(t->neigh_root_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->neigh_root_dir);
        if (!t->sysctl_header) {
                err = -ENOBUFS;
                goto free_procname;
index 6189dc03108d2da67aad2a155a3d53011a30daa0..4cbb1290a6a34707c93b0ddfa040a06f1d1d47bf 100644 (file)
@@ -340,7 +340,7 @@ static struct attribute_group netstat_group = {
        .attrs  = netstat_attrs,
 };
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 /* helper function that does all the locking etc for wireless stats */
 static ssize_t wireless_show(struct device *d, char *buf,
                             ssize_t (*format)(const struct iw_statistics *,
@@ -473,7 +473,7 @@ int netdev_register_sysfs(struct net_device *net)
        if (net->get_stats)
                *groups++ = &netstat_group;
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
        if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
                *groups++ = &wireless_group;
 #endif
index ee5a787271f6fa0afaa18b6cc23e9fe96ff55224..6055074c4b81eb83ee2be5ea7cce4228185e825f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 3d5646869022240ea2136843a17c2fa76e115750..f89ff151cfabff32a6436c98fef66e243118bc20 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
index fdcfca3e9208926809e769f469a0fd139050c153..1260aabac5e1b1cc17332d01649121b5068ca922 100644 (file)
@@ -127,7 +127,7 @@ static struct ctl_table_header *dccp_table_header;
 
 int __init dccp_sysctl_init(void)
 {
-       dccp_table_header = register_sysctl_table(dccp_root_table, 1);
+       dccp_table_header = register_sysctl_table(dccp_root_table);
 
        return dccp_table_header != NULL ? 0 : -ENOMEM;
 }
index 2b2c7fe45a719e96e52f1c1746e067b12a822326..060d725e2942b909580497b2a3c7ee9c9fe8c475 100644 (file)
@@ -261,7 +261,6 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
        for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
                long offset = (long)t->dn_dev_vars[i].data;
                t->dn_dev_vars[i].data = ((char *)parms) + offset;
-               t->dn_dev_vars[i].de = NULL;
        }
 
        if (dev) {
@@ -273,16 +272,12 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
        }
 
        t->dn_dev_dev[0].child = t->dn_dev_vars;
-       t->dn_dev_dev[0].de = NULL;
        t->dn_dev_conf_dir[0].child = t->dn_dev_dev;
-       t->dn_dev_conf_dir[0].de = NULL;
        t->dn_dev_proto_dir[0].child = t->dn_dev_conf_dir;
-       t->dn_dev_proto_dir[0].de = NULL;
        t->dn_dev_root_dir[0].child = t->dn_dev_proto_dir;
-       t->dn_dev_root_dir[0].de = NULL;
        t->dn_dev_vars[0].extra1 = (void *)dev;
 
-       t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir);
        if (t->sysctl_header == NULL)
                kfree(t);
        else
index 0f244e81a377ccd80f962e8b0fb1ecf5aee3ce4a..9d20904f6f52ebe60b5cdbe2c0b0de42a92a7a5e 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 23d5ca88dfa363ca0093fbb461d48e1d6f1c6685..2d2cda82c7db998f88db3113880143a77b143705 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index a6c067b593ab480d4757610e1361cb447647369b..52e40d7eb22d9f583c045175ae1d64aa4dde2e16 100644 (file)
@@ -491,7 +491,7 @@ static ctl_table dn_root_table[] = {
 
 void dn_register_sysctl(void)
 {
-       dn_table_header = register_sysctl_table(dn_root_table, 1);
+       dn_table_header = register_sysctl_table(dn_root_table);
 }
 
 void dn_unregister_sysctl(void)
index f2ce4143429018b33b9da9093d2dd913439152f2..bc12e36263f0d4e15bcbfa300af80a5be5915f4a 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 766a0b59c0d37451030bc17c5420c52c5a0d6ff3..7391f55904d1ba6bbdba777e88864bac2d938c98 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index c55949e5c58a990b923e747977e8e536c0f7a5fd..0292d6348e1268671ad71cba02931271122a531e 100644 (file)
@@ -502,9 +502,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                if (host_encrypt)
                        ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
                else if (host_build_iv) {
-                       struct ieee80211_crypt_data *crypt;
-
-                       crypt = ieee->crypt[ieee->tx_keyidx];
                        atomic_inc(&crypt->refcnt);
                        if (crypt->ops->build_iv)
                                crypt->ops->build_iv(skb_frag, hdr_len,
index 503e7059e312e553d5133f2989f1a9b2a3bbeb21..91f3a5cdbcf84719034369bb376e904da614cb71 100644 (file)
@@ -9,7 +9,7 @@ config IP_MULTICAST
          intend to participate in the MBONE, a high bandwidth network on top
          of the Internet which carries audio and video broadcasts. More
          information about the MBONE is on the WWW at
-         <http://www-itg.lbl.gov/mbone/>. Information about the multicast
+         <http://www.savetz.com/mbone/>. Information about the multicast
          capabilities of the various network cards is contained in
          <file:Documentation/networking/multicast.txt>. For most people, it's
          safe to say N.
index 0ffd2d2920c3dd93df7479bd8512a862896b16cc..1a3488a83f49363a7d5200f37d01371f81cfd938 100644 (file)
@@ -78,7 +78,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
index ba5e7f4cd127992809b6256d0ecc21c419215f13..8a0ec10a13a7370b536a63a20b6c6a4c0fd431c4 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -1577,7 +1576,6 @@ static void devinet_sysctl_register(struct in_device *in_dev,
                return;
        for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
                t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
-               t->devinet_vars[i].de = NULL;
        }
 
        if (dev) {
@@ -1599,15 +1597,11 @@ static void devinet_sysctl_register(struct in_device *in_dev,
 
        t->devinet_dev[0].procname    = dev_name;
        t->devinet_dev[0].child       = t->devinet_vars;
-       t->devinet_dev[0].de          = NULL;
        t->devinet_conf_dir[0].child  = t->devinet_dev;
-       t->devinet_conf_dir[0].de     = NULL;
        t->devinet_proto_dir[0].child = t->devinet_conf_dir;
-       t->devinet_proto_dir[0].de    = NULL;
        t->devinet_root_dir[0].child  = t->devinet_proto_dir;
-       t->devinet_root_dir[0].de     = NULL;
 
-       t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->devinet_root_dir);
        if (!t->sysctl_header)
            goto free_procname;
 
@@ -1641,7 +1635,7 @@ void __init devinet_init(void)
        rtnetlink_links[PF_INET] = inet_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
        devinet_sysctl.sysctl_header =
-               register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);
+               register_sysctl_table(devinet_sysctl.devinet_root_dir);
        devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
 #endif
 }
index 64f31e63db7f073436a3b805128e0f2df152b5de..1fba6439fc576c9a892af95e5f68f56168cc40c0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/capability.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
index b21bb28d1fd04335af25a642b786e9fde85c12a8..a4949f957ab5cbecf9f6b1b79685112bd82ff6b0 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
index c33dca073801b86e6b851caf88f8ec838900a532..72b3036bbc09299ada84b297f4ef50b4de453dcb 100644 (file)
@@ -57,7 +57,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
index 711eb6d0285a8a4709a8e89a9c1b88697dcce7ee..db3ef96bdfd96412c9b30d88e785a97a38aaf17b 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/random.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
index c3ea0cd2e584eb507b8ffb893ac9a59b23d4aebf..369e721c4bab3cf0fd58e61b88f170ad891373cb 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/icmp.h>
index f12c0d6623a0a6c35bb36298bcba95bb7168091d..9151da64231851199cafba4b844f8e20b81426b5 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
index bb0bb8f07c54aa5172d5a62bcd38d3a73123aa56..d096332f6c6d9e10753531364299f68672f604a7 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
index e120686c3cb8901fb648029d5af260fd1b0c3750..23048d9f3584b199164a42a21e467c054975d8c5 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/icmp.h>
index 9b561e633b007b7eaa122dc96f18f02ac85d0e99..3ec5ce0f5498cb17deead77b228e0408e3f9c050 100644 (file)
@@ -96,7 +96,6 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
index e6d11abd7841870dd3ad9a384c9451283f49b516..601e3df69258117394c7c07306cd755dd10cf8cf 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
index 8b08d9cdcbc8b00891fe13ceb1b78138561e23dc..b3050a6817e7af88ed58b7213ee342b4c6f9f1bd 100644 (file)
@@ -2359,7 +2359,7 @@ int ip_vs_control_init(void)
        proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
        proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
 
-       sysctl_header = register_sysctl_table(vs_root_table, 0);
+       sysctl_header = register_sysctl_table(vs_root_table);
 
        /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
        for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
index 76fd1fb91878b8a2bdd7fb4fe994963440f9eb23..c801273cb881151d65617f6c4ba6699bb26378ad 100644 (file)
@@ -583,7 +583,7 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler =
 static int __init ip_vs_lblc_init(void)
 {
        INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list);
-       sysctl_header = register_sysctl_table(lblc_root_table, 0);
+       sysctl_header = register_sysctl_table(lblc_root_table);
        return register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
 }
 
index bf1e7f272b8416c5f84bd8afde6876f1882be044..23f9b9e73c850f9a00e4d38c979023ad062f857b 100644 (file)
@@ -841,7 +841,7 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
 static int __init ip_vs_lblcr_init(void)
 {
        INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
-       sysctl_header = register_sysctl_table(lblcr_root_table, 0);
+       sysctl_header = register_sysctl_table(lblcr_root_table);
 #ifdef CONFIG_IP_VS_LBLCR_DEBUG
        proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
 #endif
index 8bc42b76223db8555bb2edb97cfea61c24d303d3..1602304abbf9e9055388c680503fa0325ce4ab8a 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/string.h>
index cb8fce46734900428319c55be5292d6d1d8836ff..574c735836fc9373f2d4d66115ea07b4ad7cf484 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
index 047e861f06bd42f902865bf52bf2455101dbc244..57f481498fbb39d99338187b9a0653efbb692b7a 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
index 896246d8040e2d49a9bac1a6994bfc0a802f5dc8..0ad22524f450dcbb0fad212dec428fa70472ed22 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
index 7e22f15d13dfecb562b58adadc409282835faba3..2bdbb92b450adbf859501a5d83008d2521a80818 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
index 36f2b5e5d80adaff59f6817afca14dbc4f9e844f..88af82e986589f65ed0a5ae0783188f1754cda4c 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
index ec71abead00c76caae6ce0ea217f6240dc506a11..ad70c81a21e04861c04a4e597bc00c87d0fba3eb 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
index 9d5b917f49cd27e64585c64a970315ca12e73610..e6942992b2f699634878e43e3a80c49f3f9c9e26 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/netfilter.h>
@@ -623,7 +622,7 @@ static int __init ip_conntrack_proto_sctp_init(void)
        }
 
 #ifdef CONFIG_SYSCTL
-       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
        if (ip_ct_sysctl_header == NULL) {
                ret = -ENOMEM;
                printk("ip_conntrack_proto_sctp: can't register to sysctl.\n");
index fa35b49fe2fa6c69dfc91a81b83fd5e0046a2067..170d625fad67d7d7bc51878a937b597f8b8823f6 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
index a99a7c75e5b5cd58745e5a68040503ce248bbc50..14c30c646c7fed33cdfab328ef590f89e5ce83b8 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
index c7c1ec61b0f5ce25523363155716a04e26f7873d..56b2f7546d1e9a8f5270f679812d598f386bad6b 100644 (file)
@@ -848,7 +848,7 @@ static int __init ip_conntrack_standalone_init(void)
                goto cleanup_proc_stat;
        }
 #ifdef CONFIG_SYSCTL
-       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
        if (ip_ct_sysctl_header == NULL) {
                printk("ip_conntrack: can't register to sysctl.\n");
                ret = -ENOMEM;
index 68bf19f3b01c4232875d632ec6ba50a06c1c0e03..a14798a850d7334311dad6d5170b8adcd688c356 100644 (file)
@@ -693,7 +693,7 @@ static int __init ip_queue_init(void)
        }
 
        register_netdevice_notifier(&ipq_dev_notifier);
-       ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
+       ipq_sysctl_header = register_sysctl_table(ipq_root_table);
 
        status = nf_register_queue_handler(PF_INET, &nfqh);
        if (status < 0) {
index e5aa4d849b0087528e4c45e91ea51c4f9f063af9..88cfa6aacfc150f81eb9d7d419d2400812aa8515 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
index 6cd6340de8bdb18b484551236b35063df90c4b7d..da70fef82c93f11c8caa2168eca6f5793eb85cb0 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/in.h>
index 9b5e56481d53d1929e8846cc1406faf60300a426..37e0d4d5cf94e85bc28248ab054266afbe1ecc98 100644 (file)
@@ -70,7 +70,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/string.h>
index c1b34f1edb32740fa38dc724f6792f5998118a54..5c8caf4a1244404631e162c0d93e1f2e28e77f73 100644 (file)
@@ -29,7 +29,7 @@ static struct tcp_congestion_ops *tcp_ca_find(const char *name)
 }
 
 /*
- * Attach new congestion control algorthim to the list
+ * Attach new congestion control algorithm to the list
  * of available options.
  */
 int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
index ea0755b09033caa7b0168e1e2cd9b76fc1bd2572..569a37d698f7711fbf2c61aad8b271cce11550c5 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -3999,7 +3998,6 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
                return;
        for (i=0; t->addrconf_vars[i].data; i++) {
                t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
-               t->addrconf_vars[i].de = NULL;
                t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
        }
        if (dev) {
@@ -4022,15 +4020,11 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
        t->addrconf_dev[0].procname = dev_name;
 
        t->addrconf_dev[0].child = t->addrconf_vars;
-       t->addrconf_dev[0].de = NULL;
        t->addrconf_conf_dir[0].child = t->addrconf_dev;
-       t->addrconf_conf_dir[0].de = NULL;
        t->addrconf_proto_dir[0].child = t->addrconf_conf_dir;
-       t->addrconf_proto_dir[0].de = NULL;
        t->addrconf_root_dir[0].child = t->addrconf_proto_dir;
-       t->addrconf_root_dir[0].de = NULL;
 
-       t->sysctl_header = register_sysctl_table(t->addrconf_root_dir, 0);
+       t->sysctl_header = register_sysctl_table(t->addrconf_root_dir);
        if (t->sysctl_header == NULL)
                goto free_procname;
        else
@@ -4115,7 +4109,7 @@ int __init addrconf_init(void)
        rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
        addrconf_sysctl.sysctl_header =
-               register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);
+               register_sysctl_table(addrconf_sysctl.addrconf_root_dir);
        addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
 #endif
 
index a006d242be765390f8e239b1297a528283be3d39..3585d8fa7f029930869ac900ad73ae0f4a442f22 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 6fb2e9d716c004ec6d0b0c83263fd76878c3450c..e5ef5979ade417e32d2bc11a41979f7fc0056758 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 5f54dec3e2051c5fb8ecd8553d9e8d606784c637..3b4e8dcf4c86f7992ab69ee64909f79ce30e813b 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
index 08313efc48c82660a5fd5c2ced3cc4c2b855af47..28e0c6568272054ddcae0ac4e41f71493959adc2 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/in6.h>
index 9377fea026824ca61ff7fe716c6957d62e86a8cf..edfe98bf64c3366818cfbd6b75a7fa3967ce9a64 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <linux/skbuff.h>
index 4fdded0e545a4a45449d6a6fdc9a5f24d78e0014..11bfc7c431824b3c9b0a3254b8574375f3b798a6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/in6.h>
index 3f1e779ea5c52151e748a807dcb141ecbea0786f..286c86735aed7772f6851228026d0a633a1d45bd 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 58847d3b61e503d036481309eba777081eb18c55..fdb30a5916e57b6c6cb8060640e49bf4197ed9bc 100644 (file)
@@ -683,7 +683,7 @@ static int __init ip6_queue_init(void)
        }
 
        register_netdevice_notifier(&ipq_dev_notifier);
-       ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
+       ipq_sysctl_header = register_sysctl_table(ipq_root_table);
 
        status = nf_register_queue_handler(PF_INET6, &nfqh);
        if (status < 0) {
index 19bdb7cb8ff30b1ed8fc673af6468d16831d1098..21f19cc719f34d2bd4bcad23808efa95095bd023 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
index c82257dd04b635a84fd6bb8fe1c5f85388b7967a..fa3fb509f1877c4efaac30113fbeeff6ac52484c 100644 (file)
@@ -17,7 +17,6 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-#include <linux/sched.h>
 #include <linux/socket.h>
 #include <linux/net.h>
 #include <linux/ipv6.h>
index ad0410c996753789ad8df6eb665be263a044c08c..ef43bd57baed0908307890f723c7ffed40708b10 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 1f8f6275a7e4f08018a2d6715b32f17115b98ed7..306d5d83c06803727e2b9b64cd8e57e08e11fd80 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 862ed7c52c38636efd3c17f6b8eab24ad5862aeb..08d6ed3396e42f6deb53c4422562eb9afb260765 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 25e8e7783feefd0a3b374f7cda5d70f73de3cb92..3fb44277207be3c8b318f93a1aa8d59e42227b1a 100644 (file)
@@ -107,7 +107,7 @@ static ctl_table ipv6_root_table[] = {
 
 void ipv6_sysctl_register(void)
 {
-       ipv6_sysctl_header = register_sysctl_table(ipv6_root_table, 0);
+       ipv6_sysctl_header = register_sysctl_table(ipv6_root_table);
 }
 
 void ipv6_sysctl_unregister(void)
index ccf2f4d196beb27489a320c926f8a85b28b52407..0ad471909881f31b35c94a69b78bb50f870b58e9 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 85ae35fa1e0e797655a8d774b24eb514e740f4b5..0cf52645053648c7444a86544537a2b54a0243a1 100644 (file)
@@ -52,7 +52,7 @@ static struct ctl_table_header *ipx_table_header;
 
 void ipx_register_sysctl(void)
 {
-       ipx_table_header = register_sysctl_table(ipx_root_table, 1);
+       ipx_table_header = register_sysctl_table(ipx_root_table);
 }
 
 void ipx_unregister_sysctl(void)
index ec40715dcdda97cfced91730e3d4cb1e33d328f4..4749f8f55391a32d8e5c46abb6a900f1db799636 100644 (file)
@@ -30,7 +30,6 @@
  ********************************************************************/
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
index 23d0468794e2dca53c42693ed543d543c44512e3..8ba4e59ece16041e52eb3e5db89ae48b306de888 100644 (file)
@@ -28,7 +28,6 @@
  *
  ********************************************************************/
 
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
index 22bd7529910470b00eefc9a94766f8047137b0d1..55860ee4e39e94cf68e08c4efe2c8e4b9bc9b3d1 100644 (file)
@@ -30,7 +30,6 @@
  *
  ********************************************************************/
 
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
index fbac13e95b28826223f7470a823c50cd8b3f7668..01d7c9c7b3b4ea7875e4c3d8a30ca7a5dfa7e2e9 100644 (file)
@@ -28,7 +28,6 @@
  *
  ********************************************************************/
 
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
index bb06ebaadd16f481741032ca39c8cd54cc55dbd7..712eafd0cc7676679f5f3eed20b9e077b0d9ea15 100644 (file)
@@ -29,7 +29,6 @@
  *
  ********************************************************************/
 
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
index 8d7ba93e4e09e98a0a692ff17be135e1dc0e3d32..824309dabfe9450102791912c77c8f0ba1b74b4b 100644 (file)
@@ -29,7 +29,6 @@
  *
  ********************************************************************/
 
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
index a5174e6e7ad3264fa5cad595f4eff9aa06b4f00c..6030947b6d93b2d5c171f17714217e4abf5016b7 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/termios.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
index bb53ba0be585e0f75572d9d9861c6491c23d9a3c..2e968e7d8feaddb68a99ea775f5a90a91efe7973 100644 (file)
@@ -274,7 +274,7 @@ static struct ctl_table_header *irda_table_header;
  */
 int __init irda_sysctl_register(void)
 {
-       irda_table_header = register_sysctl_table(irda_root_table, 0);
+       irda_table_header = register_sysctl_table(irda_root_table);
        if (!irda_table_header)
                return -ENOMEM;
 
index b0f8713f66cae3aeeef51bac2406d57292cd58cb..6762e7c751ebe7342fb96cdaca6ee0f8f629d2e1 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 981beb5e518780e24e38384af27a71fbfc104598..339cc5f2684f1008d930c0c2ecf943d537d9294f 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index b8739cf9156da832402741c7fb2693c42506f091..b827f47ac133c64f71e9934b5acc086505a88a79 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index d047a3e15714691f27910661e29143527e5a8fd2..46992d03601766503cc9250a25cda2b27ddccb3a 100644 (file)
@@ -116,7 +116,7 @@ static struct ctl_table_header *llc_table_header;
 
 int __init llc_sysctl_init(void)
 {
-       llc_table_header = register_sysctl_table(llc_root_table, 1);
+       llc_table_header = register_sysctl_table(llc_root_table);
 
        return llc_table_header ? 0 : -ENOMEM;
 }
index 69902531c2367d77684de80cd5083a5d70d5e23b..7c069939695a40c38bcb2c2ee00011db45344112 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
index 0133afa2c7efb07ae9b1fb47d3da3ca7655e708f..3c80558716a0b3c9f0773a9b485c38ac63935c8b 100644 (file)
@@ -19,7 +19,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
index aff65aad3c66b179584abf85b03b277ad59ad2f0..069b85ca51cd026d2799d24d82e7c5208bd40481 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
index e49cd25998c4e40a9f1caf63a953ae85beab8c9f..d0a1cee7ee52d765b144a2f53e15e3fbb1627451 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
index a0bba481d70d757535b1eb9c44dae181419eabb6..b8586360e519179864cda89ea24ce54d63eb884b 100644 (file)
@@ -445,7 +445,7 @@ static int __init nf_conntrack_standalone_init(void)
        proc_stat->owner = THIS_MODULE;
 #endif
 #ifdef CONFIG_SYSCTL
-       nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
+       nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table);
        if (nf_ct_sysctl_header == NULL) {
                printk("nf_conntrack: can't register to sysctl.\n");
                ret = -ENOMEM;
index 06ddddb2911f8f9691757bf9a130907f1bebfc47..ee34589e48a4407918b06a3f2452611d38366399 100644 (file)
@@ -56,7 +56,7 @@ nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table)
        path = path_dup(path, table);
        if (path == NULL)
                return NULL;
-       header = register_sysctl_table(path, 0);
+       header = register_sysctl_table(path);
        if (header == NULL)
                path_free(path, table);
        return header;
index f42bb1366007ea716780a72a2b851f20a87d75ee..11d504d0ac72068d8c88bc794fe4cb8c1284e3d9 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 4700d5225b78f59aff3b5f8154064bf4d06a7ebd..9a97ed6e6910d656b1a2a0c505f7238b51484db3 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/types.h>
index a7d88b5ad756a85731d97feec43a58193129367c..5560acbaaa9548d78feabbd877370b1fb214a2c7 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 7939ded9c98ccc85a48053db5deab178d9e14de5..0cbfb611465b3a6f9580b2bc22b6680901267faf 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index c2fbac9c69ceab2a6a5db77b1283dbe901662d0b..8e6bd4e9d82c76e929ce1648c51456ce9da6e60f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index cfab5721a6089c2c41f99b8e72ab181155c9f3e4..07b694d1887079280147030d46aa0360063647ff 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index e4b27d7aae79b7cd288d98b9f9ddd6cca026f0c3..2ea68da01fb836bf8f8ae5fa4b70c13686df12e7 100644 (file)
@@ -192,7 +192,7 @@ static ctl_table nr_root_table[] = {
 
 void __init nr_register_sysctl(void)
 {
-       nr_table_header = register_sysctl_table(nr_root_table, 1);
+       nr_table_header = register_sysctl_table(nr_root_table);
 }
 
 void nr_unregister_sysctl(void)
index 15ff7b15e2112c675e97b582376ce27c2c951af0..bf2699074774dc436d53d5276c2375721df58cf1 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
 #include <linux/fcntl.h>
index 50824d345fa6e43fe61d04e8f1b075081a743c35..8d88795dc663497654aeb0eb292fa91680e260c1 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/types.h>
index 8348d33f1efefceb64472f52577067c3550931bf..4ee0879d354064cad674b5423a3f9de40ef5ca38 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 2965ffc83b9b78bb8db22d7f6d25a02ee6ec90fa..69820f93414b1ca7f98fb62b5570d8d0bfbca0aa 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 1ddf7f5fa6db8578534d5fe62faf1cb1bc5f99ad..a1233e1b1ab60a103d2eca883826346f40c1ec81 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 36a77944622b8bd59bf51cdf424919712db5ddef..b05108f382da4a757b0381a106bfcbc3598dd51e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
index 27a452bc5b8d7511d1d2b4834097ff0d9da288a8..455b0555a6695518621ca558a19c77acf6410534 100644 (file)
@@ -160,7 +160,7 @@ static ctl_table rose_root_table[] = {
 
 void __init rose_register_sysctl(void)
 {
-       rose_table_header = register_sysctl_table(rose_root_table, 1);
+       rose_table_header = register_sysctl_table(rose_root_table);
 }
 
 void rose_unregister_sysctl(void)
index 0755ae028e4330073fa58af0b794ffbdbda24e38..884290754af7e905d9f3cab143cf448766e6ef66 100644 (file)
@@ -97,7 +97,7 @@ static ctl_table rxrpc_dir_sysctl_table[] = {
 int rxrpc_sysctl_init(void)
 {
 #ifdef CONFIG_SYSCTL
-       rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table, 0);
+       rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table);
        if (!rxrpc_sysctl)
                return -ENOMEM;
 #endif /* CONFIG_SYSCTL */
index ff5f4f333086974cbfa17a061c222a8bf54d6386..8e57be2df93625867d470eb5185fe22114ec513d 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <rxrpc/transport.h>
index dd0868dfbd9028d9555ae05189804e4865f81856..cb21617a5670516a9719623a5cceecd62bdca961 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 60095d86fd8f55bc843aa9ffbd8497ba33a512e6..87d0faf328672ef5d951bdd4b073a963ecc45389 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 0fdabfa9f4bf3e77e5fc376fb95745e768e28cb0..47f0b13242395d7b2e71447bdc1e9daaef2bba52 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 483897271f1598bb9d0659887f36a035e1d0381c..68f26cb278f9f74eba6a10e2e682782f4188dd33 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 53aa96cd579b8a0575166a77ad9973b1f816d059..3d6a2fcc9ce4e46aea8796108b054eb7d6e4d070 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 6ffe35da22b127e1e36bda2bdc119c7b08eb13e3..10a5a5c36f76cdd70ac7297dff3dcf215fceda6b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index f41f4ee0587af545112fe72c27620316d005af2a..5c6ffdb77d2d69bfdc35869b388a3e486ca18603 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index ea13c2c5b0618a3fff9a26eeec73d3c84f6159e4..fad08e521c24f91456590ac4cb6988776f80171b 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
index 2ce3ce5c66eb097f4738c4a53fa2ddefe6bf91cc..5dbb9d451f7300a0620019656f695dbe0506ab78 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index d3aea730d4c85d923cda240af52272d91cf6e5da..e85df07d8ce7a9e4d286505730be30a05f307409 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index ad2613790d853cb0d5ab116c36498ffa2909f260..1d4a1fb17608c2a3664711c8561cc07f8c659208 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index fde51f7848ebe1544a0bdaa9b08cb226ab24fc70..a2979d89798fc3270f62db9684013bacd76aaecc 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index a232671cfa4efdb44e482db65cb2b07781501d6c..0bcb16928d254101f03cce2607895dc89411143d 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 42103b2bdc519726f7c77152a61fc0d3e1d7622c..b4b36efce29248e37f1e2a941fa45743d76e4f52 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/tc_ematch/tc_em_nbyte.h>
index 8ad894b58fcef7223ef9fd16368af81cb36c96d9..e8f46169449d8c5985cba6baed0096aa1610b2ab 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/textsearch.h>
index d3ad36b361295ca371b8ec864738d5425546d79f..959c306c57143d9700a122d8332a3cd3ecca4a40 100644 (file)
@@ -84,7 +84,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
index 4158127bc202f60636ec1432b1ca4e4f68728c30..ecc988af4a9a8e798b5dd439b9ce3c008a8f97e9 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 48830cac1014cfe4f10972f0f4e40967ac0ab405..76c92e710a33486926c196e4f16b5c0ad4450ba2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 1f098d862f92b429e009c8cda471d03dee3f2afe..97cbb9aec946b56b2e0547206349ec615ec4a876 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 9f957ca5073b09c01192390f229d5ff37b7afb73..de889f23f22a5fdb29481c6696957e0832f95170 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index 6a66037abac9e80cb08e7bcc7c02b69681fc12b1..587123c61af94b654460ef237f02d8e6f4059feb 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
index fca6f75b0a0d8b553ea4c55f2484538f304e69ce..fa82b73c965bc17dadc5ecbaf90bd2f3dae06f21 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <linux/slab.h>
 #include <linux/in.h>
index 80294cbc0de60ecab79c8ac3ca597ffbd1c60138..fdb287a9e2e2c8c9b3baa97ca1ee11f8b59093eb 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/in.h>
 #include <net/sock.h>
 #include <net/ipv6.h>
index 286a8dbb63b7f56924bc99961e5a469c56429013..1404a9e2e78f1686487ac97142715455b16df42d 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/random.h>      /* get_random_bytes() */
index 01b27fb5dfc50f1e33942093f3fd159b9913e756..63fe1093b61635f06ecfc821e2c3caf6e68524eb 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
-#include <linux/sched.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
index 633cd178654b48da2c3acbba632ade51673bedcb..e2c679baf912ad35662837d4a6447057053218be 100644 (file)
@@ -254,7 +254,7 @@ static struct ctl_table_header * sctp_sysctl_header;
 /* Sysctl registration.  */
 void sctp_sysctl_register(void)
 {
-       sctp_sysctl_header = register_sysctl_table(sctp_root_table, 0);
+       sctp_sysctl_header = register_sysctl_table(sctp_root_table);
 }
 
 /* Sysctl deregistration.  */
index 0778c54424117ee48c6337714f3fe72403d4f7ae..9566e57ac7f58175a71021c5959a6c81e7b426f5 100644 (file)
@@ -1194,6 +1194,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
 {
        struct socket *sock1, *sock2;
        int fd1, fd2, err;
+       struct file *newfile1, *newfile2;
 
        /*
         * Obtain the first socket and check if the underlying protocol
@@ -1212,18 +1213,37 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
        if (err < 0)
                goto out_release_both;
 
-       fd1 = fd2 = -1;
+       fd1 = sock_alloc_fd(&newfile1);
+       if (unlikely(fd1 < 0))
+               goto out_release_both;
 
-       err = sock_map_fd(sock1);
-       if (err < 0)
+       fd2 = sock_alloc_fd(&newfile2);
+       if (unlikely(fd2 < 0)) {
+               put_filp(newfile1);
+               put_unused_fd(fd1);
                goto out_release_both;
-       fd1 = err;
+       }
 
-       err = sock_map_fd(sock2);
-       if (err < 0)
-               goto out_close_1;
-       fd2 = err;
+       err = sock_attach_fd(sock1, newfile1);
+       if (unlikely(err < 0)) {
+               goto out_fd2;
+       }
+
+       err = sock_attach_fd(sock2, newfile2);
+       if (unlikely(err < 0)) {
+               fput(newfile1);
+               goto out_fd1;
+       }
+
+       err = audit_fd_pair(fd1, fd2);
+       if (err < 0) {
+               fput(newfile1);
+               fput(newfile2);
+               goto out_fd;
+       }
 
+       fd_install(fd1, newfile1);
+       fd_install(fd2, newfile2);
        /* fd1 and fd2 may be already another descriptors.
         * Not kernel problem.
         */
@@ -1238,17 +1258,23 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
        sys_close(fd1);
        return err;
 
-out_close_1:
-       sock_release(sock2);
-       sys_close(fd1);
-       return err;
-
 out_release_both:
        sock_release(sock2);
 out_release_1:
        sock_release(sock1);
 out:
        return err;
+
+out_fd2:
+       put_filp(newfile1);
+       sock_release(sock1);
+out_fd1:
+       put_filp(newfile2);
+       sock_release(sock2);
+out_fd:
+       put_unused_fd(fd1);
+       put_unused_fd(fd2);
+       goto out;
 }
 
 /*
index 3be257dc32b2af4e26a5f1028ac8dc30586b7e28..3df9fccab2f8b34c17b7d04208a0c46f3d9d4219 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/sunrpc/clnt.h>
-#include <linux/sched.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_AUTH
index 2878e20ebd0422beb718eb197371e7c59d33f832..74ba7d443dfc06ec7162c2d7b1735bc2bfc67e06 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/sunrpc/clnt.h>
index d85fddeb6388f54e4293b85e1e64da965c2ebd76..43ecf62f12ef2b6797631b420009198d1ce9d883 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
 #include <linux/init.h>
@@ -137,7 +136,7 @@ EXPORT_SYMBOL(nlm_debug);
 
 extern int register_rpc_pipefs(void);
 extern void unregister_rpc_pipefs(void);
-extern struct cache_detail ip_map_cache;
+extern struct cache_detail ip_map_cache, unix_gid_cache;
 extern int init_socket_xprt(void);
 extern void cleanup_socket_xprt(void);
 
@@ -157,6 +156,7 @@ init_sunrpc(void)
        rpc_proc_init();
 #endif
        cache_register(&ip_map_cache);
+       cache_register(&unix_gid_cache);
        init_socket_xprt();
 out:
        return err;
@@ -170,6 +170,8 @@ cleanup_sunrpc(void)
        rpc_destroy_mempool();
        if (cache_unregister(&ip_map_cache))
                printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
+       if (cache_unregister(&unix_gid_cache))
+             printk(KERN_ERR "sunrpc: failed to unregister unix_gid cache\n");
 #ifdef RPC_DEBUG
        rpc_unregister_sysctl();
 #endif
index 811a24c83262fc011d90643c9ff1e47b329ac47e..f5c3808bf85ab7cf1d03edaf8c43bbebc5faa3cf 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
index 4b775dbf580d819f852afa62be6e4901b93452b4..9bae4090254c89f7fb0de7ab25529eac5ea2c90b 100644 (file)
@@ -418,6 +418,214 @@ svcauth_unix_info_release(void *info)
        cache_put(&ipm->h, &ip_map_cache);
 }
 
+/****************************************************************************
+ * auth.unix.gid cache
+ * simple cache to map a UID to a list of GIDs
+ * because AUTH_UNIX aka AUTH_SYS has a max of 16
+ */
+#define        GID_HASHBITS    8
+#define        GID_HASHMAX     (1<<GID_HASHBITS)
+#define        GID_HASHMASK    (GID_HASHMAX - 1)
+
+struct unix_gid {
+       struct cache_head       h;
+       uid_t                   uid;
+       struct group_info       *gi;
+};
+static struct cache_head       *gid_table[GID_HASHMAX];
+
+static void unix_gid_put(struct kref *kref)
+{
+       struct cache_head *item = container_of(kref, struct cache_head, ref);
+       struct unix_gid *ug = container_of(item, struct unix_gid, h);
+       if (test_bit(CACHE_VALID, &item->flags) &&
+           !test_bit(CACHE_NEGATIVE, &item->flags))
+               put_group_info(ug->gi);
+       kfree(ug);
+}
+
+static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
+{
+       struct unix_gid *orig = container_of(corig, struct unix_gid, h);
+       struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+       return orig->uid == new->uid;
+}
+static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
+{
+       struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+       struct unix_gid *item = container_of(citem, struct unix_gid, h);
+       new->uid = item->uid;
+}
+static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
+{
+       struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+       struct unix_gid *item = container_of(citem, struct unix_gid, h);
+
+       get_group_info(item->gi);
+       new->gi = item->gi;
+}
+static struct cache_head *unix_gid_alloc(void)
+{
+       struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
+       if (g)
+               return &g->h;
+       else
+               return NULL;
+}
+
+static void unix_gid_request(struct cache_detail *cd,
+                            struct cache_head *h,
+                            char **bpp, int *blen)
+{
+       char tuid[20];
+       struct unix_gid *ug = container_of(h, struct unix_gid, h);
+
+       snprintf(tuid, 20, "%u", ug->uid);
+       qword_add(bpp, blen, tuid);
+       (*bpp)[-1] = '\n';
+}
+
+static struct unix_gid *unix_gid_lookup(uid_t uid);
+extern struct cache_detail unix_gid_cache;
+
+static int unix_gid_parse(struct cache_detail *cd,
+                       char *mesg, int mlen)
+{
+       /* uid expiry Ngid gid0 gid1 ... gidN-1 */
+       int uid;
+       int gids;
+       int rv;
+       int i;
+       int err;
+       time_t expiry;
+       struct unix_gid ug, *ugp;
+
+       if (mlen <= 0 || mesg[mlen-1] != '\n')
+               return -EINVAL;
+       mesg[mlen-1] = 0;
+
+       rv = get_int(&mesg, &uid);
+       if (rv)
+               return -EINVAL;
+       ug.uid = uid;
+
+       expiry = get_expiry(&mesg);
+       if (expiry == 0)
+               return -EINVAL;
+
+       rv = get_int(&mesg, &gids);
+       if (rv || gids < 0 || gids > 8192)
+               return -EINVAL;
+
+       ug.gi = groups_alloc(gids);
+       if (!ug.gi)
+               return -ENOMEM;
+
+       for (i = 0 ; i < gids ; i++) {
+               int gid;
+               rv = get_int(&mesg, &gid);
+               err = -EINVAL;
+               if (rv)
+                       goto out;
+               GROUP_AT(ug.gi, i) = gid;
+       }
+
+       ugp = unix_gid_lookup(uid);
+       if (ugp) {
+               struct cache_head *ch;
+               ug.h.flags = 0;
+               ug.h.expiry_time = expiry;
+               ch = sunrpc_cache_update(&unix_gid_cache,
+                                        &ug.h, &ugp->h,
+                                        hash_long(uid, GID_HASHBITS));
+               if (!ch)
+                       err = -ENOMEM;
+               else {
+                       err = 0;
+                       cache_put(ch, &unix_gid_cache);
+               }
+       } else
+               err = -ENOMEM;
+ out:
+       if (ug.gi)
+               put_group_info(ug.gi);
+       return err;
+}
+
+static int unix_gid_show(struct seq_file *m,
+                        struct cache_detail *cd,
+                        struct cache_head *h)
+{
+       struct unix_gid *ug;
+       int i;
+       int glen;
+
+       if (h == NULL) {
+               seq_puts(m, "#uid cnt: gids...\n");
+               return 0;
+       }
+       ug = container_of(h, struct unix_gid, h);
+       if (test_bit(CACHE_VALID, &h->flags) &&
+           !test_bit(CACHE_NEGATIVE, &h->flags))
+               glen = ug->gi->ngroups;
+       else
+               glen = 0;
+
+       seq_printf(m, "%d %d:", ug->uid, glen);
+       for (i = 0; i < glen; i++)
+               seq_printf(m, " %d", GROUP_AT(ug->gi, i));
+       seq_printf(m, "\n");
+       return 0;
+}
+
+struct cache_detail unix_gid_cache = {
+       .owner          = THIS_MODULE,
+       .hash_size      = GID_HASHMAX,
+       .hash_table     = gid_table,
+       .name           = "auth.unix.gid",
+       .cache_put      = unix_gid_put,
+       .cache_request  = unix_gid_request,
+       .cache_parse    = unix_gid_parse,
+       .cache_show     = unix_gid_show,
+       .match          = unix_gid_match,
+       .init           = unix_gid_init,
+       .update         = unix_gid_update,
+       .alloc          = unix_gid_alloc,
+};
+
+static struct unix_gid *unix_gid_lookup(uid_t uid)
+{
+       struct unix_gid ug;
+       struct cache_head *ch;
+
+       ug.uid = uid;
+       ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h,
+                                hash_long(uid, GID_HASHBITS));
+       if (ch)
+               return container_of(ch, struct unix_gid, h);
+       else
+               return NULL;
+}
+
+static int unix_gid_find(uid_t uid, struct group_info **gip,
+                        struct svc_rqst *rqstp)
+{
+       struct unix_gid *ug = unix_gid_lookup(uid);
+       if (!ug)
+               return -EAGAIN;
+       switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
+       case -ENOENT:
+               *gip = NULL;
+               return 0;
+       case 0:
+               *gip = ug->gi;
+               get_group_info(*gip);
+               return 0;
+       default:
+               return -EAGAIN;
+       }
+}
+
 static int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
@@ -543,12 +751,19 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > 16 || (len -= (slen + 2)*4) < 0)
                goto badcred;
-       cred->cr_group_info = groups_alloc(slen);
-       if (cred->cr_group_info == NULL)
+       if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
+           == -EAGAIN)
                return SVC_DROP;
-       for (i = 0; i < slen; i++)
-               GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
-
+       if (cred->cr_group_info == NULL) {
+               cred->cr_group_info = groups_alloc(slen);
+               if (cred->cr_group_info == NULL)
+                       return SVC_DROP;
+               for (i = 0; i < slen; i++)
+                       GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
+       } else {
+               for (i = 0; i < slen ; i++)
+                       svc_getnl(argv);
+       }
        if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
                *authp = rpc_autherr_badverf;
                return SVC_DENIED;
index 47d8df2b5eb2a94bf378704a748555efdcc86221..738db32a287d0be1500e0f67d1ce3676f439783b 100644 (file)
@@ -35,14 +35,8 @@ static ctl_table             sunrpc_table[];
 void
 rpc_register_sysctl(void)
 {
-       if (!sunrpc_table_header) {
-               sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
-#ifdef CONFIG_PROC_FS
-               if (sunrpc_table[0].de)
-                       sunrpc_table[0].de->owner = THIS_MODULE;
-#endif
-       }
-
+       if (!sunrpc_table_header)
+               sunrpc_table_header = register_sysctl_table(sunrpc_table);
 }
 
 void
index 64736b3a59a782f7992d8f8ea5ec63ed3718c970..a5a32029e7283e9ef2bf7b834fef64e202e3330d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/socket.h>
@@ -1636,13 +1635,8 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_
 int init_socket_xprt(void)
 {
 #ifdef RPC_DEBUG
-       if (!sunrpc_table_header) {
-               sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
-#ifdef CONFIG_PROC_FS
-               if (sunrpc_table[0].de)
-                       sunrpc_table[0].de->owner = THIS_MODULE;
-#endif
-       }
+       if (!sunrpc_table_header)
+               sunrpc_table_header = register_sysctl_table(sunrpc_table);
 #endif
 
        return 0;
index f8bcf5d114d9738ba86e84d58fde8d84ffba708e..f20b7ea7c5553264b5ecd18fc3e5196a8f012500 100644 (file)
@@ -65,7 +65,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/un.h>
index 690ffa5d5bfbf5bd5e01e0bf0fa61ca263f68b10..eb0bd57ebadac12b613e0881f9b6566aa0185cc6 100644 (file)
@@ -50,7 +50,7 @@ static struct ctl_table_header * unix_sysctl_header;
 
 void unix_sysctl_register(void)
 {
-       unix_sysctl_header = register_sysctl_table(unix_root_table, 0);
+       unix_sysctl_header = register_sysctl_table(unix_root_table);
 }
 
 void unix_sysctl_unregister(void)
index 5f631061c229457e93981ded6809683c474af17e..a59b77f18234d498748d8dac63f55889eb742f03 100644 (file)
@@ -106,7 +106,7 @@ static struct ctl_table x25_root_table[] = {
 
 void __init x25_register_sysctl(void)
 {
-       x25_table_header = register_sysctl_table(x25_root_table, 1);
+       x25_table_header = register_sysctl_table(x25_root_table);
 }
 
 void x25_unregister_sysctl(void)
index c0ae0a7ddb427e2ba05fc4c67a0b64ddf4f1fbb4..512c2f5c341d015cc06b5e9361ee06592ab57b9d 100644 (file)
@@ -89,6 +89,7 @@ void ConfigItem::okRename(int col)
 {
        Parent::okRename(col);
        sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+       listView()->updateList(this);
 }
 #endif
 
@@ -605,6 +606,8 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
 
                visible = menu_is_visible(child);
                if (showAll || visible) {
+                       if (!child->sym && !child->list && !child->prompt)
+                               continue;
                        if (!item || item->menu != child)
                                item = new ConfigItem(parent, last, child, visible);
                        else
@@ -1247,6 +1250,7 @@ void ConfigSearchWindow::search(void)
 
        free(result);
        list->list->clear();
+       info->clear();
 
        result = sym_re_search(editField->text().latin1());
        if (!result)
@@ -1316,7 +1320,7 @@ ConfigMainWindow::ConfigMainWindow(void)
        conf_changed();
        QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
          connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
-       QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
+       QAction *searchAction = new QAction("Find", "&Find", CTRL+Key_F, this);
          connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
        QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
          connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
@@ -1373,10 +1377,13 @@ ConfigMainWindow::ConfigMainWindow(void)
        saveAction->addTo(config);
        saveAsAction->addTo(config);
        config->insertSeparator();
-       searchAction->addTo(config);
-       config->insertSeparator();
        quitAction->addTo(config);
 
+       // create edit menu
+       QPopupMenu* editMenu = new QPopupMenu(this);
+       menu->insertItem("&Edit", editMenu);
+       searchAction->addTo(editMenu);
+
        // create options menu
        QPopupMenu* optionMenu = new QPopupMenu(this);
        menu->insertItem("&Option", optionMenu);
@@ -1467,7 +1474,10 @@ void ConfigMainWindow::searchConfig(void)
 void ConfigMainWindow::changeMenu(struct menu *menu)
 {
        configList->setRootMenu(menu);
-       backAction->setEnabled(TRUE);
+       if (configList->rootEntry->parent == &rootmenu)
+               backAction->setEnabled(FALSE);
+       else
+               backAction->setEnabled(TRUE);
 }
 
 void ConfigMainWindow::setMenuLink(struct menu *menu)
index d7b8a384b4a7991960d33c7c01c60d6f58f92fd6..82d0af46f0ef01a6b10ccdbfc22614cc56436bed 100755 (executable)
@@ -58,7 +58,7 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
     echo \#define LINUX_COMPILE_DOMAIN
   fi
 
-  echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
+  echo \#define LINUX_COMPILER \"`LC_ALL=C LANG=C $CC -v 2>&1 | tail -n 1`\"
 ) > .tmpcompile
 
 # Only replace the real compile.h if the new one is different,
index 52a17ab97eb0c371070b4e310fb3822936ed79a1..4b06c5eea7283a94524c149f598cfef66872eaaa 100755 (executable)
@@ -4,12 +4,15 @@
 # Build U-Boot image when `mkimage' tool is available.
 #
 
-MKIMAGE=$(type -path mkimage)
+MKIMAGE=$(type -path ${CROSS_COMPILE}mkimage)
 
 if [ -z "${MKIMAGE}" ]; then
-       # Doesn't exist
-       echo '"mkimage" command not found - U-Boot images will not be built' >&2
-       exit 0;
+       MKIMAGE=$(type -path mkimage)
+       if [ -z "${MKIMAGE}" ]; then
+               # Doesn't exist
+               echo '"mkimage" command not found - U-Boot images will not be built' >&2
+               exit 0;
+       fi
 fi
 
 # Call "mkimage" to create U-Boot image
index 2aa47623f5f8cec51322f883b60d6c932722663c..569e68410d7a96a78f2673d4fdaf12bfc65136af 100644 (file)
@@ -641,12 +641,20 @@ static int secref_whitelist(const char *modname, const char *tosec,
        if (f1 && f2)
                return 1;
 
-       /* Whitelist all references from .pci_fixup section if vmlinux */
+       /* Whitelist all references from .pci_fixup section if vmlinux
+        * Whitelist all refereces from .text.head to .init.data if vmlinux
+        * Whitelist all refereces from .text.head to .init.text if vmlinux
+        */
        if (is_vmlinux(modname)) {
                if ((strcmp(fromsec, ".pci_fixup") == 0) &&
                    (strcmp(tosec, ".init.text") == 0))
                return 1;
 
+               if ((strcmp(fromsec, ".text.head") == 0) &&
+                       ((strcmp(tosec, ".init.data") == 0) ||
+                       (strcmp(tosec, ".init.text") == 0)))
+               return 1;
+
                /* Check for pattern 3 */
                for (s = pat3refsym; *s; s++)
                        if (strcmp(refsymname, *s) == 0)
index bcdb285337339d108160e8fb305220088dec9eb5..e10ec995f2751101d39a7dfbd145cd8ce52cc6ee 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/keyctl.h>
 #include <linux/compat.h>
index 5bbfdebb7acfb79436d615851ec91d57c2d74c49..7c687d568221cd71a3e863b9c9c50f5cd9352005 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
index ee4e0701b6e0bbfb431c5d1fa5672ab036492fa0..fc8601b2b7acabde473cc86a0fdc4b342a00e97a 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/security.h>
 
 #define SECURITY_FRAMEWORK_VERSION     "1.0.0"
index 35eb8de892fc513bd187ad3c5acbce9cd271ebd1..b1ac22d231954bc5e900c07da670962c953ba1c2 100644 (file)
@@ -1077,6 +1077,9 @@ static int inode_has_perm(struct task_struct *tsk,
        struct inode_security_struct *isec;
        struct avc_audit_data ad;
 
+       if (unlikely (IS_PRIVATE (inode)))
+               return 0;
+
        tsec = tsk->security;
        isec = inode->i_security;
 
@@ -1423,6 +1426,47 @@ static int selinux_capable(struct task_struct *tsk, int cap)
        return task_has_capability(tsk,cap);
 }
 
+static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+{
+       int buflen, rc;
+       char *buffer, *path, *end;
+
+       rc = -ENOMEM;
+       buffer = (char*)__get_free_page(GFP_KERNEL);
+       if (!buffer)
+               goto out;
+
+       buflen = PAGE_SIZE;
+       end = buffer+buflen;
+       *--end = '\0';
+       buflen--;
+       path = end-1;
+       *path = '/';
+       while (table) {
+               const char *name = table->procname;
+               size_t namelen = strlen(name);
+               buflen -= namelen + 1;
+               if (buflen < 0)
+                       goto out_free;
+               end -= namelen;
+               memcpy(end, name, namelen);
+               *--end = '/';
+               path = end;
+               table = table->parent;
+       }
+       buflen -= 4;
+       if (buflen < 0)
+               goto out_free;
+       end -= 4;
+       memcpy(end, "/sys", 4);
+       path = end;
+       rc = security_genfs_sid("proc", path, tclass, sid);
+out_free:
+       free_page((unsigned long)buffer);
+out:
+       return rc;
+}
+
 static int selinux_sysctl(ctl_table *table, int op)
 {
        int error = 0;
@@ -1437,8 +1481,8 @@ static int selinux_sysctl(ctl_table *table, int op)
 
        tsec = current->security;
 
-       rc = selinux_proc_get_sid(table->de, (op == 001) ?
-                                 SECCLASS_DIR : SECCLASS_FILE, &tsid);
+       rc = selinux_sysctl_get_sid(table, (op == 0001) ?
+                                   SECCLASS_DIR : SECCLASS_FILE, &tsid);
        if (rc) {
                /* Default to the well-defined sysctl SID. */
                tsid = SECINITSID_SYSCTL;
index 871c33bd0741315638ef15dce4ef1e888850246b..d78f9ff30da906bb30edefcc9f63aaccf2fce5aa 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include "flask.h"
 #include "security.h"
 #include "sidtab.h"
index 53675cf4de44c1bc4968c3227f45ab46fb573921..5190d7acdb9fd6306761c8a7da2a689d561e1f0c 100644 (file)
@@ -65,10 +65,12 @@ static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)
  *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
  *  register.
  */
-static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
+static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+                           unsigned short val)
 {
        struct aaci *aaci = ac97->private_data;
        u32 v;
+       int timeout = 5000;
 
        if (ac97->num >= 4)
                return;
@@ -89,7 +91,11 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned
         */
        do {
                v = readl(aaci->base + AACI_SLFR);
-       } while (v & (SLFR_1TXB|SLFR_2TXB));
+       } while ((v & (SLFR_1TXB|SLFR_2TXB)) && timeout--);
+
+       if (!timeout)
+               dev_err(&aaci->dev->dev,
+                       "timeout waiting for write to complete\n");
 
        mutex_unlock(&aaci->ac97_sem);
 }
@@ -101,6 +107,8 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
        struct aaci *aaci = ac97->private_data;
        u32 v;
+       int timeout = 5000;
+       int retries = 10;
 
        if (ac97->num >= 4)
                return ~0;
@@ -119,7 +127,13 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
         */
        do {
                v = readl(aaci->base + AACI_SLFR);
-       } while (v & SLFR_1TXB);
+       } while ((v & SLFR_1TXB) && timeout--);
+
+       if (!timeout) {
+               dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
+               v = ~0;
+               goto out;
+       }
 
        /*
         * Give the AC'97 codec more than enough time
@@ -130,21 +144,35 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        /*
         * Wait for slot 2 to indicate data.
         */
+       timeout = 5000;
        do {
                cond_resched();
                v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
-       } while (v != (SLFR_1RXV|SLFR_2RXV));
+       } while ((v != (SLFR_1RXV|SLFR_2RXV)) && timeout--);
 
-       v = readl(aaci->base + AACI_SL1RX) >> 12;
-       if (v == reg) {
-               v = readl(aaci->base + AACI_SL2RX) >> 4;
-       } else {
-               dev_err(&aaci->dev->dev,
-                       "wrong ac97 register read back (%x != %x)\n",
-                       v, reg);
+       if (!timeout) {
+               dev_err(&aaci->dev->dev, "timeout on RX valid\n");
                v = ~0;
+               goto out;
        }
 
+       do {
+               v = readl(aaci->base + AACI_SL1RX) >> 12;
+               if (v == reg) {
+                       v = readl(aaci->base + AACI_SL2RX) >> 4;
+                       break;
+               } else if (--retries) {
+                       dev_warn(&aaci->dev->dev,
+                                "ac97 read back fail.  retry\n");
+                       continue;
+               } else {
+                       dev_warn(&aaci->dev->dev,
+                               "wrong ac97 register read back (%x != %x)\n",
+                               v, reg);
+                       v = ~0;
+               }
+       } while (retries);
+ out:
        mutex_unlock(&aaci->ac97_sem);
        return v;
 }
@@ -164,10 +192,70 @@ static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
 /*
  * Interrupt support.
  */
-static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 {
+       if (mask & ISR_ORINTR) {
+               dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);
+               writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);
+       }
+
+       if (mask & ISR_RXTOINTR) {
+               dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);
+               writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);
+       }
+
+       if (mask & ISR_RXINTR) {
+               struct aaci_runtime *aacirun = &aaci->capture;
+               void *ptr;
+
+               if (!aacirun->substream || !aacirun->start) {
+                       dev_warn(&aaci->dev->dev, "RX interrupt???");
+                       writel(0, aacirun->base + AACI_IE);
+                       return;
+               }
+               ptr = aacirun->ptr;
+
+               do {
+                       unsigned int len = aacirun->fifosz;
+                       u32 val;
+
+                       if (aacirun->bytes <= 0) {
+                               aacirun->bytes += aacirun->period;
+                               aacirun->ptr = ptr;
+                               spin_unlock(&aaci->lock);
+                               snd_pcm_period_elapsed(aacirun->substream);
+                               spin_lock(&aaci->lock);
+                       }
+                       if (!(aacirun->cr & CR_EN))
+                               break;
+
+                       val = readl(aacirun->base + AACI_SR);
+                       if (!(val & SR_RXHF))
+                               break;
+                       if (!(val & SR_RXFF))
+                               len >>= 1;
+
+                       aacirun->bytes -= len;
+
+                       /* reading 16 bytes at a time */
+                       for( ; len > 0; len -= 16) {
+                               asm(
+                                       "ldmia  %1, {r0, r1, r2, r3}\n\t"
+                                       "stmia  %0!, {r0, r1, r2, r3}"
+                                       : "+r" (ptr)
+                                       : "r" (aacirun->fifo)
+                                       : "r0", "r1", "r2", "r3", "cc");
+
+                               if (ptr >= aacirun->end)
+                                       ptr = aacirun->start;
+                       }
+               } while(1);
+               aacirun->ptr = ptr;
+       }
+
        if (mask & ISR_URINTR) {
-               writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+               dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
+               writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
        }
 
        if (mask & ISR_TXINTR) {
@@ -192,7 +280,7 @@ static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
                                snd_pcm_period_elapsed(aacirun->substream);
                                spin_lock(&aaci->lock);
                        }
-                       if (!(aacirun->cr & TXCR_TXEN))
+                       if (!(aacirun->cr & CR_EN))
                                break;
 
                        val = readl(aacirun->base + AACI_SR);
@@ -233,7 +321,7 @@ static irqreturn_t aaci_irq(int irq, void *devid)
                u32 m = mask;
                for (i = 0; i < 4; i++, m >>= 7) {
                        if (m & 0x7f) {
-                               aaci_fifo_irq(aaci, m);
+                               aaci_fifo_irq(aaci, i, m);
                        }
                }
        }
@@ -330,8 +418,9 @@ static struct snd_pcm_hardware aaci_hw_info = {
        .periods_max            = PAGE_SIZE / 16,
 };
 
-static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream,
-                        struct aaci_runtime *aacirun)
+static int __aaci_pcm_open(struct aaci *aaci,
+                          struct snd_pcm_substream *substream,
+                          struct aaci_runtime *aacirun)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
@@ -380,7 +469,7 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
        struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
 
-       WARN_ON(aacirun->cr & TXCR_TXEN);
+       WARN_ON(aacirun->cr & CR_EN);
 
        aacirun->substream = NULL;
        free_irq(aaci->dev->irq[0], aaci);
@@ -395,7 +484,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
        /*
         * This must not be called with the device enabled.
         */
-       WARN_ON(aacirun->cr & TXCR_TXEN);
+       WARN_ON(aacirun->cr & CR_EN);
 
        if (aacirun->pcm_open)
                snd_ac97_pcm_close(aacirun->pcm);
@@ -422,9 +511,15 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
        if (err < 0)
                goto out;
 
-       err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
-                               params_channels(params),
-                               aacirun->pcm->r[0].slots);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+                                       params_channels(params),
+                                       aacirun->pcm->r[0].slots);
+       else
+               err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+                                       params_channels(params),
+                                       aacirun->pcm->r[1].slots);
+
        if (err)
                goto out;
 
@@ -467,9 +562,9 @@ static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_str
  * Playback specific ALSA stuff
  */
 static const u32 channels_to_txmask[] = {
-       [2] = TXCR_TX3 | TXCR_TX4,
-       [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
-       [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+       [2] = CR_SL3 | CR_SL4,
+       [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
+       [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
 };
 
 /*
@@ -504,7 +599,7 @@ aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
                                 chan_mask);
 }
 
-static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
 {
        struct aaci *aaci = substream->private_data;
        int ret;
@@ -519,7 +614,12 @@ static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
        if (ret)
                return ret;
 
-       return aaci_pcm_open(aaci, substream, &aaci->playback);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
+       } else {
+               ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
+       }
+       return ret;
 }
 
 static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -540,11 +640,11 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
         * FIXME: double rate slots?
         */
        if (ret >= 0) {
-               aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
                aacirun->cr |= channels_to_txmask[channels];
 
                aacirun->fifosz = aaci->fifosize * 4;
-               if (aacirun->cr & TXCR_COMPACT)
+               if (aacirun->cr & CR_COMPACT)
                        aacirun->fifosz >>= 1;
        }
        return ret;
@@ -557,7 +657,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
        ie = readl(aacirun->base + AACI_IE);
        ie &= ~(IE_URIE|IE_TXIE);
        writel(ie, aacirun->base + AACI_IE);
-       aacirun->cr &= ~TXCR_TXEN;
+       aacirun->cr &= ~CR_EN;
        aaci_chan_wait_ready(aacirun);
        writel(aacirun->cr, aacirun->base + AACI_TXCR);
 }
@@ -567,7 +667,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
        u32 ie;
 
        aaci_chan_wait_ready(aacirun);
-       aacirun->cr |= TXCR_TXEN;
+       aacirun->cr |= CR_EN;
 
        ie = readl(aacirun->base + AACI_IE);
        ie |= IE_URIE | IE_TXIE;
@@ -615,7 +715,7 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
 }
 
 static struct snd_pcm_ops aaci_playback_ops = {
-       .open           = aaci_pcm_playback_open,
+       .open           = aaci_pcm_open,
        .close          = aaci_pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = aaci_pcm_playback_hw_params,
@@ -626,7 +726,133 @@ static struct snd_pcm_ops aaci_playback_ops = {
        .mmap           = aaci_pcm_mmap,
 };
 
+static int aaci_pcm_capture_hw_params(snd_pcm_substream_t *substream,
+                                     snd_pcm_hw_params_t *params)
+{
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+       int ret;
+
+       ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+       if (ret >= 0) {
+               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+
+               /* Line in record: slot 3 and 4 */
+               aacirun->cr |= CR_SL3 | CR_SL4;
+
+               aacirun->fifosz = aaci->fifosize * 4;
+
+               if (aacirun->cr & CR_COMPACT)
+                       aacirun->fifosz >>= 1;
+       }
+       return ret;
+}
+
+static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
+{
+       u32 ie;
+
+       aaci_chan_wait_ready(aacirun);
+
+       ie = readl(aacirun->base + AACI_IE);
+       ie &= ~(IE_ORIE | IE_RXIE);
+       writel(ie, aacirun->base+AACI_IE);
+
+       aacirun->cr &= ~CR_EN;
+
+       writel(aacirun->cr, aacirun->base + AACI_RXCR);
+}
+
+static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
+{
+       u32 ie;
+
+       aaci_chan_wait_ready(aacirun);
+
+#ifdef DEBUG
+       /* RX Timeout value: bits 28:17 in RXCR */
+       aacirun->cr |= 0xf << 17;
+#endif
+
+       aacirun->cr |= CR_EN;
+       writel(aacirun->cr, aacirun->base + AACI_RXCR);
+
+       ie = readl(aacirun->base + AACI_IE);
+       ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full
+       writel(ie, aacirun->base + AACI_IE);
+}
+
+static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
+
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&aaci->lock, flags);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               aaci_pcm_capture_start(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_RESUME:
+               aaci_pcm_capture_start(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+               aaci_pcm_capture_stop(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               aaci_pcm_capture_stop(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               break;
+
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       spin_unlock_irqrestore(&aaci->lock, flags);
+
+       return ret;
+}
 
+static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct aaci *aaci = substream->private_data;
+
+       aaci_pcm_prepare(substream);
+
+       /* allow changing of sample rate */
+       aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */
+       aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
+       aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);
+
+       /* Record select: Mic: 0, Aux: 3, Line: 4 */
+       aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);
+
+       return 0;
+}
+
+static snd_pcm_ops_t aaci_capture_ops = {
+       .open           = aaci_pcm_open,
+       .close          = aaci_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = aaci_pcm_capture_hw_params,
+       .hw_free        = aaci_pcm_hw_free,
+       .prepare        = aaci_pcm_capture_prepare,
+       .trigger        = aaci_pcm_capture_trigger,
+       .pointer        = aaci_pcm_pointer,
+       .mmap           = aaci_pcm_mmap,
+};
 
 /*
  * Power Management.
@@ -666,7 +892,7 @@ static int aaci_resume(struct amba_device *dev)
 
 
 static struct ac97_pcm ac97_defs[] __devinitdata = {
-       [0] = {         /* Front PCM */
+       [0] = { /* Front PCM */
                .exclusive = 1,
                .r = {
                        [0] = {
@@ -740,6 +966,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
        ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
        if (ret)
                goto out;
+       aaci->ac97 = ac97;
 
        /*
         * Disable AC97 PC Beep input on audio codecs.
@@ -752,6 +979,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
                goto out;
 
        aaci->playback.pcm = &ac97_bus->pcms[0];
+       aaci->capture.pcm  = &ac97_bus->pcms[1];
 
  out:
        return ret;
@@ -801,7 +1029,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
        struct snd_pcm *pcm;
        int ret;
 
-       ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+       ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);
        if (ret == 0) {
                aaci->pcm = pcm;
                pcm->private_data = aaci;
@@ -810,6 +1038,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
                strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
 
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
        }
 
        return ret;
@@ -817,15 +1046,15 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
 
 static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 {
-       void __iomem *base = aaci->base + AACI_CSCH1;
+       struct aaci_runtime *aacirun = &aaci->playback;
        int i;
 
-       writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+       writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
 
-       for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
-               writel(0, aaci->base + AACI_DR1);
+       for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+               writel(0, aacirun->fifo);
 
-       writel(0, base + AACI_TXCR);
+       writel(0, aacirun->base + AACI_TXCR);
 
        /*
         * Re-initialise the AACI after the FIFO depth test, to
@@ -872,6 +1101,12 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
        aaci->playback.base = aaci->base + AACI_CSCH1;
        aaci->playback.fifo = aaci->base + AACI_DR1;
 
+       /*
+        * Capture uses AACI channel 0
+        */
+       aaci->capture.base = aaci->base + AACI_CSCH1;
+       aaci->capture.fifo = aaci->base + AACI_DR1;
+
        for (i = 0; i < 4; i++) {
                void __iomem *base = aaci->base + i * 0x14;
 
@@ -907,7 +1142,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
        ret = snd_card_register(aaci->card);
        if (ret == 0) {
                dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
-                       aaci->fifosize);
+                        aaci->fifosize);
                amba_set_drvdata(dev, aaci->card);
                return ret;
        }
index 9175ff9ded0165500514d630edd4e1603ad34d16..924f69c1c44c4bd39340c006db12572ab80a341e 100644 (file)
 #define AACI_DR4       0x0f0   /* data read/written fifo 4 */
 
 /*
- * transmit fifo control register. P48
+ * TX/RX fifo control register (CR). P48
  */
-#define TXCR_FEN       (1 << 16)       /* fifo enable */
-#define TXCR_COMPACT   (1 << 15)       /* compact mode */
-#define TXCR_TSZ16     (0 << 13)       /* 16 bits */
-#define TXCR_TSZ18     (1 << 13)       /* 18 bits */
-#define TXCR_TSZ20     (2 << 13)       /* 20 bits */
-#define TXCR_TSZ12     (3 << 13)       /* 12 bits */
-#define TXCR_TX12      (1 << 12)       /* transmits slot 12 */
-#define TXCR_TX11      (1 << 11)       /* transmits slot 12 */
-#define TXCR_TX10      (1 << 10)       /* transmits slot 12 */
-#define TXCR_TX9       (1 << 9)        /* transmits slot 12 */
-#define TXCR_TX8       (1 << 8)        /* transmits slot 12 */
-#define TXCR_TX7       (1 << 7)        /* transmits slot 12 */
-#define TXCR_TX6       (1 << 6)        /* transmits slot 12 */
-#define TXCR_TX5       (1 << 5)        /* transmits slot 12 */
-#define TXCR_TX4       (1 << 4)        /* transmits slot 12 */
-#define TXCR_TX3       (1 << 3)        /* transmits slot 12 */
-#define TXCR_TX2       (1 << 2)        /* transmits slot 12 */
-#define TXCR_TX1       (1 << 1)        /* transmits slot 12 */
-#define TXCR_TXEN      (1 << 0)        /* transmit enable */
+#define CR_FEN         (1 << 16)       /* fifo enable */
+#define CR_COMPACT     (1 << 15)       /* compact mode */
+#define CR_SZ16                (0 << 13)       /* 16 bits */
+#define CR_SZ18                (1 << 13)       /* 18 bits */
+#define CR_SZ20                (2 << 13)       /* 20 bits */
+#define CR_SZ12                (3 << 13)       /* 12 bits */
+#define CR_SL12                (1 << 12)
+#define CR_SL11                (1 << 11)
+#define CR_SL10                (1 << 10)
+#define CR_SL9         (1 << 9)
+#define CR_SL8         (1 << 8)
+#define CR_SL7         (1 << 7)
+#define CR_SL6         (1 << 6)
+#define CR_SL5         (1 << 5)
+#define CR_SL4         (1 << 4)
+#define CR_SL3         (1 << 3)
+#define CR_SL2         (1 << 2)
+#define CR_SL1         (1 << 1)
+#define CR_EN          (1 << 0)        /* transmit enable */
 
 /*
  * status register bits. P49
@@ -229,6 +229,7 @@ struct aaci {
        /* AC'97 */
        struct mutex            ac97_sem;
        struct snd_ac97_bus     *ac97_bus;
+       struct snd_ac97         *ac97;
 
        u32                     maincr;
        spinlock_t              lock;
index dede954b2c657e0c1db1f135c38da9f630e5442b..28db4be7a16f28b79d582689c8fb1388927310b3 100644 (file)
@@ -305,7 +305,7 @@ static int pxa2xx_ac97_resume(struct platform_device *dev)
 #define pxa2xx_ac97_resume     NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct platform_device *dev)
+static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
 {
        struct snd_card *card;
        struct snd_ac97_bus *ac97_bus;
@@ -369,7 +369,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
        return ret;
 }
 
-static int pxa2xx_ac97_remove(struct platform_device *dev)
+static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
 {
        struct snd_card *card = platform_get_drvdata(dev);
 
@@ -386,7 +386,7 @@ static int pxa2xx_ac97_remove(struct platform_device *dev)
 
 static struct platform_driver pxa2xx_ac97_driver = {
        .probe          = pxa2xx_ac97_probe,
-       .remove         = pxa2xx_ac97_remove,
+       .remove         = __devexit_p(pxa2xx_ac97_remove),
        .suspend        = pxa2xx_ac97_suspend,
        .resume         = pxa2xx_ac97_resume,
        .driver         = {
index 6db86a7c9704047fbc352a4efb5e2f1ee3352489..f78cd000e88d6ec0a8d54df79ce393c5e68fb66e 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
index b09babf272cd0e88ae62650af6ab48ba013b77d9..f80fab8f2ed199abf1b7037058862db13bd3acec 100644 (file)
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <sound/core.h>
 #include <sound/ainstr_fm.h>
 #include <sound/initval.h>
index 3c31038a74bae4dce539aecf5718b7284b2d5584..c640e1cf854d2ae9af99b4afe02f1c5f87c717e6 100644 (file)
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_gf1.h>
index 7f8df19ba5638f70dc65b7e980f49a738e1a96e7..5367baee2d08b87dfd2c1a48b3336e2899659713 100644 (file)
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_iw.h>
index 6d6ffece7cbe88b5f5b135f182c04f4cd3c9f2dc..ac717bef9d7788b8473fe2a47af8ba17cf038402 100644 (file)
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_simple.h>
index 972f93405364ec59efc62a35f97fda81d250d74d..061a7c61402a7fefc4f16f00fe0c99a710486962 100644 (file)
@@ -38,7 +38,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
index 8339bad969bab9fc4decf1a14a0b37d337952296..a0f28f51fc7eb89c0b7ea30da694a224390df8b8 100644 (file)
@@ -423,7 +423,8 @@ static struct snd_pcm_ops snd_card_dummy_capture_ops = {
        .pointer =              snd_card_dummy_pcm_pointer,
 };
 
-static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams)
+static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
+                                       int substreams)
 {
        struct snd_pcm *pcm;
        int err;
@@ -562,7 +563,7 @@ DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
 };
 
-static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
 {
        struct snd_card *card = dummy->card;
        unsigned int idx;
@@ -579,7 +580,7 @@ static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy)
        return 0;
 }
 
-static int __init snd_dummy_probe(struct platform_device *devptr)
+static int __devinit snd_dummy_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_dummy *dummy;
@@ -617,7 +618,7 @@ static int __init snd_dummy_probe(struct platform_device *devptr)
        return err;
 }
 
-static int snd_dummy_remove(struct platform_device *devptr)
+static int __devexit snd_dummy_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -648,7 +649,7 @@ static int snd_dummy_resume(struct platform_device *pdev)
 
 static struct platform_driver snd_dummy_driver = {
        .probe          = snd_dummy_probe,
-       .remove         = snd_dummy_remove,
+       .remove         = __devexit_p(snd_dummy_remove),
 #ifdef CONFIG_PM
        .suspend        = snd_dummy_suspend,
        .resume         = snd_dummy_resume,
index a9ff391258e707c3ac7bf696e457e61de0fe0d92..40eb026c86ed4d817349ae614573493646578662 100644 (file)
@@ -583,7 +583,7 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
 /*
  * get ISA resources
  */
-static int __init snd_mtpav_get_ISA(struct mtpav * mcard)
+static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
 {
        if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
                snd_printk("MTVAP port 0x%lx is busy\n", port);
@@ -619,7 +619,7 @@ static struct snd_rawmidi_ops snd_mtpav_input = {
  * get RAWMIDI resources
  */
 
-static void __init snd_mtpav_set_name(struct mtpav *chip,
+static void __devinit snd_mtpav_set_name(struct mtpav *chip,
                                      struct snd_rawmidi_substream *substream)
 {
        if (substream->number >= 0 && substream->number < chip->num_ports)
@@ -634,7 +634,7 @@ static void __init snd_mtpav_set_name(struct mtpav *chip,
                strcpy(substream->name, "MTP broadcast");
 }
 
-static int __init snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
+static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
 {
        int rval;
        struct snd_rawmidi *rawmidi;
@@ -691,7 +691,7 @@ static void snd_mtpav_free(struct snd_card *card)
 
 /*
  */
-static int __init snd_mtpav_probe(struct platform_device *dev)
+static int __devinit snd_mtpav_probe(struct platform_device *dev)
 {
        struct snd_card *card;
        int err;
@@ -745,7 +745,7 @@ static int __init snd_mtpav_probe(struct platform_device *dev)
        return err;
 }
 
-static int snd_mtpav_remove(struct platform_device *devptr)
+static int __devexit snd_mtpav_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -756,7 +756,7 @@ static int snd_mtpav_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_mtpav_driver = {
        .probe          = snd_mtpav_probe,
-       .remove         = snd_mtpav_remove,
+       .remove         = __devexit_p(snd_mtpav_remove),
        .driver         = {
                .name   = SND_MTPAV_DRIVER
        },
index 5327c6f841f40aad39888b5005137c78d2dcbe9e..6c9f4c9bfeb6c3616063daf1b8fe127a65360f17 100644 (file)
@@ -1026,7 +1026,7 @@ __err:
        return err;
 }
 
-static int snd_mts64_remove(struct platform_device *pdev)
+static int __devexit snd_mts64_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -1039,7 +1039,7 @@ static int snd_mts64_remove(struct platform_device *pdev)
 
 static struct platform_driver snd_mts64_driver = {
        .probe  = snd_mts64_probe,
-       .remove = snd_mts64_remove,
+       .remove = __devexit_p(snd_mts64_remove),
        .driver = {
                .name = PLATFORM_DRIVER
        }
@@ -1048,7 +1048,7 @@ static struct platform_driver snd_mts64_driver = {
 /*********************************************************************
  * module init stuff
  *********************************************************************/
-static void snd_mts64_unregister_all(void)
+static void __init_or_module snd_mts64_unregister_all(void)
 {
        int i;
 
index 6c48772aaefd851d837618e449a85dee16ab9857..b2d0ba4bd184073ad5b07fa2a2f25a7c81d1cc1a 100644 (file)
@@ -811,7 +811,7 @@ __err:
        return err;
 }
 
-static int snd_portman_remove(struct platform_device *pdev)
+static int __devexit snd_portman_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -824,7 +824,7 @@ static int snd_portman_remove(struct platform_device *pdev)
 
 static struct platform_driver snd_portman_driver = {
        .probe  = snd_portman_probe,
-       .remove = snd_portman_remove,
+       .remove = __devexit_p(snd_portman_remove),
        .driver = {
                .name = PLATFORM_DRIVER
        }
@@ -833,7 +833,7 @@ static struct platform_driver snd_portman_driver = {
 /*********************************************************************
  * module init stuff
  *********************************************************************/
-static void snd_portman_unregister_all(void)
+static void __init_or_module snd_portman_unregister_all(void)
 {
        int i;
 
index 3a86a58207269c3169c6e6457a0700d2138b0728..838a4277929d8060bc0fdda7389e0273cfc4bea7 100644 (file)
@@ -327,7 +327,7 @@ static void snd_uart16550_buffer_timer(unsigned long data)
  *  return 0 if found
  *  return negative error if not found
  */
-static int __init snd_uart16550_detect(struct snd_uart16550 *uart)
+static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
 {
        unsigned long io_base = uart->base;
        int ok;
@@ -781,7 +781,7 @@ static int snd_uart16550_dev_free(struct snd_device *device)
        return snd_uart16550_free(uart);
 }
 
-static int __init snd_uart16550_create(struct snd_card *card,
+static int __devinit snd_uart16550_create(struct snd_card *card,
                                       unsigned long iobase,
                                       int irq,
                                       unsigned int speed,
@@ -860,7 +860,7 @@ static int __init snd_uart16550_create(struct snd_card *card,
        return 0;
 }
 
-static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
 {
        struct snd_rawmidi_substream *substream;
 
@@ -869,7 +869,7 @@ static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream)
        }
 }
 
-static int __init snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
                                      int outs, int ins,
                                      struct snd_rawmidi **rmidi)
 {
@@ -896,7 +896,7 @@ static int __init snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
        return 0;
 }
 
-static int __init snd_serial_probe(struct platform_device *devptr)
+static int __devinit snd_serial_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_uart16550 *uart;
@@ -981,7 +981,7 @@ static int __init snd_serial_probe(struct platform_device *devptr)
        return err;
 }
 
-static int snd_serial_remove(struct platform_device *devptr)
+static int __devexit snd_serial_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -992,7 +992,7 @@ static int snd_serial_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_serial_driver = {
        .probe          = snd_serial_probe,
-       .remove         = snd_serial_remove,
+       .remove         = __devexit_p( snd_serial_remove),
        .driver         = {
                .name   = SND_SERIAL_DRIVER
        },
index 59171f8200dfb8fd1dd957e5bb37dd273d292b79..46f3d34860679c677abe9ee83a32316f5005e243 100644 (file)
@@ -44,7 +44,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
@@ -85,7 +84,7 @@ struct snd_card_virmidi {
 static struct platform_device *devices[SNDRV_CARDS];
 
 
-static int __init snd_virmidi_probe(struct platform_device *devptr)
+static int __devinit snd_virmidi_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_card_virmidi *vmidi;
@@ -129,7 +128,7 @@ static int __init snd_virmidi_probe(struct platform_device *devptr)
        return err;
 }
 
-static int snd_virmidi_remove(struct platform_device *devptr)
+static int __devexit snd_virmidi_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -140,7 +139,7 @@ static int snd_virmidi_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_virmidi_driver = {
        .probe          = snd_virmidi_probe,
-       .remove         = snd_virmidi_remove,
+       .remove         = __devexit_p(snd_virmidi_remove),
        .driver         = {
                .name   = SND_VIRMIDI_DRIVER
        },
index 99908e44124da32593b6fa85ea87eafeb4cc1c6b..74e501dea8b1f935141f38a0b77cea08d7a8f125 100644 (file)
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 3
 static struct platform_device *devices[SNDRV_CARDS];
 
 
-static int __init snd_ad1848_probe(struct platform_device *pdev)
+static int __devinit snd_ad1848_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        struct snd_card *card;
index d1f6dfcec46edfd73e55fce385be78e618b76189..c09a8009d2fa7230196a27fab89231dcfcc4fb7b 100644 (file)
@@ -574,7 +574,7 @@ static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -597,7 +597,7 @@ static int snd_cmi8330_nonpnp_resume(struct platform_device *dev)
 
 static struct platform_driver snd_cmi8330_driver = {
        .probe          = snd_cmi8330_nonpnp_probe,
-       .remove         = snd_cmi8330_nonpnp_remove,
+       .remove         = __devexit_p(snd_cmi8330_nonpnp_remove),
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_nonpnp_suspend,
        .resume         = snd_cmi8330_nonpnp_resume,
index c20a4b1b1536532f93d8a0274b0d24d28cc81751..ce57d526f7bc3e5b8fc6608c83d97ff248a99f71 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
index 7f29f56e405b29a26e0c62d43182e804f0555451..65f97ff4eef1e747d7ba5bb0a1d6f875415cad13 100644 (file)
@@ -73,7 +73,7 @@ static struct platform_device *devices[SNDRV_CARDS];
 
 #define PFX    "es1688: "
 
-static int __init snd_es1688_probe(struct platform_device *pdev)
+static int __devinit snd_es1688_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -171,7 +171,7 @@ static int __init snd_es1688_probe(struct platform_device *pdev)
        return err;
 }
 
-static int snd_es1688_remove(struct platform_device *devptr)
+static int __devexit snd_es1688_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -182,7 +182,7 @@ static int snd_es1688_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_es1688_driver = {
        .probe          = snd_es1688_probe,
-       .remove         = snd_es1688_remove,
+       .remove         = __devexit_p(snd_es1688_remove),
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = ES1688_DRIVER
index 37057a37dc30a870b611473113cd6b39425fa845..0395e2e0dd038290f6bb16dff43944b0acd40cf3 100644 (file)
@@ -76,7 +76,7 @@ static struct platform_device *devices[SNDRV_CARDS];
 
 #define PFX    "gusclassic: "
 
-static int __init snd_gusclassic_detect(struct snd_gus_card * gus)
+static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus)
 {
        unsigned char d;
 
@@ -95,7 +95,7 @@ static int __init snd_gusclassic_detect(struct snd_gus_card * gus)
        return 0;
 }
 
-static void __init snd_gusclassic_init(int dev, struct snd_gus_card * gus)
+static void __devinit snd_gusclassic_init(int dev, struct snd_gus_card * gus)
 {
        gus->equal_irq = 0;
        gus->codec_flag = 0;
@@ -103,7 +103,7 @@ static void __init snd_gusclassic_init(int dev, struct snd_gus_card * gus)
        gus->joystick_dac = joystick_dac[dev];
 }
 
-static int __init snd_gusclassic_probe(struct platform_device *pdev)
+static int __devinit snd_gusclassic_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
@@ -211,7 +211,7 @@ static int __init snd_gusclassic_probe(struct platform_device *pdev)
        return err;
 }
 
-static int snd_gusclassic_remove(struct platform_device *devptr)
+static int __devexit snd_gusclassic_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -222,7 +222,7 @@ static int snd_gusclassic_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_gusclassic_driver = {
        .probe          = snd_gusclassic_probe,
-       .remove         = snd_gusclassic_remove,
+       .remove         = __devexit_p(snd_gusclassic_remove),
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = GUSCLASSIC_DRIVER
index 532c56e35ca496fd7a28c3252ce2823b840452e5..4f55fc3e66c14cc1dd167fe1b60c19693fab6170 100644 (file)
@@ -92,7 +92,7 @@ static struct platform_device *devices[SNDRV_CARDS];
 
 #define PFX    "gusextreme: "
 
-static int __init snd_gusextreme_detect(int dev,
+static int __devinit snd_gusextreme_detect(int dev,
                                        struct snd_card *card,
                                        struct snd_gus_card * gus,
                                        struct snd_es1688 *es1688)
@@ -142,12 +142,12 @@ static int __init snd_gusextreme_detect(int dev,
        return 0;
 }
 
-static void __init snd_gusextreme_init(int dev, struct snd_gus_card * gus)
+static void __devinit snd_gusextreme_init(int dev, struct snd_gus_card * gus)
 {
        gus->joystick_dac = joystick_dac[dev];
 }
 
-static int __init snd_gusextreme_mixer(struct snd_es1688 *chip)
+static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id1, id2;
@@ -169,7 +169,7 @@ static int __init snd_gusextreme_mixer(struct snd_es1688 *chip)
        return 0;
 }
 
-static int __init snd_gusextreme_probe(struct platform_device *pdev)
+static int __devinit snd_gusextreme_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
@@ -321,7 +321,7 @@ static int __init snd_gusextreme_probe(struct platform_device *pdev)
        return err;
 }
 
-static int snd_gusextreme_remove(struct platform_device *devptr)
+static int __devexit snd_gusextreme_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -332,7 +332,7 @@ static int snd_gusextreme_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_gusextreme_driver = {
        .probe          = snd_gusextreme_probe,
-       .remove         = snd_gusextreme_remove,
+       .remove         = __devexit_p(snd_gusextreme_remove),
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = GUSEXTREME_DRIVER
index c1c69e3cbfd040c3ee7636d0a7c0feec6a6fac8a..d1ad90ca035de59760b9b500aa139372e0b47586 100644 (file)
@@ -85,7 +85,7 @@ struct snd_gusmax {
 
 #define PFX    "gusmax: "
 
-static int __init snd_gusmax_detect(struct snd_gus_card * gus)
+static int __devinit snd_gusmax_detect(struct snd_gus_card * gus)
 {
        unsigned char d;
 
@@ -127,7 +127,8 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
        return IRQ_RETVAL(handled);
 }
 
-static void __init snd_gusmax_init(int dev, struct snd_card *card, struct snd_gus_card * gus)
+static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
+                                     struct snd_gus_card * gus)
 {
        gus->equal_irq = 1;
        gus->codec_flag = 1;
@@ -145,7 +146,7 @@ static void __init snd_gusmax_init(int dev, struct snd_card *card, struct snd_gu
 #define CS4231_PRIVATE( left, right, shift, mute ) \
                        ((left << 24)|(right << 16)|(shift<<8)|mute)
 
-static int __init snd_gusmax_mixer(struct snd_cs4231 *chip)
+static int __devinit snd_gusmax_mixer(struct snd_cs4231 *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id1, id2;
@@ -204,7 +205,7 @@ static void snd_gusmax_free(struct snd_card *card)
                free_irq(maxcard->irq, (void *)maxcard);
 }
 
-static int __init snd_gusmax_probe(struct platform_device *pdev)
+static int __devinit snd_gusmax_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
@@ -348,7 +349,7 @@ static int __init snd_gusmax_probe(struct platform_device *pdev)
        return err;
 }
 
-static int snd_gusmax_remove(struct platform_device *devptr)
+static int __devexit snd_gusmax_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -359,7 +360,7 @@ static int snd_gusmax_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_gusmax_driver = {
        .probe          = snd_gusmax_probe,
-       .remove         = snd_gusmax_remove,
+       .remove         = __devexit_p(snd_gusmax_remove),
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = GUSMAX_DRIVER
index 1e30713d2cada591a3a3228adf600356715227e8..f3db686b1c0c5da850bfeda7bb790e59df9d8cf6 100644 (file)
@@ -919,7 +919,7 @@ static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -942,7 +942,7 @@ static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev)
 
 static struct platform_driver snd_opl3sa2_nonpnp_driver = {
        .probe          = snd_opl3sa2_nonpnp_probe,
-       .remove         = snd_opl3sa2_nonpnp_remove,
+       .remove         = __devexit( snd_opl3sa2_nonpnp_remove),
 #ifdef CONFIG_PM
        .suspend        = snd_opl3sa2_nonpnp_suspend,
        .resume         = snd_opl3sa2_nonpnp_resume,
index 268ebd34703ec1fa821b5c31083b16e7bd6bb3a8..be1e83e6dea32b7132e252416c83fa2dae7872b1 100644 (file)
@@ -83,7 +83,7 @@ static void snd_sb8_free(struct snd_card *card)
        release_and_free_resource(acard->fm_res);
 }
 
-static int __init snd_sb8_probe(struct platform_device *pdev)
+static int __devinit snd_sb8_probe(struct platform_device *pdev)
 {
        int dev = pdev->id;
        struct snd_sb *chip;
@@ -193,7 +193,7 @@ static int __init snd_sb8_probe(struct platform_device *pdev)
        return err;
 }
 
-static int snd_sb8_remove(struct platform_device *pdev)
+static int __devexit snd_sb8_remove(struct platform_device *pdev)
 {
        snd_card_free(platform_get_drvdata(pdev));
        platform_set_drvdata(pdev, NULL);
@@ -230,7 +230,7 @@ static int snd_sb8_resume(struct platform_device *dev)
 
 static struct platform_driver snd_sb8_driver = {
        .probe          = snd_sb8_probe,
-       .remove         = snd_sb8_remove,
+       .remove         = __devexit_p(snd_sb8_remove),
 #ifdef CONFIG_PM
        .suspend        = snd_sb8_suspend,
        .resume         = snd_sb8_resume,
index 602db497929abd70d048d1d5215b0d869651ab5f..fef56cac06c832650db596299af04185dc9919dc 100644 (file)
@@ -744,11 +744,10 @@ static int ac97_check_modem(struct ac97_codec *codec)
  
 struct ac97_codec *ac97_alloc_codec(void)
 {
-       struct ac97_codec *codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL);
+       struct ac97_codec *codec = kzalloc(sizeof(struct ac97_codec), GFP_KERNEL);
        if(!codec)
                return NULL;
 
-       memset(codec, 0, sizeof(*codec));
        spin_lock_init(&codec->lock);
        INIT_LIST_HEAD(&codec->list);
        return codec;
index f0724327493c0c47e66a822e009ee0602c064a9b..c0730a3563a2962ab86a4c24ec39c063c4df0de4 100644 (file)
@@ -230,9 +230,8 @@ static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
        struct dmabuf *dmabuf;
        int i;
 
-       if ((dev = kmalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL) 
+       if ((dev = kzalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
                return NULL;
-       memset(dev, 0, sizeof(ad1889_dev_t));
        spin_lock_init(&dev->lock);
        dev->pci = pci;
 
index f845528e1facc8713e025a4b600f37343c4f6fc1..f813ae9c2134e2e7b17f41c486bf23c7d167a543 100644 (file)
@@ -915,12 +915,11 @@ static int __devinit btaudio_probe(struct pci_dev *pci_dev,
                return -EBUSY;
        }
 
-       bta = kmalloc(sizeof(*bta),GFP_ATOMIC);
+       bta = kzalloc(sizeof(*bta),GFP_ATOMIC);
        if (!bta) {
                rc = -ENOMEM;
                goto fail0;
        }
-       memset(bta,0,sizeof(*bta));
 
        bta->pci  = pci_dev;
        bta->irq  = pci_dev->irq;
index 147c8a951137a4452fb059a66dab5cbfbc381c7d..2a1f0d9ac968083f5ec0ec3a6164bf15ff6bc5b4 100644 (file)
@@ -3048,10 +3048,9 @@ static int cs_open(struct inode *inode, struct file *file)
                CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
                if (card->states[0] == NULL) {
                        state = card->states[0] =
-                               kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+                               kzalloc(sizeof(struct cs_state), GFP_KERNEL);
                        if (state == NULL)
                                return -ENOMEM;
-                       memset(state, 0, sizeof(struct cs_state));
                        mutex_init(&state->sem);
                        dmabuf = &state->dmabuf;
                        dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -3114,10 +3113,9 @@ static int cs_open(struct inode *inode, struct file *file)
                CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
                if (card->states[1] == NULL) {
                        state = card->states[1] =
-                               kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+                               kzalloc(sizeof(struct cs_state), GFP_KERNEL);
                        if (state == NULL)
                                return -ENOMEM;
-                       memset(state, 0, sizeof(struct cs_state));
                        mutex_init(&state->sem);
                        dmabuf = &state->dmabuf;
                        dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -5075,11 +5073,10 @@ static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
        pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
        pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
 
-       if ((card = kmalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
+       if ((card = kzalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "cs46xx: out of memory\n");
                return -ENOMEM;
        }
-       memset(card, 0, sizeof(*card));
        card->ba0_addr = RSRCADDRESS(pci_dev, 0);
        card->ba1_addr = RSRCADDRESS(pci_dev, 1);
        card->pci_dev = pci_dev;
index 7360d8954d6009009f57e7b18b8f437fb15f9c52..0f0d03a55dab71139fbac2fd1da9fb3832f605ba 100644 (file)
@@ -163,10 +163,9 @@ static int daca_detect_client(struct i2c_adapter *adapter, int address)
        struct i2c_client *new_client;
        int rc = -ENODEV;
 
-       new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
+       new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
        if (!new_client)
                return -ENOMEM;
-       memset(new_client, 0, sizeof(*new_client));
 
        new_client->addr = address;
        new_client->adapter = adapter;
index 2f21a3c00374ad2b40e40482ab1aff41594f9a09..4b7dbdd2a43833c2553c2b994a28f599e3d6bc46 100644 (file)
@@ -807,10 +807,9 @@ tas3001c_init(struct i2c_client *client)
        size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
        int i, j;
 
-       self = kmalloc(sz, GFP_KERNEL);
+       self = kzalloc(sz, GFP_KERNEL);
        if (!self)
                return -ENOMEM;
-       memset(self, 0, sz);
 
        self->super.client = client;
        self->super.shadow = (tas_shadow_t *)(self+1);
index af34fb39bc29ed2323572097dd8c8d99cd778502..678bf0ff6da27329ad0951b9b2bf2ae7bb7714c9 100644 (file)
@@ -1092,10 +1092,9 @@ tas3004_init(struct i2c_client *client)
        char mcr2 = 0;
        int i, j;
 
-       self = kmalloc(sz, GFP_KERNEL);
+       self = kzalloc(sz, GFP_KERNEL);
        if (!self)
                return -ENOMEM;
-       memset(self, 0, sz);
 
        self->super.client = client;
        self->super.shadow = (tas_shadow_t *)(self+1);
index 882ae98a41b127c7b23d76d4465bc1cc3e5f2acf..665e85b5562bd56785494bbfbd428b9459afaa5a 100644 (file)
@@ -135,10 +135,9 @@ tas_detect_client(struct i2c_adapter *adapter, int address)
                return -ENODEV;
        }
        
-       new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
+       new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
        if (!new_client)
                return -ENOMEM;
-       memset(new_client, 0, sizeof(*new_client));
 
        new_client->addr = address;
        new_client->adapter = adapter;
index 6c59df7b00011965f04cad5f5f3a3bd17319ae5d..16ac02540a3f77ac0ee591abe4e529abe8430e02 100644 (file)
@@ -455,15 +455,13 @@ static int __devinit emu10k1_midi_init(struct emu10k1_card *card)
 {
        int ret;
 
-       card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
+       card->mpuout = kzalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
        if (card->mpuout == NULL) {
                printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
                ret = -ENOMEM;
                goto err_out1;
        }
 
-       memset(card->mpuout, 0, sizeof(struct emu10k1_mpuout));
-
        card->mpuout->intr = 1;
        card->mpuout->status = FLAGS_AVAILABLE;
        card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;
@@ -472,15 +470,13 @@ static int __devinit emu10k1_midi_init(struct emu10k1_card *card)
 
        spin_lock_init(&card->mpuout->lock);
 
-       card->mpuin = kmalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
+       card->mpuin = kzalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
        if (card->mpuin == NULL) {
                printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
                ret = -ENOMEM;
                 goto err_out2;
        }
 
-       memset(card->mpuin, 0, sizeof(struct emu10k1_mpuin));
-
        card->mpuin->status = FLAGS_AVAILABLE;
 
        tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);
@@ -1280,11 +1276,10 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
 
        pci_set_master(pci_dev);
 
-       if ((card = kmalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
+       if ((card = kzalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
                 printk(KERN_ERR "emu10k1: out of memory\n");
                 return -ENOMEM;
         }
-        memset(card, 0, sizeof(struct emu10k1_card));
 
        card->iobase = pci_resource_start(pci_dev, 0);
        card->length = pci_resource_len(pci_dev, 0); 
index e1fbcca8e72236beb0d05240281f08f0e0c8153c..974dd732b1499606c37d6b324e6b932a4dddab14 100644 (file)
@@ -2871,11 +2871,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
                printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
                return i;
        }
-       if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+       if (!(s = kzalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
                printk(KERN_WARNING PFX "out of memory\n");
                return -ENOMEM;
        }
-       memset(s, 0, sizeof(struct es1371_state));
        
        s->codec = ac97_alloc_codec();
        if(s->codec == NULL)
index 80a42773c6485c98cbc80706a97741861ef713ef..a94b9df489dcbcae8c8253b28a552288495cdd53 100644 (file)
@@ -1435,10 +1435,9 @@ static int hal2_init_card(struct hal2_card **phal2, struct hpc3_regs *hpc3)
        int ret = 0;
        struct hal2_card *hal2;
 
-       hal2 = kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
+       hal2 = kzalloc(sizeof(struct hal2_card), GFP_KERNEL);
        if (!hal2)
                return -ENOMEM;
-       memset(hal2, 0, sizeof(struct hal2_card));
 
        hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0];
        hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1];
index c3c8a720d555a73749c1b9f62587f16097f7fae2..f5e31f11973d39a1ae995dd0d311c253c028551c 100644 (file)
@@ -2580,10 +2580,9 @@ static int i810_open(struct inode *inode, struct file *file)
                for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) {
                        if (card->states[i] == NULL) {
                                state = card->states[i] = (struct i810_state *)
-                                       kmalloc(sizeof(struct i810_state), GFP_KERNEL);
+                                       kzalloc(sizeof(struct i810_state), GFP_KERNEL);
                                if (state == NULL)
                                        return -ENOMEM;
-                               memset(state, 0, sizeof(struct i810_state));
                                dmabuf = &state->dmabuf;
                                goto found_virt;
                        }
@@ -3205,10 +3204,9 @@ static void __devinit i810_configure_clocking (void)
         */
        if(card != NULL) {
                state = card->states[0] = (struct i810_state *)
-                                       kmalloc(sizeof(struct i810_state), GFP_KERNEL);
+                                       kzalloc(sizeof(struct i810_state), GFP_KERNEL);
                if (state == NULL)
                        return;
-               memset(state, 0, sizeof(struct i810_state));
                dmabuf = &state->dmabuf;
 
                dmabuf->write_channel = card->alloc_pcm_channel(card);
@@ -3273,11 +3271,10 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
                return -ENODEV;
        }
        
-       if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
+       if ((card = kzalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "i810_audio: out of memory\n");
                return -ENOMEM;
        }
-       memset(card, 0, sizeof(*card));
 
        card->initializing = 1;
        card->pci_dev = pci_dev;
index 12e7b3038be2bb8a05dcb2c27045d4023c340464..dfe670f12e67d71117904db746c2a2b8e87af10d 100644 (file)
@@ -139,13 +139,12 @@ static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id
        printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n",
                irq, dma8, dma16);
        
-       hw_config = kmalloc(sizeof(struct address_info), GFP_KERNEL);
+       hw_config = kzalloc(sizeof(struct address_info), GFP_KERNEL);
        if(hw_config == NULL)
        {
                printk(KERN_ERR "kahlua: out of memory.\n");
                return 1;
        }
-       memset(hw_config, 0, sizeof(*hw_config));
        
        pci_set_drvdata(pdev, hw_config);
        
index d459bdb14154e9c11907ae8e8cd7e1a386c31a53..27b4ba3aaa7cc78746c3469ce95f5894afb62bcc 100644 (file)
@@ -1860,11 +1860,10 @@ static int __devinit vrc5477_ac97_probe(struct pci_dev *pcidev,
        if (pcidev->irq == 0) 
                return -1;
 
-       if (!(s = kmalloc(sizeof(struct vrc5477_ac97_state), GFP_KERNEL))) {
+       if (!(s = kzalloc(sizeof(struct vrc5477_ac97_state), GFP_KERNEL))) {
                printk(KERN_ERR PFX "alloc of device struct failed\n");
                return -1;
        }
-       memset(s, 0, sizeof(struct vrc5477_ac97_state));
 
        init_waitqueue_head(&s->dma_adc.wait);
        init_waitqueue_head(&s->dma_dac.wait);
index 2e8cfa5481f28c4e1e7d7f2d40b5326538bd02d7..fc273e55094480db93f3ad351c4e6aea49137c28 100644 (file)
@@ -166,7 +166,7 @@ int opl3_detect(int ioaddr, int *osp)
                return 0;
        }
 
-       devc = kmalloc(sizeof(*devc), GFP_KERNEL);
+       devc = kzalloc(sizeof(*devc), GFP_KERNEL);
 
        if (devc == NULL)
        {
@@ -175,7 +175,6 @@ int opl3_detect(int ioaddr, int *osp)
                return 0;
        }
 
-       memset(devc, 0, sizeof(*devc));
        strcpy(devc->fm_info.name, "OPL2");
 
        if (!request_region(ioaddr, 4, devc->fm_info.name)) {
index 8666291c00523fccca590df1d6a5fbedbf6c28c7..27acd6f29b98ffe06e4ffddd737e2d49218ce7c3 100644 (file)
@@ -137,11 +137,10 @@ static int __init sb_init_legacy(void)
 {
        struct sb_module_options sbmo = {0};
 
-       if((legacy = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+       if((legacy = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "sb: Error: Could not allocate memory\n");
                return -ENOMEM;
        }
-       memset(legacy, 0, sizeof(struct sb_card_config));
 
        legacy->conf.io_base      = io;
        legacy->conf.irq          = irq;
@@ -247,11 +246,10 @@ static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device
                return -EBUSY;
        }
 
-       if((scc = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+       if((scc = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "sb: Error: Could not allocate memory\n");
                return -ENOMEM;
        }
-       memset(scc, 0, sizeof(struct sb_card_config));
 
        printk(KERN_INFO "sb: PnP: Found Card Named = \"%s\", Card PnP id = " \
               "%s, Device PnP id = %s\n", card->card->name, card_id->id,
index 9f7e5f59ac82b3560d1717b8840aa0e2d840b789..016b918329ada95227ddb95666fdd6ccc7615531 100644 (file)
@@ -616,25 +616,23 @@ static int init_serdma(serdma_t *dma)
 
         /* Descriptors */
         dma->ringsz = DMA_DESCR;
-        dma->descrtab = kmalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL);
+        dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL);
         if (!dma->descrtab) {
-                printk(KERN_ERR "cs4297a: kmalloc descrtab failed\n");
+                printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n");
                 return -1;
         }
-        memset(dma->descrtab, 0, dma->ringsz * sizeof(serdma_descr_t));
         dma->descrtab_end = dma->descrtab + dma->ringsz;
        /* XXX bloddy mess, use proper DMA API here ...  */
        dma->descrtab_phys = CPHYSADDR((long)dma->descrtab);
         dma->descr_add = dma->descr_rem = dma->descrtab;
 
         /* Frame buffer area */
-        dma->dma_buf = kmalloc(DMA_BUF_SIZE, GFP_KERNEL);
+        dma->dma_buf = kzalloc(DMA_BUF_SIZE, GFP_KERNEL);
         if (!dma->dma_buf) {
-                printk(KERN_ERR "cs4297a: kmalloc dma_buf failed\n");
+                printk(KERN_ERR "cs4297a: kzalloc dma_buf failed\n");
                 kfree(dma->descrtab);
                 return -1;
         }
-        memset(dma->dma_buf, 0, DMA_BUF_SIZE);
         dma->dma_buf_phys = CPHYSADDR((long)dma->dma_buf);
 
         /* Samples buffer area */
@@ -2619,12 +2617,11 @@ static int __init cs4297a_init(void)
         udelay(100);
 #endif
 
-       if (!(s = kmalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) {
+       if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) {
                CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
                      "cs4297a: probe() no memory for state struct.\n"));
                return -1;
        }
-       memset(s, 0, sizeof(struct cs4297a_state));
         s->magic = CS4297a_MAGIC;
        init_waitqueue_head(&s->dma_adc.wait);
        init_waitqueue_head(&s->dma_dac.wait);
index 6b1f8c9cdcf870419924dad10156dcf395df4e9f..72a8a0ed36a2855cca84d0d64a1c3844a96ab344 100644 (file)
@@ -2729,12 +2729,11 @@ trident_open(struct inode *inode, struct file *file)
                }
                for (i = 0; i < NR_HW_CH; i++) {
                        if (card->states[i] == NULL) {
-                               state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL);
+                               state = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
                                if (state == NULL) {
                                        mutex_unlock(&card->open_mutex);
                                        return -ENOMEM;
                                }
-                               memset(state, 0, sizeof(*state));
                                mutex_init(&state->sem);
                                dmabuf = &state->dmabuf;
                                goto found_virt;
@@ -3618,7 +3617,7 @@ ali_allocate_other_states_resources(struct trident_state *state, int chan_nums)
                        }
                        return -EBUSY;
                }
-               s = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL);
+               s = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
                if (!s) {
                        num = ali_multi_channels_5_1[state_count];
                        ali_free_pcm_channel(card, num);
@@ -3630,7 +3629,6 @@ ali_allocate_other_states_resources(struct trident_state *state, int chan_nums)
                        }
                        return -ENOMEM;
                }
-               memset(s, 0, sizeof(*state));
 
                s->dmabuf.channel = channel;
                s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags =
@@ -4399,11 +4397,10 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
        }
 
        rc = -ENOMEM;
-       if ((card = kmalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
+       if ((card = kzalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "trident: out of memory\n");
                goto out_release_region;
        }
-       memset(card, 0, sizeof (*card));
 
        init_timer(&card->timer);
        card->iobase = iobase;
index 26a7c6af95bcc5c18992cbe2a2ebea1763f741c7..b48c72923a13dfb30c35669213112a31baa4ffc2 100644 (file)
@@ -1267,12 +1267,10 @@ static int __init waveartist_init(wavnc_info *devc)
        conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
                     devc->hw.dma, devc->hw.dma2);
 
-       portc = kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+       portc = kzalloc(sizeof(wavnc_port_info), GFP_KERNEL);
        if (portc == NULL)
                goto nomem;
 
-       memset(portc, 0, sizeof(wavnc_port_info));
-
        my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
                        &waveartist_audio_driver, sizeof(struct audio_driver),
                        devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
index 74ed81081478c1266a8851f6c8709fcdcc90c486..a9eec2a2357d5fae8638d2234444aca90ffe1bc2 100644 (file)
@@ -143,6 +143,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x43525970, 0xfffffff8, "CS4202",            NULL,           NULL },
 { 0x43585421, 0xffffffff, "HSD11246",          NULL,           NULL }, // SmartMC II
 { 0x43585428, 0xfffffff8, "Cx20468",           patch_conexant, NULL }, // SmartAMC fixme: the mask might be different
+{ 0x43585431, 0xffffffff, "Cx20551",           patch_cx20551,  NULL },
 { 0x44543031, 0xfffffff0, "DT0398",            NULL,           NULL },
 { 0x454d4328, 0xffffffff, "EM28028",           NULL,           NULL },  // same as TR28028?
 { 0x45838308, 0xffffffff, "ESS1988",           NULL,           NULL },
index 641d0c8d659ed222f7540e8483f7881c1c232ab3..bfc2fed16da3a0208a6a5be3d146a81032ecffd1 100644 (file)
@@ -1338,6 +1338,12 @@ int patch_conexant(struct snd_ac97 * ac97)
        return 0;
 }
 
+int patch_cx20551(struct snd_ac97 *ac97)
+{
+       snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
+       return 0;
+}
+
 /*
  * Analog Device AD18xx, AD19xx codecs
  */
index 94340daaaf1f7a64835c2923b0780230fd01a260..555d1c9a98fd724f2dc977a7ac860a4cfcf923b0 100644 (file)
@@ -39,6 +39,7 @@ int patch_sigmatel_stac9758(struct snd_ac97 * ac97);
 int patch_cirrus_cs4299(struct snd_ac97 * ac97);
 int patch_cirrus_spdif(struct snd_ac97 * ac97);
 int patch_conexant(struct snd_ac97 * ac97);
+int patch_cx20551(struct snd_ac97 * ac97);
 int patch_ad1819(struct snd_ac97 * ac97);
 int patch_ad1881(struct snd_ac97 * ac97);
 int patch_ad1885(struct snd_ac97 * ac97);
index 73f4668238c6034cad86c749ee405767b8d1eada..23a1c75085b58fcd742a0e015003005a43a72931 100644 (file)
@@ -57,6 +57,7 @@ struct conexant_spec {
                                         * dig_out_nid and hp_nid are optional
                                         */
        unsigned int cur_eapd;
+       unsigned int hp_present;
        unsigned int need_dac_fix;
 
        /* capture */
@@ -354,7 +355,7 @@ static struct hda_codec_ops conexant_patch_ops = {
  * the private value = nid | (invert << 8)
  */
 
-static int conexant_eapd_info(struct snd_kcontrol *kcontrol,
+static int cxt_eapd_info(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -364,7 +365,7 @@ static int conexant_eapd_info(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int conexant_eapd_get(struct snd_kcontrol *kcontrol,
+static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_value *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -375,9 +376,10 @@ static int conexant_eapd_get(struct snd_kcontrol *kcontrol,
        else
                ucontrol->value.integer.value[0] = spec->cur_eapd;
        return 0;
+
 }
 
-static int conexant_eapd_put(struct snd_kcontrol *kcontrol,
+static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_value *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -385,11 +387,13 @@ static int conexant_eapd_put(struct snd_kcontrol *kcontrol,
        int invert = (kcontrol->private_value >> 8) & 1;
        hda_nid_t nid = kcontrol->private_value & 0xff;
        unsigned int eapd;
+
        eapd = ucontrol->value.integer.value[0];
        if (invert)
                eapd = !eapd;
        if (eapd == spec->cur_eapd && !codec->in_resume)
                return 0;
+       
        spec->cur_eapd = eapd;
        snd_hda_codec_write(codec, nid,
                            0, AC_VERB_SET_EAPD_BTLENABLE,
@@ -400,6 +404,15 @@ static int conexant_eapd_put(struct snd_kcontrol *kcontrol,
 /* controls for test mode */
 #ifdef CONFIG_SND_DEBUG
 
+#define CXT_EAPD_SWITCH(xname, nid, mask) \
+       { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+         .info = cxt_eapd_info, \
+         .get = cxt_eapd_get, \
+         .put = cxt_eapd_put, \
+         .private_value = nid | (mask<<16) }
+
+
+
 static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_info *uinfo)
 {
@@ -492,7 +505,7 @@ static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol,
          .get = cxt_gpio_data_get, \
          .put = cxt_gpio_data_put, \
          .private_value = nid | (mask<<16) }
-
+#if 0
 static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_info *uinfo)
 {
@@ -547,7 +560,7 @@ static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
          .get = cxt_spdif_ctrl_get, \
          .put = cxt_spdif_ctrl_put, \
          .private_value = nid | (mask<<16) }
-
+#endif
 #endif /* CONFIG_SND_DEBUG */
 
 /* Conexant 5045 specific */
@@ -564,7 +577,7 @@ static struct hda_channel_mode cxt5045_modes[1] = {
 static struct hda_input_mux cxt5045_capture_source = {
        .num_items = 2,
        .items = {
-               { "ExtMic", 0x1 },
+               { "IntMic", 0x1 },
                { "LineIn", 0x2 },
        }
 };
@@ -575,15 +588,20 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct conexant_spec *spec = codec->spec;
+       unsigned int bits;
 
-       if (!conexant_eapd_put(kcontrol, ucontrol))
+       if (!cxt_eapd_put(kcontrol, ucontrol))
                return 0;
 
-       /* toggle HP mute appropriately */
-       snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
-                                0x80, spec->cur_eapd ? 0 : 0x80);
-       snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
-                                0x80, spec->cur_eapd ? 0 : 0x80);
+       /* toggle internal speakers mute depending of presence of
+        * the headphone jack
+        */
+       bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
+       snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+       bits = spec->cur_eapd ? 0 : 0x80;
+       snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits);
        return 1;
 }
 
@@ -610,14 +628,13 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
 /* mute internal speaker if HP is plugged */
 static void cxt5045_hp_automute(struct hda_codec *codec)
 {
-       unsigned int present;
+       struct conexant_spec *spec = codec->spec;
+       unsigned int bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
 
-       present = snd_hda_codec_read(codec, 0x11, 0,
+       spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
-                                0x80, present ? 0x80 : 0);
-       snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
-                                0x80, present ? 0x80 : 0);
+       snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -640,25 +657,27 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
                .get = conexant_mux_enum_get,
                .put = conexant_mux_enum_put
        },
-       HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x17, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x17, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Volume",
                .info = snd_hda_mixer_amp_volume_info,
                .get = snd_hda_mixer_amp_volume_get,
                .put = cxt5045_hp_master_vol_put,
-               .private_value = HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
+               .private_value = HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
-               .info = conexant_eapd_info,
-               .get = conexant_eapd_get,
+               .info = cxt_eapd_info,
+               .get = cxt_eapd_get,
                .put = cxt5045_hp_master_sw_put,
-               .private_value = 0x11,
+               .private_value = 0x10,
        },
 
        {}
@@ -669,22 +688,26 @@ static struct hda_verb cxt5045_init_verbs[] = {
        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
        /* HP, Amp  */
-       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-       {0x1A, AC_VERB_SET_CONNECT_SEL,0x01},
-       {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-        AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
-       {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
+       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+       {0x17, AC_VERB_SET_CONNECT_SEL,0x01},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+        AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x01},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+        AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x02},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
         AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
-       /* Record selector: Front mic */
-       {0x14, AC_VERB_SET_CONNECT_SEL,0x03},
        {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+        AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04},
+       /* Record selector: Int mic */
+       {0x1a, AC_VERB_SET_CONNECT_SEL,0x0},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
         AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
        /* SPDIF route: PCM */
        { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
        /* pin sensing on HP and Mic jacks */
        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
        /* EAPD */
-       {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */
+       {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
        { } /* end */
 };
 
@@ -706,8 +729,6 @@ static struct hda_input_mux cxt5045_test_capture_source = {
 static struct snd_kcontrol_new cxt5045_test_mixer[] = {
 
        /* Output controls */
-       HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x19, 0x00, HDA_OUTPUT),
-       HDA_CODEC_MUTE("OutAmp-1 Switch", 0x19,0x00, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
        
@@ -715,6 +736,9 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
        CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
        CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
 
+       /* EAPD Switch Control */
+       CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
+
        /* Loopback mixer controls */
        HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT),
@@ -725,17 +749,16 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
        HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT),
 
-       /* Controls for GPIO pins, assuming they exist and are configured as outputs */
-       CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-#if 0   /* limit this to one GPIO pin for now */       
-       CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-       CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-       CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-#endif
-       CXT_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x13, 0x01),
-
-       HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Input Source",
@@ -748,14 +771,9 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
 };
 
 static struct hda_verb cxt5045_test_init_verbs[] = {
-       /* Enable all GPIOs as outputs with an initial value of 0 */
-       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
-       {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-       {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
        /* Enable retasking pins as output, initially without power amp */
        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 
        /* Disable digital (SPDIF) pins initially, but users can enable
         * them via a mixer switch.  In the case of SPDIF-out, this initverb
@@ -823,6 +841,8 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
 
 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP),
+       SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP),
+       SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP),
        {}
 };
 
@@ -880,11 +900,11 @@ static int patch_cxt5045(struct hda_codec *codec)
 
 
 /* Conexant 5047 specific */
+#define CXT5047_SPDIF_OUT      0x11
 
-static hda_nid_t cxt5047_dac_nids[1] = { 0x10 };
+static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c };
 static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
 static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
-#define CXT5047_SPDIF_OUT      0x11
 
 static struct hda_channel_mode cxt5047_modes[1] = {
        { 2, NULL },
@@ -893,15 +913,23 @@ static struct hda_channel_mode cxt5047_modes[1] = {
 static struct hda_input_mux cxt5047_capture_source = {
        .num_items = 2,
        .items = {
-               { "ExtMic", 0x1 },
-               { "IntMic", 0x2 },
+               { "ExtMic", 0x0 },
+               { "IntMic", 0x1 },
        }
 };
 
 static struct hda_input_mux cxt5047_hp_capture_source = {
        .num_items = 1,
        .items = {
-               { "ExtMic", 0x1 },
+               { "ExtMic", 0x2 },
+       }
+};
+
+static struct hda_input_mux cxt5047_toshiba_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "ExtMic", 0x2 },
+               { "Line-In", 0x1 },
        }
 };
 
@@ -911,20 +939,24 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct conexant_spec *spec = codec->spec;
+       unsigned int bits;
 
-       if (!conexant_eapd_put(kcontrol, ucontrol))
+       if (!cxt_eapd_put(kcontrol, ucontrol))
                return 0;
 
-       /* toggle HP mute appropriately */
-       snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
-                                0x80, spec->cur_eapd ? 0 : 0x80);
-       snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
-                                0x80, spec->cur_eapd ? 0 : 0x80);
+       /* toggle internal speakers mute depending of presence of
+        * the headphone jack
+        */
+       bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
+       snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+       bits = spec->cur_eapd ? 0 : 0x80;
+       snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits);
        return 1;
 }
 
-#if 0
-/* bind volumes of both NID 0x13 and 0x1d */
+/* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */
 static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
                                     struct snd_ctl_elem_value *ucontrol)
 {
@@ -932,9 +964,9 @@ static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0,
+       change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0,
                                          0x7f, valp[0] & 0x7f);
-       change |= snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0,
+       change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0,
                                           0x7f, valp[1] & 0x7f);
        snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
                                 0x7f, valp[0] & 0x7f);
@@ -942,19 +974,20 @@ static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
                                 0x7f, valp[1] & 0x7f);
        return change;
 }
-#endif
 
 /* mute internal speaker if HP is plugged */
 static void cxt5047_hp_automute(struct hda_codec *codec)
 {
-       unsigned int present;
+       struct conexant_spec *spec = codec->spec;
+       unsigned int bits = spec->hp_present || !spec->cur_eapd ? 0x80 : 0;
 
-       present = snd_hda_codec_read(codec, 0x13, 0,
+       spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0,
-                                0x80, present ? 0x80 : 0);
-       snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0,
-                                0x80, present ? 0x80 : 0);
+       snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+       /* Mute/Unmute PCM 2 for good measure - some systems need this */
+       snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
+       snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
 }
 
 /* toggle input of built-in and mic jack appropriately */
@@ -1009,12 +1042,55 @@ static struct snd_kcontrol_new cxt5047_mixers[] = {
        HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
        HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
        HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Volume",
+               .info = snd_hda_mixer_amp_volume_info,
+               .get = snd_hda_mixer_amp_volume_get,
+               .put = cxt5047_hp_master_vol_put,
+               .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
+       },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
-               .info = conexant_eapd_info,
-               .get = conexant_eapd_get,
+               .info = cxt_eapd_info,
+               .get = cxt_eapd_get,
+               .put = cxt5047_hp_master_sw_put,
+               .private_value = 0x13,
+       },
+
+       {}
+};
+
+static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = conexant_mux_enum_info,
+               .get = conexant_mux_enum_get,
+               .put = conexant_mux_enum_put
+       },
+       HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
+       HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Volume",
+               .info = snd_hda_mixer_amp_volume_info,
+               .get = snd_hda_mixer_amp_volume_get,
+               .put = cxt5047_hp_master_vol_put,
+               .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Switch",
+               .info = cxt_eapd_info,
+               .get = cxt_eapd_get,
                .put = cxt5047_hp_master_sw_put,
                .private_value = 0x13,
        },
@@ -1040,8 +1116,8 @@ static struct snd_kcontrol_new cxt5047_hp_mixers[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
-               .info = conexant_eapd_info,
-               .get = conexant_eapd_get,
+               .info = cxt_eapd_info,
+               .get = cxt_eapd_get,
                .put = cxt5047_hp_master_sw_put,
                .private_value = 0x13,
        },
@@ -1053,19 +1129,23 @@ static struct hda_verb cxt5047_init_verbs[] = {
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-       /* HP, Amp  */
+       /* HP, Amp, Speaker  */
        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-       {0x1A, AC_VERB_SET_CONNECT_SEL,0x03},
+       {0x1A, AC_VERB_SET_CONNECT_SEL,0x00},
        {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
         AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
        {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
         AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
+       {0x1d, AC_VERB_SET_CONNECT_SEL,0x0},
        /* Record selector: Front mic */
        {0x12, AC_VERB_SET_CONNECT_SEL,0x03},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE,
         AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
        /* SPDIF route: PCM */
        { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
+       /* Enable unsolicited events */
+       {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
        { } /* end */
 };
 
@@ -1075,14 +1155,24 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = {
        /* pin sensing on HP and Mic jacks */
        {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
        {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+       /* Speaker routing */
+       {0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
+       /* Change default to ExtMic for recording */
+       {0x1a, AC_VERB_SET_CONNECT_SEL,0x2},
        {}
 };
 
 /* configuration for HP Laptops */
 static struct hda_verb cxt5047_hp_init_verbs[] = {
-       /* pin sensing on HP and Mic jacks */
+       /* pin sensing on HP jack */
        {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+       /* Record selector: Ext Mic */
+       {0x12, AC_VERB_SET_CONNECT_SEL,0x03},
+       {0x1a, AC_VERB_SET_CONNECT_SEL,0x02},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE,
+        AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
+       /* Speaker routing */
+       {0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
        {}
 };
 
@@ -1091,53 +1181,56 @@ static struct hda_verb cxt5047_hp_init_verbs[] = {
  */
 #ifdef CONFIG_SND_DEBUG
 static struct hda_input_mux cxt5047_test_capture_source = {
-       .num_items = 5,
+       .num_items = 4,
        .items = {
-               { "MIXER", 0x0 },
-               { "LINE1 pin", 0x1 },
-               { "MIC1 pin", 0x2 },
-               { "MIC2 pin", 0x3 },
-               { "CD pin", 0x4 },
+               { "LINE1 pin", 0x0 },
+               { "MIC1 pin", 0x1 },
+               { "MIC2 pin", 0x2 },
+               { "CD pin", 0x3 },
         },
 };
 
 static struct snd_kcontrol_new cxt5047_test_mixer[] = {
 
        /* Output only controls */
-       HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x00, HDA_OUTPUT),
-       HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x00, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
-       HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 
        /* Modes for retasking pin widgets */
        CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
        CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
 
-       /* Loopback mixer controls */
-       HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x19, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("MIC1 Playback Switch", 0x19, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x19, 0x03, HDA_INPUT),
-       HDA_CODEC_MUTE("MIC2 Playback Switch", 0x19, 0x03, HDA_INPUT),
-       HDA_CODEC_VOLUME("LINE Playback Volume", 0x19, 0x01, HDA_INPUT),
-       HDA_CODEC_MUTE("LINE Playback Switch", 0x19, 0x01, HDA_INPUT),
-       HDA_CODEC_VOLUME("CD Playback Volume", 0x19, 0x04, HDA_INPUT),
-       HDA_CODEC_MUTE("CD Playback Switch", 0x19, 0x04, HDA_INPUT),
-
-#if 0   
-       /* Controls for GPIO pins, assuming they exist and are configured as outputs */
-       CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-       CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-       CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-       CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-#endif
-       CXT_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x18, 0x01),
+       /* EAPD Switch Control */
+       CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
 
-       HDA_CODEC_VOLUME("Capture Volume", 0x19, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x19, 0x0, HDA_OUTPUT),
+       /* Loopback mixer controls */
+       HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
+
+       HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Input Source",
@@ -1145,16 +1238,18 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
                .get = conexant_mux_enum_get,
                .put = conexant_mux_enum_put,
        },
+       /* Controls for GPIO pins, assuming they exist and are configured
+       * as outputs
+       */
+       CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
+       CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
+       CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
+       CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
 
        { } /* end */
 };
 
 static struct hda_verb cxt5047_test_init_verbs[] = {
-       /* Enable all GPIOs as outputs with an initial value of 0 */
-       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
-       {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-       {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
        /* Enable retasking pins as output, initially without power amp */
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -1215,7 +1310,6 @@ static int cxt5047_hp_init(struct hda_codec *codec)
 {
        conexant_init(codec);
        cxt5047_hp_automute(codec);
-       cxt5047_hp_automic(codec);
        return 0;
 }
 
@@ -1242,6 +1336,7 @@ static const char *cxt5047_models[CXT5047_MODELS] = {
 static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP),
+       SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
        SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
        {}
@@ -1291,8 +1386,10 @@ static int patch_cxt5047(struct hda_codec *codec)
                codec->patch_ops.init = cxt5047_hp_init;
                break;
        case CXT5047_LAPTOP_EAPD:
+               spec->input_mux = &cxt5047_toshiba_capture_source;
                spec->num_init_verbs = 2;
                spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
+               spec->mixers[0] = cxt5047_toshiba_mixers;
                break;
 #ifdef CONFIG_SND_DEBUG
        case CXT5047_TEST:
@@ -1305,7 +1402,9 @@ static int patch_cxt5047(struct hda_codec *codec)
 }
 
 struct hda_codec_preset snd_hda_preset_conexant[] = {
-       { .id = 0x14f15045, .name = "CXT5045", .patch = patch_cxt5045 },
-       { .id = 0x14f15047, .name = "CXT5047", .patch = patch_cxt5047 },
+       { .id = 0x14f15045, .name = "CX20549 (Venice)",
+         .patch = patch_cxt5045 },
+       { .id = 0x14f15047, .name = "CX20551 (Waikiki)",
+         .patch = patch_cxt5047 },
        {} /* terminator */
 };
index 6f4a39273b988f8a99f8ac83283684a925cfc1ec..f7ef9c5afe8732d70d98b6191df4dc1b00f6571a 100644 (file)
@@ -457,6 +457,10 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
                      "Dell Latitude 120L", STAC_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,
                      "Dell Latitude D820", STAC_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd,
+                     "Dell Inspiron E1705/9400", STAC_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,
+                     "Dell XPS M1710", STAC_REF),
        {} /* terminator */
 };
 
@@ -1800,6 +1804,7 @@ static int patch_stac925x(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
                                                        stac925x_models,
                                                        stac925x_cfg_tbl);
+ again:
        if (spec->board_config < 0) {
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x, using BIOS defaults\n");
                err = stac92xx_save_bios_config_regs(codec);
@@ -1825,6 +1830,15 @@ static int patch_stac925x(struct hda_codec *codec)
        spec->mixer = stac925x_mixer;
 
        err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
+       if (!err) {
+               if (spec->board_config < 0) {
+                       printk(KERN_WARNING "hda_codec: No auto-config is "
+                              "available, default to model=ref\n");
+                       spec->board_config = STAC_925x_REF;
+                       goto again;
+               }
+               err = -EINVAL;
+       }
        if (err < 0) {
                stac92xx_free(codec);
                return err;
@@ -1850,6 +1864,7 @@ static int patch_stac922x(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
                                                        stac922x_models,
                                                        stac922x_cfg_tbl);
+ again:
        if (spec->board_config < 0) {
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
                        "using BIOS defaults\n");
@@ -1875,6 +1890,15 @@ static int patch_stac922x(struct hda_codec *codec)
        spec->multiout.dac_nids = spec->dac_nids;
        
        err = stac92xx_parse_auto_config(codec, 0x08, 0x09);
+       if (!err) {
+               if (spec->board_config < 0) {
+                       printk(KERN_WARNING "hda_codec: No auto-config is "
+                              "available, default to model=ref\n");
+                       spec->board_config = STAC_D945_REF;
+                       goto again;
+               }
+               err = -EINVAL;
+       }
        if (err < 0) {
                stac92xx_free(codec);
                return err;
@@ -1903,6 +1927,7 @@ static int patch_stac927x(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
                                                        stac927x_models,
                                                        stac927x_cfg_tbl);
+ again:
        if (spec->board_config < 0) {
                 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n");
                err = stac92xx_save_bios_config_regs(codec);
@@ -1945,6 +1970,15 @@ static int patch_stac927x(struct hda_codec *codec)
        spec->multiout.dac_nids = spec->dac_nids;
 
        err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
+       if (!err) {
+               if (spec->board_config < 0) {
+                       printk(KERN_WARNING "hda_codec: No auto-config is "
+                              "available, default to model=ref\n");
+                       spec->board_config = STAC_D965_REF;
+                       goto again;
+               }
+               err = -EINVAL;
+       }
        if (err < 0) {
                stac92xx_free(codec);
                return err;
@@ -1970,6 +2004,7 @@ static int patch_stac9205(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
                                                        stac9205_models,
                                                        stac9205_cfg_tbl);
+ again:
        if (spec->board_config < 0) {
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
                err = stac92xx_save_bios_config_regs(codec);
@@ -2008,6 +2043,15 @@ static int patch_stac9205(struct hda_codec *codec)
                            AC_VERB_SET_GPIO_MASK, 0x00000001);
 
        err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
+       if (!err) {
+               if (spec->board_config < 0) {
+                       printk(KERN_WARNING "hda_codec: No auto-config is "
+                              "available, default to model=ref\n");
+                       spec->board_config = STAC_9205_REF;
+                       goto again;
+               }
+               err = -EINVAL;
+       }
        if (err < 0) {
                stac92xx_free(codec);
                return err;
index fcc544a96ba3e80552f6ff4b7584ee6ddbcbf0ea..9fc0c0388881cdfca722e2504bfd9ae369716af2 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -29,7 +31,6 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_ssc.h>
-#include <asm/arch/at91_pdc.h>
 
 #include "at91-pcm.h"
 #include "at91-i2s.h"
  * SSC PDC registers required by the PCM DMA engine.
  */
 static struct at91_pdc_regs pdc_tx_reg = {
-       .xpr            = AT91_PDC_TPR,
-       .xcr            = AT91_PDC_TCR,
-       .xnpr           = AT91_PDC_TNPR,
-       .xncr           = AT91_PDC_TNCR,
+       .xpr            = ATMEL_PDC_TPR,
+       .xcr            = ATMEL_PDC_TCR,
+       .xnpr           = ATMEL_PDC_TNPR,
+       .xncr           = ATMEL_PDC_TNCR,
 };
 
 static struct at91_pdc_regs pdc_rx_reg = {
-       .xpr            = AT91_PDC_RPR,
-       .xcr            = AT91_PDC_RCR,
-       .xnpr           = AT91_PDC_RNPR,
-       .xncr           = AT91_PDC_RNCR,
+       .xpr            = ATMEL_PDC_RPR,
+       .xcr            = ATMEL_PDC_RCR,
+       .xnpr           = ATMEL_PDC_RNPR,
+       .xncr           = ATMEL_PDC_RNCR,
 };
 
 /*
@@ -72,8 +73,8 @@ static struct at91_ssc_mask ssc_tx_mask = {
        .ssc_disable    = AT91_SSC_TXDIS,
        .ssc_endx       = AT91_SSC_ENDTX,
        .ssc_endbuf     = AT91_SSC_TXBUFE,
-       .pdc_enable     = AT91_PDC_TXTEN,
-       .pdc_disable    = AT91_PDC_TXTDIS,
+       .pdc_enable     = ATMEL_PDC_TXTEN,
+       .pdc_disable    = ATMEL_PDC_TXTDIS,
 };
 
 static struct at91_ssc_mask ssc_rx_mask = {
@@ -81,8 +82,8 @@ static struct at91_ssc_mask ssc_rx_mask = {
        .ssc_disable    = AT91_SSC_RXDIS,
        .ssc_endx       = AT91_SSC_ENDRX,
        .ssc_endbuf     = AT91_SSC_RXBUFF,
-       .pdc_enable     = AT91_PDC_RXTEN,
-       .pdc_disable    = AT91_PDC_RXTDIS,
+       .pdc_enable     = ATMEL_PDC_RXTEN,
+       .pdc_disable    = ATMEL_PDC_RXTDIS,
 };
 
 
@@ -508,14 +509,14 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
                /* Reset the SSC and its PDC registers */
                at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
 
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RCR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNPR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNCR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TPR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TCR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0);
-               at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
+               at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
 
                if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
                                        0, ssc_p->name, ssc_p)) < 0) {
index e88b12e7cc40395aab427d3c27e3509f60573934..b39b95a470401edd66f8789826317ede5e59e593 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
 
 #include <sound/driver.h>
 #include <sound/core.h>
@@ -30,7 +31,6 @@
 
 #include <asm/arch/hardware.h>
 #include <asm/arch/at91_ssc.h>
-#include <asm/arch/at91_pdc.h>
 
 #include "at91-pcm.h"
 
@@ -83,7 +83,7 @@ static void at91_pcm_dma_irq(u32 ssc_sr,
                        params->name, ssc_sr, count);
 
                /* re-start the PDC */
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
 
                prtd->period_ptr += prtd->period_size;
                if (prtd->period_ptr >= prtd->dma_buffer_end) {
@@ -94,7 +94,7 @@ static void at91_pcm_dma_irq(u32 ssc_sr,
                at91_ssc_write(params->ssc_base + params->pdc->xcr,
                                prtd->period_size / params->pdc_xfer_size);
 
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
        }
 
        if (ssc_sr & params->mask->ssc_endx) {
@@ -143,7 +143,7 @@ static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
        struct at91_pcm_dma_params *params = prtd->params;
 
        if (params != NULL) {
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
                prtd->params->dma_intr_handler = NULL;
        }
 
@@ -158,7 +158,7 @@ static int at91_pcm_prepare(struct snd_pcm_substream *substream)
        at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
                        params->mask->ssc_endx | params->mask->ssc_endbuf);
 
-       at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
+       at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
        return 0;
 }
 
@@ -192,7 +192,7 @@ static int at91_pcm_trigger(struct snd_pcm_substream *substream,
                at91_ssc_write(params->ssc_base + AT91_SSC_IER,
                        params->mask->ssc_endx | params->mask->ssc_endbuf);
 
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
 
                DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc_base + AT91_SSC_SR),
                                        at91_ssc_read(params->ssc_base + AT91_SSC_IER));
@@ -201,12 +201,12 @@ static int at91_pcm_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
                break;
 
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
+               at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
                break;
 
        default:
@@ -379,7 +379,7 @@ static int at91_pcm_suspend(struct platform_device *pdev,
 
        /* disable the PDC and save the PDC registers */
 
-       at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
+       at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
 
        prtd->pdc_xpr_save  = at91_ssc_read(params->ssc_base + params->pdc->xpr);
        prtd->pdc_xcr_save  = at91_ssc_read(params->ssc_base + params->pdc->xcr);
@@ -408,7 +408,7 @@ static int at91_pcm_resume(struct platform_device *pdev,
        at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
        at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
 
-       at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
+       at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
        return 0;
 }
 #else
index 78ac2688e1247dfbe082a150466f5b1116ef4cb1..ec2a2787957a2d56497dec1dc3bda83f5a7842df 100644 (file)
@@ -1,15 +1,15 @@
 config SND_SOC_AC97_CODEC
        tristate
-       depends SND_SOC
+       depends on SND_SOC
 
 config SND_SOC_WM8731
        tristate
-       depends SND_SOC
+       depends on SND_SOC
 
 config SND_SOC_WM8750
        tristate
-       depends SND_SOC
+       depends on SND_SOC
 
 config SND_SOC_WM9712
        tristate
-       depends SND_SOC
+       depends on SND_SOC
index 573e3701c14f02f526bac8777d86fa922e36d2a0..ebcac13fd3970cd0c0fd989748b6a08c89a4b636 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <sound/driver.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <sound/core.h>
index 59144ec026e4c4534b136e99c059f67b513034d7..680f2b7fec207158abd4ef28cec6c72364ac9d83 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <sound/driver.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/emux_synth.h>
index 4dfb91d4398a02fb6962ba07310f658d7cc30fe9..b6d886373bb001b46da476a0cb1a2f3c6d44db19 100644 (file)
@@ -325,16 +325,6 @@ static int prepare_capture_urb(struct snd_usb_substream *subs,
        }
        urb->transfer_buffer_length = offs;
        urb->number_of_packets = ctx->packets;
-#if 0 // for check
-       if (! urb->bandwidth) {
-               int bustime;
-               bustime = usb_check_bandwidth(urb->dev, urb);
-               if (bustime < 0)
-                       return bustime;
-               printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets);
-               usb_claim_bandwidth(urb->dev, urb, bustime, 1);
-       }
-#endif // for check
        return 0;
 }
 
index 25b4ab4f61e7299d1eda8dc84b5eb1b47c2f17fd..858262068f4fe5ff4502e0d1df9221ef029f6532 100644 (file)
@@ -947,6 +947,29 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
        /* TODO: add Edirol M-100FX support */
+{
+       /* has ID 0x004e when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x004c),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "EDIROL",
+               .product_name = "PCR-A",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        /* has ID 0x004f when not in "Advanced Driver" mode */
        USB_DEVICE(0x0582, 0x004d),